├── .gitignore ├── CHANGES.txt ├── Dockerfile ├── Docs ├── Authority-zh.md ├── Authority.md ├── Parameter-zh.md ├── Parameter.md ├── Similar-zh.md ├── Similar.md └── images │ ├── home.png │ ├── logo_full_color.png │ ├── logo_full_color_h100.png │ ├── logo_full_white.png │ ├── logo_head_color.png │ ├── logo_head_white.png │ ├── logo_word_color.png │ ├── logo_word_white.png │ ├── node-view.png │ └── permission-design.png ├── LICENSE.txt ├── NOTICE.txt ├── README-zh.md ├── README.md ├── VERSION ├── bin ├── docker-run.sh ├── run.sh └── wait-for-it.sh ├── conf ├── application-base.properties ├── application-default.properties ├── application-docker.properties └── logback-spring.xml ├── db └── init.sql ├── docker-compose.yml ├── pom.xml ├── shepher-common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── xiaomi │ └── shepher │ ├── common │ ├── Action.java │ ├── Auth.java │ ├── Jurisdiction.java │ ├── LoginRequired.java │ ├── ReviewStatus.java │ ├── Role.java │ └── Status.java │ └── util │ ├── IpPathFilter.java │ ├── ParamUtils.java │ ├── ParentPathParser.java │ └── ShepherConstants.java ├── shepher-model ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── xiaomi │ └── shepher │ └── model │ ├── Cluster.java │ ├── NeedReview.java │ ├── Permission.java │ ├── PermissionTeam.java │ ├── ReviewRequest.java │ ├── Snapshot.java │ ├── Team.java │ ├── User.java │ └── UserTeam.java ├── shepher-packaging ├── pom.xml └── src │ └── main │ └── assembly │ ├── bin.xml │ └── src.xml ├── shepher-service ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── xiaomi │ │ └── shepher │ │ ├── biz │ │ ├── ClusterAdminBiz.java │ │ ├── NodeBiz.java │ │ ├── PermissionBiz.java │ │ ├── PermissionTeamBiz.java │ │ ├── ReviewBiz.java │ │ ├── SnapshotBiz.java │ │ ├── TeamBiz.java │ │ ├── UserBiz.java │ │ └── UserTeamBiz.java │ │ ├── common │ │ ├── CustomMailSender.java │ │ ├── DaoValidator.java │ │ ├── GeneralMailSender.java │ │ ├── MailSender.java │ │ ├── MailSenderAbstract.java │ │ ├── MailSenderFactory.java │ │ ├── UserHolder.java │ │ └── UserHolderImpl.java │ │ ├── dao │ │ ├── ClusterAdminMapper.java │ │ ├── NodeDAO.java │ │ ├── PermissionMapper.java │ │ ├── PermissionTeamMapper.java │ │ ├── ReviewMapper.java │ │ ├── SnapshotMapper.java │ │ ├── TeamMapper.java │ │ ├── UserMapper.java │ │ ├── UserTeamMapper.java │ │ └── mybatis │ │ │ └── MybatisExtendedLanguageDriver.java │ │ ├── exception │ │ └── ShepherException.java │ │ ├── service │ │ ├── ClusterAdminService.java │ │ ├── NodeService.java │ │ ├── PermissionService.java │ │ ├── ReviewService.java │ │ ├── SnapshotService.java │ │ ├── TeamService.java │ │ └── UserService.java │ │ └── util │ │ ├── ClusterUtil.java │ │ ├── ReviewUtil.java │ │ ├── StringSerializer.java │ │ └── ZkPool.java │ └── test │ ├── java │ └── com │ │ └── xiaomi │ │ └── shepher │ │ ├── BaseTest.java │ │ ├── ShepherApplicationTests.java │ │ ├── TestContextConfiguration.java │ │ ├── dao │ │ ├── ClusterAdminMapperTest.java │ │ ├── PermissionMapperTest.java │ │ ├── PermissionTeamMapperTest.java │ │ ├── ReviewMapperTest.java │ │ ├── SnapshotMapperTest.java │ │ ├── TeamMapperTest.java │ │ ├── UserMapperTest.java │ │ └── UserTeamMapperTest.java │ │ └── service │ │ ├── ClusterAdminServiceTest.java │ │ ├── NodeServiceTest.java │ │ ├── PermissionServiceTest.java │ │ ├── ReviewServiceTest.java │ │ ├── SnapshotServiceTest.java │ │ ├── TeamServiceTest.java │ │ └── UserServiceTest.java │ └── resources │ ├── application.properties │ └── h2database │ ├── data.sql │ ├── schema.sql │ └── teardown.sql ├── shepher-web ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── xiaomi │ │ └── shepher │ │ ├── ServletInitializer.java │ │ ├── ShepherApplication.java │ │ ├── configuration │ │ ├── WebConfiguration.java │ │ └── WebSecurityConfig.java │ │ ├── controller │ │ ├── ClusterAdminController.java │ │ ├── ClusterController.java │ │ ├── IndexController.java │ │ ├── NodeController.java │ │ ├── PermissionController.java │ │ ├── ReviewController.java │ │ ├── ShepherExceptionHandler.java │ │ └── TeamController.java │ │ ├── interceptor │ │ ├── AuthorizationInterceptor.java │ │ ├── LoginRequiredInterceptor.java │ │ ├── NavInterceptor.java │ │ └── PassportInterceptor.java │ │ └── util │ │ └── AuthStrategy.java │ └── resources │ ├── static │ └── static │ │ ├── css │ │ └── vendor │ │ │ ├── bootstrap.min.css │ │ │ ├── codemirror.min.css │ │ │ ├── codemirror.min.css.map │ │ │ ├── dracula.min.css │ │ │ ├── dracula.min.css.map │ │ │ ├── merge.min.css │ │ │ └── merge.min.css.map │ │ ├── fonts │ │ └── vendor │ │ │ ├── 1YwB1sO8YE1Lyjf12WNiUA.woff2 │ │ │ ├── H2DMvhDLycM56KNuAtbJYA.woff2 │ │ │ ├── ObQr5XYcoH0WBoUxiaYK3_Y6323mHUZFJMgTvxaG2iE.woff2 │ │ │ ├── PLygLKRVCQnA5fhu3qk5fQ.woff2 │ │ │ ├── UyBMtLsHKBKXelqf4x7VRQ.woff2 │ │ │ ├── YMOYVM-eg6Qs9YzV9OSqZfesZW2xOQ-xsNqO47m55DA.woff2 │ │ │ └── fonts.css │ │ ├── img │ │ └── favicon.ico │ │ ├── js │ │ └── vendor │ │ │ ├── bootstrap.min.js │ │ │ ├── codemirror.min.js │ │ │ ├── diff_match_patch.js │ │ │ ├── htmlmixed.min.js │ │ │ ├── jquery.min.js │ │ │ ├── merge.min.js │ │ │ ├── properties.min.js │ │ │ └── xml.min.js │ │ └── main.css │ └── templates │ ├── admin │ ├── create-modal.ftl │ ├── delete-modal.ftl │ ├── index.ftl │ └── update-modal.ftl │ ├── cluster │ ├── create-modal.ftl │ ├── create.ftl │ ├── delete-modal.ftl │ ├── import-modal.ftl │ ├── index.ftl │ ├── list.ftl │ ├── sider.ftl │ ├── snapshot-modal.ftl │ ├── stat-modal.ftl │ └── update-modal.ftl │ ├── error.ftl │ ├── header.ftl │ ├── login.ftl │ ├── nav.ftl │ ├── permission │ ├── add-modal.ftl │ ├── delete-modal.ftl │ └── manage.ftl │ ├── review │ ├── accept-modal.ftl │ ├── reject-modal.ftl │ ├── review.ftl │ ├── snapshot.ftl │ └── snapshots.ftl │ ├── script.ftl │ └── team │ ├── add_member-modal.ftl │ ├── apply.ftl │ ├── apply_permission-modal.ftl │ ├── index.ftl │ ├── manage.ftl │ ├── member.ftl │ └── permission.ftl └── site ├── checkstyle.xml ├── findbugs-exclude-filter.xml └── pmd-ruleset.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | target 4 | release 5 | logs 6 | .arcconfig 7 | *.xml.versionsBackup 8 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## 1.0 4 | * Initial release! -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8-jdk 2 | 3 | 4 | MAINTAINER banchuanyu 5 | MAINTAINER zhangpeng 6 | 7 | ENV SHEPHER_HOME /usr/shepher 8 | ENV BASE_DIR /usr/shepher 9 | 10 | WORKDIR $SHEPHER_HOME 11 | 12 | COPY ./lib/*.jar $SHEPHER_HOME/lib/ 13 | COPY ./bin/wait-for-it.sh $SHEPHER_HOME 14 | COPY ./conf/* $SHEPHER_HOME/conf/ 15 | CMD ./wait-for-it.sh -t 300 db:3306 && java -jar lib/shepher-web-1.0.jar --spring.config.location=conf/application-base.properties,conf/application-docker.properties -Djava.ext.dirs=lib 16 | -------------------------------------------------------------------------------- /Docs/Authority-zh.md: -------------------------------------------------------------------------------- 1 | # 权限管理说明 2 | 3 | ## 设计思路 4 | 5 | 与常见的管理员统一管理所有权限不同,本项目将权限以小组为单位授权,采用管理员管理小组,小组的组长管理组内成员的方式。这种分级的权限管理模式大大减少了管理员的审核负担,组内自治也增加了灵活性。 6 | 7 | 权限管理结构图: 8 | 其中,zookeeper的权限以节点为单位,小组向管理员申请权限,由超级管理员负责审核和授权。小组成员由用户组成,用户可以选择创建新的小组或者加入已有的小组。 9 | 10 | ![权限管理结构图](images/permission-design.png) 11 | 12 | ## 功能说明 13 | 14 | ### 超级管理员 15 | 16 | 超级管理员都属于一个特殊的小组 -- admin,需要负责如下管理: 17 | 18 | - 审核小组的权限申请(同意/拒绝) 19 | - 给小组授予某个节点的权限 20 | 21 | ### 权限 22 | 23 | 权限是以节点为粒度划分的,是以小组为单位下放的。 24 | 25 | - 节点权限:每个节点由集群和路径唯一确定,拥有父节点权限即拥有该节点的子节点权限 26 | 27 | ### 小组 28 | 29 | #### 小组角色 30 | 31 | 小组成员分为不同的角色,目前有三种角色: 32 | 33 | - master:小组的管理者。可以管理组内成员,向管理员申请权限;拥有节点的增、删、改权限 34 | - developer:开发者。拥有节点的增改权限,没有删除权限 35 | - member:暂时同developer 36 | 37 | 一个小组可以拥有多个节点的权限,同一小组的所有成员共享节点权限。 38 | 小组成员均可增改该小组拥有权限的节点,但只有小组的 master 能够删除节点。 39 | 40 | #### 小组管理 41 | 42 | - 处理用户的入组申请 43 | - 添加/删除小组成员 44 | - 更改小组成员的角色 45 | - 申请新的节点权限 46 | 47 | 48 | ### 用户 49 | 50 | 用户在操作节点前需要申请权限,主要有两种方式: 51 | 52 | - 新建小组:用户在新建小组的时候即会对当前节点发出权限申请,待管理员审核通过即可 53 | - 申请入组:用户申请加入拥有某个节点权限的任意小组,等待小组 master 同意即可 54 | 55 | ## 使用方法 56 | 57 | 本部分主要介绍系统功能入口,并附上效果截图。 58 | 59 | 域名和端口号为 serverName:serverPort,下文只给出相对链接。 60 | 61 | ### 超级管理员 62 | 63 | - 集群管理: `/admin` 64 | 65 | - 权限管理: `/permission` 66 | 67 | ### 小组管理 68 | 69 | - 该用户所属小组列表: `/teams` 70 | 71 | - 小组成员管理: `/teams/{teamId}/manage` 72 | 73 | - 小组权限管理: `/teams/{teamId}/permission` 74 | 75 | 76 | ### 用户申请 77 | 78 | - 用户申请权限: `/teams/apply?path=/zookeeper&cluster=local_test` -------------------------------------------------------------------------------- /Docs/Parameter-zh.md: -------------------------------------------------------------------------------- 1 | # 参数说明 2 | 3 | 参数 | 含义 | 限定可选值 | 备注 4 | ---|---|---|--- 5 | mail.hostname | generalMailSender 使用的邮件服务器 | 6 | mail.port | generalMailSender 使用的邮件服务器端口 | 7 | mail.username | generalMailSender 用户名 | 8 | mail.password | generalMailSender 认证码 | 9 | mail.from | generalMailSender 发件人 | 10 | mail.fromname | generalMailSender 发件人显示名 | 11 | **mail.sender** | Shepher 系统使用的邮件发送方式 | generalMailSender/customMailSender | customMailSender 是自定义邮件类,参考CustomMailSender 12 | **cas.server.url.prefix** | CAS 认证服务器地址 | 13 | cas.login.url | CAS 认证服务器登录入口 | 14 | cas.logout.url | CAS 认证服务器登出入口 | 15 | **ldap.url** | LDAP 认证服务地址 | 16 | ldap.password | LDAP 认证密码 | 17 | ldap.dn | LDAP 认证 DN | 18 | **server.url** | Shepher 服务地址 | 19 | **server.port** | Shepher 服务端口 | 20 | **mail.mailToSuffix** | 邮件接收人地址后缀 | 21 | mail.mailAddressEndSeparator | 多邮件接收人分隔符 | 22 | **server.login.type** | Shepher 登录类型 | CAS/LDAP | 目前仅支持 CAS 和 LDAP 两种登录方式 -------------------------------------------------------------------------------- /Docs/Parameter.md: -------------------------------------------------------------------------------- 1 | # Parameter instruction 2 | 3 | Parameter | Implication | Limited optional | Remark 4 | ---|---|---|--- 5 | mail.hostname | generalMailSender used mail server | 6 | mail.port | generalMailSender used port of mail server | 7 | mail.username | generalMailSender user name | 8 | mail.password | generalMailSender authentication code | 9 | mail.from | generalMailSender sender | 10 | mail.fromname | generalMailSender display name of the sender | 11 | **mail.sender** | Mail sending method used by Shepher | generalMailSender/customMailSender | customMailSender is self-defined mail type, reference CustomMailSender 12 | **cas.server.url.prefix** | CAS authentication server address | 13 | cas.login.url | CAS authentication server login access | 14 | cas.logout.url | CAS authentication server logout access | 15 | **ldap.url** | LDAP authentication server address | 16 | ldap.password | LDAP authentication password | 17 | ldap.dn | LDAP authentication DN | 18 | **server.url** | Shepher server address | 19 | **server.port** | Shepher server port | 20 | **mail.mailToSuffix** | Suffix of the address of a mail receiver | 21 | mail.mailAddressEndSeparator | Separator for many receivers of a mail | 22 | **server.login.type** | Shepher login type | CAS/LDAP | Only CAS and LDAP are supported at present -------------------------------------------------------------------------------- /Docs/Similar-zh.md: -------------------------------------------------------------------------------- 1 | ## 同类产品功能对比 2 | 3 | 产品 | 简介 | 节点的CURD 操作 | 快照管理 | 节点修改的 Diff 和 Review 功能 | 节点操作邮件通知 | CAS 和 LDAP 登录 | 权限管理 | 级联删除 | 系统状态监控 4 | ---|---|---|---|---|---|---|---|---|--- 5 | Shepher | ZK 管理 | √ | √ | √ | √ | √ | √ | | 6 | TaoKeeper | ZK 集群监控与报表 | | | | | | | | √ 7 | Zkdash | ZK 管理 | √ | √ | | | | | √ | 8 | Disconf | ZK 管理 | √ | √ | | √ | | √ | √ | √ 9 | XDiamond | 配置中心 | √ | | | | √ | √ | | √ -------------------------------------------------------------------------------- /Docs/Similar.md: -------------------------------------------------------------------------------- 1 | ## Function comparison of similar products 2 | 3 | Product | Introduction | CURD operation of nodes | Snapshot management | Node modified Diff and Review function | Node operated mail notification | CAS and LDAP log | Authority management | Cascade delete | System status monitor 4 | ---|---|---|---|---|---|---|---|---|--- 5 | Shepher | ZK management | √ | √ | √ | √ | √ | √ | | 6 | TaoKeeper | ZK cluster monitor and statement | | | | | | | | √ 7 | Zkdash | ZK management | √ | √ | | | | | √ | 8 | Disconf | ZK management | √ | √ | | √ | | √ | √ | √ 9 | XDiamond | Configuration center | √ | | | | √ | √ | | √ -------------------------------------------------------------------------------- /Docs/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/home.png -------------------------------------------------------------------------------- /Docs/images/logo_full_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_full_color.png -------------------------------------------------------------------------------- /Docs/images/logo_full_color_h100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_full_color_h100.png -------------------------------------------------------------------------------- /Docs/images/logo_full_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_full_white.png -------------------------------------------------------------------------------- /Docs/images/logo_head_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_head_color.png -------------------------------------------------------------------------------- /Docs/images/logo_head_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_head_white.png -------------------------------------------------------------------------------- /Docs/images/logo_word_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_word_color.png -------------------------------------------------------------------------------- /Docs/images/logo_word_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/logo_word_white.png -------------------------------------------------------------------------------- /Docs/images/node-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/node-view.png -------------------------------------------------------------------------------- /Docs/images/permission-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/Docs/images/permission-design.png -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017 Xiaomi, Inc. All Rights Reserved. 2 | This product includes software developed by Xiaomi, Inc. 3 | (http://www.mi.com/). 4 | 5 | This product is licensed to you under the Apache License, Version 2.0 6 | (the "License"). You may not use this product except in compliance with 7 | the License. 8 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.0 -------------------------------------------------------------------------------- /conf/application-base.properties: -------------------------------------------------------------------------------- 1 | # DATABASE 2 | spring.datasource.driverClassName=com.mysql.jdbc.Driver 3 | 4 | spring.datasource.test-on-borrow=true 5 | spring.datasource.validation-query=select 1 from dual 6 | 7 | # MYBATIS 8 | mybatis.configuration.useGeneratedKeys=true 9 | mybatis.configuration.mapUnderscoreToCamelCase=true 10 | 11 | # FREEMARKER 12 | spring.freemarker.suffix=.ftl 13 | 14 | # DEFAULT MAIL 15 | mail.hostname=smtp.163.com 16 | mail.port=25 17 | mail.username=shepher_zk 18 | mail.password=shepher1111 19 | mail.from=shepher_zk@163.com 20 | mail.fromname=Shepher 21 | 22 | # mapped to constants in MailSenderFactory 23 | mail.sender=generalMailSender 24 | 25 | logging.config=${BASE_DIR}/conf/logback-spring.xml 26 | -------------------------------------------------------------------------------- /conf/application-default.properties: -------------------------------------------------------------------------------- 1 | # DATABASE 2 | spring.datasource.url=jdbc:mysql://localhost:3306/shepher?characterEncoding=UTF-8&autoReconnect=true 3 | spring.datasource.username=root 4 | spring.datasource.password=root 5 | 6 | # CAS 7 | cas.server.url.prefix=https://casdev.example.com 8 | cas.login.url=${cas.server.url.prefix}/login 9 | cas.logout.url=${cas.server.url.prefix}/logout 10 | 11 | # LDAP 12 | ldap.url=ldap://ldap.example.com:389/dc=example,dc=com 13 | ldap.password=123456 14 | ldap.dn=cn=admin,dc=example,dc=com 15 | 16 | # DEMO LOGIN 17 | demo.admin.name=youradmin 18 | demo.admin.password=123456 19 | 20 | # SERVER 21 | server.url=http://localhost 22 | server.port=8089 23 | 24 | # MAIL 25 | mail.mailToSuffix=@example.com 26 | mail.mailAddressEndSeparator=; 27 | 28 | # LOGIN TYPE (CAS or LDAP) 29 | server.login.type=DEMO 30 | -------------------------------------------------------------------------------- /conf/application-docker.properties: -------------------------------------------------------------------------------- 1 | # DATABASE 2 | spring.datasource.url=jdbc:mysql://db:3306/shepher?characterEncoding=UTF-8&autoReconnect=true 3 | spring.datasource.username=root 4 | spring.datasource.password=root 5 | 6 | # CAS 7 | cas.server.url.prefix=https://casdev.example.com 8 | cas.login.url=${cas.server.url.prefix}/login 9 | cas.logout.url=${cas.server.url.prefix}/logout 10 | 11 | # LDAP 12 | ldap.url=ldap://ldap.example.com:389/dc=example,dc=com 13 | ldap.password=123456 14 | ldap.dn=cn=admin,dc=example,dc=com 15 | 16 | # DEMO LOGIN 17 | demo.admin.name=youradmin 18 | demo.admin.password=123456 19 | 20 | # SERVER 21 | server.url=http://localhost 22 | server.port=8089 23 | 24 | # MAIL 25 | mail.mailToSuffix=@example.com 26 | mail.mailAddressEndSeparator=; 27 | 28 | # LOGIN TYPE (CAS or LDAP) 29 | server.login.type=DEMO 30 | -------------------------------------------------------------------------------- /conf/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ${FILE_LOG_PATTERN} 9 | 10 | ${LOG_FILE} 11 | 12 | ${LOG_FILE}.%d{yyyy-MM-dd}.%i 13 | 20MB 14 | 30 15 | 1GB 16 | 17 | 18 | 19 | 20 | ${CONSOLE_LOG_PATTERN} 21 | utf8 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | db: 4 | image: mysql 5 | environment: 6 | MYSQL_ROOT_PASSWORD: root 7 | volumes: 8 | - ./db:/docker-entrypoint-initdb.d 9 | web: 10 | build: ./ 11 | image: shepher 12 | ports: 13 | - "8089:8089" 14 | depends_on: 15 | - db 16 | - zookeeper 17 | links: 18 | - db 19 | zookeeper: 20 | image: zookeeper 21 | expose: 22 | - 2181 23 | - 2888 24 | - 3888 25 | -------------------------------------------------------------------------------- /shepher-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | shepher 7 | com.xiaomi 8 | 1.0 9 | 10 | 4.0.0 11 | 12 | shepher-common 13 | 14 | 15 | 16 | org.apache.commons 17 | commons-lang3 18 | 3.1 19 | 20 | 21 | commons-codec 22 | commons-codec 23 | 1.4 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/Action.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | /** 20 | * Created by banchuanyu on 16-6-12. 21 | */ 22 | public enum Action { 23 | ADD(10, "add"), 24 | 25 | DELETE(20, "delete"), 26 | 27 | UPDATE(30, "update"); 28 | 29 | private int value; 30 | private String description; 31 | 32 | Action(int value, String description) { 33 | this.value = value; 34 | this.description = description; 35 | } 36 | 37 | public static Action get(int value) { 38 | for (Action action : Action.values()) { 39 | if (action.getValue() == value) { 40 | return action; 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | public int getValue() { 47 | return value; 48 | } 49 | 50 | public String getDescription() { 51 | return description; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/Auth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Created by weichuyang on 16-7-27. 26 | */ 27 | @Target({ElementType.TYPE, ElementType.METHOD}) 28 | @Retention(RetentionPolicy.RUNTIME) 29 | public @interface Auth { 30 | Jurisdiction value() default Jurisdiction.SUPER_ADMIN; 31 | } 32 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/Jurisdiction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | /** 20 | * Created by weichuyang on 16-7-27. 21 | */ 22 | public enum Jurisdiction { 23 | SUPER_ADMIN, 24 | TEAM_OWNER, 25 | TEAM_MASTER, 26 | TEAM_MEMBER 27 | } 28 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/LoginRequired.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Created by banchuanyu on 16-7-21. 26 | */ 27 | @Target({ElementType.TYPE, ElementType.METHOD}) 28 | @Retention(RetentionPolicy.RUNTIME) 29 | public @interface LoginRequired { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/ReviewStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | /** 20 | * Created by banchuanyu on 16-7-28. 21 | */ 22 | public enum ReviewStatus { 23 | NEW(0, "new"), 24 | 25 | ACCEPTED(10, "accepted"), 26 | 27 | REJECTED(-10, "rejected"), 28 | 29 | DELETED(-100, "deleted"); 30 | 31 | private int value; 32 | private String description; 33 | 34 | ReviewStatus(int value, String description) { 35 | this.value = value; 36 | this.description = description; 37 | } 38 | 39 | public static ReviewStatus get(int value) { 40 | for (ReviewStatus reviewStatus : ReviewStatus.values()) { 41 | if (reviewStatus.getValue() == value) { 42 | return reviewStatus; 43 | } 44 | } 45 | return null; 46 | } 47 | 48 | public int getValue() { 49 | return value; 50 | } 51 | 52 | public String getDescription() { 53 | return description; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/Role.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * Created by weichuyang on 16-7-8. 24 | */ 25 | public enum Role { 26 | MASTER(100, "master"), 27 | 28 | DEVELOPER(60, "developer"), 29 | 30 | MEMBER(10, "member"); 31 | 32 | private static final Map LOOKUP = new HashMap<>(); 33 | 34 | static { 35 | for (Role role : Role.values()) { 36 | LOOKUP.put(role.getValue(), role); 37 | } 38 | } 39 | 40 | private int value; 41 | private String description; 42 | 43 | Role(int value, String description) { 44 | this.value = value; 45 | this.description = description; 46 | } 47 | 48 | public static Role get(int value) { 49 | return LOOKUP.get(value); 50 | } 51 | 52 | public int getValue() { 53 | return value; 54 | } 55 | 56 | public String getDescription() { 57 | return description; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/common/Status.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * Created by weichuyang on 16-7-8. 24 | */ 25 | public enum Status { 26 | AGREE(10, "accepted"), 27 | 28 | REFUSE(-10, "refused"), 29 | 30 | PENDING(0, "pending"), 31 | 32 | DELETE(-100, "deleted"); 33 | 34 | private static final Map LOOKUP = new HashMap<>(); 35 | 36 | static { 37 | for (Status status : Status.values()) { 38 | LOOKUP.put(status.getValue(), status); 39 | } 40 | } 41 | 42 | private int value; 43 | private String description; 44 | 45 | Status(int value, String description) { 46 | this.value = value; 47 | this.description = description; 48 | } 49 | 50 | public static Status get(int value) { 51 | return LOOKUP.get(value); 52 | } 53 | 54 | public int getValue() { 55 | return value; 56 | } 57 | 58 | public String getDescription() { 59 | return description; 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/util/IpPathFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | import java.util.ArrayList; 20 | import java.util.HashSet; 21 | import java.util.LinkedList; 22 | import java.util.List; 23 | import java.util.Set; 24 | import java.util.regex.Matcher; 25 | import java.util.regex.Pattern; 26 | 27 | /** 28 | * Created by banchuanyu on 16-8-15. 29 | */ 30 | public class IpPathFilter { 31 | public static List filter(List nodes, String showIp) { 32 | Pattern pattern = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); 33 | List result = new LinkedList<>(); 34 | List ipResult = new ArrayList<>(); 35 | 36 | String[] showIps = showIp.split(","); 37 | Set allowIpSet = new HashSet<>(); 38 | for (String ip : showIps) { 39 | allowIpSet.add(ip.trim()); 40 | } 41 | 42 | for (String node : nodes) { 43 | Matcher matcher = pattern.matcher(node); 44 | if (matcher.matches()) { 45 | if (allowIpSet.contains(node)) { 46 | result.add(0, node); 47 | } 48 | } else { 49 | result.add(node); 50 | } 51 | } 52 | result.addAll(ipResult); 53 | 54 | return result; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/util/ParamUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | import org.apache.commons.codec.binary.StringUtils; 20 | import org.apache.commons.codec.net.URLCodec; 21 | 22 | import java.nio.charset.Charset; 23 | 24 | /** 25 | * Created by banchuanyu on 16-10-10. 26 | */ 27 | public class ParamUtils { 28 | public static String encodeUrl(String data) { 29 | return StringUtils.newStringUtf8(URLCodec.encodeUrl(null, data.getBytes(Charset.defaultCharset()))); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/util/ParentPathParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | /** 26 | * Created by banchuanyu on 16-8-5. 27 | */ 28 | public class ParentPathParser { 29 | public static List parse(String path) { 30 | if (path == null) { 31 | return Collections.emptyList(); 32 | } 33 | List parents = new ArrayList<>(); 34 | String[] pathSegments = path.split("/"); 35 | StringBuilder parent = new StringBuilder(""); 36 | parents.add("/"); 37 | for (String pathSegment : pathSegments) { 38 | if (StringUtils.isEmpty(pathSegment)) { 39 | continue; 40 | } 41 | parent.append("/"); 42 | String[] dotPathSegment = pathSegment.split("\\."); 43 | for (int i = 0; i < dotPathSegment.length; i++) { 44 | if (i != 0) { 45 | parent.append("."); 46 | } 47 | parent.append(dotPathSegment[i]); 48 | parents.add(parent.toString()); 49 | } 50 | } 51 | return parents; 52 | } 53 | 54 | public static String getParent(String path) { 55 | int lastIndex = path.lastIndexOf('/'); 56 | String parentPath = path.substring(0, lastIndex); 57 | return parentPath; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /shepher-common/src/main/java/com/xiaomi/shepher/util/ShepherConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | /** 20 | * Created by zhangpeng on 16-11-2. 21 | */ 22 | public interface ShepherConstants { 23 | 24 | String DB_OPERATE_CREATE = "create"; 25 | String DB_OPERATE_UPDATE = "update"; 26 | String DB_OPERATE_DELETE = "delete"; 27 | 28 | String LOGIN_TYPE_LDAP = "LDAP"; 29 | String LOGIN_TYPE_CAS = "CAS"; 30 | String LOGIN_TYPE_DEMO = "DEMO"; 31 | 32 | int DEFAULT_ROLEVALUE = 0; 33 | String ADMIN = "admin"; 34 | } 35 | -------------------------------------------------------------------------------- /shepher-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | shepher 7 | com.xiaomi 8 | 1.0 9 | 10 | 4.0.0 11 | 12 | shepher-model 13 | 14 | 15 | 16 | com.xiaomi 17 | shepher-common 18 | ${project.version} 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /shepher-model/src/main/java/com/xiaomi/shepher/model/Cluster.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Created by banchuanyu on 16-5-19. 23 | */ 24 | public class Cluster { 25 | private long id; 26 | // unique 27 | private String name; 28 | private String config; 29 | private Date time; 30 | 31 | public Cluster() { 32 | 33 | } 34 | 35 | public Cluster(String name, String config) { 36 | this.name = name; 37 | this.config = config; 38 | } 39 | 40 | public long getId() { 41 | return id; 42 | } 43 | 44 | public void setId(long id) { 45 | this.id = id; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public Date getTime() { 57 | return time; 58 | } 59 | 60 | public void setTime(Date time) { 61 | this.time = time; 62 | } 63 | 64 | public String getConfig() { 65 | return config; 66 | } 67 | 68 | public void setConfig(String config) { 69 | this.config = config; 70 | } 71 | 72 | @Override 73 | public int hashCode() { 74 | int result = name.hashCode(); 75 | result = 31 * result + config.hashCode(); 76 | return result; 77 | } 78 | 79 | @Override 80 | public boolean equals(Object obj) { 81 | if (this == obj) return true; 82 | if (!(obj instanceof Cluster)) return false; 83 | 84 | final Cluster cluster = (Cluster) obj; 85 | 86 | if (!config.equals(cluster.config)) return false; 87 | if (!name.equals(cluster.name)) return false; 88 | 89 | return true; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return "Cluster{" + 95 | "id=" + id + 96 | ", name='" + name + '\'' + 97 | ", config='" + config + '\'' + 98 | ", time=" + time + 99 | '}'; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /shepher-model/src/main/java/com/xiaomi/shepher/model/NeedReview.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Created by banchuanyu on 16-5-19. 23 | */ 24 | public class NeedReview { 25 | private long id; 26 | private String cluster; 27 | private String pathPrefix; 28 | private String reviewerList; 29 | private Date time; 30 | 31 | public long getId() { 32 | return id; 33 | } 34 | 35 | public void setId(long id) { 36 | this.id = id; 37 | } 38 | 39 | public String getCluster() { 40 | return cluster; 41 | } 42 | 43 | public void setCluster(String cluster) { 44 | this.cluster = cluster; 45 | } 46 | 47 | public String getPathPrefix() { 48 | return pathPrefix; 49 | } 50 | 51 | public void setPathPrefix(String pathPrefix) { 52 | this.pathPrefix = pathPrefix; 53 | } 54 | 55 | public String getReviewerList() { 56 | return reviewerList; 57 | } 58 | 59 | public void setReviewerList(String reviewerList) { 60 | this.reviewerList = reviewerList; 61 | } 62 | 63 | public Date getTime() { 64 | return time; 65 | } 66 | 67 | public void setTime(Date time) { 68 | this.time = time; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "NeedReview{" + 74 | "id=" + id + 75 | ", cluster='" + cluster + '\'' + 76 | ", pathPrefix='" + pathPrefix + '\'' + 77 | ", reviewerList='" + reviewerList + '\'' + 78 | ", time=" + time + 79 | '}'; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /shepher-model/src/main/java/com/xiaomi/shepher/model/Permission.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Created by banchuanyu on 16-5-19. 23 | */ 24 | public class Permission { 25 | private long id; 26 | private String cluster; 27 | private String path; 28 | private Date time; 29 | 30 | public Permission() { 31 | } 32 | 33 | public Permission(String cluster, String path) { 34 | this.cluster = cluster; 35 | this.path = path; 36 | } 37 | 38 | public long getId() { 39 | return id; 40 | } 41 | 42 | public void setId(long id) { 43 | this.id = id; 44 | } 45 | 46 | public String getCluster() { 47 | return cluster; 48 | } 49 | 50 | public void setCluster(String cluster) { 51 | this.cluster = cluster; 52 | } 53 | 54 | public String getPath() { 55 | return path; 56 | } 57 | 58 | public void setPath(String path) { 59 | this.path = path; 60 | } 61 | 62 | public Date getTime() { 63 | return time; 64 | } 65 | 66 | public void setTime(Date time) { 67 | this.time = time; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return "Permission{" + 73 | "id=" + id + 74 | ", cluster='" + cluster + '\'' + 75 | ", path='" + path + '\'' + 76 | ", time=" + time + 77 | '}'; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /shepher-model/src/main/java/com/xiaomi/shepher/model/Team.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Created by banchuanyu on 16-5-19. 23 | */ 24 | public class Team { 25 | private long id; 26 | private String name; 27 | private long owner; 28 | private Date time; 29 | 30 | public Team() { 31 | 32 | } 33 | 34 | public Team(String name, long owner) { 35 | this.name = name; 36 | this.owner = owner; 37 | } 38 | 39 | public long getId() { 40 | return id; 41 | } 42 | 43 | public void setId(long id) { 44 | this.id = id; 45 | } 46 | 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | public void setName(String name) { 52 | this.name = name; 53 | } 54 | 55 | public long getOwner() { 56 | return owner; 57 | } 58 | 59 | public void setOwner(long owner) { 60 | this.owner = owner; 61 | } 62 | 63 | public Date getTime() { 64 | return time; 65 | } 66 | 67 | public void setTime(Date time) { 68 | this.time = time; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "Team{" + 74 | "id=" + id + 75 | ", name='" + name + '\'' + 76 | ", owner=" + owner + 77 | ", time=" + time + 78 | '}'; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /shepher-model/src/main/java/com/xiaomi/shepher/model/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Created by banchuanyu on 16-5-19. 23 | */ 24 | public class User { 25 | private long id; 26 | private String name; 27 | private Date time; 28 | 29 | public User() { 30 | } 31 | 32 | public User(String name) { 33 | this.name = name; 34 | } 35 | 36 | public long getId() { 37 | return id; 38 | } 39 | 40 | public void setId(long id) { 41 | this.id = id; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | public Date getTime() { 53 | return time; 54 | } 55 | 56 | public void setTime(Date time) { 57 | this.time = time; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "User{" + 63 | "id=" + id + 64 | ", name='" + name + '\'' + 65 | ", time=" + time + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /shepher-packaging/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xiaomi 8 | shepher 9 | 1.0 10 | ../pom.xml 11 | 12 | 13 | shepher-packaging 14 | pom 15 | shepher-packaging 16 | 17 | 18 | shepher-packaging 19 | ${project.build.directory}/${module-name}-${project.version}-bin 20 | 21 | 22 | 23 | 24 | com.xiaomi 25 | shepher-web 26 | ${project.version} 27 | 28 | 29 | com.xiaomi 30 | shepher-model 31 | ${project.version} 32 | 33 | 34 | com.xiaomi 35 | shepher-service 36 | ${project.version} 37 | 38 | 39 | com.xiaomi 40 | shepher-common 41 | ${project.version} 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-assembly-plugin 50 | 51 | 52 | assemble 53 | package 54 | 55 | single 56 | 57 | 58 | posix 59 | 60 | src/main/assembly/bin.xml 61 | src/main/assembly/src.xml 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-dependency-plugin 70 | 2.8 71 | 72 | 73 | copy-dependencies 74 | package 75 | 76 | copy-dependencies 77 | 78 | 79 | ${project.build.path}/lib 80 | false 81 | false 82 | true 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /shepher-packaging/src/main/assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | bin 7 | 8 | 9 | dir 10 | 11 | 12 | false 13 | 14 | 15 | true 16 | 17 | com.xiaomi:shepher-web 18 | com.xiaomi:shepher-model 19 | com.xiaomi:shepher-common 20 | com.xiaomi:shepher-service 21 | 22 | 23 | lib 24 | false 25 | 26 | 27 | 28 | 29 | 30 | 31 | ${project.parent.basedir} 32 | 33 | 34 | **/*.jar 35 | **/target/** 36 | logs 37 | 38 | 39 | 40 | README.md 41 | README-zh.md 42 | LICENSE.txt 43 | NOTICE.txt 44 | CHANGES.txt 45 | VERSION 46 | Dockerfile 47 | docker-compose.yml 48 | bin/**/* 49 | conf/**/* 50 | db/**/* 51 | deploy/**/* 52 | 53 | / 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /shepher-packaging/src/main/assembly/src.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | src 7 | 8 | 9 | tar.gz 10 | 11 | 12 | shepher-${project.version}-src 13 | 14 | 15 | 16 | ${project.parent.basedir} 17 | 18 | 19 | **/*.jar 20 | **/target/** 21 | logs 22 | 23 | 24 | 25 | README.md 26 | README-zh.md 27 | LICENSE.txt 28 | NOTICE.txt 29 | CHANGES.txt 30 | VERSION 31 | Dockerfile 32 | docker-compose.yml 33 | bin/**/* 34 | conf/**/* 35 | db/**/* 36 | deploy/**/* 37 | Docs/**/* 38 | packaging/pom.xml 39 | packaging/src/**/* 40 | pom.xml 41 | shepher-web/**/* 42 | shepher-common/**/* 43 | shepher-model/**/* 44 | shepher-service/**/* 45 | 46 | / 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/biz/ClusterAdminBiz.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.biz; 18 | 19 | import com.xiaomi.shepher.common.DaoValidator; 20 | import com.xiaomi.shepher.dao.ClusterAdminMapper; 21 | import com.xiaomi.shepher.exception.ShepherException; 22 | import com.xiaomi.shepher.model.Cluster; 23 | import com.xiaomi.shepher.util.ShepherConstants; 24 | import org.apache.commons.lang3.StringUtils; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.dao.DuplicateKeyException; 27 | import org.springframework.stereotype.Service; 28 | 29 | import java.util.List; 30 | 31 | /** 32 | * Created by zhangpeng on 16-11-7. 33 | */ 34 | 35 | @Service 36 | public class ClusterAdminBiz { 37 | 38 | @Autowired 39 | private ClusterAdminMapper clusterAdminMapper; 40 | 41 | public void create(String name, String config) throws ShepherException { 42 | if (StringUtils.isBlank(config) || StringUtils.isBlank(name)) { 43 | throw ShepherException.createIllegalParameterException(); 44 | } 45 | 46 | int count; 47 | try { 48 | count = clusterAdminMapper.create(new Cluster(name, config)); 49 | } catch (DuplicateKeyException e) { 50 | throw ShepherException.createDuplicateKeyException(); 51 | } catch (Exception e) { 52 | throw ShepherException.createDBDeleteErrorException(); 53 | } 54 | DaoValidator.checkSqlReturn(count, ShepherConstants.DB_OPERATE_CREATE); 55 | } 56 | 57 | public void update(String name, String config) throws ShepherException { 58 | if (StringUtils.isBlank(config) || StringUtils.isBlank(name)) { 59 | throw ShepherException.createIllegalParameterException(); 60 | } 61 | 62 | int count; 63 | try { 64 | count = clusterAdminMapper.update(name, config); 65 | } catch (Exception e) { 66 | throw ShepherException.createDBUpdateErrorException(); 67 | } 68 | DaoValidator.checkSqlReturn(count, ShepherConstants.DB_OPERATE_UPDATE); 69 | } 70 | 71 | public void delete(String name) throws ShepherException { 72 | if (StringUtils.isBlank(name)) { 73 | throw ShepherException.createIllegalParameterException(); 74 | } 75 | 76 | int count; 77 | try { 78 | count = clusterAdminMapper.delete(name); 79 | } catch (Exception e) { 80 | throw ShepherException.createDBDeleteErrorException(); 81 | } 82 | DaoValidator.checkSqlReturn(count, ShepherConstants.DB_OPERATE_DELETE); 83 | } 84 | 85 | public List all() { 86 | return clusterAdminMapper.all(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/biz/NodeBiz.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.biz; 18 | 19 | import com.xiaomi.shepher.dao.NodeDAO; 20 | import com.xiaomi.shepher.dao.SnapshotMapper; 21 | import com.xiaomi.shepher.exception.ShepherException; 22 | import com.xiaomi.shepher.model.Snapshot; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.stereotype.Service; 25 | 26 | /** 27 | * Created by banchuanyu on 16-8-9. 28 | */ 29 | @Service 30 | public class NodeBiz { 31 | 32 | @Autowired 33 | private SnapshotMapper snapshotMapper; 34 | 35 | @Autowired 36 | private NodeDAO nodeDAO; 37 | 38 | public void update(String cluster, String path, String data, long snapshotId) throws ShepherException { 39 | Snapshot snapshot = snapshotMapper.get(snapshotId); 40 | nodeDAO.update(cluster, path, data, snapshot == null ? null : (snapshot.getZkVersion() - 1)); 41 | } 42 | 43 | public void update(String cluster, String path, String data) throws ShepherException { 44 | nodeDAO.update(cluster, path, data, null); 45 | } 46 | 47 | public void create(String cluster, String path, String data) throws ShepherException { 48 | nodeDAO.create(cluster, path, data); 49 | } 50 | 51 | public void create(String cluster, String path, String data, boolean createParents)throws ShepherException { 52 | nodeDAO.create(cluster, path, data, createParents); 53 | } 54 | 55 | public void createEphemeral(String cluster, String path, String data) throws ShepherException{ 56 | nodeDAO.createEphemeral(cluster, path, data); 57 | } 58 | 59 | public void delete(String cluster, String path) throws ShepherException { 60 | nodeDAO.delete(cluster, path); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/biz/PermissionBiz.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.biz; 18 | 19 | import com.xiaomi.shepher.common.DaoValidator; 20 | import com.xiaomi.shepher.dao.PermissionMapper; 21 | import com.xiaomi.shepher.exception.ShepherException; 22 | import com.xiaomi.shepher.model.Permission; 23 | import com.xiaomi.shepher.util.ShepherConstants; 24 | import org.apache.commons.lang3.StringUtils; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.dao.DuplicateKeyException; 27 | import org.springframework.stereotype.Service; 28 | 29 | /** 30 | * Created by banchuanyu on 16-8-10. 31 | */ 32 | @Service 33 | public class PermissionBiz { 34 | 35 | @Autowired 36 | private PermissionMapper permissionMapper; 37 | 38 | public long createIfNotExists(String cluster, String path) throws ShepherException { 39 | if (StringUtils.isBlank(cluster) || StringUtils.isBlank(path)) { 40 | throw ShepherException.createIllegalParameterException(); 41 | } 42 | Permission permission = permissionMapper.get(cluster, path); 43 | try { 44 | if (permission == null) { 45 | return this.create(cluster, path).getId(); 46 | } 47 | } catch (DuplicateKeyException e) { 48 | throw ShepherException.createDuplicateKeyException(); 49 | } catch (Exception e) { 50 | throw ShepherException.createDBCreateErrorException(); 51 | } 52 | return permission.getId(); 53 | } 54 | 55 | public Permission create(String cluster, String path) throws ShepherException { 56 | if (StringUtils.isBlank(cluster) || StringUtils.isBlank(path)) { 57 | throw ShepherException.createIllegalParameterException(); 58 | } 59 | Permission permission = new Permission(cluster, path); 60 | int count; 61 | try { 62 | count = permissionMapper.create(permission); 63 | } catch (DuplicateKeyException e) { 64 | throw ShepherException.createDuplicateKeyException(); 65 | } catch (Exception e) { 66 | throw ShepherException.createDBCreateErrorException(); 67 | } 68 | DaoValidator.checkSqlReturn(count, ShepherConstants.DB_OPERATE_CREATE); 69 | return permission; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/CustomMailSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.beans.factory.annotation.Value; 23 | import org.springframework.stereotype.Service; 24 | 25 | /** 26 | * Created by banchuanyu on 16-8-2. 27 | */ 28 | @Service("customMailSender") 29 | public class CustomMailSender extends MailSenderAbstract { 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(CustomMailSender.class); 32 | 33 | @Value("${mail.mailToSuffix:}") 34 | private String mailToSuffix; 35 | 36 | protected void send(String mailAddress, String title, String content) { 37 | if (StringUtils.isBlank(mailAddress)) { 38 | return; 39 | } 40 | // TODO: use your own mail sender 41 | } 42 | } -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/DaoValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import com.xiaomi.shepher.exception.ShepherException; 20 | import com.xiaomi.shepher.util.ShepherConstants; 21 | 22 | /** 23 | * Created by zhangpeng on 16-11-3. 24 | */ 25 | public class DaoValidator { 26 | public static void checkSqlReturn(int count, String operate) throws ShepherException { 27 | if (count > 0) { 28 | return; 29 | } 30 | if (ShepherConstants.DB_OPERATE_CREATE.equals(operate)) { 31 | throw ShepherException.createDBNoDataCreateException(); 32 | } else if (ShepherConstants.DB_OPERATE_UPDATE.equals(operate)) { 33 | throw ShepherException.createDBNoDataUpdateException(); 34 | } else if (ShepherConstants.DB_OPERATE_DELETE.equals(operate)) { 35 | throw ShepherException.createDBNoDataDeleteException(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/GeneralMailSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | import org.apache.commons.mail.DefaultAuthenticator; 21 | import org.apache.commons.mail.Email; 22 | import org.apache.commons.mail.HtmlEmail; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Value; 26 | import org.springframework.stereotype.Service; 27 | 28 | /** 29 | * Created by zhangpeng on 16-11-11. 30 | */ 31 | @Service("generalMailSender") 32 | public class GeneralMailSender extends MailSenderAbstract { 33 | 34 | private static final Logger logger = LoggerFactory.getLogger(GeneralMailSender.class); 35 | 36 | @Value("${mail.hostname:}") 37 | private String hostname; 38 | 39 | @Value("${mail.port:25}") 40 | private int port; 41 | 42 | @Value("${mail.username:}") 43 | private String username; 44 | 45 | @Value("${mail.password:}") 46 | private String password; 47 | 48 | @Value("${mail.from:}") 49 | private String from; 50 | 51 | @Value("${mail.fromname:}") 52 | private String fromname; 53 | 54 | protected void send(String mailAddress, String title, String content) { 55 | if (StringUtils.isBlank(mailAddress)) { 56 | return; 57 | } 58 | 59 | try { 60 | Email email = new HtmlEmail(); 61 | email.setHostName(hostname); 62 | email.setAuthenticator(new DefaultAuthenticator(username, password)); 63 | email.setSmtpPort(port); 64 | email.setFrom(from, fromname); 65 | email.setSubject(title); 66 | email.setMsg(content); 67 | email.addTo(mailAddress.split(mailAddressEndSeparator)); 68 | email.send(); 69 | } catch (Exception e) { 70 | logger.error("Send Mail Error", e); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/MailSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import java.util.Set; 20 | 21 | /** 22 | * Created by banchuanyu on 16-8-2. 23 | */ 24 | public interface MailSender { 25 | void noticeUpdate(Set receivers, String creator, String path, String cluster, String link); 26 | 27 | void noticeReview(String receiver, String creator, String path, String cluster, String link, String action); 28 | 29 | void noticeDelete(Set receivers, String creator, String path, String cluster, String link); 30 | 31 | void noticeJoinTeam(Set receivers, String creator, String teamName, String link); 32 | 33 | void noticeJoinTeamHandled(Set receivers, String creator, Status status, String teamName, String link); 34 | } -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/MailSenderFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import com.xiaomi.shepher.exception.ShepherException; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.beans.factory.annotation.Qualifier; 22 | import org.springframework.beans.factory.annotation.Value; 23 | import org.springframework.stereotype.Service; 24 | 25 | /** 26 | * Created by banchuanyu on 16-11-15. 27 | */ 28 | @Service 29 | public class MailSenderFactory { 30 | 31 | // customBean and generalBean mapped to property mail.sender in application.properties 32 | private static final String CUSTOM_BEAN = "customMailSender"; 33 | private static final String GENERAL_BEAN = "generalMailSender"; 34 | 35 | @Value("${mail.sender:generalMailSender}") 36 | private String mailSender; 37 | 38 | @Autowired 39 | @Qualifier(CUSTOM_BEAN) 40 | private MailSender customMailSender; 41 | 42 | @Autowired 43 | @Qualifier(GENERAL_BEAN) 44 | private MailSender generalMailSender; 45 | 46 | public MailSender getMailSender() throws ShepherException { 47 | if (mailSender.equals(CUSTOM_BEAN)) { 48 | return customMailSender; 49 | } else if (mailSender.equals(GENERAL_BEAN)) { 50 | return generalMailSender; 51 | } else { 52 | throw ShepherException.createIllegalParameterException(); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/UserHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import com.xiaomi.shepher.model.User; 20 | 21 | /** 22 | * Created by banchuanyu on 16-7-21. 23 | */ 24 | public interface UserHolder { 25 | User getUser(); 26 | 27 | void setUser(User user); 28 | 29 | void clean(); 30 | } 31 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/common/UserHolderImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.common; 18 | 19 | import com.xiaomi.shepher.model.User; 20 | import org.springframework.stereotype.Service; 21 | 22 | /** 23 | * Created by banchuanyu on 16-7-21. 24 | */ 25 | @Service 26 | public class UserHolderImpl implements UserHolder { 27 | 28 | private ThreadLocal contextHolder = new ThreadLocal(); 29 | 30 | @Override 31 | public User getUser() { 32 | return contextHolder.get(); 33 | } 34 | 35 | @Override 36 | public void setUser(User user) { 37 | contextHolder.set(user); 38 | } 39 | 40 | @Override 41 | public void clean() { 42 | contextHolder.remove(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/ClusterAdminMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.model.Cluster; 20 | import org.apache.ibatis.annotations.Delete; 21 | import org.apache.ibatis.annotations.Insert; 22 | import org.apache.ibatis.annotations.Mapper; 23 | import org.apache.ibatis.annotations.Param; 24 | import org.apache.ibatis.annotations.Select; 25 | import org.apache.ibatis.annotations.Update; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Created by banchuanyu on 15-8-25. 31 | */ 32 | @Mapper 33 | public interface ClusterAdminMapper { 34 | 35 | @Insert("INSERT INTO cluster(name, config) VALUES (#{name}, #{config})") 36 | int create(Cluster cluster); 37 | 38 | @Update("UPDATE cluster SET config = #{config} WHERE name = #{name}") 39 | int update(@Param("name") String name, @Param("config") String config); 40 | 41 | @Delete("DELETE FROM cluster WHERE name = #{name}") 42 | int delete(@Param("name") String name); 43 | 44 | @Select("SELECT id, name, config, time FROM cluster") 45 | List all(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/PermissionMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.model.Permission; 20 | import org.apache.ibatis.annotations.Insert; 21 | import org.apache.ibatis.annotations.Mapper; 22 | import org.apache.ibatis.annotations.Param; 23 | import org.apache.ibatis.annotations.Select; 24 | 25 | /** 26 | * Created by banchuanyu on 16-11-3. 27 | */ 28 | @Mapper 29 | public interface PermissionMapper { 30 | @Select("SELECT id, cluster, path, time FROM permission WHERE cluster = #{cluster} AND path = #{path}") 31 | Permission get(@Param("cluster") String cluster, @Param("path") String path); 32 | 33 | @Insert("INSERT INTO permission(cluster, path ) VALUES (#{cluster}, #{path})") 34 | int create(Permission permission); 35 | } 36 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/ReviewMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.model.ReviewRequest; 20 | import org.apache.ibatis.annotations.Delete; 21 | import org.apache.ibatis.annotations.Insert; 22 | import org.apache.ibatis.annotations.Mapper; 23 | import org.apache.ibatis.annotations.Param; 24 | import org.apache.ibatis.annotations.Select; 25 | import org.apache.ibatis.annotations.Update; 26 | 27 | /** 28 | * Created by banchuanyu on 16-11-4. 29 | */ 30 | @Mapper 31 | public interface ReviewMapper { 32 | @Select("SELECT review.id, review.cluster, review.path, review.snapshot, review.new_snapshot, review.review_status, " + 33 | "review.creator, review.reviewer, review.time, review.update_time, review.action, old_snapshot.content AS snapshot_content, " + 34 | "new_snapshot.content AS new_snapshot_content " + 35 | "FROM review_request AS review, snapshot AS old_snapshot, snapshot AS new_snapshot " + 36 | "WHERE review.id = #{id} AND review.snapshot = old_snapshot.id AND review.new_snapshot = new_snapshot.id") 37 | ReviewRequest get(@Param("id") long id); 38 | 39 | @Insert("INSERT INTO review_request(cluster, path, snapshot, new_snapshot, review_status, creator, reviewer, update_time, action) " + 40 | "VALUES (#{cluster}, #{path}, #{snapshot}, #{newSnapshot}, #{reviewStatus}, #{creator}, #{reviewer}, #{updateTime}, #{action})") 41 | int create(ReviewRequest reviewRequest); 42 | 43 | @Update("UPDATE review_request SET review_status = #{reviewStatus}, update_time = now(), reviewer = #{reviewer} WHERE id = #{id}") 44 | int update(@Param("id") long id, @Param("reviewStatus") int reviewStatus, @Param("reviewer") String reviewer); 45 | 46 | @Delete("DELETE FROM review_request WHERE id = #{id}") 47 | int delete(@Param("id") long id); 48 | } 49 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/SnapshotMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.model.Snapshot; 20 | import org.apache.ibatis.annotations.Delete; 21 | import org.apache.ibatis.annotations.Insert; 22 | import org.apache.ibatis.annotations.Mapper; 23 | import org.apache.ibatis.annotations.Param; 24 | import org.apache.ibatis.annotations.Select; 25 | import org.apache.ibatis.annotations.Update; 26 | 27 | import java.util.Date; 28 | import java.util.List; 29 | 30 | /** 31 | * Created by banchuanyu on 16-11-4. 32 | */ 33 | @Mapper 34 | public interface SnapshotMapper { 35 | 36 | @Select("SELECT id, cluster, path, content, creator, action, zk_mtime, time, status, zk_version, reviewer FROM snapshot WHERE id = #{id}") 37 | Snapshot get(@Param("id") long id); 38 | 39 | @Select("SELECT id, cluster, path, content, creator, action, zk_mtime, time, status, zk_version, reviewer " + 40 | "FROM snapshot WHERE path = #{path} AND cluster = #{cluster} AND status > 0 ORDER BY id DESC limit #{offset}, #{limit}") 41 | List listByPath(@Param("path") String path, @Param("cluster") String cluster, @Param("offset") int offset, @Param("limit") int limit); 42 | 43 | @Select("SELECT id, cluster, path, content, creator, action, zk_mtime, time, status, zk_version, reviewer " + 44 | "FROM snapshot WHERE path = #{path} AND cluster = #{cluster} AND zk_mtime = #{zkMtime} AND zk_version = #{zkVersion} AND status > 0") 45 | Snapshot getByPathAndZk(@Param("path") String path, @Param("cluster") String cluster, 46 | @Param("zkMtime") Date zkMtime, @Param("zkVersion") int zkVersion); 47 | 48 | @Update("UPDATE snapshot SET status = #{status}, reviewer = #{reviewer}, zk_mtime = #{zkMtime} WHERE id = #{id}") 49 | int update(@Param("id") long id, @Param("status") int status, @Param("reviewer") String reviewer, @Param("zkMtime") Date zkMtime); 50 | 51 | @Insert("INSERT INTO snapshot(cluster, path, content, creator, action, zk_mtime, status, zk_version, reviewer) VALUES " + 52 | "(#{cluster}, #{path}, #{content}, #{creator}, #{action}, #{zkMtime}, #{status}, #{zkVersion}, #{reviewer})") 53 | int create(Snapshot snapshot); 54 | 55 | @Delete("DELETE FROM snapshot WHERE id = #{id}") 56 | int delete(@Param("id") long id); 57 | } 58 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/TeamMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.model.Team; 20 | import org.apache.ibatis.annotations.Delete; 21 | import org.apache.ibatis.annotations.Insert; 22 | import org.apache.ibatis.annotations.Mapper; 23 | import org.apache.ibatis.annotations.Param; 24 | import org.apache.ibatis.annotations.Select; 25 | 26 | /** 27 | * Created by banchuanyu on 16-11-3. 28 | */ 29 | @Mapper 30 | public interface TeamMapper { 31 | 32 | @Select("SELECT id, name, owner, time FROM team WHERE id = #{id}") 33 | Team getById(@Param("id") long id); 34 | 35 | @Select("SELECT id, name, owner, time FROM team WHERE name = #{name}") 36 | Team getByName(@Param("name") String name); 37 | 38 | @Insert("INSERT INTO team(name, owner) VALUES (#{name}, #{owner})") 39 | int create(Team team); 40 | 41 | @Delete("DELETE FROM team WHERE id = #{id}") 42 | int delete(@Param("id") long id); 43 | } 44 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/UserMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.dao.mybatis.MybatisExtendedLanguageDriver; 20 | import com.xiaomi.shepher.model.User; 21 | import org.apache.ibatis.annotations.Insert; 22 | import org.apache.ibatis.annotations.Lang; 23 | import org.apache.ibatis.annotations.Mapper; 24 | import org.apache.ibatis.annotations.Param; 25 | import org.apache.ibatis.annotations.Select; 26 | 27 | import java.util.List; 28 | import java.util.Set; 29 | 30 | /** 31 | * Created by banchuanyu on 16-11-2. 32 | */ 33 | @Mapper 34 | public interface UserMapper { 35 | 36 | @Select("SELECT id, name, time FROM user WHERE name = #{name}") 37 | User getByName(@Param("name") String name); 38 | 39 | @Select("SELECT id, name, time FROM user WHERE id = #{id}") 40 | User getById(@Param("id") long id); 41 | 42 | @Lang(MybatisExtendedLanguageDriver.class) 43 | @Select("SELECT DISTINCT user.id, user.name, user.time FROM user, user_team WHERE user_team.team_id IN (#{teams}) " + 44 | "AND user_team.user_id = user.id AND user_team.status >= #{status} AND user_team.role >= #{role}") 45 | List list(@Param("teams") Set teams, @Param("status") int status, @Param("role") int role); 46 | 47 | @Insert("INSERT INTO user(name) VALUES (#{name})") 48 | int create(User user); 49 | } 50 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/dao/mybatis/MybatisExtendedLanguageDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao.mybatis; 18 | 19 | import org.apache.ibatis.mapping.SqlSource; 20 | import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver; 21 | import org.apache.ibatis.session.Configuration; 22 | 23 | import java.util.regex.Matcher; 24 | import java.util.regex.Pattern; 25 | 26 | /** 27 | * Created by banchuanyu on 16-11-3. 28 | */ 29 | public class MybatisExtendedLanguageDriver extends XMLLanguageDriver { 30 | private final Pattern inPattern = Pattern.compile("\\(#\\{(\\w+)\\}\\)"); 31 | 32 | public SqlSource createSqlSource(Configuration configuration, String script, Class parameterType) { 33 | String result = script; 34 | Matcher matcher = inPattern.matcher(result); 35 | if (matcher.find()) { 36 | result = matcher.replaceAll("(#{__item})"); 37 | } 38 | result = ""; 39 | return super.createSqlSource(configuration, result, parameterType); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/service/ClusterAdminService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.service; 18 | 19 | import com.xiaomi.shepher.biz.ClusterAdminBiz; 20 | import com.xiaomi.shepher.common.UserHolder; 21 | import com.xiaomi.shepher.exception.ShepherException; 22 | import com.xiaomi.shepher.model.Cluster; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.stereotype.Service; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * Created by banchuanyu on 15-8-25. 32 | */ 33 | @Service 34 | public class ClusterAdminService { 35 | 36 | private static final Logger logger = LoggerFactory.getLogger(ClusterAdminService.class); 37 | 38 | @Autowired 39 | private ClusterAdminBiz clusterAdminBiz; 40 | 41 | @Autowired 42 | private UserHolder userHolder; 43 | 44 | public void create(String name, String config) throws ShepherException { 45 | clusterAdminBiz.create(name, config); 46 | logger.info("Create cluster, config={}, name={}, operator={}", config, name, userHolder.getUser().getName()); 47 | } 48 | 49 | public void update(String name, String config) throws ShepherException { 50 | clusterAdminBiz.update(name, config); 51 | logger.info("Update cluster, config={}, name={}, operator={}", config, name, userHolder.getUser().getName()); 52 | } 53 | 54 | public void delete(String name) throws ShepherException { 55 | clusterAdminBiz.delete(name); 56 | logger.info("Delete cluster, name={}, operator={}", name, userHolder.getUser().getName()); 57 | } 58 | 59 | public List all() { 60 | return clusterAdminBiz.all(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/service/SnapshotService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.service; 18 | 19 | import com.xiaomi.shepher.biz.SnapshotBiz; 20 | import com.xiaomi.shepher.exception.ShepherException; 21 | import com.xiaomi.shepher.model.Snapshot; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.stereotype.Service; 24 | 25 | import java.util.List; 26 | 27 | /** 28 | * Created by banchuanyu on 15-8-25. 29 | */ 30 | @Service 31 | public class SnapshotService { 32 | 33 | @Autowired 34 | private SnapshotBiz snapshotBiz; 35 | 36 | public List getByPath(String path, String cluster, int offset, int limit) throws ShepherException { 37 | return snapshotBiz.listByPath(path, cluster, offset, limit); 38 | } 39 | 40 | public Snapshot getById(long id) { 41 | return snapshotBiz.get(id); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/service/UserService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.service; 18 | 19 | import com.xiaomi.shepher.biz.UserBiz; 20 | import com.xiaomi.shepher.common.Role; 21 | import com.xiaomi.shepher.common.Status; 22 | import com.xiaomi.shepher.exception.ShepherException; 23 | import com.xiaomi.shepher.model.User; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.stereotype.Service; 26 | 27 | import java.util.List; 28 | import java.util.Set; 29 | 30 | /** 31 | * Created by banchuanyu on 15-8-25. 32 | */ 33 | @Service 34 | public class UserService { 35 | 36 | @Autowired 37 | private UserBiz userBiz; 38 | 39 | public User get(long id) { 40 | return userBiz.getById(id); 41 | } 42 | 43 | public User get(String name) throws ShepherException { 44 | return userBiz.getByName(name); 45 | } 46 | 47 | public User create(String name) throws ShepherException { 48 | return userBiz.create(name); 49 | } 50 | 51 | public User createIfNotExist(String name) throws ShepherException { 52 | User user = this.get(name); 53 | if (user == null) { 54 | user = this.create(name); 55 | } 56 | return user; 57 | } 58 | 59 | public List listByTeams(Set teams, Status status, Role role) throws ShepherException { 60 | return userBiz.list(teams, status, role); 61 | } 62 | 63 | public Set listNamesByTeams(Set teamIds, Status status, Role role) throws ShepherException { 64 | return userBiz.listNames(teamIds, status, role); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/util/ClusterUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | import com.xiaomi.shepher.model.Cluster; 20 | import com.xiaomi.shepher.service.ClusterAdminService; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.scheduling.annotation.Scheduled; 23 | import org.springframework.stereotype.Component; 24 | 25 | import java.util.HashSet; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.Set; 29 | import java.util.concurrent.ConcurrentHashMap; 30 | import java.util.concurrent.CopyOnWriteArrayList; 31 | 32 | /** 33 | * Created by banchuanyu on 16-5-31. 34 | */ 35 | @Component 36 | public class ClusterUtil { 37 | 38 | private static Set publicClusters = new HashSet<>(); 39 | private static List clusters = new CopyOnWriteArrayList<>(); 40 | private static Map clusterMap = new ConcurrentHashMap<>(); 41 | 42 | public static List getClusters() { 43 | return clusters; 44 | } 45 | 46 | public static Map getClusterMap() { 47 | return clusterMap; 48 | } 49 | 50 | public static boolean isPublicCluster(String cluster) { 51 | return publicClusters.contains(cluster); 52 | } 53 | 54 | /** 55 | * Cluster config load schedule. 56 | */ 57 | @Component 58 | private static class ClusterLoadSchedule { 59 | 60 | @Autowired 61 | private ClusterAdminService clusterAdminService; 62 | 63 | @Scheduled(fixedRate = 5000) 64 | public void loadCluster() { 65 | List clustersNew = clusterAdminService.all(); 66 | if (clustersNew.isEmpty()) { 67 | return; 68 | } else { 69 | // if cluster deleted or cluster config changed, delete it 70 | for (Cluster cluster : clusters) { 71 | if (!clustersNew.contains(cluster)) { 72 | clusters.remove(cluster); 73 | clusterMap.remove(cluster.getName()); 74 | } 75 | } 76 | 77 | // if cluster added or cluster config changed, update it 78 | for (Cluster cluster : clustersNew) { 79 | if (!clusters.contains(cluster)) { 80 | clusters.add(cluster); 81 | clusterMap.put(cluster.getName(), cluster.getConfig()); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/util/ReviewUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | import com.xiaomi.shepher.model.Snapshot; 20 | import org.apache.commons.lang3.StringEscapeUtils; 21 | import org.apache.commons.lang3.StringUtils; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * Created by banchuanyu on 16-6-14. 27 | */ 28 | public class ReviewUtil { 29 | 30 | public static final int NEW_CREATE_VERSION = 0; 31 | 32 | public static final String DEFAULT_CREATOR = "AUTO_CREATED"; 33 | public static final String DEFAULT_REVIEWER = "AUTO_REVIEWED"; 34 | public static final long DEFAULT_MTIME = 946656000000L; //2000-01-01 00:00:00 35 | public static final int DEFAULT_PAGINATION_LIMIT = 10; 36 | public static final int MAX_PAGINATION_LIMIT = 100; 37 | 38 | public static final String EMPTY_CONTENT = ""; 39 | 40 | public static void generateSummary(List snapshotList) { 41 | for (Snapshot snapshot : snapshotList) { 42 | snapshot.setContent(generateSummary(snapshot.getContent())); 43 | } 44 | } 45 | 46 | public static String generateSummary(String content) { 47 | String summary = StringEscapeUtils.escapeXml(content); 48 | summary = StringUtils.substring(summary, 0, 50); 49 | return summary; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /shepher-service/src/main/java/com/xiaomi/shepher/util/StringSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.util; 18 | 19 | import org.I0Itec.zkclient.serialize.ZkSerializer; 20 | 21 | import java.nio.charset.Charset; 22 | 23 | /** 24 | * Created by zhangpeng on 16-11-15. 25 | */ 26 | 27 | public class StringSerializer implements ZkSerializer { 28 | 29 | private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 30 | 31 | @Override 32 | public byte[] serialize(Object data) { 33 | return data.toString().getBytes(DEFAULT_CHARSET); 34 | } 35 | 36 | @Override 37 | public String deserialize(byte[] bytes) { 38 | return new String(bytes, DEFAULT_CHARSET); 39 | } 40 | } -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/BaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher; 18 | 19 | import org.junit.Rule; 20 | import org.junit.rules.ExpectedException; 21 | import org.springframework.boot.test.SpringApplicationConfiguration; 22 | import org.springframework.test.context.jdbc.Sql; 23 | import org.springframework.test.context.jdbc.SqlGroup; 24 | 25 | /** 26 | * Base test of this project. 27 | * Load table and data from directory resources/h2database. 28 | * 29 | * Created by weichuyang on 16-8-8. 30 | */ 31 | @SpringApplicationConfiguration(classes = TestContextConfiguration.class) 32 | @SqlGroup({ 33 | @Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:h2database/schema.sql"), 34 | @Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:h2database/data.sql"), 35 | @Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:h2database/teardown.sql") 36 | }) 37 | public class BaseTest { 38 | 39 | protected static final int RESULT_OK = 1; 40 | protected static final int RESULT_FAILED = 0; 41 | @Rule 42 | public ExpectedException thrown = ExpectedException.none(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/ShepherApplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher; 18 | 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.springframework.boot.test.SpringApplicationConfiguration; 22 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 23 | 24 | @RunWith(SpringJUnit4ClassRunner.class) 25 | @SpringApplicationConfiguration(classes = TestContextConfiguration.class) 26 | public class ShepherApplicationTests { 27 | 28 | @Test 29 | public void contextLoads() { 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/TestContextConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher; 18 | 19 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 20 | import org.springframework.context.annotation.ComponentScan; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.transaction.annotation.EnableTransactionManagement; 23 | 24 | /** 25 | * Created by banchuanyu on 16-11-15. 26 | */ 27 | @Configuration 28 | @ComponentScan 29 | @EnableAutoConfiguration 30 | @EnableTransactionManagement 31 | public class TestContextConfiguration { 32 | 33 | } -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/dao/ClusterAdminMapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.model.Cluster; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Created by zhangpeng on 16-11-3. 31 | */ 32 | @RunWith(SpringJUnit4ClassRunner.class) 33 | public class ClusterAdminMapperTest extends BaseTest { 34 | @Autowired 35 | private ClusterAdminMapper clusterAdminMapper; 36 | 37 | @Test 38 | public void testCreate() { 39 | int result = clusterAdminMapper.create(new Cluster("name1", "config1")); 40 | Assert.assertEquals(1, result); 41 | } 42 | 43 | @Test 44 | public void testUpdate() { 45 | int result = clusterAdminMapper.update("local_test", "config2"); 46 | Assert.assertEquals(1, result); 47 | } 48 | 49 | @Test 50 | public void testGetAll() { 51 | List clusters = clusterAdminMapper.all(); 52 | Assert.assertNotNull(clusters); 53 | Assert.assertEquals(1, clusters.size()); 54 | } 55 | 56 | @Test 57 | public void testDelete() { 58 | int result = clusterAdminMapper.delete("local_test"); 59 | Assert.assertEquals(1, result); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/dao/PermissionMapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.model.Permission; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 26 | 27 | /** 28 | * Created by banchuanyu on 16-11-3. 29 | */ 30 | @RunWith(SpringJUnit4ClassRunner.class) 31 | public class PermissionMapperTest extends BaseTest { 32 | 33 | @Autowired 34 | private PermissionMapper permissionMapper; 35 | 36 | @Test 37 | public void testGet() { 38 | String cluster = "local_test"; 39 | String path = "/test"; 40 | String noPath = "/no/such/pah"; 41 | 42 | Permission permission = permissionMapper.get(cluster, path); 43 | Assert.assertEquals(3, permission.getId()); 44 | 45 | Permission noPermission = permissionMapper.get(cluster, noPath); 46 | Assert.assertNull(noPermission); 47 | } 48 | 49 | @Test 50 | public void testCreate() { 51 | String cluster = "local_test"; 52 | String path = "/test/sub3"; 53 | Permission permission = new Permission(cluster, path); 54 | 55 | Assert.assertEquals(1, permissionMapper.create(permission)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/dao/ReviewMapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.model.ReviewRequest; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 26 | 27 | import java.util.Date; 28 | 29 | /** 30 | * Created by banchuanyu on 16-8-6. 31 | */ 32 | @RunWith(SpringJUnit4ClassRunner.class) 33 | public class ReviewMapperTest extends BaseTest { 34 | 35 | @Autowired 36 | private ReviewMapper reviewMapper; 37 | 38 | @Test 39 | public void testCreate() { 40 | ReviewRequest reviewRequest = new ReviewRequest("local_test", "/test/test2", 1, 2, 10, "banchuanyu", "reviewer", new Date(), 30); 41 | int result = reviewMapper.create(reviewRequest); 42 | Assert.assertEquals(1, result); 43 | Assert.assertEquals(2, reviewRequest.getId()); 44 | } 45 | 46 | @Test 47 | public void testDelete() { 48 | int result = reviewMapper.delete(1); 49 | Assert.assertEquals(1, result); 50 | } 51 | 52 | @Test 53 | public void testUpdate() { 54 | ReviewRequest reviewRequest = new ReviewRequest("local_test", "/test/test2", 1, 2, 10, "banchuanyu", "reviewer", new Date(), 30); 55 | int result = reviewMapper.update(1, reviewRequest.getReviewStatus(), reviewRequest.getReviewer()); 56 | Assert.assertEquals(1, result); 57 | } 58 | 59 | @Test 60 | public void testGet() { 61 | ReviewRequest reviewRequest = reviewMapper.get(1); 62 | Assert.assertEquals(1, reviewRequest.getId()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/dao/SnapshotMapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.common.Action; 21 | import com.xiaomi.shepher.common.Status; 22 | import com.xiaomi.shepher.model.Snapshot; 23 | import org.apache.commons.lang3.time.DateUtils; 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 29 | 30 | import java.text.ParseException; 31 | import java.util.Date; 32 | import java.util.List; 33 | 34 | /** 35 | * Created by banchuanyu on 16-8-6. 36 | */ 37 | @RunWith(SpringJUnit4ClassRunner.class) 38 | public class SnapshotMapperTest extends BaseTest { 39 | 40 | @Autowired 41 | private SnapshotMapper snapshotMapper; 42 | 43 | @Test 44 | public void testCreate() { 45 | Snapshot snapshot = new Snapshot("local_test", "/test", "content", "creator", Action.ADD.getValue(), new Date(), Status.AGREE.getValue(), 1, "reviewer"); 46 | int result = snapshotMapper.create(snapshot); 47 | Assert.assertEquals(1, result); 48 | Assert.assertEquals(3, snapshot.getId()); 49 | } 50 | 51 | @Test 52 | public void testListByPath() { 53 | List snapshots = snapshotMapper.listByPath("/test/test2", "local_test", 0, 10); 54 | Assert.assertEquals(false, snapshots.isEmpty()); 55 | Assert.assertEquals(2, snapshots.size()); 56 | } 57 | 58 | @Test 59 | public void testGetByPath() throws ParseException { 60 | Snapshot snapshot = snapshotMapper.getByPathAndZk("/test/test2", "local_test", DateUtils.parseDate("2016-09-20 02:07:59", new String[] {"yyyy-MM-dd hh:mm:ss"}), 0); 61 | Assert.assertNotNull(snapshot); 62 | } 63 | 64 | @Test 65 | public void testGet() throws ParseException { 66 | Snapshot snapshot = snapshotMapper.get(1); 67 | Assert.assertNotNull(snapshot); 68 | } 69 | 70 | @Test 71 | public void testUpdate() throws ParseException { 72 | int result = snapshotMapper.update(1, Status.AGREE.getValue(), "reviewer", new Date()); 73 | Assert.assertEquals(1, result); 74 | } 75 | 76 | @Test 77 | public void testDelete() throws ParseException { 78 | int result = snapshotMapper.delete(1); 79 | Assert.assertEquals(1, result); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/dao/TeamMapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.model.Team; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 26 | 27 | /** 28 | * Created by weichuyang on 16-8-10. 29 | */ 30 | @RunWith(SpringJUnit4ClassRunner.class) 31 | public class TeamMapperTest extends BaseTest { 32 | @Autowired 33 | private TeamMapper teamMapper; 34 | 35 | @Test 36 | public void testGetById() { 37 | Team team = teamMapper.getById(1); 38 | Assert.assertEquals("admin", team.getName()); 39 | } 40 | 41 | @Test 42 | public void testGetByName() { 43 | String name = "theone"; 44 | Team team = teamMapper.getByName(name); 45 | Assert.assertEquals(5, team.getId()); 46 | } 47 | 48 | @Test 49 | public void testCreate() { 50 | Team team = new Team("test_team2", 1); 51 | long result = teamMapper.create(team); 52 | Assert.assertEquals(1, result); 53 | Assert.assertEquals(6, team.getId()); 54 | } 55 | 56 | @Test 57 | public void testDelete() { 58 | Team team = new Team("test_team3", 2); 59 | long result = teamMapper.create(team); 60 | Assert.assertEquals(1, result); 61 | 62 | int deleteResult = teamMapper.delete(team.getId()); 63 | Assert.assertEquals(RESULT_OK, deleteResult); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/dao/UserMapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.dao; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.common.Role; 21 | import com.xiaomi.shepher.common.Status; 22 | import com.xiaomi.shepher.model.User; 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 28 | 29 | import java.util.HashSet; 30 | import java.util.List; 31 | import java.util.Set; 32 | 33 | /** 34 | * Created by banchuanyu on 16-8-6. 35 | */ 36 | @RunWith(SpringJUnit4ClassRunner.class) 37 | public class UserMapperTest extends BaseTest { 38 | 39 | @Autowired 40 | private UserMapper userMapper; 41 | 42 | @Test 43 | public void testGetByName() { 44 | User user = userMapper.getByName("banchuanyu"); 45 | Assert.assertEquals(1, user.getId()); 46 | } 47 | 48 | @Test 49 | public void testGetById() { 50 | User user = userMapper.getById(1); 51 | Assert.assertEquals(1, user.getId()); 52 | } 53 | 54 | @Test 55 | public void testList() { 56 | Set teams = new HashSet<>(); 57 | teams.add(1L); 58 | teams.add(5L); 59 | List users = userMapper.list(teams, Status.PENDING.getValue(), Role.MEMBER.getValue()); 60 | Assert.assertNotNull(users); 61 | Assert.assertEquals(3, users.size()); 62 | } 63 | 64 | @Test 65 | public void testCreate() { 66 | String name = "testuser1"; 67 | User user = new User(name); 68 | int result = userMapper.create(user); 69 | 70 | Assert.assertEquals(4, user.getId()); 71 | Assert.assertEquals(1, result); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /shepher-service/src/test/java/com/xiaomi/shepher/service/SnapshotServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.service; 18 | 19 | import com.xiaomi.shepher.BaseTest; 20 | import com.xiaomi.shepher.model.Snapshot; 21 | import org.junit.After; 22 | import org.junit.Assert; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 28 | 29 | import java.util.List; 30 | 31 | /** 32 | * SnapshotService Tester. 33 | * 34 | * Created by banchuanyu on 16-11-18. 35 | */ 36 | @RunWith(SpringJUnit4ClassRunner.class) 37 | public class SnapshotServiceTest extends BaseTest { 38 | 39 | @Autowired 40 | private SnapshotService snapshotService; 41 | 42 | @Before 43 | public void before() throws Exception { 44 | } 45 | 46 | @After 47 | public void after() throws Exception { 48 | } 49 | 50 | /** 51 | * Method: getByPath(String path, String cluster, int offset, int limit) 52 | */ 53 | @Test 54 | public void testGetByPath() throws Exception { 55 | String path = "/test/test2"; 56 | String cluster = "local_test"; 57 | int offset = 0; 58 | int limit = 20; 59 | List snapshots = snapshotService.getByPath(path, cluster, offset, limit); 60 | Assert.assertNotNull(snapshots); 61 | Assert.assertEquals(2, snapshots.size()); 62 | } 63 | 64 | /** 65 | * Method: getById(long id) 66 | */ 67 | @Test 68 | public void testGetById() throws Exception { 69 | Snapshot snapshot = snapshotService.getById(1); 70 | Assert.assertNotNull(snapshot); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /shepher-service/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | # h2 database 2 | spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;DB_CLOSE_ON_EXIT=FALSE 3 | spring.datasource.driverClassName=org.h2.Driver 4 | spring.datasource.username=sa 5 | spring.datasource.password= 6 | spring.datasource.schema = classpath:h2database/schema.sql 7 | spring.datasource.data = classpath:h2database/data.sql 8 | spring.datasource.initialize=false 9 | 10 | # MYBATIS 11 | mybatis.configuration.useGeneratedKeys=true 12 | mybatis.configuration.mapUnderscoreToCamelCase=true 13 | 14 | # freemarker 15 | spring.freemarker.suffix=.ftl 16 | 17 | # cas 18 | cas.server.url.prefix=https://casdev.example.com 19 | cas.login.url=${cas.server.url.prefix}/login 20 | cas.logout.url=/logout 21 | server.url=http://shepher.example.com 22 | 23 | # LDAP EXAMPLE 24 | ldap.url=ldap://ldap.example.com:389/dc=example,dc=com 25 | ldap.password=123456 26 | ldap.dn=cn=admin,dc=example,dc=com 27 | 28 | # LOGIN TYPE 29 | server.login.type=CAS 30 | 31 | # DEFAULT MAIL 32 | mail.hostname=smtp.163.com 33 | mail.port=25 34 | mail.username=shepher_zk 35 | 36 | #Authorization code 37 | mail.password=shepher1111 38 | 39 | mail.from=shepher_zk@163.com 40 | mail.fromname=Shepher 41 | 42 | mail.mailToSuffix=@example.com 43 | mail.mailAddressEndSeparator=; 44 | 45 | # mapped to constants in MailSenderFactory 46 | mail.sender=customMailSender 47 | 48 | -------------------------------------------------------------------------------- /shepher-service/src/test/resources/h2database/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO `cluster` VALUES (3,'local_test','localhost:2181','2016-08-03 01:49:21'); 2 | INSERT INTO `permission` VALUES (3,'local_test','/test','2016-08-03 01:56:44'),(4,'local_test','/test/sub1','2016-08-03 01:56:45'),(5,'local_test','/test/sub1/ss1','2016-08-03 01:56:46'),(6,'local_test','/test/sub2','2016-08-03 01:56:49'); 3 | INSERT INTO `permission_team` VALUES (2,4,5,10,'2016-08-03 01:56:45'),(3,6,5,0,'2016-08-03 01:56:49'); 4 | INSERT INTO `team` VALUES (1,'admin',1,'2016-08-03 01:45:00'),(5,'theone',1,'2016-08-03 01:56:45'); 5 | INSERT INTO `user` VALUES (1,'banchuanyu','2016-08-03 01:43:50'),(2,'weichuyang','2016-08-03 01:43:50'),(3,'testuser','2016-08-03 01:43:50'); 6 | INSERT INTO `user_team` VALUES (1,1,1,100,10,'2016-08-03 01:47:44'),(2,2,1,100,10,'2016-08-03 01:47:44'),(3,3,1,100,10,'2016-08-03 01:48:14'),(12,1,5,100,10,'2016-08-03 01:56:49'),(13,3,5,100,10,'2016-08-03 02:00:43'); 7 | INSERT INTO `snapshot` VALUES (1,'local_test','/test/test2','','2016-11-02 09:06:06',30,'2016-09-20 02:07:59',10,0,'AUTO_CREATED','AUTO_REVIEWED'),(2,'local_test','/test/test2','111','2016-11-02 09:06:06',30,'2016-11-02 09:06:10',10,1,'banchuanyu','banchuanyu'); 8 | INSERT INTO `review_request` VALUES (1,'local_test','/test/test2',1,2,10,'banchuanyu','banchuanyu','2016-11-02 09:06:06','2016-11-02 09:06:10',30); -------------------------------------------------------------------------------- /shepher-service/src/test/resources/h2database/teardown.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `cluster`; 2 | DROP TABLE `need_review`; 3 | DROP TABLE `permission`; 4 | DROP TABLE `permission_team`; 5 | DROP TABLE `review_request`; 6 | DROP TABLE `snapshot`; 7 | DROP TABLE `team`; 8 | DROP TABLE `user`; 9 | DROP TABLE `user_team`; -------------------------------------------------------------------------------- /shepher-web/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | shepher 7 | com.xiaomi 8 | 1.0 9 | 10 | 4.0.0 11 | 12 | shepher-web 13 | 14 | 15 | 16 | com.xiaomi 17 | shepher-common 18 | ${project.version} 19 | 20 | 21 | com.xiaomi 22 | shepher-model 23 | ${project.version} 24 | 25 | 26 | com.xiaomi 27 | shepher-service 28 | ${project.version} 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-security 37 | 38 | 39 | org.springframework.security 40 | spring-security-ldap 41 | 42 | 43 | org.springframework.security 44 | spring-security-cas 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-freemarker 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-tomcat 53 | 54 | 55 | 56 | 57 | org.jasig.cas.client 58 | cas-client-core 59 | ${java-cas-client-version} 60 | 61 | 62 | 63 | shepher-1.0 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-maven-plugin 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher; 18 | 19 | import org.springframework.boot.builder.SpringApplicationBuilder; 20 | import org.springframework.boot.context.web.SpringBootServletInitializer; 21 | 22 | /** 23 | * Created by zhangpeng on 16-11-15. 24 | */ 25 | 26 | public class ServletInitializer extends SpringBootServletInitializer { 27 | 28 | @Override 29 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 30 | return application.sources(ShepherApplication.class); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/ShepherApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 21 | import org.springframework.context.annotation.ComponentScan; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.scheduling.annotation.EnableScheduling; 24 | import org.springframework.transaction.annotation.EnableTransactionManagement; 25 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 26 | 27 | /** 28 | * Created by zhangpeng on 16-11-15. 29 | */ 30 | 31 | @Configuration 32 | @ComponentScan 33 | @EnableAutoConfiguration 34 | @EnableScheduling 35 | @EnableTransactionManagement 36 | public class ShepherApplication extends WebMvcConfigurerAdapter { 37 | 38 | public static void main(String[] args) { 39 | SpringApplication.run(ShepherApplication.class, args); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/configuration/WebConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.configuration; 18 | 19 | import com.xiaomi.shepher.interceptor.AuthorizationInterceptor; 20 | import com.xiaomi.shepher.interceptor.LoginRequiredInterceptor; 21 | import com.xiaomi.shepher.interceptor.NavInterceptor; 22 | import com.xiaomi.shepher.interceptor.PassportInterceptor; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.Configuration; 25 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 26 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 27 | 28 | /** 29 | * Registers all interceptors to {@link InterceptorRegistry}. 30 | * 31 | * Created by weichuyang on 16-7-4. 32 | */ 33 | @Configuration 34 | public class WebConfiguration extends WebMvcConfigurerAdapter { 35 | 36 | @Bean 37 | public NavInterceptor getNavInterceptor() { 38 | return new NavInterceptor(); 39 | } 40 | 41 | @Bean 42 | public AuthorizationInterceptor getAuthorizationInterceptor() { 43 | return new AuthorizationInterceptor(); 44 | } 45 | 46 | @Bean 47 | public PassportInterceptor getPassportInterceptor() { 48 | return new PassportInterceptor(); 49 | } 50 | 51 | @Bean 52 | public LoginRequiredInterceptor getLoginRequiredInterceptor() { 53 | return new LoginRequiredInterceptor(); 54 | } 55 | 56 | @Override 57 | public void addInterceptors(InterceptorRegistry registry) { 58 | registry.addInterceptor(getPassportInterceptor()); 59 | registry.addInterceptor(getLoginRequiredInterceptor()); 60 | registry.addInterceptor(getAuthorizationInterceptor()); 61 | registry.addInterceptor(getNavInterceptor()); 62 | super.addInterceptors(registry); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/controller/ClusterController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.controller; 18 | 19 | import com.xiaomi.shepher.common.LoginRequired; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.RequestMapping; 22 | import org.springframework.web.bind.annotation.RequestMethod; 23 | 24 | /** 25 | * The {@link ClusterController} is entrance of cluster list, 26 | * mapped to freemarker in directory templates/cluster. 27 | * 28 | * Created by zhangpeng on 16-11-03. 29 | */ 30 | 31 | @Controller 32 | @LoginRequired 33 | @RequestMapping({"/clusters", "/"}) 34 | public class ClusterController { 35 | 36 | /** 37 | * Lists clusters of the root path. 38 | * 39 | * @return 40 | */ 41 | @RequestMapping(value = "", method = RequestMethod.GET) 42 | public String list() { 43 | return "/cluster/list"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.controller; 18 | 19 | import com.xiaomi.shepher.common.LoginRequired; 20 | import com.xiaomi.shepher.common.UserHolder; 21 | import com.xiaomi.shepher.util.ShepherConstants; 22 | import org.apache.commons.lang3.StringUtils; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.beans.factory.annotation.Value; 27 | import org.springframework.http.HttpHeaders; 28 | import org.springframework.stereotype.Controller; 29 | import org.springframework.web.bind.annotation.RequestMapping; 30 | import org.springframework.web.bind.annotation.RequestMethod; 31 | 32 | import javax.servlet.http.HttpServletRequest; 33 | 34 | /** 35 | * The {@link IndexController} is entrance of basic module, 36 | * such as logouts. 37 | * 38 | * Created by weichuyang on 16-8-1. 39 | */ 40 | @Controller 41 | @RequestMapping("/") 42 | public class IndexController { 43 | 44 | private static final Logger logger = LoggerFactory.getLogger(IndexController.class); 45 | 46 | @Value("${cas.logout.url}") 47 | private String casServerLogoutUrl; 48 | 49 | @Value("${server.url}") 50 | private String serverUrl; 51 | 52 | @Value("${server.login.type}") 53 | private String loginType; 54 | 55 | @Autowired 56 | private UserHolder userHolder; 57 | 58 | /** 59 | * Logouts. 60 | * 61 | * @param request 62 | * @return 63 | */ 64 | @RequestMapping("logout") 65 | public String logout(HttpServletRequest request) { 66 | request.getSession().invalidate(); 67 | String referer = request.getHeader(HttpHeaders.REFERER); 68 | if (StringUtils.isBlank(referer)) { 69 | referer = serverUrl; 70 | } 71 | if (ShepherConstants.LOGIN_TYPE_CAS.equals(loginType.toUpperCase())) { 72 | return "redirect:" + casServerLogoutUrl + "?service=" + referer; 73 | } 74 | return "redirect:" + referer; 75 | } 76 | 77 | /** 78 | * Login. 79 | * 80 | * @param request 81 | * @return 82 | */ 83 | @RequestMapping(value = "login", method = RequestMethod.GET) 84 | public String login(HttpServletRequest request) { 85 | if (userHolder == null || userHolder.getUser() == null) { 86 | return "login"; 87 | } else { 88 | return "redirect:/"; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/interceptor/AuthorizationInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.interceptor; 18 | 19 | import com.xiaomi.shepher.common.Auth; 20 | import com.xiaomi.shepher.exception.ShepherException; 21 | import com.xiaomi.shepher.util.AuthStrategy; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.method.HandlerMethod; 24 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 25 | 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.servlet.http.HttpServletResponse; 28 | 29 | /** 30 | * The {@link AuthorizationInterceptor} checks user's authorization. 31 | * 32 | * Created by weichuyang on 16-7-14. 33 | */ 34 | public class AuthorizationInterceptor extends HandlerInterceptorAdapter { 35 | 36 | @Autowired 37 | private AuthStrategy authStrategy; 38 | 39 | @Override 40 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 41 | if (handler instanceof HandlerMethod) { 42 | HandlerMethod handlerMethod = (HandlerMethod) handler; 43 | Auth annotation = getAnnotation(handlerMethod); 44 | 45 | if (annotation != null && !authStrategy.validate(request, annotation.value())) { 46 | throw ShepherException.createNoAuthorizationException(); 47 | } 48 | } 49 | 50 | return true; 51 | } 52 | 53 | private Auth getAnnotation(HandlerMethod handlerMethod) { 54 | Auth annotation = handlerMethod.getMethodAnnotation(Auth.class); 55 | 56 | Class beanType = handlerMethod.getBeanType(); 57 | if (beanType.isAnnotationPresent(Auth.class)) { 58 | annotation = beanType.getAnnotation(Auth.class); 59 | } 60 | return annotation; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/interceptor/LoginRequiredInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.interceptor; 18 | 19 | import com.xiaomi.shepher.common.LoginRequired; 20 | import com.xiaomi.shepher.common.UserHolder; 21 | import com.xiaomi.shepher.exception.ShepherException; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.method.HandlerMethod; 24 | import org.springframework.web.servlet.ModelAndView; 25 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 26 | 27 | import javax.servlet.http.HttpServletRequest; 28 | import javax.servlet.http.HttpServletResponse; 29 | 30 | /** 31 | * The {@link LoginRequiredInterceptor} checks login status of user. 32 | * 33 | * Created by banchuanyu on 16-7-21. 34 | */ 35 | public class LoginRequiredInterceptor extends HandlerInterceptorAdapter { 36 | 37 | @Autowired 38 | private UserHolder userHolder; 39 | 40 | @Override 41 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 42 | 43 | if (handler instanceof HandlerMethod) { 44 | HandlerMethod handlerMethod = (HandlerMethod) handler; 45 | if ((handlerMethod.getBeanType().isAnnotationPresent(LoginRequired.class) || 46 | handlerMethod.getMethodAnnotation(LoginRequired.class) != null) && 47 | userHolder.getUser() == null) { 48 | throw ShepherException.createNoLoginException(); 49 | } 50 | } 51 | 52 | return true; 53 | } 54 | 55 | @Override 56 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 57 | throws Exception { 58 | super.postHandle(request, response, handler, modelAndView); 59 | } 60 | 61 | @Override 62 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 63 | super.afterCompletion(request, response, handler, ex); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /shepher-web/src/main/java/com/xiaomi/shepher/interceptor/NavInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Xiaomi, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xiaomi.shepher.interceptor; 18 | 19 | import com.xiaomi.shepher.common.UserHolder; 20 | import com.xiaomi.shepher.model.Cluster; 21 | import com.xiaomi.shepher.model.User; 22 | import com.xiaomi.shepher.util.AuthStrategy; 23 | import com.xiaomi.shepher.util.ClusterUtil; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.web.servlet.ModelAndView; 26 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 27 | 28 | import java.util.List; 29 | import javax.servlet.http.HttpServletRequest; 30 | import javax.servlet.http.HttpServletResponse; 31 | 32 | /** 33 | * The {@link NavInterceptor} inject basic data to nav bar. 34 | * 35 | * Created by weichuyang on 16-7-8. 36 | */ 37 | public class NavInterceptor extends HandlerInterceptorAdapter { 38 | 39 | @Autowired 40 | UserHolder userHolder; 41 | 42 | @Autowired 43 | private AuthStrategy authStrategy; 44 | 45 | @Override 46 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 47 | throws Exception { 48 | List clusters = ClusterUtil.getClusters(); 49 | User user = userHolder.getUser(); 50 | modelAndView.addObject("clusters", clusters); 51 | modelAndView.addObject("user", user); 52 | modelAndView.addObject("isAdmin", authStrategy.isAdmin()); 53 | 54 | super.postHandle(request, response, handler, modelAndView); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/css/vendor/codemirror.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["codemirror.css"],"names":[],"mappings":"AAEA,YAEE,YAA2F,UAC3F,OAAQ,MACR,MAAO,KAKT,kBACE,QAAS,IAAI,EAEf,gBACE,QAAS,EAAE,IAGiB,0BAA9B,6BACE,iBAAkB,KAKpB,oBACE,aAAc,IAAI,MAAM,KACxB,iBAAkB,QAClB,YAAa,OAGf,uBACE,QAAS,EAAE,IAAI,EAAE,IACjB,UAAW,KACX,WAAY,MACZ,MAAO,KACP,YAAa,OAGf,yBAA2B,MAAO,KAClC,gCAAkC,MAAO,KAIzC,mBACE,YAAa,IAAI,MAAM,KACvB,aAAc,KACd,MAAO,EAGT,2CACE,YAAa,IAAI,MAAM,OAEzB,kCACE,MAAO,KACP,OAAQ,YACR,WAAY,KAEd,sCACE,QAAS,EAGX,uBACE,MAAO,KACP,OAAQ,EACR,kBAAmB,MAAM,MAAM,SAAS,SACxC,eAAgB,MAAM,MAAM,SAAS,SACrC,UAAW,MAAM,MAAM,SAAS,SAChC,iBAAkB,KAEpB,sBAEE,IAAM,iBAAkB,aAG1B,yBAEE,IAAM,iBAAkB,aAG1B,iBAEE,IAAM,iBAAkB,aAO1B,QAAU,QAAS,aAAc,gBAAiB,QAElD,mBACE,SAAU,SACV,KAAM,EAAG,MAAO,EAAG,IAAK,MAAO,OAAQ,MACvC,SAAU,OAEZ,kBACE,YAAa,IAAI,MAAM,KACvB,IAAK,EAAG,OAAQ,EAChB,SAAU,SAKZ,yBAA0B,MAAO,KACjC,wBAAyB,MAAO,KAChC,aAAc,MAAO,KACrB,aAAc,MAAO,KACrB,WAAY,WAAY,YAAa,IACrC,OAAQ,WAAY,OACpB,SAAU,gBAAiB,UAC3B,kBAAmB,gBAAiB,aAEpC,0BAA2B,MAAO,KAClC,uBAAwB,MAAO,KAC/B,yBAA0B,MAAO,KACjC,sBAAuB,MAAO,KAK9B,6BAA8B,MAAO,KACrC,6BAA8B,MAAO,KACrC,0BAA2B,MAAO,KAClC,yBAA0B,MAAO,KACjC,2BAA4B,MAAO,KACnC,uBACA,4BADwB,MAAO,KAE/B,0BAA2B,MAAO,KAClC,0BAA2B,MAAO,KAClC,sBAAuB,MAAO,KAC9B,4BAA6B,MAAO,KACpC,qBAAsB,MAAO,KAC7B,uBAAwB,MAAO,KAG/B,gBADA,wBAAyB,MAAO,IAGhC,sBAAwB,cAAe,IAAI,MAI3C,+CAAgD,MAAO,KACvD,kDAAmD,MAAO,KAC1D,wBAA0B,WAAY,mBACtC,kCAAmC,WAAY,QAO/C,YACE,SAAU,SACV,SAAU,OACV,WAAY,KAGd,mBACE,SAAU,iBAGV,cAAmf,MAAO,aAAc,MACxgB,eAAgB,KAChB,OAAQ,KACR,QAAS,EACT,SAAqR,SAEvR,kBACE,SAAU,SACV,aAAc,KAAK,MAAM,YAMmD,0BAAtD,uBAAwB,6BAAhD,uBACE,SAAU,SACV,QAAS,EACT,QAAS,KAEX,uBACE,MAAO,EAAG,IAAK,EACf,WAAY,OACZ,WAAY,OAEd,uBACE,OAAQ,EAAG,KAAM,EACjB,WAAY,OACZ,WAAY,OAEd,6BACE,MAAO,EAAG,OAAQ,EAEpB,0BACE,KAAM,EAAG,OAAQ,EAGnB,oBACE,SAAU,SAAU,KAAM,EAAG,IAAK,EAClC,WAAY,KACZ,QAAS,EAEX,mBACE,YAAa,OACb,OAAQ,KACR,QAAS,aACT,eAAgB,IAChB,cAAe,MAKjB,2BACE,SAAU,SACV,QAAS,EACT,yBACA,sBAaA,oBAAqB,KACrB,iBAAkB,KAClB,YAAa,KAbf,8BACE,SAAU,SACV,IAAK,EAAG,OAAQ,EAChB,QAAS,EAEX,uBACE,SAAU,SACV,OAAQ,QACR,QAAS,EAQX,kBACE,OAAQ,KACR,WAAY,IAEd,gBAEE,mBAA0L,EAAG,sBAAuB,EAAG,cAAe,EACtO,aAAc,EACd,eACA,YAAa,QACb,UAAW,QACX,OAAQ,EACR,YAAa,IACb,UAAW,OACX,YAAa,QACb,MAAO,QACP,QAAS,EACT,SAAU,SACV,SAAU,QACV,4BAA6B,YAC7B,+BAAgC,KAChC,uBAAwB,KAE1B,qBACE,UAAW,WACX,YAAa,SACb,WAAY,OAGd,2BACE,SAAU,SACV,KAAM,EAAG,MAAO,EAAG,IAAK,EAAG,OAAQ,EACnC,QAAS,EAGX,uBACE,SAAU,SACV,QAAS,EACT,SAAU,KAKZ,iBACE,QAAS,EAMX,mBACA,oBACA,uBAJA,mBACA,kBAIE,gBAAiB,YACjB,WAAY,YAGd,oBACE,SAAU,SACV,MAAO,KACP,OAAQ,EACR,SAAU,OACV,WAAY,OAGd,mBACE,SAAU,SACV,eAAgB,KAElB,wBAA0B,SAAU,OAEpC,uBACE,WAAY,OACZ,SAAU,SACV,QAAS,EAMX,2CAJA,2BACE,WAAY,QAOd,qBAAuB,WAAY,QACnC,yCAEA,4BAA6B,iCAAoC,sCAC2D,WAAY,QAFxI,sBAAwB,OAAQ,UAEhC,iCAAkC,sCAAyC,2CAAiD,WAAY,QAExI,cACE,WAAY,KACZ,WAAY,mBAOd,iBAAmB,cAAe,KAElC,aAEE,mCACE,WAAY,QAKhB,wBAA0B,QAAS,GAGnC,6BAA+B"} -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/css/vendor/dracula.min.css: -------------------------------------------------------------------------------- 1 | .cm-s-dracula .CodeMirror-gutters,.cm-s-dracula.CodeMirror{background-color:#282a36!important;color:#f8f8f2!important;border:none}.cm-s-dracula .CodeMirror-activeline-background,.cm-s-dracula .CodeMirror-line::selection,.cm-s-dracula .CodeMirror-line>span::selection,.cm-s-dracula .CodeMirror-line>span>span::selection,.cm-s-dracula.CodeMirror-focused div.CodeMirror-selected{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-gutters{color:#282a36}.cm-s-dracula .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-dracula .CodeMirror-linenumber{color:#6D8A88}.cm-s-dracula .CodeMirror-line::-moz-selection,.cm-s-dracula .CodeMirror-line>span::-moz-selection,.cm-s-dracula .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,.1)}.cm-s-dracula span.cm-comment{color:#6272a4}.cm-s-dracula span.cm-string,.cm-s-dracula span.cm-string-2{color:#f1fa8c}.cm-s-dracula span.cm-number{color:#bd93f9}.cm-s-dracula span.cm-variable{color:#50fa7b}.cm-s-dracula span.cm-variable-2{color:#fff}.cm-s-dracula span.cm-def{color:#ffb86c}.cm-s-dracula span.cm-keyword,.cm-s-dracula span.cm-operator{color:#ff79c6}.cm-s-dracula span.cm-atom{color:#bd93f9}.cm-s-dracula span.cm-meta{color:#f8f8f2}.cm-s-dracula span.cm-tag{color:#ff79c6}.cm-s-dracula span.cm-attribute,.cm-s-dracula span.cm-qualifier{color:#50fa7b}.cm-s-dracula span.cm-property{color:#66d9ef}.cm-s-dracula span.cm-builtin,.cm-s-dracula span.cm-variable-3{color:#50fa7b}.cm-s-dracula .CodeMirror-matchingbracket{text-decoration:underline;color:#fff!important}/*# sourceMappingURL=dracula.min.css.map */ -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/css/vendor/dracula.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["dracula.css"],"names":[],"mappings":"AAU0B,kCAA1B,yBACE,iBAAkB,kBAClB,MAAO,kBACP,YA0BF,gDApBA,0CAA2C,+CAAkD,oDAD7F,yDAqBkD,WAAY,qBAxB9D,kCAAoC,MAAO,QAC3C,iCAAmC,YAAa,MAAM,KAAK,QAC3D,qCAAuC,MAAO,QAG9C,+CAAgD,oDAAuD,yDAA+D,WAAY,qBAClL,8BAAgC,MAAO,QACvC,6BAA8B,+BAAiC,MAAO,QACtE,6BAA+B,MAAO,QACtC,+BAAiC,MAAO,QACxC,iCAAmC,MAAO,KAC1C,0BAA4B,MAAO,QAGnC,8BADA,+BAAiC,MAAO,QAExC,2BAA6B,MAAO,QACpC,2BAA6B,MAAO,QACpC,0BAA4B,MAAO,QACnC,gCACA,gCADkC,MAAO,QAEzC,+BAAiC,MAAO,QACxC,8BACA,iCADgC,MAAO,QAIvC,0CAA4C,gBAAiB,UAAW,MAAO"} -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/css/vendor/merge.min.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-merge{position:relative;border:1px solid #ddd;white-space:pre}.CodeMirror-merge,.CodeMirror-merge .CodeMirror{height:350px}.CodeMirror-merge-2pane .CodeMirror-merge-pane{width:47%}.CodeMirror-merge-2pane .CodeMirror-merge-gap{width:6%}.CodeMirror-merge-3pane .CodeMirror-merge-pane{width:31%}.CodeMirror-merge-3pane .CodeMirror-merge-gap{width:3.5%}.CodeMirror-merge-pane{display:inline-block;white-space:normal;vertical-align:top}.CodeMirror-merge-pane-rightmost{position:absolute;right:0;z-index:1}.CodeMirror-merge-gap{z-index:2;display:inline-block;height:100%;-moz-box-sizing:border-box;box-sizing:border-box;overflow:hidden;border-left:1px solid #ddd;border-right:1px solid #ddd;position:relative;background:#f8f8f8}.CodeMirror-merge-scrolllock-wrap{position:absolute;bottom:0;left:50%}.CodeMirror-merge-scrolllock{position:relative;left:-50%;cursor:pointer;color:#555;line-height:1}.CodeMirror-merge-copy,.CodeMirror-merge-copy-reverse{position:absolute;color:#44c;cursor:pointer}.CodeMirror-merge-copybuttons-left,.CodeMirror-merge-copybuttons-right{position:absolute;left:0;top:0;right:0;bottom:0;line-height:1}.CodeMirror-merge-copy{z-index:3}.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy{left:2px}.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy{right:2px}.CodeMirror-merge-l-inserted,.CodeMirror-merge-r-inserted{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);background-position:bottom left;background-repeat:repeat-x}.CodeMirror-merge-l-deleted,.CodeMirror-merge-r-deleted{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);background-position:bottom left;background-repeat:repeat-x}.CodeMirror-merge-r-chunk{background:#ffffe0}.CodeMirror-merge-r-chunk-start{border-top:1px solid #ee8}.CodeMirror-merge-r-chunk-end{border-bottom:1px solid #ee8}.CodeMirror-merge-r-connect{fill:#ffffe0;stroke:#ee8;stroke-width:1px}.CodeMirror-merge-l-chunk{background:#eef}.CodeMirror-merge-l-chunk-start{border-top:1px solid #88e}.CodeMirror-merge-l-chunk-end{border-bottom:1px solid #88e}.CodeMirror-merge-l-connect{fill:#eef;stroke:#88e;stroke-width:1px}.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk{background:#dfd}.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start{border-top:1px solid #4e4}.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end{border-bottom:1px solid #4e4}.CodeMirror-merge-collapsed-widget:before{content:"(...)"}.CodeMirror-merge-collapsed-widget{cursor:pointer;color:#88b;background:#eef;border:1px solid #ddf;font-size:90%;padding:0 3px;border-radius:4px}.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt{display:none}/*# sourceMappingURL=merge.min.css.map */ -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/css/vendor/merge.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["merge.css"],"names":[],"mappings":"AAAA,kBACE,SAAU,SACV,OAAQ,IAAI,MAAM,KAClB,YAAa,IAGf,kBAAmB,8BACjB,OAAQ,MAGV,+CAAiD,MAAO,IACxD,8CAAgD,MAAO,GACvD,+CAAiD,MAAO,IACxD,8CAAgD,MAAO,KAEvD,uBACE,QAAS,aACT,YAAa,OACb,eAAgB,IAElB,iCACE,SAAU,SACV,MAAO,EACP,QAAS,EAGX,sBACE,QAAS,EACT,QAAS,aACT,OAAQ,KACR,gBAAiB,WACjB,WAAY,WACZ,SAAU,OACV,YAAa,IAAI,MAAM,KACvB,aAAc,IAAI,MAAM,KACxB,SAAU,SACV,WAAY,QAGd,kCACE,SAAU,SACV,OAAQ,EAAG,KAAM,IAEnB,6BACE,SAAU,SACV,KAAM,KACN,OAAQ,QACR,MAAO,KACP,YAAa,EAUf,uBAOA,+BACE,SAAU,SAEV,MAAO,KAoCP,OAAQ,QArDV,mCAAoC,oCAClC,SAAU,SACV,KAAM,EAAG,IAAK,EACd,MAAO,EAAG,OAAQ,EAClB,YAAa,EAGf,uBAIE,QAAS,EASX,0DAA4D,KAAM,IAClE,2DAA6D,MAAO,IAEtC,6BAA9B,6BACE,iBAAkB,4IAClB,oBAAqB,OAAO,KAC5B,kBAAmB,SAGQ,4BAA7B,4BACE,iBAAkB,4IAClB,oBAAqB,OAAO,KAC5B,kBAAmB,SAGrB,0BAA4B,WAAY,QACxC,gCAAkC,WAAY,IAAI,MAAM,KACxD,8BAAgC,cAAe,IAAI,MAAM,KACzD,4BAA8B,KAAM,QAAS,OAAQ,KAAM,aAAc,IAEzE,0BAA4B,WAAY,KACxC,gCAAkC,WAAY,IAAI,MAAM,KACxD,8BAAgC,cAAe,IAAI,MAAM,KACzD,4BAA8B,KAAM,KAAM,OAAQ,KAAM,aAAc,IAEtE,mDAAqD,WAAY,KACjE,+DAAiE,WAAY,IAAI,MAAM,KACvF,2DAA6D,cAAe,IAAI,MAAM,KAEtF,0CACE,QAAS,QAEX,mCACE,OAAQ,QACR,MAAO,KACP,WAAY,KACZ,OAAQ,IAAI,MAAM,KAClB,UAAW,IACX,QAAS,EAAE,IACX,cAAe,IAEjB,wDAA0D,QAAS"} -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/1YwB1sO8YE1Lyjf12WNiUA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/fonts/vendor/1YwB1sO8YE1Lyjf12WNiUA.woff2 -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/H2DMvhDLycM56KNuAtbJYA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/fonts/vendor/H2DMvhDLycM56KNuAtbJYA.woff2 -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/ObQr5XYcoH0WBoUxiaYK3_Y6323mHUZFJMgTvxaG2iE.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/fonts/vendor/ObQr5XYcoH0WBoUxiaYK3_Y6323mHUZFJMgTvxaG2iE.woff2 -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/PLygLKRVCQnA5fhu3qk5fQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/fonts/vendor/PLygLKRVCQnA5fhu3qk5fQ.woff2 -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/UyBMtLsHKBKXelqf4x7VRQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/fonts/vendor/UyBMtLsHKBKXelqf4x7VRQ.woff2 -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/YMOYVM-eg6Qs9YzV9OSqZfesZW2xOQ-xsNqO47m55DA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/fonts/vendor/YMOYVM-eg6Qs9YzV9OSqZfesZW2xOQ-xsNqO47m55DA.woff2 -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/fonts/vendor/fonts.css: -------------------------------------------------------------------------------- 1 | /* latin-ext */ 2 | @font-face { 3 | font-family: 'Lato'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Lato Regular'), local('Lato-Regular'), url(/static/fonts/vendor/UyBMtLsHKBKXelqf4x7VRQ.woff2) format('woff2'); 7 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 8 | } 9 | /* latin */ 10 | @font-face { 11 | font-family: 'Lato'; 12 | font-style: normal; 13 | font-weight: 400; 14 | src: local('Lato Regular'), local('Lato-Regular'), url(/static/fonts/vendor/1YwB1sO8YE1Lyjf12WNiUA.woff2) format('woff2'); 15 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 16 | } 17 | /* latin-ext */ 18 | @font-face { 19 | font-family: 'Lato'; 20 | font-style: normal; 21 | font-weight: 700; 22 | src: local('Lato Bold'), local('Lato-Bold'), url(/static/fonts/vendor/ObQr5XYcoH0WBoUxiaYK3_Y6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); 23 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 24 | } 25 | /* latin */ 26 | @font-face { 27 | font-family: 'Lato'; 28 | font-style: normal; 29 | font-weight: 700; 30 | src: local('Lato Bold'), local('Lato-Bold'), url(/static/fonts/vendor/H2DMvhDLycM56KNuAtbJYA.woff2) format('woff2'); 31 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 32 | } 33 | /* latin-ext */ 34 | @font-face { 35 | font-family: 'Lato'; 36 | font-style: italic; 37 | font-weight: 400; 38 | src: local('Lato Italic'), local('Lato-Italic'), url(/static/fonts/vendor/YMOYVM-eg6Qs9YzV9OSqZfesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 39 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 40 | } 41 | /* latin */ 42 | @font-face { 43 | font-family: 'Lato'; 44 | font-style: italic; 45 | font-weight: 400; 46 | src: local('Lato Italic'), local('Lato-Italic'), url(/static/fonts/vendor/PLygLKRVCQnA5fhu3qk5fQ.woff2) format('woff2'); 47 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 48 | } 49 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoMi/shepher/53117572ee94c846922db9f86adb14372075f2cb/shepher-web/src/main/resources/static/static/img/favicon.ico -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/js/vendor/htmlmixed.min.js: -------------------------------------------------------------------------------- 1 | !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror"),require("../xml/xml"),require("../javascript/javascript"),require("../css/css")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../xml/xml","../javascript/javascript","../css/css"],t):t(CodeMirror)}(function(t){"use strict";function e(t,e,a){var n=t.current(),l=n.search(e);return l>-1?t.backUp(n.length-l):n.match(/<\/?$/)&&(t.backUp(n.length),t.match(e,!1)||t.match(n)),a}function a(t){var e=i[t];return e?e:i[t]=new RegExp("\\s+"+t+"\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*")}function n(t,e){var n=t.match(a(e));return n?/^\s*(.*?)\s*$/.exec(n[2])[1]:""}function l(t,e){return new RegExp((e?"^":"")+"","i")}function r(t,e){for(var a in t)for(var n=e[a]||(e[a]=[]),l=t[a],r=l.length-1;r>=0;r--)n.unshift(l[r])}function o(t,e){for(var a=0;a\s\/]/.test(n.current())&&(c=r.htmlState.tagName&&r.htmlState.tagName.toLowerCase())&&u.hasOwnProperty(c))r.inTag=c+" ";else if(r.inTag&&d&&/>$/.test(n.current())){var f=/^([\S]+) (.*)/.exec(r.inTag);r.inTag=null;var p=">"==n.current()&&o(u[f[1]],f[2]),g=t.getMode(a,p),h=l(f[1],!0),v=l(f[1],!1);r.token=function(t,a){return t.match(h,!1)?(a.token=i,a.localState=a.localMode=null,null):e(t,v,a.localMode.token(t,a.localState))},r.localMode=g,r.localState=t.startState(g,s.indent(r.htmlState,""))}else r.inTag&&(r.inTag+=n.current(),n.eol()&&(r.inTag+=" "));return m}var s=t.getMode(a,{name:"xml",htmlMode:!0,multilineTagIndentFactor:n.multilineTagIndentFactor,multilineTagIndentPastTag:n.multilineTagIndentPastTag}),u={},m=n&&n.tags,d=n&&n.scriptTypes;if(r(c,u),m&&r(m,u),d)for(var f=d.length-1;f>=0;f--)u.script.unshift(["type",d[f].matches,d[f].mode]);return{startState:function(){var e=t.startState(s);return{token:i,inTag:null,localMode:null,localState:null,htmlState:e}},copyState:function(e){var a;return e.localState&&(a=t.copyState(e.localMode,e.localState)),{token:e.token,inTag:e.inTag,localMode:e.localMode,localState:a,htmlState:t.copyState(s,e.htmlState)}},token:function(t,e){return e.token(t,e)},indent:function(e,a){return!e.localMode||/^\s*<\//.test(a)?s.indent(e.htmlState,a):e.localMode.indent?e.localMode.indent(e.localState,a):t.Pass},innerMode:function(t){return{state:t.localState||t.htmlState,mode:t.localMode||s}}}},"xml","javascript","css"),t.defineMIME("text/html","htmlmixed")}); 2 | //# sourceMappingURL=htmlmixed.min.js.map -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/js/vendor/properties.min.js: -------------------------------------------------------------------------------- 1 | !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("properties",function(){return{token:function(e,i){var t=e.sol()||i.afterSection,n=e.eol();if(i.afterSection=!1,t&&(i.nextMultiline?(i.inMultiline=!0,i.nextMultiline=!1):i.position="def"),n&&!i.nextMultiline&&(i.inMultiline=!1,i.position="def"),t)for(;e.eatSpace(););var o=e.next();return!t||"#"!==o&&"!"!==o&&";"!==o?t&&"["===o?(i.afterSection=!0,e.skipTo("]"),e.eat("]"),"header"):"="===o||":"===o?(i.position="quote",null):("\\"===o&&"quote"===i.position&&e.eol()&&(i.nextMultiline=!0),i.position):(i.position="comment",e.skipToEnd(),"comment")},startState:function(){return{position:"def",nextMultiline:!1,inMultiline:!1,afterSection:!1}}}}),e.defineMIME("text/x-properties","properties"),e.defineMIME("text/x-ini","properties")}); 2 | //# sourceMappingURL=properties.min.js.map -------------------------------------------------------------------------------- /shepher-web/src/main/resources/static/static/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | /*font-size: 16px;*/ 3 | min-height: 800px; 4 | } 5 | 6 | .navbar-static-top { 7 | margin-bottom: 10px; 8 | } 9 | 10 | .placeholder { 11 | margin-bottom: 15px; 12 | } 13 | 14 | .checkbox { 15 | display: inline-block; 16 | padding-left: 25px; 17 | margin-left: 20px; 18 | } 19 | 20 | .rowbtn { 21 | margin-left: 5px; 22 | } 23 | 24 | .formatRadio { 25 | display: inline-block; 26 | float: right; 27 | margin-right: 10px; 28 | padding: 10px; 29 | } 30 | 31 | .radio { 32 | display: inline-block; 33 | padding-left: 25px; 34 | } 35 | 36 | .CodeMirror-merge, .CodeMirror-merge .CodeMirror, .CodeMirror { 37 | min-height: 750px; 38 | height: 750px; 39 | } 40 | 41 | .CodeMirror-merge-l-chunk { 42 | background: #555871; 43 | } 44 | 45 | .CodeMirror pre { 46 | font-size: 14px; 47 | } 48 | 49 | .CodeMirror-merge-2pane .CodeMirror-merge-gap { 50 | width: 2%; 51 | } 52 | 53 | .CodeMirror-merge-2pane .CodeMirror-merge-pane { 54 | width: 49%; 55 | } 56 | 57 | .caption { 58 | background-color: #ECF0F1; 59 | border-color: #ECF0F1; 60 | color: #2C3E50; 61 | } 62 | 63 | .list-group { 64 | overflow: hidden; 65 | font-size: 16px; 66 | } 67 | 68 | .list-group-item { 69 | padding: 1px 10px; 70 | word-break: break-all; 71 | } 72 | 73 | .breadcrumb { 74 | overflow: hidden; 75 | word-break: break-all; 76 | font-size: 16px; 77 | } 78 | 79 | .diff-breadcrumb { 80 | margin-bottom: 0px; 81 | } 82 | 83 | .info-table { 84 | margin-bottom: 0px; 85 | } 86 | 87 | .diff-view { 88 | min-height: 600px; 89 | height: 600px; 90 | } 91 | 92 | .diff-form { 93 | display: inline-block; 94 | } -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/admin/create-modal.ftl: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/admin/delete-modal.ftl: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/admin/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | <#list clusters as cluster> 19 | 20 | 21 | 22 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 |

Shepher Clusters Management

NameConfigOperation
${cluster.name}${cluster.config} 23 | 26 | 29 |
36 | 37 |
41 |
42 | 43 | 44 | <#include "create-modal.ftl"> 45 | <#include "update-modal.ftl"> 46 | <#include "delete-modal.ftl"> 47 | 48 | <#include "../script.ftl"> 49 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/admin/update-modal.ftl: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/create-modal.ftl: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/create.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 | <#include "sider.ftl"> 9 |
10 |
11 |
12 |
Parent Node: ${path!}
13 | 15 | 17 | 19 |
20 | 21 |
22 |
23 | 24 |
25 | 26 |
27 | 28 |
29 |
30 | 31 |
32 | 33 | <#include "create-modal.ftl"> 34 | 35 | <#include "../script.ftl"> 36 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/delete-modal.ftl: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/import-modal.ftl: -------------------------------------------------------------------------------- 1 | 53 | 54 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/list.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | <#list clusters as cluster> 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |

Shepher Clusters

NameConfig
${cluster.name}${cluster.config}
26 |
27 | 28 | 29 | <#include "../script.ftl"> 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/sider.ftl: -------------------------------------------------------------------------------- 1 |
2 | <#if isOnebox> 3 | 12 | 13 | 23 | 24 |
    25 | <#list children as child> 26 | <#if path == "/"> 27 |
  • ${child}
  • 28 | <#else> 29 |
  • ${child} 30 |
  • 31 | 32 | 33 |
34 |
-------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/snapshot-modal.ftl: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/stat-modal.ftl: -------------------------------------------------------------------------------- 1 | 60 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/cluster/update-modal.ftl: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/error.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "header.ftl"> 4 | 5 | 6 | 18 | 19 | 20 |
21 |
22 |
23 |

Shepher Error Page

24 |
25 |
26 |

${message!} ,click here to home page

27 |
28 |
29 |
30 | 31 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/header.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | Shepher 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | <#setting url_escaping_charset='utf-8'> 19 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/login.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "./header.ftl"> 4 | 5 | <#include "./nav.ftl"> 6 | 7 |
8 |
9 |
10 |
11 |
12 | Login 13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/nav.ftl: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/permission/add-modal.ftl: -------------------------------------------------------------------------------- 1 | 55 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/permission/delete-modal.ftl: -------------------------------------------------------------------------------- 1 | 54 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/review/accept-modal.ftl: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/review/reject-modal.ftl: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/review/snapshot.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 |
9 | 10 | 11 | 12 |
13 | 14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
Cluster${snapshot.cluster}Path${snapshot.path}
Creator${snapshot.creator}Action${snapshot.actionDetail.description}
ZkVersion${snapshot.zkVersion?c}ZkMtime${snapshot.zkMtime?string("yyyy-MM-dd HH:mm:ss")}
Reviewer${snapshot.reviewer}Time${snapshot.time?string("yyyy-MM-dd HH:mm:ss")}
45 |
46 | 47 | 48 |
49 | 50 |
51 |
52 | 53 | 54 | <#include "../script.ftl"> 55 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/review/snapshots.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 |
9 | 10 | 11 | 12 |
13 | 14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | <#list snapshots as snapshot> 29 | 30 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
ZkVersionCreatorActionReviewerTime
31 | <#if snapshot_index == 0> 32 | current 33 | <#else> 34 | ${snapshot.zkVersion} 35 | 36 | ${snapshot.creator}${snapshot.actionDetail.description}${snapshot.reviewer}${snapshot.time?string("yyyy-MM-dd HH:mm:ss")}
45 |
46 |
47 | 48 | 49 | <#include "../script.ftl"> 50 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/script.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/team/add_member-modal.ftl: -------------------------------------------------------------------------------- 1 | 52 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/team/apply_permission-modal.ftl: -------------------------------------------------------------------------------- 1 | 48 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/team/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 |
9 | 10 | 11 | <#if teams?has_content> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | <#list teams as team> 20 | 21 | <#if team.userId?c == user.id?c && team.role == "MASTER"> 22 | 23 | <#else > 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |

Joined Teams

Team NameRole
${team.teamName}${team.teamName}${team.role.description}
32 |
33 | 34 | <#if !teams?has_content > 35 |
36 | You haven't joined any teams yet. 37 |
38 | 39 | 40 |
41 | 42 | 43 | 44 | <#include "../script.ftl"> 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /shepher-web/src/main/resources/templates/team/member.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../header.ftl"> 4 | 5 | <#include "../nav.ftl"> 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | <#list members as member> 28 | 29 | 30 | 31 | 32 | 33 | 34 |

${currentTeam.name}

14 | 18 |
MemberRole
${member.userName}${member.role.description}
35 | 36 |
37 | 38 | 39 | <#include "../script.ftl"> 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /site/findbugs-exclude-filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /site/pmd-ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | This ruleset checks the code for discouraged programming constructs. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | --------------------------------------------------------------------------------