commit edead1a02659efb892b6308c12641a4e83220f7b Author: LuRuiqian <2632862493@qq.com> Date: Fri Apr 17 11:46:16 2026 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..631d03f --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ +target + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar +*.iml +.idea + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..15625aa --- /dev/null +++ b/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "{}" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright 2018 人人开源 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d76064 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +### 项目说明 +- renren-security是一个轻量级的,前后端分离的Java快速开发平台,能快速开发项目并交付【接私活利器】 +- 采用SpringBoot4.x、Shiro、MyBatis-Plus、Vue3、TypeScript、Element Plus、Vue Router、Pinia、Axios、Vite框架,开发的一套权限系统,极低门槛,拿来即用。设计之初,就非常注重安全性,为企业系统保驾护航,让一切都变得如此简单。 +- 提供了代码生成器,只需编写30%左右代码,其余的代码交给系统自动生成,可快速完成开发任务 +- 支持MySQL、达梦、Oracle、SQL Server、PostgreSQL等主流数据库 +- 演示地址:http://demo.open.renren.io/renren-security (账号密码:admin/admin) + +
+ +### 微信交流群 +我们提供了微信交流群,扫码下面的二维码,关注【人人开源】公众号,回复【加群】,即可根据提示加入微信群! +

+![输入图片说明](renren-admin/src/main/resources/public/wechat.jpg) + +
+ +### 具有如下特点 +- 友好的代码结构及注释,便于阅读及二次开发 +- 实现前后端分离,通过token进行数据交互,前端再也不用关注后端技术 +- 灵活的权限控制,可控制到页面或按钮,满足绝大部分的权限需求 +- 提供CrudService接口,对增删改查进行封装,代码更简洁 +- 页面交互使用Vue3.x,极大的提高了开发效率 +- 完善的部门管理及数据权限,通过注解实现数据权限的控制 +- 完善的XSS防范及脚本过滤,彻底杜绝XSS攻击 +- 完善的代码生成机制,可在线生成entity、xml、dao、service、vue、sql代码,减少70%以上的开发任务 +- 引入quartz定时任务,可动态完成任务的添加、修改、删除、暂停、恢复及日志查看等功能 +- 引入Hibernate Validator校验框架,轻松实现后端校验 +- 引入云存储服务,已支持:七牛云、阿里云、腾讯云等 +- 引入swagger文档支持,方便编写API接口文档 + +
+ +### 数据权限设计思想 +- 用户管理、角色管理、部门管理,可操作本部门及子部门数据 +- 菜单管理、定时任务、参数管理、字典管理、系统日志,没有数据权限 +- 业务功能,按照用户数据权限,查询、操作数据【没有本部门数据权限,也能查询本人数据】 + +
+ + +**项目结构** +``` +renren-security +├─renren-common 公共模块 +│ +├─renren-admin 管理后台 +│ ├─db 数据库SQL脚本 +│ │ +│ ├─modules 模块 +│ │ ├─job 定时任务 +│ │ ├─log 日志管理 +│ │ ├─oss 文件存储 +│ │ ├─security 安全模块 +│ │ └─sys 系统管理(核心) +│ │ +│ └─resources +│ ├─mapper MyBatis文件 +│ ├─public 静态资源 +│ └─application.yml 全局配置文件 +│ +│ +├─renren-api API服务 +│ +├─renren-generator 代码生成器 +│ └─resources +│ ├─mapper MyBatis文件 +│ ├─template 代码生成器模板(可增加或修改相应模板) +│ ├─application.yml 全局配置文件 +│ └─generator.properties 代码生成器,配置文件 +│ +├─renren-ui Vue3前端工程 +``` + +
+ +**技术选型:** +- 核心框架:Spring Boot 4.x +- 安全框架:Apache Shiro 2.1 +- 持久层框架:MyBatis 3.5 +- 定时器:Quartz 2.5 +- 数据库连接池:Druid 1.2 +- 日志管理:Logback +- 页面交互:Vue3.x + +
+ +**软件需求** +- JDK17+ +- Maven3.6+ +- MySQL8.0+ +- Oracle 11g+ +- SQLServer 2012+ +- PostgreSQL 12+ +- 达梦8 +
+ + +**本地部署** +- 通过git下载源码 +- 创建数据库renren_security,数据库编码为UTF-8 +- 执行db/mysql.sql文件,初始化数据 +- 修改application-dev.yml文件,更新MySQL账号和密码 +- 在renren-security目录下,执行mvn clean install +- IDEA运行AdminApplication.java,则可启动项目【renren-admin】 +- renren-admin访问路径:http://localhost:8080/renren-admin +- swagger文档路径:http://localhost:8080/renren-admin/doc.html +- 再启动前端工程 +- 账号密码:admin/admin +
+ +![输入图片说明](renren-admin/src/main/resources/public/1.png) + +
+ +![输入图片说明](renren-admin/src/main/resources/public/2.png) + +
+ +### 如何交流、反馈、参与贡献? +- 开发文档:https://www.renren.io/guide/security +- Gitee仓库:https://gitee.com/renrenio/renren-security +- GitCode仓库:https://gitcode.com/renrenio/renren-security +- [人人开源](https://www.renren.io):https://www.renren.io +- 如需关注项目最新动态,请Watch、Star项目,同时也是对项目最好的支持 +
+ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f01e567 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '2' +services: + renren-admin: + image: renren/renren-admin + ports: + - "8080:8080" + environment: + - spring.profiles.active=dev + renren-api: + image: renren/renren-api + ports: + - "8081:8081" + environment: + - spring.profiles.active=dev \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..00bd97a --- /dev/null +++ b/pom.xml @@ -0,0 +1,164 @@ + + 4.0.0 + io.renren + renren-security + 5.5.0 + pom + + renren-security + 人人权限系统 + https://www.renren.io + + + org.springframework.boot + spring-boot-starter-parent + 4.0.5 + + + + renren-common + renren-dynamic-datasource + renren-admin + renren-api + renren-generator + + + + UTF-8 + UTF-8 + 17 + 1.2.28 + 3.5.16 + 4.0 + 11.2.0.3 + 8.1.2.141 + 5.8.43 + 1.15.3 + 4.5.0 + 3.0.2 + + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-aspectj + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + com.mysql + mysql-connector-j + + + + com.oracle + ojdbc6 + ${oracle.version} + + + + com.microsoft.sqlserver + sqljdbc4 + ${sqlserver.version} + + + + org.postgresql + postgresql + + + + com.dameng + DmJdbcDriver18 + ${dameng.version} + + + com.alibaba + druid-spring-boot-4-starter + ${druid.version} + + + com.baomidou + mybatis-plus-spring-boot4-starter + ${mybatisplus.version} + + + com.baomidou + mybatis-plus-jsqlparser + ${mybatisplus.version} + + + cn.hutool + hutool-all + ${hutool.version} + + + org.jsoup + jsoup + ${jsoup.version} + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + ${knife4j.version} + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + false + + + + diff --git a/renren-admin/Dockerfile b/renren-admin/Dockerfile new file mode 100644 index 0000000..9db81f6 --- /dev/null +++ b/renren-admin/Dockerfile @@ -0,0 +1,7 @@ +FROM java:8 +EXPOSE 8080 + +VOLUME /tmp +ADD renren-admin.jar /app.jar +RUN bash -c 'touch /app.jar' +ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/renren-admin/db/dm8.sql b/renren-admin/db/dm8.sql new file mode 100644 index 0000000..c8ba6a7 --- /dev/null +++ b/renren-admin/db/dm8.sql @@ -0,0 +1,674 @@ +CREATE TABLE sys_user ( + id bigint NOT NULL, + username varchar(50) NOT NULL, + password varchar(100), + real_name varchar(50), + head_url varchar(200), + gender int, + email varchar(100), + mobile varchar(100), + dept_id bigint, + super_admin int, + status int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); + +CREATE UNIQUE INDEX uk_sys_user_username on sys_user(username); +CREATE INDEX idx_sys_user_create_date on sys_user(create_date); + +COMMENT ON TABLE sys_user IS '用户管理'; +COMMENT ON COLUMN sys_user.id IS 'id'; +COMMENT ON COLUMN sys_user.username IS '用户名'; +COMMENT ON COLUMN sys_user.password IS '密码'; +COMMENT ON COLUMN sys_user.real_name IS '姓名'; +COMMENT ON COLUMN sys_user.head_url IS '头像'; +COMMENT ON COLUMN sys_user.gender IS '性别 0:男 1:女 2:保密'; +COMMENT ON COLUMN sys_user.email IS '邮箱'; +COMMENT ON COLUMN sys_user.mobile IS '手机号'; +COMMENT ON COLUMN sys_user.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_user.super_admin IS '超级管理员 0:否 1:是'; +COMMENT ON COLUMN sys_user.status IS '状态 0:停用 1:正常'; +COMMENT ON COLUMN sys_user.creator IS '创建者'; +COMMENT ON COLUMN sys_user.create_date IS '创建时间'; +COMMENT ON COLUMN sys_user.updater IS '更新者'; +COMMENT ON COLUMN sys_user.update_date IS '更新时间'; + + +CREATE TABLE sys_dept ( + id bigint NOT NULL, + pid bigint, + pids varchar(500), + name varchar(50), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE INDEX idx_sys_dept_pid on sys_dept(pid); +CREATE INDEX idx_sys_dept_idx_sort on sys_dept(sort); + +COMMENT ON TABLE sys_dept IS '部门管理'; +COMMENT ON COLUMN sys_dept.id IS 'id'; +COMMENT ON COLUMN sys_dept.pid IS '上级ID'; +COMMENT ON COLUMN sys_dept.pids IS '所有上级ID,用逗号分开'; +COMMENT ON COLUMN sys_dept.name IS '部门名称'; +COMMENT ON COLUMN sys_dept.sort IS '排序'; +COMMENT ON COLUMN sys_dept.creator IS '创建者'; +COMMENT ON COLUMN sys_dept.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dept.updater IS '更新者'; +COMMENT ON COLUMN sys_dept.update_date IS '更新时间'; + + +create table sys_role +( + id bigint NOT NULL, + name varchar(50), + remark varchar(100), + dept_id bigint, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_role_dept_id on sys_role(dept_id); + +COMMENT ON TABLE sys_role IS '角色管理'; +COMMENT ON COLUMN sys_role.id IS 'id'; +COMMENT ON COLUMN sys_role.name IS '角色名称'; +COMMENT ON COLUMN sys_role.remark IS '备注'; +COMMENT ON COLUMN sys_role.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_role.creator IS '创建者'; +COMMENT ON COLUMN sys_role.create_date IS '创建时间'; +COMMENT ON COLUMN sys_role.updater IS '更新者'; +COMMENT ON COLUMN sys_role.update_date IS '更新时间'; + + +create table sys_menu +( + id bigint NOT NULL, + pid bigint, + name varchar(200), + url varchar(200), + permissions varchar(500), + menu_type int, + icon varchar(50), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_menu_pid on sys_menu(pid); +CREATE INDEX idx_sys_menu_sort on sys_menu(sort); + +COMMENT ON TABLE sys_menu IS '菜单管理'; +COMMENT ON COLUMN sys_menu.id IS 'id'; +COMMENT ON COLUMN sys_menu.pid IS '上级ID,一级菜单为0'; +COMMENT ON COLUMN sys_menu.name IS '名称'; +COMMENT ON COLUMN sys_menu.url IS '菜单URL'; +COMMENT ON COLUMN sys_menu.permissions IS '授权(多个用逗号分隔,如:sys:user:list,sys:user:save)'; +COMMENT ON COLUMN sys_menu.menu_type IS '类型 0:菜单 1:按钮'; +COMMENT ON COLUMN sys_menu.icon IS '菜单图标'; +COMMENT ON COLUMN sys_menu.sort IS '排序'; +COMMENT ON COLUMN sys_menu.creator IS '创建者'; +COMMENT ON COLUMN sys_menu.create_date IS '创建时间'; +COMMENT ON COLUMN sys_menu.updater IS '更新者'; +COMMENT ON COLUMN sys_menu.update_date IS '更新时间'; + + +create table sys_role_user +( + id bigint NOT NULL, + role_id bigint, + user_id bigint, + creator bigint, + create_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_role_user_role_id on sys_role_user(role_id); +CREATE INDEX idx_sys_role_user_user_id on sys_role_user(user_id); + +COMMENT ON TABLE sys_role_user IS '角色用户关系'; +COMMENT ON COLUMN sys_role_user.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_user.user_id IS '用户ID'; +COMMENT ON COLUMN sys_role_user.creator IS '创建者'; +COMMENT ON COLUMN sys_role_user.create_date IS '创建时间'; + + +create table sys_role_menu +( + id bigint NOT NULL, + role_id bigint, + menu_id bigint, + creator bigint, + create_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_role_menu_role_id on sys_role_menu(role_id); +CREATE INDEX idx_sys_role_menu_menu_id on sys_role_menu(menu_id); + +COMMENT ON TABLE sys_role_menu IS '角色菜单关系'; +COMMENT ON COLUMN sys_role_menu.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_menu.menu_id IS '菜单ID'; +COMMENT ON COLUMN sys_role_menu.creator IS '创建者'; +COMMENT ON COLUMN sys_role_menu.create_date IS '创建时间'; + + +create table sys_role_data_scope +( + id bigint NOT NULL, + role_id bigint, + dept_id bigint, + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_data_scope_role_id on sys_role_data_scope(role_id); + +COMMENT ON TABLE sys_role_data_scope IS '角色数据权限'; +COMMENT ON COLUMN sys_role_data_scope.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_data_scope.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_role_data_scope.creator IS '创建者'; +COMMENT ON COLUMN sys_role_data_scope.create_date IS '创建时间'; + + +create table sys_params +( + id bigint NOT NULL, + param_code varchar(32), + param_value varchar(2000), + param_type int DEFAULT 1 NOT NULL, + remark varchar(200), + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_params_param_code on sys_params(param_code); +CREATE INDEX idx_sys_params_create_date on sys_params(create_date); + +COMMENT ON TABLE sys_params IS '参数管理'; +COMMENT ON COLUMN sys_params.param_code IS '参数编码'; +COMMENT ON COLUMN sys_params.param_value IS '参数值'; +COMMENT ON COLUMN sys_params.param_type IS '类型 0:系统参数 1:非系统参数'; +COMMENT ON COLUMN sys_params.remark IS '备注'; +COMMENT ON COLUMN sys_params.creator IS '创建者'; +COMMENT ON COLUMN sys_params.create_date IS '创建时间'; +COMMENT ON COLUMN sys_params.updater IS '更新者'; +COMMENT ON COLUMN sys_params.update_date IS '更新时间'; + + +create table sys_dict_type +( + id bigint NOT NULL, + dict_type varchar(100), + dict_name varchar(255), + remark varchar(255), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_dict_type_dict_type on sys_dict_type(dict_type); + +COMMENT ON TABLE sys_dict_type IS '字典类型'; +COMMENT ON COLUMN sys_dict_type.id IS 'id'; +COMMENT ON COLUMN sys_dict_type.dict_type IS '字典类型'; +COMMENT ON COLUMN sys_dict_type.dict_name IS '字典名称'; +COMMENT ON COLUMN sys_dict_type.remark IS '备注'; +COMMENT ON COLUMN sys_dict_type.sort IS '排序'; +COMMENT ON COLUMN sys_dict_type.creator IS '创建者'; +COMMENT ON COLUMN sys_dict_type.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dict_type.updater IS '更新者'; +COMMENT ON COLUMN sys_dict_type.update_date IS '更新时间'; + +create table sys_dict_data +( + id bigint NOT NULL, + dict_type_id bigint NOT NULL, + dict_label varchar(255), + dict_value varchar(255), + remark varchar(255), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE INDEX idx_sys_dict_data_sort on sys_dict_data(sort); +CREATE UNIQUE INDEX uk_dict_type_value on sys_dict_data(dict_type_id, dict_value); + +COMMENT ON TABLE sys_dict_data IS '字典数据'; +COMMENT ON COLUMN sys_dict_data.id IS 'id'; +COMMENT ON COLUMN sys_dict_data.dict_type_id IS '字典类型ID'; +COMMENT ON COLUMN sys_dict_data.dict_label IS '字典标签'; +COMMENT ON COLUMN sys_dict_data.dict_value IS '字典值'; +COMMENT ON COLUMN sys_dict_data.remark IS '备注'; +COMMENT ON COLUMN sys_dict_data.sort IS '排序'; +COMMENT ON COLUMN sys_dict_data.creator IS '创建者'; +COMMENT ON COLUMN sys_dict_data.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dict_data.updater IS '更新者'; +COMMENT ON COLUMN sys_dict_data.update_date IS '更新时间'; + + +create table sys_log_login +( + id bigint NOT NULL, + operation int, + status int, + user_agent varchar(500), + ip varchar(32), + creator_name varchar(50), + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_login_status on sys_log_login(status); +CREATE INDEX idx_login_create_date on sys_log_login(create_date); + +COMMENT ON TABLE sys_log_login IS '登录日志'; +COMMENT ON COLUMN sys_log_login.id IS 'id'; +COMMENT ON COLUMN sys_log_login.operation IS '用户操作 0:用户登录 1:用户退出'; +COMMENT ON COLUMN sys_log_login.status IS '状态 0:失败 1:成功 2:账号已锁定'; +COMMENT ON COLUMN sys_log_login.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_login.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_login.creator_name IS '用户名'; +COMMENT ON COLUMN sys_log_login.creator IS '创建者'; +COMMENT ON COLUMN sys_log_login.create_date IS '创建时间'; + + +create table sys_log_operation +( + id bigint NOT NULL, + operation varchar(50), + request_uri varchar(200), + request_method varchar(20), + request_params text, + request_time int, + user_agent varchar(500), + ip varchar(32), + status int, + creator_name varchar(50), + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_operation_create_date on sys_log_operation(create_date); + +COMMENT ON TABLE sys_log_operation IS '操作日志'; +COMMENT ON COLUMN sys_log_operation.id IS 'id'; +COMMENT ON COLUMN sys_log_operation.operation IS '用户操作'; +COMMENT ON COLUMN sys_log_operation.request_uri IS '请求URI'; +COMMENT ON COLUMN sys_log_operation.request_method IS '请求方式'; +COMMENT ON COLUMN sys_log_operation.request_params IS '请求参数'; +COMMENT ON COLUMN sys_log_operation.request_time IS '请求时长(毫秒)'; +COMMENT ON COLUMN sys_log_operation.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_operation.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_operation.status IS '状态 0:失败 1:成功'; +COMMENT ON COLUMN sys_log_operation.creator_name IS '用户名'; +COMMENT ON COLUMN sys_log_operation.creator IS '创建者'; +COMMENT ON COLUMN sys_log_operation.create_date IS '创建时间'; + + +create table sys_log_error +( + id bigint NOT NULL, + request_uri varchar(200), + request_method varchar(20), + request_params text, + user_agent varchar(500), + ip varchar(32), + error_info text, + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_error_create_date on sys_log_error(create_date); + +COMMENT ON TABLE sys_log_error IS '异常日志'; +COMMENT ON COLUMN sys_log_error.id IS 'id'; +COMMENT ON COLUMN sys_log_error.request_uri IS '请求URI'; +COMMENT ON COLUMN sys_log_error.request_method IS '请求方式'; +COMMENT ON COLUMN sys_log_error.request_params IS '请求参数'; +COMMENT ON COLUMN sys_log_error.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_error.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_error.error_info IS '异常信息'; +COMMENT ON COLUMN sys_log_error.creator IS '创建者'; +COMMENT ON COLUMN sys_log_error.create_date IS '创建时间'; + + + +CREATE TABLE sys_oss ( + id bigint NOT NULL, + url varchar(200), + creator bigint, + create_date datetime, + PRIMARY KEY (id) +); +CREATE INDEX idx_sys_oss_create_date on sys_oss(create_date); + +COMMENT ON TABLE sys_oss IS '文件上传'; +COMMENT ON COLUMN sys_oss.id IS 'id'; +COMMENT ON COLUMN sys_oss.url IS 'URL地址'; +COMMENT ON COLUMN sys_oss.creator IS '创建者'; +COMMENT ON COLUMN sys_oss.create_date IS '创建时间'; + + +CREATE TABLE schedule_job ( + id bigint NOT NULL, + bean_name varchar(200), + params varchar(2000), + cron_expression varchar(100), + status int, + remark varchar(255), + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + PRIMARY KEY (id) +); + +CREATE INDEX idx_schedule_job_create_date on schedule_job(create_date); + +COMMENT ON TABLE schedule_job IS '定时任务'; +COMMENT ON COLUMN schedule_job.id IS 'id'; +COMMENT ON COLUMN schedule_job.bean_name IS 'spring bean名称'; +COMMENT ON COLUMN schedule_job.params IS '参数'; +COMMENT ON COLUMN schedule_job.cron_expression IS 'cron表达式'; +COMMENT ON COLUMN schedule_job.status IS '任务状态 0:暂停 1:正常'; +COMMENT ON COLUMN schedule_job.remark IS '备注'; +COMMENT ON COLUMN schedule_job.creator IS '创建者'; +COMMENT ON COLUMN schedule_job.create_date IS '创建时间'; +COMMENT ON COLUMN schedule_job.updater IS '更新者'; +COMMENT ON COLUMN schedule_job.update_date IS '更新时间'; + + +CREATE TABLE schedule_job_log ( + id bigint NOT NULL, + job_id bigint NOT NULL, + bean_name varchar(200), + params varchar(2000), + status int, + error varchar(2000), + times int, + create_date datetime, + PRIMARY KEY (id) +); + +CREATE INDEX idx_job_log_job_id on schedule_job_log(job_id); +CREATE INDEX idx_job_log_create_date on schedule_job_log(create_date); + +COMMENT ON TABLE schedule_job_log IS '定时任务日志'; +COMMENT ON COLUMN schedule_job_log.id IS 'id'; +COMMENT ON COLUMN schedule_job_log.bean_name IS 'spring bean名称'; +COMMENT ON COLUMN schedule_job_log.params IS '参数'; +COMMENT ON COLUMN schedule_job_log.status IS '任务状态 0:失败 1:成功'; +COMMENT ON COLUMN schedule_job_log.error IS '失败信息'; +COMMENT ON COLUMN schedule_job_log.times IS '耗时(单位:毫秒)'; +COMMENT ON COLUMN schedule_job.create_date IS '创建时间'; + + +CREATE TABLE sys_user_token ( + id bigint NOT NULL, + user_id bigint, + token varchar(100), + expire_date datetime, + update_date datetime, + create_date datetime, + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX uk_sys_user_token_user_id on sys_user_token(user_id); +CREATE UNIQUE INDEX uk_sys_user_token on sys_user_token(token); + +COMMENT ON TABLE sys_user_token IS '系统用户Token'; +COMMENT ON COLUMN sys_user_token.id IS 'id'; +COMMENT ON COLUMN sys_user_token.user_id IS '用户id'; +COMMENT ON COLUMN sys_user_token.token IS '用户token'; +COMMENT ON COLUMN sys_user_token.expire_date IS '过期时间'; +COMMENT ON COLUMN sys_user_token.update_date IS '更新时间'; +COMMENT ON COLUMN sys_user_token.create_date IS '创建时间'; + + + +-- 初始数据 +INSERT INTO sys_user(id, username, password, real_name, gender, email, mobile, status, dept_id, super_admin, creator, create_date, updater, update_date) VALUES (1067246875800000001, 'admin', '$2a$10$012Kx2ba5jzqr9gLlG4MX.bnQJTD9UWqF57XDo2N3.fPtLne02u/m', '管理员', 0, 'root@renren.io', '13612345678', 1, null, 1, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000002, 0, '权限管理', NULL, NULL, 0, 'icon-safetycertificate', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000003, 1067246875800000055, '新增', NULL, 'sys:user:save,sys:dept:list,sys:role:list', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000004, 1067246875800000055, '修改', NULL, 'sys:user:update,sys:dept:list,sys:role:list', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000005, 1067246875800000055, '删除', NULL, 'sys:user:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000006, 1067246875800000055, '导出', NULL, 'sys:user:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000007, 1067246875800000002, '角色管理', 'sys/role', NULL, 0, 'icon-team', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000008, 1067246875800000007, '查看', NULL, 'sys:role:page,sys:role:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000009, 1067246875800000007, '新增', NULL, 'sys:role:save,sys:menu:select,sys:dept:list', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000010, 1067246875800000007, '修改', NULL, 'sys:role:update,sys:menu:select,sys:dept:list', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000011, 1067246875800000007, '删除', NULL, 'sys:role:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000012, 1067246875800000002, '部门管理', 'sys/dept', NULL, 0, 'icon-apartment', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000014, 1067246875800000012, '查看', NULL, 'sys:dept:list,sys:dept:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000015, 1067246875800000012, '新增', NULL, 'sys:dept:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000016, 1067246875800000012, '修改', NULL, 'sys:dept:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000017, 1067246875800000012, '删除', NULL, 'sys:dept:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000025, 1067246875800000035, '菜单管理', 'sys/menu', NULL, 0, 'icon-unorderedlist', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000026, 1067246875800000025, '查看', NULL, 'sys:menu:list,sys:menu:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000027, 1067246875800000025, '新增', NULL, 'sys:menu:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000028, 1067246875800000025, '修改', NULL, 'sys:menu:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000029, 1067246875800000025, '删除', NULL, 'sys:menu:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000030, 1067246875800000035, '定时任务', 'job/schedule', NULL, 0, 'icon-dashboard', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000031, 1067246875800000030, '查看', NULL, 'sys:schedule:page,sys:schedule:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000032, 1067246875800000030, '新增', NULL, 'sys:schedule:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000033, 1067246875800000030, '修改', NULL, 'sys:schedule:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000034, 1067246875800000030, '删除', NULL, 'sys:schedule:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000035, 0, '系统设置', NULL, NULL, 0, 'icon-setting', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000036, 1067246875800000030, '暂停', NULL, 'sys:schedule:pause', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000037, 1067246875800000030, '恢复', NULL, 'sys:schedule:resume', 1, NULL, 5, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000038, 1067246875800000030, '立即执行', NULL, 'sys:schedule:run', 1, NULL, 6, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000039, 1067246875800000030, '日志列表', NULL, 'sys:schedule:log', 1, NULL, 7, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000040, 1067246875800000035, '参数管理', 'sys/params', '', 0, 'icon-fileprotect', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000041, 1067246875800000035, '字典管理', 'sys/dict-type', NULL, 0, 'icon-golden-fill', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000042, 1067246875800000041, '查看', NULL, 'sys:dict:page,sys:dict:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000043, 1067246875800000041, '新增', NULL, 'sys:dict:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000044, 1067246875800000041, '修改', NULL, 'sys:dict:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000045, 1067246875800000041, '删除', NULL, 'sys:dict:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000046, 0, '日志管理', NULL, NULL, 0, 'icon-container', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000047, 1067246875800000035, '文件上传', 'oss/oss', 'sys:oss:all', 0, 'icon-upload', 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000048, 1067246875800000046, '登录日志', 'sys/log-login', 'sys:log:login', 0, 'icon-filedone', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000049, 1067246875800000046, '操作日志', 'sys/log-operation', 'sys:log:operation', 0, 'icon-solution', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000050, 1067246875800000046, '异常日志', 'sys/log-error', 'sys:log:error', 0, 'icon-file-exception', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000051, 1067246875800000053, 'SQL监控', '{{ApiUrl}}/druid/sql.html', NULL, 0, 'icon-database', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000053, 0, '系统监控', NULL, NULL, 0, 'icon-desktop', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000055, 1067246875800000002, '用户管理', 'sys/user', NULL, 0, 'icon-user', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000056, 1067246875800000055, '查看', NULL, 'sys:user:page,sys:user:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000057, 1067246875800000040, '新增', NULL, 'sys:params:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000058, 1067246875800000040, '导出', NULL, 'sys:params:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000059, 1067246875800000040, '查看', '', 'sys:params:page,sys:params:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000060, 1067246875800000040, '修改', NULL, 'sys:params:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000061, 1067246875800000040, '删除', '', 'sys:params:delete', 1, '', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1156748733921165314, 1067246875800000053, '接口文档', '{{ApiUrl}}/doc.html', '', 0, 'icon-file-word', 1, 1067246875800000001, now(), 1067246875800000001, now()); + + +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000062, 1067246875800000063, '1067246875800000066,1067246875800000063', '技术部', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000063, 1067246875800000066, '1067246875800000066', '长沙分公司', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000064, 1067246875800000066, '1067246875800000066', '上海分公司', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000065, 1067246875800000064, '1067246875800000066,1067246875800000064', '市场部', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000066, 0, '0', '人人开源集团', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000067, 1067246875800000064, '1067246875800000066,1067246875800000064', '销售部', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000068, 1067246875800000063, '1067246875800000066,1067246875800000063', '产品部', 1, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1160061077912858625, 'gender', '性别', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061112075464705, 1160061077912858625, '男', '0', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061146967879681, 1160061077912858625, '女', '1', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061190127267841, 1160061077912858625, '保密', '2', '', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1225813644059140097, 'notice_type', '站内通知-类型', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814069634195457, 1225813644059140097, '公告', '0', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814107559092225, 1225813644059140097, '会议', '1', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814271879340034, 1225813644059140097, '其他', '2', '', 2, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_params(id, param_code, param_value, param_type, remark, creator, create_date, updater, update_date) VALUES (1067246875800000073, 'CLOUD_STORAGE_CONFIG_KEY', '{"type":1,"qiniuDomain":"http://test.oss.renren.io","qiniuPrefix":"upload","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","qiniuBucketName":"renren-oss","aliyunDomain":"","aliyunPrefix":"","aliyunEndPoint":"","aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qcloudBucketName":""}', '0', '云存储配置信息', 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO schedule_job (id, bean_name, params, cron_expression, status, remark, creator, create_date, updater, update_date) VALUES (1067246875800000076, 'testTask', 'renren', '0 0/30 * * * ?', 0, '有参测试,多个参数使用json', 1067246875800000001, now(), 1067246875800000001, now()); + + + + +-- quartz自带表结构 +DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; +DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; +DROP TABLE IF EXISTS QRTZ_LOCKS; +DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; +DROP TABLE IF EXISTS QRTZ_CALENDARS; + +create table QRTZ_JOB_DETAILS ( + sched_name varchar(120) not null, + job_name varchar(200) not null, + job_group varchar(200) not null, + description varchar(250) null, + job_class_name varchar(250) not null, + is_durable varchar(1) not null, + is_nonconcurrent varchar(1) not null, + is_update_data varchar(1) not null, + requests_recovery varchar(1) not null, + job_data blob null, + primary key (sched_name, job_name, job_group) +); + +create table QRTZ_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + job_name varchar(200) not null, + job_group varchar(200) not null, + description varchar(250) null, + next_fire_time bigint null, + prev_fire_time bigint null, + priority int null, + trigger_state varchar(16) not null, + trigger_type varchar(8) not null, + start_time bigint not null, + end_time bigint null, + calendar_name varchar(200) null, + misfire_instr int null, + job_data blob null, + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, job_name, job_group) + references QRTZ_JOB_DETAILS(sched_name, job_name, job_group) +); + +create table QRTZ_SIMPLE_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + repeat_count bigint not null, + repeat_interval bigint not null, + times_triggered bigint not null, + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) + references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +); + +create table QRTZ_CRON_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + cron_expression varchar(200) not null, + time_zone_id varchar(80), + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) + references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +); + +create table QRTZ_BLOB_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + blob_data blob null, + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) + references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +); + +create table QRTZ_CALENDARS ( + sched_name varchar(120) not null, + calendar_name varchar(200) not null, + calendar blob not null, + primary key (sched_name, calendar_name) +); + +create table QRTZ_PAUSED_TRIGGER_GRPS ( + sched_name varchar(120) not null, + trigger_group varchar(200) not null, + primary key (sched_name, trigger_group) +); + +create table QRTZ_FIRED_TRIGGERS ( + sched_name varchar(120) not null, + entry_id varchar(95) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + instance_name varchar(200) not null, + fired_time bigint not null, + sched_time bigint not null, + priority int not null, + state varchar(16) not null, + job_name varchar(200) null, + job_group varchar(200) null, + is_nonconcurrent varchar(1) null, + requests_recovery varchar(1) null, + primary key (sched_name, entry_id) +); + +create table QRTZ_SCHEDULER_STATE ( + sched_name varchar(120) not null, + instance_name varchar(200) not null, + last_checkin_time bigint not null, + checkin_interval bigint not null, + primary key (sched_name, instance_name) +); + +create table QRTZ_LOCKS ( + sched_name varchar(120) not null, + lock_name varchar(40) not null, + primary key (sched_name, lock_name) +); + +create table QRTZ_SIMPROP_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + str_prop_1 varchar(512) null, + str_prop_2 varchar(512) null, + str_prop_3 varchar(512) null, + int_prop_1 int null, + int_prop_2 int null, + long_prop_1 bigint null, + long_prop_2 bigint null, + dec_prop_1 numeric(13,4) null, + dec_prop_2 numeric(13,4) null, + bool_prop_1 varchar(1) null, + bool_prop_2 varchar(1) null, + primary key (sched_name, trigger_name, trigger_group), + foreign key (sched_name, trigger_name, trigger_group) + references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) +); \ No newline at end of file diff --git a/renren-admin/db/mysql.sql b/renren-admin/db/mysql.sql new file mode 100644 index 0000000..1f9c9e3 --- /dev/null +++ b/renren-admin/db/mysql.sql @@ -0,0 +1,504 @@ +-- 系统用户 +CREATE TABLE sys_user ( + id bigint NOT NULL COMMENT 'id', + username varchar(50) NOT NULL COMMENT '用户名', + password varchar(100) COMMENT '密码', + real_name varchar(50) COMMENT '姓名', + head_url varchar(200) COMMENT '头像', + gender tinyint unsigned COMMENT '性别 0:男 1:女 2:保密', + email varchar(100) COMMENT '邮箱', + mobile varchar(100) COMMENT '手机号', + dept_id bigint COMMENT '部门ID', + super_admin tinyint unsigned COMMENT '超级管理员 0:否 1:是', + status tinyint COMMENT '状态 0:停用 1:正常', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + unique key uk_username (username), + key idx_create_date (create_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户'; + +-- 部门 +CREATE TABLE sys_dept ( + id bigint NOT NULL COMMENT 'id', + pid bigint COMMENT '上级ID', + pids varchar(500) COMMENT '所有上级ID,用逗号分开', + name varchar(50) COMMENT '部门名称', + sort int unsigned COMMENT '排序', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + key idx_pid (pid), + key idx_sort (sort) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='部门管理'; + +-- 角色管理 +create table sys_role +( + id bigint NOT NULL COMMENT 'id', + name varchar(50) COMMENT '角色名称', + remark varchar(100) COMMENT '备注', + dept_id bigint COMMENT '部门ID', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + key idx_dept_id (dept_id) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='角色管理'; + +-- 菜单管理 +create table sys_menu +( + id bigint NOT NULL COMMENT 'id', + pid bigint COMMENT '上级ID,一级菜单为0', + name varchar(200) COMMENT '名称', + url varchar(200) COMMENT '菜单URL', + permissions varchar(500) COMMENT '授权(多个用逗号分隔,如:sys:user:list,sys:user:save)', + menu_type tinyint unsigned COMMENT '类型 0:菜单 1:按钮', + icon varchar(50) COMMENT '菜单图标', + sort int COMMENT '排序', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + key idx_pid (pid), + key idx_sort (sort) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='菜单管理'; + +-- 角色用户关系 +create table sys_role_user +( + id bigint NOT NULL COMMENT 'id', + role_id bigint COMMENT '角色ID', + user_id bigint COMMENT '用户ID', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + primary key (id), + key idx_role_id (role_id), + key idx_user_id (user_id) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='角色用户关系'; + +-- 角色菜单关系 +create table sys_role_menu +( + id bigint NOT NULL COMMENT 'id', + role_id bigint COMMENT '角色ID', + menu_id bigint COMMENT '菜单ID', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + primary key (id), + key idx_role_id (role_id), + key idx_menu_id (menu_id) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='角色菜单关系'; + +-- 角色数据权限 +create table sys_role_data_scope +( + id bigint NOT NULL COMMENT 'id', + role_id bigint COMMENT '角色ID', + dept_id bigint COMMENT '部门ID', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + primary key (id), + key idx_role_id (role_id) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='角色数据权限'; + +-- 参数管理 +create table sys_params +( + id bigint NOT NULL COMMENT 'id', + param_code varchar(32) COMMENT '参数编码', + param_value varchar(2000) COMMENT '参数值', + param_type tinyint unsigned default 1 COMMENT '类型 0:系统参数 1:非系统参数', + remark varchar(200) COMMENT '备注', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + unique key uk_param_code (param_code), + key idx_create_date (create_date) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='参数管理'; + +-- 字典类型 +create table sys_dict_type +( + id bigint NOT NULL COMMENT 'id', + dict_type varchar(100) NOT NULL COMMENT '字典类型', + dict_name varchar(255) NOT NULL COMMENT '字典名称', + remark varchar(255) COMMENT '备注', + sort int unsigned COMMENT '排序', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + UNIQUE KEY(dict_type) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='字典类型'; + +-- 字典数据 +create table sys_dict_data +( + id bigint NOT NULL COMMENT 'id', + dict_type_id bigint NOT NULL COMMENT '字典类型ID', + dict_label varchar(255) NOT NULL COMMENT '字典标签', + dict_value varchar(255) COMMENT '字典值', + remark varchar(255) COMMENT '备注', + sort int unsigned COMMENT '排序', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + primary key (id), + unique key uk_dict_type_value (dict_type_id, dict_value), + key idx_sort (sort) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='字典数据'; + +-- 登录日志 +create table sys_log_login +( + id bigint NOT NULL COMMENT 'id', + operation tinyint unsigned COMMENT '用户操作 0:用户登录 1:用户退出', + status tinyint unsigned NOT NULL COMMENT '状态 0:失败 1:成功 2:账号已锁定', + user_agent varchar(500) COMMENT '用户代理', + ip varchar(32) COMMENT '操作IP', + creator_name varchar(50) COMMENT '用户名', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + primary key (id), + key idx_status (status), + key idx_create_date (create_date) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='登录日志'; + +-- 操作日志 +create table sys_log_operation +( + id bigint NOT NULL COMMENT 'id', + operation varchar(50) COMMENT '用户操作', + request_uri varchar(200) COMMENT '请求URI', + request_method varchar(20) COMMENT '请求方式', + request_params text COMMENT '请求参数', + request_time int unsigned NOT NULL COMMENT '请求时长(毫秒)', + user_agent varchar(500) COMMENT '用户代理', + ip varchar(32) COMMENT '操作IP', + status tinyint unsigned NOT NULL COMMENT '状态 0:失败 1:成功', + creator_name varchar(50) COMMENT '用户名', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + primary key (id), + key idx_create_date (create_date) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='操作日志'; + +-- 异常日志 +create table sys_log_error +( + id bigint NOT NULL COMMENT 'id', + request_uri varchar(200) COMMENT '请求URI', + request_method varchar(20) COMMENT '请求方式', + request_params text COMMENT '请求参数', + user_agent varchar(500) COMMENT '用户代理', + ip varchar(32) COMMENT '操作IP', + error_info text COMMENT '异常信息', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + primary key (id), + key idx_create_date (create_date) +)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='异常日志'; + + +-- 文件上传 +CREATE TABLE sys_oss ( + id bigint NOT NULL COMMENT 'id', + url varchar(200) COMMENT 'URL地址', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + PRIMARY KEY (id), + key idx_create_date (create_date) +) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='文件上传'; + +-- 定时任务 +CREATE TABLE schedule_job ( + id bigint NOT NULL COMMENT 'id', + bean_name varchar(200) DEFAULT NULL COMMENT 'spring bean名称', + params varchar(2000) DEFAULT NULL COMMENT '参数', + cron_expression varchar(100) DEFAULT NULL COMMENT 'cron表达式', + status tinyint unsigned COMMENT '任务状态 0:暂停 1:正常', + remark varchar(255) DEFAULT NULL COMMENT '备注', + creator bigint COMMENT '创建者', + create_date datetime COMMENT '创建时间', + updater bigint COMMENT '更新者', + update_date datetime COMMENT '更新时间', + PRIMARY KEY (id), + key idx_create_date (create_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='定时任务'; + +-- 定时任务日志 +CREATE TABLE schedule_job_log ( + id bigint NOT NULL COMMENT 'id', + job_id bigint NOT NULL COMMENT '任务id', + bean_name varchar(200) DEFAULT NULL COMMENT 'spring bean名称', + params varchar(2000) DEFAULT NULL COMMENT '参数', + status tinyint unsigned NOT NULL COMMENT '任务状态 0:失败 1:成功', + error varchar(2000) DEFAULT NULL COMMENT '失败信息', + times int NOT NULL COMMENT '耗时(单位:毫秒)', + create_date datetime COMMENT '创建时间', + PRIMARY KEY (id), + key idx_job_id (job_id), + key idx_create_date (create_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志'; + +-- 系统用户Token +CREATE TABLE sys_user_token ( + id bigint NOT NULL COMMENT 'id', + user_id bigint NOT NULL COMMENT '用户id', + token varchar(100) NOT NULL COMMENT '用户token', + expire_date datetime COMMENT '过期时间', + update_date datetime COMMENT '更新时间', + create_date datetime COMMENT '创建时间', + PRIMARY KEY (id), + UNIQUE KEY user_id (user_id), + UNIQUE KEY token (token) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户Token'; + +-- 初始数据 +INSERT INTO sys_user(id, username, password, real_name, gender, email, mobile, status, dept_id, super_admin, creator, create_date, updater, update_date) VALUES (1067246875800000001, 'admin', '$2a$10$012Kx2ba5jzqr9gLlG4MX.bnQJTD9UWqF57XDo2N3.fPtLne02u/m', '管理员', 0, 'root@renren.io', '13612345678', 1, null, 1, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000002, 0, '权限管理', NULL, NULL, 0, 'icon-safetycertificate', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000003, 1067246875800000055, '新增', NULL, 'sys:user:save,sys:dept:list,sys:role:list', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000004, 1067246875800000055, '修改', NULL, 'sys:user:update,sys:dept:list,sys:role:list', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000005, 1067246875800000055, '删除', NULL, 'sys:user:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000006, 1067246875800000055, '导出', NULL, 'sys:user:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000007, 1067246875800000002, '角色管理', 'sys/role', NULL, 0, 'icon-team', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000008, 1067246875800000007, '查看', NULL, 'sys:role:page,sys:role:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000009, 1067246875800000007, '新增', NULL, 'sys:role:save,sys:menu:select,sys:dept:list', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000010, 1067246875800000007, '修改', NULL, 'sys:role:update,sys:menu:select,sys:dept:list', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000011, 1067246875800000007, '删除', NULL, 'sys:role:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000012, 1067246875800000002, '部门管理', 'sys/dept', NULL, 0, 'icon-apartment', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000014, 1067246875800000012, '查看', NULL, 'sys:dept:list,sys:dept:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000015, 1067246875800000012, '新增', NULL, 'sys:dept:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000016, 1067246875800000012, '修改', NULL, 'sys:dept:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000017, 1067246875800000012, '删除', NULL, 'sys:dept:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000025, 1067246875800000035, '菜单管理', 'sys/menu', NULL, 0, 'icon-unorderedlist', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000026, 1067246875800000025, '查看', NULL, 'sys:menu:list,sys:menu:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000027, 1067246875800000025, '新增', NULL, 'sys:menu:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000028, 1067246875800000025, '修改', NULL, 'sys:menu:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000029, 1067246875800000025, '删除', NULL, 'sys:menu:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000030, 1067246875800000035, '定时任务', 'job/schedule', NULL, 0, 'icon-dashboard', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000031, 1067246875800000030, '查看', NULL, 'sys:schedule:page,sys:schedule:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000032, 1067246875800000030, '新增', NULL, 'sys:schedule:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000033, 1067246875800000030, '修改', NULL, 'sys:schedule:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000034, 1067246875800000030, '删除', NULL, 'sys:schedule:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000035, 0, '系统设置', NULL, NULL, 0, 'icon-setting', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000036, 1067246875800000030, '暂停', NULL, 'sys:schedule:pause', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000037, 1067246875800000030, '恢复', NULL, 'sys:schedule:resume', 1, NULL, 5, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000038, 1067246875800000030, '立即执行', NULL, 'sys:schedule:run', 1, NULL, 6, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000039, 1067246875800000030, '日志列表', NULL, 'sys:schedule:log', 1, NULL, 7, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000040, 1067246875800000035, '参数管理', 'sys/params', '', 0, 'icon-fileprotect', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000041, 1067246875800000035, '字典管理', 'sys/dict-type', NULL, 0, 'icon-golden-fill', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000042, 1067246875800000041, '查看', NULL, 'sys:dict:page,sys:dict:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000043, 1067246875800000041, '新增', NULL, 'sys:dict:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000044, 1067246875800000041, '修改', NULL, 'sys:dict:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000045, 1067246875800000041, '删除', NULL, 'sys:dict:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000046, 0, '日志管理', NULL, NULL, 0, 'icon-container', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000047, 1067246875800000035, '文件上传', 'oss/oss', 'sys:oss:all', 0, 'icon-upload', 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000048, 1067246875800000046, '登录日志', 'sys/log-login', 'sys:log:login', 0, 'icon-filedone', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000049, 1067246875800000046, '操作日志', 'sys/log-operation', 'sys:log:operation', 0, 'icon-solution', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000050, 1067246875800000046, '异常日志', 'sys/log-error', 'sys:log:error', 0, 'icon-file-exception', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000051, 1067246875800000053, 'SQL监控', '{{ApiUrl}}/druid/sql.html', NULL, 0, 'icon-database', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000053, 0, '系统监控', NULL, NULL, 0, 'icon-desktop', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000055, 1067246875800000002, '用户管理', 'sys/user', NULL, 0, 'icon-user', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000056, 1067246875800000055, '查看', NULL, 'sys:user:page,sys:user:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000057, 1067246875800000040, '新增', NULL, 'sys:params:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000058, 1067246875800000040, '导出', NULL, 'sys:params:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000059, 1067246875800000040, '查看', '', 'sys:params:page,sys:params:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000060, 1067246875800000040, '修改', NULL, 'sys:params:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000061, 1067246875800000040, '删除', '', 'sys:params:delete', 1, '', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1156748733921165314, 1067246875800000053, '接口文档', '{{ApiUrl}}/doc.html', '', 0, 'icon-file-word', 1, 1067246875800000001, now(), 1067246875800000001, now()); + + +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000062, 1067246875800000063, '1067246875800000066,1067246875800000063', '技术部', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000063, 1067246875800000066, '1067246875800000066', '长沙分公司', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000064, 1067246875800000066, '1067246875800000066', '上海分公司', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000065, 1067246875800000064, '1067246875800000066,1067246875800000064', '市场部', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000066, 0, '0', '人人开源集团', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000067, 1067246875800000064, '1067246875800000066,1067246875800000064', '销售部', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000068, 1067246875800000063, '1067246875800000066,1067246875800000063', '产品部', 1, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1160061077912858625, 'gender', '性别', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061112075464705, 1160061077912858625, '男', '0', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061146967879681, 1160061077912858625, '女', '1', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061190127267841, 1160061077912858625, '保密', '2', '', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1225813644059140097, 'notice_type', '站内通知-类型', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814069634195457, 1225813644059140097, '公告', '0', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814107559092225, 1225813644059140097, '会议', '1', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814271879340034, 1225813644059140097, '其他', '2', '', 2, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_params(id, param_code, param_value, param_type, remark, creator, create_date, updater, update_date) VALUES (1067246875800000073, 'CLOUD_STORAGE_CONFIG_KEY', '{"type":1,"qiniuDomain":"http://test.oss.renren.io","qiniuPrefix":"upload","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","qiniuBucketName":"renren-oss","aliyunDomain":"","aliyunPrefix":"","aliyunEndPoint":"","aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qcloudBucketName":""}', '0', '云存储配置信息', 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO schedule_job (id, bean_name, params, cron_expression, status, remark, creator, create_date, updater, update_date) VALUES (1067246875800000076, 'testTask', 'renren', '0 0/30 * * * ?', 0, '有参测试,多个参数使用json', 1067246875800000001, now(), 1067246875800000001, now()); + + +-- quartz自带表结构 +CREATE TABLE QRTZ_JOB_DETAILS( + SCHED_NAME VARCHAR(120) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + JOB_CLASS_NAME VARCHAR(250) NOT NULL, + IS_DURABLE VARCHAR(1) NOT NULL, + IS_NONCONCURRENT VARCHAR(1) NOT NULL, + IS_UPDATE_DATA VARCHAR(1) NOT NULL, + REQUESTS_RECOVERY VARCHAR(1) NOT NULL, + JOB_DATA BLOB NULL, + PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + NEXT_FIRE_TIME BIGINT(13) NULL, + PREV_FIRE_TIME BIGINT(13) NULL, + PRIORITY INTEGER NULL, + TRIGGER_STATE VARCHAR(16) NOT NULL, + TRIGGER_TYPE VARCHAR(8) NOT NULL, + START_TIME BIGINT(13) NOT NULL, + END_TIME BIGINT(13) NULL, + CALENDAR_NAME VARCHAR(200) NULL, + MISFIRE_INSTR SMALLINT(2) NULL, + JOB_DATA BLOB NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) + REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_SIMPLE_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + REPEAT_COUNT BIGINT(7) NOT NULL, + REPEAT_INTERVAL BIGINT(12) NOT NULL, + TIMES_TRIGGERED BIGINT(10) NOT NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_CRON_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + CRON_EXPRESSION VARCHAR(120) NOT NULL, + TIME_ZONE_ID VARCHAR(80), + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_SIMPROP_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + STR_PROP_1 VARCHAR(512) NULL, + STR_PROP_2 VARCHAR(512) NULL, + STR_PROP_3 VARCHAR(512) NULL, + INT_PROP_1 INT NULL, + INT_PROP_2 INT NULL, + LONG_PROP_1 BIGINT NULL, + LONG_PROP_2 BIGINT NULL, + DEC_PROP_1 NUMERIC(13,4) NULL, + DEC_PROP_2 NUMERIC(13,4) NULL, + BOOL_PROP_1 VARCHAR(1) NULL, + BOOL_PROP_2 VARCHAR(1) NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_BLOB_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + BLOB_DATA BLOB NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_CALENDARS ( + SCHED_NAME VARCHAR(120) NOT NULL, + CALENDAR_NAME VARCHAR(200) NOT NULL, + CALENDAR BLOB NOT NULL, + PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_FIRED_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + ENTRY_ID VARCHAR(95) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + FIRED_TIME BIGINT(13) NOT NULL, + SCHED_TIME BIGINT(13) NOT NULL, + PRIORITY INTEGER NOT NULL, + STATE VARCHAR(16) NOT NULL, + JOB_NAME VARCHAR(200) NULL, + JOB_GROUP VARCHAR(200) NULL, + IS_NONCONCURRENT VARCHAR(1) NULL, + REQUESTS_RECOVERY VARCHAR(1) NULL, + PRIMARY KEY (SCHED_NAME,ENTRY_ID)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_SCHEDULER_STATE ( + SCHED_NAME VARCHAR(120) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + LAST_CHECKIN_TIME BIGINT(13) NOT NULL, + CHECKIN_INTERVAL BIGINT(13) NOT NULL, + PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE QRTZ_LOCKS ( + SCHED_NAME VARCHAR(120) NOT NULL, + LOCK_NAME VARCHAR(40) NOT NULL, + PRIMARY KEY (SCHED_NAME,LOCK_NAME)) + ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY); +CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP); + +CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME); +CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); +CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); + +CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME); +CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); +CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); +CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); \ No newline at end of file diff --git a/renren-admin/db/oracle.sql b/renren-admin/db/oracle.sql new file mode 100644 index 0000000..8f36a16 --- /dev/null +++ b/renren-admin/db/oracle.sql @@ -0,0 +1,684 @@ +CREATE TABLE sys_user ( + id NUMBER(20, 0) NOT NULL, + username varchar2(50) NOT NULL, + password varchar2(100), + real_name varchar2(50), + head_url varchar2(200), + gender NUMBER(2, 0), + email varchar2(100), + mobile varchar2(100), + dept_id NUMBER(20, 0), + super_admin NUMBER(2, 0), + status NUMBER(2, 0), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); + +CREATE UNIQUE INDEX uk_sys_user_username on sys_user(username); +CREATE INDEX idx_sys_user_create_date on sys_user(create_date); + +COMMENT ON TABLE sys_user IS '用户管理'; +COMMENT ON COLUMN sys_user.id IS 'id'; +COMMENT ON COLUMN sys_user.username IS '用户名'; +COMMENT ON COLUMN sys_user.password IS '密码'; +COMMENT ON COLUMN sys_user.real_name IS '姓名'; +COMMENT ON COLUMN sys_user.head_url IS '头像'; +COMMENT ON COLUMN sys_user.gender IS '性别 0:男 1:女 2:保密'; +COMMENT ON COLUMN sys_user.email IS '邮箱'; +COMMENT ON COLUMN sys_user.mobile IS '手机号'; +COMMENT ON COLUMN sys_user.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_user.super_admin IS '超级管理员 0:否 1:是'; +COMMENT ON COLUMN sys_user.status IS '状态 0:停用 1:正常'; +COMMENT ON COLUMN sys_user.creator IS '创建者'; +COMMENT ON COLUMN sys_user.create_date IS '创建时间'; +COMMENT ON COLUMN sys_user.updater IS '更新者'; +COMMENT ON COLUMN sys_user.update_date IS '更新时间'; + + +CREATE TABLE sys_dept ( + id NUMBER(20, 0) NOT NULL, + pid NUMBER(20, 0), + pids varchar2(500), + name varchar2(50), + sort NUMBER(10, 0), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); +CREATE INDEX idx_sys_dept_pid on sys_dept(pid); +CREATE INDEX idx_sys_dept_idx_sort on sys_dept(sort); + +COMMENT ON TABLE sys_dept IS '部门管理'; +COMMENT ON COLUMN sys_dept.id IS 'id'; +COMMENT ON COLUMN sys_dept.pid IS '上级ID'; +COMMENT ON COLUMN sys_dept.pids IS '所有上级ID,用逗号分开'; +COMMENT ON COLUMN sys_dept.name IS '部门名称'; +COMMENT ON COLUMN sys_dept.sort IS '排序'; +COMMENT ON COLUMN sys_dept.creator IS '创建者'; +COMMENT ON COLUMN sys_dept.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dept.updater IS '更新者'; +COMMENT ON COLUMN sys_dept.update_date IS '更新时间'; + + +create table sys_role +( + id NUMBER(20, 0) NOT NULL, + name varchar2(32), + remark varchar2(100), + dept_id NUMBER(20, 0), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); + +CREATE INDEX idx_sys_role_dept_id on sys_role(dept_id); + +COMMENT ON TABLE sys_role IS '角色管理'; +COMMENT ON COLUMN sys_role.id IS 'id'; +COMMENT ON COLUMN sys_role.name IS '角色名称'; +COMMENT ON COLUMN sys_role.remark IS '备注'; +COMMENT ON COLUMN sys_role.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_role.creator IS '创建者'; +COMMENT ON COLUMN sys_role.create_date IS '创建时间'; +COMMENT ON COLUMN sys_role.updater IS '更新者'; +COMMENT ON COLUMN sys_role.update_date IS '更新时间'; + + +create table sys_menu +( + id NUMBER(20, 0) NOT NULL, + pid NUMBER(20, 0), + name varchar2(200), + url varchar2(200), + permissions varchar2(500), + menu_type NUMBER(2, 0), + icon varchar2(50), + sort NUMBER(10, 0), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); + +CREATE INDEX idx_sys_menu_pid on sys_menu(pid); +CREATE INDEX idx_sys_menu_sort on sys_menu(sort); + +COMMENT ON TABLE sys_menu IS '菜单管理'; +COMMENT ON COLUMN sys_menu.id IS 'id'; +COMMENT ON COLUMN sys_menu.pid IS '上级ID,一级菜单为0'; +COMMENT ON COLUMN sys_menu.name IS '名称'; +COMMENT ON COLUMN sys_menu.url IS '菜单URL'; +COMMENT ON COLUMN sys_menu.permissions IS '授权(多个用逗号分隔,如:sys:user:list,sys:user:save)'; +COMMENT ON COLUMN sys_menu.menu_type IS '类型 0:菜单 1:按钮'; +COMMENT ON COLUMN sys_menu.icon IS '菜单图标'; +COMMENT ON COLUMN sys_menu.sort IS '排序'; +COMMENT ON COLUMN sys_menu.creator IS '创建者'; +COMMENT ON COLUMN sys_menu.create_date IS '创建时间'; +COMMENT ON COLUMN sys_menu.updater IS '更新者'; +COMMENT ON COLUMN sys_menu.update_date IS '更新时间'; + + +create table sys_role_user +( + id varchar2(32) NOT NULL, + role_id varchar2(32), + user_id varchar2(32), + creator varchar2(32), + create_date date, + primary key (id) +); + +CREATE INDEX idx_sys_role_user_role_id on sys_role_user(role_id); +CREATE INDEX idx_sys_role_user_user_id on sys_role_user(user_id); + +COMMENT ON TABLE sys_role_user IS '角色用户关系'; +COMMENT ON COLUMN sys_role_user.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_user.user_id IS '用户ID'; +COMMENT ON COLUMN sys_role_user.creator IS '创建者'; +COMMENT ON COLUMN sys_role_user.create_date IS '创建时间'; + + +create table sys_role_menu +( + id NUMBER(20, 0) NOT NULL, + role_id NUMBER(20, 0), + menu_id NUMBER(20, 0), + creator NUMBER(20, 0), + create_date date, + primary key (id) +); + +CREATE INDEX idx_sys_role_menu_role_id on sys_role_menu(role_id); +CREATE INDEX idx_sys_role_menu_menu_id on sys_role_menu(menu_id); + +COMMENT ON TABLE sys_role_menu IS '角色菜单关系'; +COMMENT ON COLUMN sys_role_menu.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_menu.menu_id IS '菜单ID'; +COMMENT ON COLUMN sys_role_menu.creator IS '创建者'; +COMMENT ON COLUMN sys_role_menu.create_date IS '创建时间'; + + +create table sys_role_data_scope +( + id NUMBER(20, 0) NOT NULL, + role_id NUMBER(20, 0), + dept_id NUMBER(20, 0), + creator NUMBER(20, 0), + create_date date, + primary key (id) +); +CREATE INDEX idx_data_scope_role_id on sys_role_data_scope(role_id); + +COMMENT ON TABLE sys_role_data_scope IS '角色数据权限'; +COMMENT ON COLUMN sys_role_data_scope.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_data_scope.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_role_data_scope.creator IS '创建者'; +COMMENT ON COLUMN sys_role_data_scope.create_date IS '创建时间'; + + +create table sys_params +( + id NUMBER(20, 0) NOT NULL, + param_code varchar2(32), + param_value varchar2(2000), + param_type NUMBER(2, 0) DEFAULT 1 NOT NULL, + remark varchar2(200), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_params_param_code on sys_params(param_code); +CREATE INDEX idx_sys_params_create_date on sys_params(create_date); + +COMMENT ON TABLE sys_params IS '参数管理'; +COMMENT ON COLUMN sys_params.param_code IS '参数编码'; +COMMENT ON COLUMN sys_params.param_value IS '参数值'; +COMMENT ON COLUMN sys_params.param_type IS '类型 0:系统参数 1:非系统参数'; +COMMENT ON COLUMN sys_params.remark IS '备注'; +COMMENT ON COLUMN sys_params.creator IS '创建者'; +COMMENT ON COLUMN sys_params.create_date IS '创建时间'; +COMMENT ON COLUMN sys_params.updater IS '更新者'; +COMMENT ON COLUMN sys_params.update_date IS '更新时间'; + + +create table sys_dict_type +( + id NUMBER(20, 0) NOT NULL, + dict_type varchar2(100), + dict_name varchar2(255), + remark varchar2(255), + sort NUMBER(10, 0), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_dict_type_dict_type on sys_dict_type(dict_type); + +COMMENT ON TABLE sys_dict_type IS '字典类型'; +COMMENT ON COLUMN sys_dict_type.id IS 'id'; +COMMENT ON COLUMN sys_dict_type.dict_type IS '字典类型'; +COMMENT ON COLUMN sys_dict_type.dict_name IS '字典名称'; +COMMENT ON COLUMN sys_dict_type.remark IS '备注'; +COMMENT ON COLUMN sys_dict_type.sort IS '排序'; +COMMENT ON COLUMN sys_dict_type.creator IS '创建者'; +COMMENT ON COLUMN sys_dict_type.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dict_type.updater IS '更新者'; +COMMENT ON COLUMN sys_dict_type.update_date IS '更新时间'; + +create table sys_dict_data +( + id NUMBER(20, 0) NOT NULL, + dict_type_id NUMBER(20, 0) NOT NULL, + dict_label varchar2(255), + dict_value varchar2(255), + remark varchar2(255), + sort NUMBER(10, 0), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + primary key (id) +); +CREATE INDEX idx_sys_dict_data_sort on sys_dict_data(sort); +CREATE UNIQUE INDEX uk_dict_type_value on sys_dict_data(dict_type_id, dict_value); + +COMMENT ON TABLE sys_dict_data IS '字典数据'; +COMMENT ON COLUMN sys_dict_data.id IS 'id'; +COMMENT ON COLUMN sys_dict_data.dict_type_id IS '字典类型ID'; +COMMENT ON COLUMN sys_dict_data.dict_label IS '字典标签'; +COMMENT ON COLUMN sys_dict_data.dict_value IS '字典值'; +COMMENT ON COLUMN sys_dict_data.remark IS '备注'; +COMMENT ON COLUMN sys_dict_data.sort IS '排序'; +COMMENT ON COLUMN sys_dict_data.creator IS '创建者'; +COMMENT ON COLUMN sys_dict_data.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dict_data.updater IS '更新者'; +COMMENT ON COLUMN sys_dict_data.update_date IS '更新时间'; + +create table sys_log_login +( + id NUMBER(20, 0) NOT NULL, + operation NUMBER(2, 0), + status NUMBER(2, 0), + user_agent varchar2(500), + ip varchar2(32), + creator_name varchar2(50), + creator NUMBER(20, 0), + create_date date, + primary key (id) +); +CREATE INDEX idx_login_status on sys_log_login(status); +CREATE INDEX idx_login_create_date on sys_log_login(create_date); + +COMMENT ON TABLE sys_log_login IS '登录日志'; +COMMENT ON COLUMN sys_log_login.id IS 'id'; +COMMENT ON COLUMN sys_log_login.operation IS '用户操作 0:用户登录 1:用户退出'; +COMMENT ON COLUMN sys_log_login.status IS '状态 0:失败 1:成功 2:账号已锁定'; +COMMENT ON COLUMN sys_log_login.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_login.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_login.creator_name IS '用户名'; +COMMENT ON COLUMN sys_log_login.creator IS '创建者'; +COMMENT ON COLUMN sys_log_login.create_date IS '创建时间'; + + +create table sys_log_operation +( + id NUMBER(20, 0) NOT NULL, + operation varchar2(50), + request_uri varchar2(200), + request_method varchar2(20), + request_params clob, + request_time NUMBER(10, 0), + user_agent varchar2(500), + ip varchar2(32), + status NUMBER(2, 0), + creator_name varchar2(50), + creator NUMBER(20, 0), + create_date date, + primary key (id) +); +CREATE INDEX idx_operation_create_date on sys_log_operation(create_date); + +COMMENT ON TABLE sys_log_operation IS '操作日志'; +COMMENT ON COLUMN sys_log_operation.id IS 'id'; +COMMENT ON COLUMN sys_log_operation.operation IS '用户操作'; +COMMENT ON COLUMN sys_log_operation.request_uri IS '请求URI'; +COMMENT ON COLUMN sys_log_operation.request_method IS '请求方式'; +COMMENT ON COLUMN sys_log_operation.request_params IS '请求参数'; +COMMENT ON COLUMN sys_log_operation.request_time IS '请求时长(毫秒)'; +COMMENT ON COLUMN sys_log_operation.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_operation.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_operation.status IS '状态 0:失败 1:成功'; +COMMENT ON COLUMN sys_log_operation.creator_name IS '用户名'; +COMMENT ON COLUMN sys_log_operation.creator IS '创建者'; +COMMENT ON COLUMN sys_log_operation.create_date IS '创建时间'; + + +create table sys_log_error +( + id NUMBER(20, 0) NOT NULL, + request_uri varchar2(200), + request_method varchar2(20), + request_params clob, + user_agent varchar2(500), + ip varchar2(32), + error_info clob, + creator NUMBER(20, 0), + create_date date, + primary key (id) +); +CREATE INDEX idx_error_create_date on sys_log_error(create_date); + +COMMENT ON TABLE sys_log_error IS '异常日志'; +COMMENT ON COLUMN sys_log_error.id IS 'id'; +COMMENT ON COLUMN sys_log_error.request_uri IS '请求URI'; +COMMENT ON COLUMN sys_log_error.request_method IS '请求方式'; +COMMENT ON COLUMN sys_log_error.request_params IS '请求参数'; +COMMENT ON COLUMN sys_log_error.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_error.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_error.error_info IS '异常信息'; +COMMENT ON COLUMN sys_log_error.creator IS '创建者'; +COMMENT ON COLUMN sys_log_error.create_date IS '创建时间'; + + +CREATE TABLE sys_oss ( + id NUMBER(20, 0) NOT NULL, + url varchar2(200), + creator NUMBER(20, 0), + create_date date, + PRIMARY KEY (id) +); +CREATE INDEX idx_sys_oss_create_date on sys_oss(create_date); + +COMMENT ON TABLE sys_oss IS '文件上传'; +COMMENT ON COLUMN sys_oss.id IS 'id'; +COMMENT ON COLUMN sys_oss.url IS 'URL地址'; +COMMENT ON COLUMN sys_mail_log.creator IS '创建者'; +COMMENT ON COLUMN sys_mail_log.create_date IS '创建时间'; + + +CREATE TABLE schedule_job ( + id NUMBER(20, 0) NOT NULL, + bean_name varchar2(200), + params varchar2(2000), + cron_expression varchar2(100), + status NUMBER(2, 0), + remark varchar2(255), + creator NUMBER(20, 0), + create_date date, + updater NUMBER(20, 0), + update_date date, + PRIMARY KEY (id) +); + +CREATE INDEX idx_schedule_job_create_date on schedule_job(create_date); + +COMMENT ON TABLE schedule_job IS '定时任务'; +COMMENT ON COLUMN schedule_job.id IS 'id'; +COMMENT ON COLUMN schedule_job.bean_name IS 'spring bean名称'; +COMMENT ON COLUMN schedule_job.params IS '参数'; +COMMENT ON COLUMN schedule_job.cron_expression IS 'cron表达式'; +COMMENT ON COLUMN schedule_job.status IS '任务状态 0:暂停 1:正常'; +COMMENT ON COLUMN schedule_job.remark IS '备注'; +COMMENT ON COLUMN schedule_job.creator IS '创建者'; +COMMENT ON COLUMN schedule_job.create_date IS '创建时间'; +COMMENT ON COLUMN schedule_job.updater IS '更新者'; +COMMENT ON COLUMN schedule_job.update_date IS '更新时间'; + + +CREATE TABLE schedule_job_log ( + id NUMBER(20, 0) NOT NULL, + job_id NUMBER(20, 0) NOT NULL, + bean_name varchar2(200), + params varchar2(2000), + status NUMBER(2, 0), + error varchar2(2000), + times NUMBER(10, 0), + create_date date, + PRIMARY KEY (id) +); + +CREATE INDEX idx_job_log_job_id on schedule_job_log(job_id); +CREATE INDEX idx_job_log_create_date on schedule_job_log(create_date); + +COMMENT ON TABLE schedule_job_log IS '定时任务日志'; +COMMENT ON COLUMN schedule_job_log.id IS 'id'; +COMMENT ON COLUMN schedule_job_log.bean_name IS 'spring bean名称'; +COMMENT ON COLUMN schedule_job_log.params IS '参数'; +COMMENT ON COLUMN schedule_job_log.status IS '任务状态 0:失败 1:成功'; +COMMENT ON COLUMN schedule_job_log.error IS '失败信息'; +COMMENT ON COLUMN schedule_job_log.times IS '耗时(单位:毫秒)'; +COMMENT ON COLUMN schedule_job.create_date IS '创建时间'; + + +CREATE TABLE sys_user_token ( + id NUMBER(20, 0) NOT NULL, + user_id NUMBER(20, 0), + token varchar2(100), + expire_date date, + update_date date, + create_date date, + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX uk_sys_user_token_user_id on sys_user_token(user_id); +CREATE UNIQUE INDEX uk_sys_user_token on sys_user_token(token); + +COMMENT ON TABLE sys_user_token IS '系统用户Token'; +COMMENT ON COLUMN sys_user_token.id IS 'id'; +COMMENT ON COLUMN sys_user_token.user_id IS '用户id'; +COMMENT ON COLUMN sys_user_token.token IS '用户token'; +COMMENT ON COLUMN sys_user_token.expire_date IS '过期时间'; +COMMENT ON COLUMN sys_user_token.update_date IS '更新时间'; +COMMENT ON COLUMN sys_user_token.create_date IS '创建时间'; + + + +-- 初始数据 +INSERT INTO sys_user(id, username, password, real_name, gender, email, mobile, status, dept_id, super_admin, creator, create_date, updater, update_date) VALUES (1067246875800000001, 'admin', '$2a$10$012Kx2ba5jzqr9gLlG4MX.bnQJTD9UWqF57XDo2N3.fPtLne02u/m', '管理员', 0, 'root@renren.io', '13612345678', 1, null, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); + +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000002, 0, '权限管理', NULL, NULL, 0, 'icon-safetycertificate', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000003, 1067246875800000055, '新增', NULL, 'sys:user:save,sys:dept:list,sys:role:list', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000004, 1067246875800000055, '修改', NULL, 'sys:user:update,sys:dept:list,sys:role:list', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000005, 1067246875800000055, '删除', NULL, 'sys:user:delete', 1, NULL, 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000006, 1067246875800000055, '导出', NULL, 'sys:user:export', 1, NULL, 4, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000007, 1067246875800000002, '角色管理', 'sys/role', NULL, 0, 'icon-team', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000008, 1067246875800000007, '查看', NULL, 'sys:role:page,sys:role:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000009, 1067246875800000007, '新增', NULL, 'sys:role:save,sys:menu:select,sys:dept:list', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000010, 1067246875800000007, '修改', NULL, 'sys:role:update,sys:menu:select,sys:dept:list', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000011, 1067246875800000007, '删除', NULL, 'sys:role:delete', 1, NULL, 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000012, 1067246875800000002, '部门管理', 'sys/dept', NULL, 0, 'icon-apartment', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000014, 1067246875800000012, '查看', NULL, 'sys:dept:list,sys:dept:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000015, 1067246875800000012, '新增', NULL, 'sys:dept:save', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000016, 1067246875800000012, '修改', NULL, 'sys:dept:update', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000017, 1067246875800000012, '删除', NULL, 'sys:dept:delete', 1, NULL, 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000025, 1067246875800000035, '菜单管理', 'sys/menu', NULL, 0, 'icon-unorderedlist', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000026, 1067246875800000025, '查看', NULL, 'sys:menu:list,sys:menu:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000027, 1067246875800000025, '新增', NULL, 'sys:menu:save', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000028, 1067246875800000025, '修改', NULL, 'sys:menu:update', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000029, 1067246875800000025, '删除', NULL, 'sys:menu:delete', 1, NULL, 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000030, 1067246875800000035, '定时任务', 'job/schedule', NULL, 0, 'icon-dashboard', 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000031, 1067246875800000030, '查看', NULL, 'sys:schedule:page,sys:schedule:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000032, 1067246875800000030, '新增', NULL, 'sys:schedule:save', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000033, 1067246875800000030, '修改', NULL, 'sys:schedule:update', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000034, 1067246875800000030, '删除', NULL, 'sys:schedule:delete', 1, NULL, 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000035, 0, '系统设置', NULL, NULL, 0, 'icon-setting', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000036, 1067246875800000030, '暂停', NULL, 'sys:schedule:pause', 1, NULL, 4, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000037, 1067246875800000030, '恢复', NULL, 'sys:schedule:resume', 1, NULL, 5, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000038, 1067246875800000030, '立即执行', NULL, 'sys:schedule:run', 1, NULL, 6, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000039, 1067246875800000030, '日志列表', NULL, 'sys:schedule:log', 1, NULL, 7, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000040, 1067246875800000035, '参数管理', 'sys/params', '', 0, 'icon-fileprotect', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000041, 1067246875800000035, '字典管理', 'sys/dict-type', NULL, 0, 'icon-golden-fill', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000042, 1067246875800000041, '查看', NULL, 'sys:dict:page,sys:dict:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000043, 1067246875800000041, '新增', NULL, 'sys:dict:save', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000044, 1067246875800000041, '修改', NULL, 'sys:dict:update', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000045, 1067246875800000041, '删除', NULL, 'sys:dict:delete', 1, NULL, 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000046, 0, '日志管理', NULL, NULL, 0, 'icon-container', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000047, 1067246875800000035, '文件上传', 'oss/oss', 'sys:oss:all', 0, 'icon-upload', 4, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000048, 1067246875800000046, '登录日志', 'sys/log-login', 'sys:log:login', 0, 'icon-filedone', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000049, 1067246875800000046, '操作日志', 'sys/log-operation', 'sys:log:operation', 0, 'icon-solution', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000050, 1067246875800000046, '异常日志', 'sys/log-error', 'sys:log:error', 0, 'icon-file-exception', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000051, 1067246875800000053, 'SQL监控', '{{ApiUrl}}/druid/sql.html', NULL, 0, 'icon-database', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000053, 0, '系统监控', NULL, NULL, 0, 'icon-desktop', 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000055, 1067246875800000002, '用户管理', 'sys/user', NULL, 0, 'icon-user', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000056, 1067246875800000055, '查看', NULL, 'sys:user:page,sys:user:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000057, 1067246875800000040, '新增', NULL, 'sys:params:save', 1, NULL, 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000058, 1067246875800000040, '导出', NULL, 'sys:params:export', 1, NULL, 4, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000059, 1067246875800000040, '查看', '', 'sys:params:page,sys:params:info', 1, NULL, 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000060, 1067246875800000040, '修改', NULL, 'sys:params:update', 1, NULL, 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000061, 1067246875800000040, '删除', '', 'sys:params:delete', 1, '', 3, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1156748733921165314, 1067246875800000053, '接口文档', '{{ApiUrl}}/doc.html', '', 0, 'icon-file-word', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); + + +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000062, 1067246875800000063, '1067246875800000066,1067246875800000063', '技术部', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000063, 1067246875800000066, '1067246875800000066', '长沙分公司', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000064, 1067246875800000066, '1067246875800000066', '上海分公司', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000065, 1067246875800000064, '1067246875800000066,1067246875800000064', '市场部', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000066, 0, '0', '人人开源集团', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000067, 1067246875800000064, '1067246875800000066,1067246875800000064', '销售部', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000068, 1067246875800000063, '1067246875800000066,1067246875800000063', '产品部', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); + +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1160061077912858625, 'gender', '性别', '', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061112075464705, 1160061077912858625, '男', '0', '', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061146967879681, 1160061077912858625, '女', '1', '', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061190127267841, 1160061077912858625, '保密', '2', '', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1225813644059140097, 'notice_type', '站内通知-类型', '', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814069634195457, 1225813644059140097, '公告', '0', '', 0, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814107559092225, 1225813644059140097, '会议', '1', '', 1, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814271879340034, 1225813644059140097, '其他', '2', '', 2, 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); + +INSERT INTO sys_params(id, param_code, param_value, param_type, remark, creator, create_date, updater, update_date) VALUES (1067246875800000073, 'CLOUD_STORAGE_CONFIG_KEY', '{"type":1,"qiniuDomain":"http://test.oss.renren.io","qiniuPrefix":"upload","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","qiniuBucketName":"renren-oss","aliyunDomain":"","aliyunPrefix":"","aliyunEndPoint":"","aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qcloudBucketName":""}', '0', '云存储配置信息', 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); + +INSERT INTO schedule_job (id, bean_name, params, cron_expression, status, remark, creator, create_date, updater, update_date) VALUES (1067246875800000076, 'testTask', 'renren', '0 0/30 * * * ?', 0, '有参测试,多个参数使用json', 1067246875800000001, CURRENT_DATE, 1067246875800000001, CURRENT_DATE); + + +-- quartz自带表结构 +CREATE TABLE qrtz_job_details +( + SCHED_NAME VARCHAR2(120) NOT NULL, + JOB_NAME VARCHAR2(200) NOT NULL, + JOB_GROUP VARCHAR2(200) NOT NULL, + DESCRIPTION VARCHAR2(250) NULL, + JOB_CLASS_NAME VARCHAR2(250) NOT NULL, + IS_DURABLE VARCHAR2(1) NOT NULL, + IS_NONCONCURRENT VARCHAR2(1) NOT NULL, + IS_UPDATE_DATA VARCHAR2(1) NOT NULL, + REQUESTS_RECOVERY VARCHAR2(1) NOT NULL, + JOB_DATA BLOB NULL, + CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) +); +CREATE TABLE qrtz_triggers +( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + JOB_NAME VARCHAR2(200) NOT NULL, + JOB_GROUP VARCHAR2(200) NOT NULL, + DESCRIPTION VARCHAR2(250) NULL, + NEXT_FIRE_TIME NUMBER(13) NULL, + PREV_FIRE_TIME NUMBER(13) NULL, + PRIORITY NUMBER(13) NULL, + TRIGGER_STATE VARCHAR2(16) NOT NULL, + TRIGGER_TYPE VARCHAR2(8) NOT NULL, + START_TIME NUMBER(13) NOT NULL, + END_TIME NUMBER(13) NULL, + CALENDAR_NAME VARCHAR2(200) NULL, + MISFIRE_INSTR NUMBER(2) NULL, + JOB_DATA BLOB NULL, + CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) + REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) +); +CREATE TABLE qrtz_simple_triggers +( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + REPEAT_COUNT NUMBER(7) NOT NULL, + REPEAT_INTERVAL NUMBER(12) NOT NULL, + TIMES_TRIGGERED NUMBER(10) NOT NULL, + CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_cron_triggers +( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + CRON_EXPRESSION VARCHAR2(120) NOT NULL, + TIME_ZONE_ID VARCHAR2(80), + CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_simprop_triggers +( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + STR_PROP_1 VARCHAR2(512) NULL, + STR_PROP_2 VARCHAR2(512) NULL, + STR_PROP_3 VARCHAR2(512) NULL, + INT_PROP_1 NUMBER(10) NULL, + INT_PROP_2 NUMBER(10) NULL, + LONG_PROP_1 NUMBER(13) NULL, + LONG_PROP_2 NUMBER(13) NULL, + DEC_PROP_1 NUMERIC(13,4) NULL, + DEC_PROP_2 NUMERIC(13,4) NULL, + BOOL_PROP_1 VARCHAR2(1) NULL, + BOOL_PROP_2 VARCHAR2(1) NULL, + CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_blob_triggers +( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + BLOB_DATA BLOB NULL, + CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_calendars +( + SCHED_NAME VARCHAR2(120) NOT NULL, + CALENDAR_NAME VARCHAR2(200) NOT NULL, + CALENDAR BLOB NOT NULL, + CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) +); +CREATE TABLE qrtz_paused_trigger_grps +( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_fired_triggers +( + SCHED_NAME VARCHAR2(120) NOT NULL, + ENTRY_ID VARCHAR2(95) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + INSTANCE_NAME VARCHAR2(200) NOT NULL, + FIRED_TIME NUMBER(13) NOT NULL, + SCHED_TIME NUMBER(13) NOT NULL, + PRIORITY NUMBER(13) NOT NULL, + STATE VARCHAR2(16) NOT NULL, + JOB_NAME VARCHAR2(200) NULL, + JOB_GROUP VARCHAR2(200) NULL, + IS_NONCONCURRENT VARCHAR2(1) NULL, + REQUESTS_RECOVERY VARCHAR2(1) NULL, + CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID) +); +CREATE TABLE qrtz_scheduler_state +( + SCHED_NAME VARCHAR2(120) NOT NULL, + INSTANCE_NAME VARCHAR2(200) NOT NULL, + LAST_CHECKIN_TIME NUMBER(13) NOT NULL, + CHECKIN_INTERVAL NUMBER(13) NOT NULL, + CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) +); +CREATE TABLE qrtz_locks +( + SCHED_NAME VARCHAR2(120) NOT NULL, + LOCK_NAME VARCHAR2(40) NOT NULL, + CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME) +); + +create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); +create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); + +create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); +create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); +create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); +create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); +create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); +create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); +create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); +create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); +create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); + +create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); +create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); +create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); +create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); +create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); +create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP); + + diff --git a/renren-admin/db/postgresql.sql b/renren-admin/db/postgresql.sql new file mode 100644 index 0000000..b4f928d --- /dev/null +++ b/renren-admin/db/postgresql.sql @@ -0,0 +1,699 @@ +CREATE TABLE sys_user ( + id int8 NOT NULL, + username varchar(50) NOT NULL, + password varchar(100), + real_name varchar(50), + head_url varchar(200), + gender int, + email varchar(100), + mobile varchar(100), + dept_id int8, + super_admin int, + status int, + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); + +CREATE UNIQUE INDEX uk_sys_user_username on sys_user(username); +CREATE INDEX idx_sys_user_create_date on sys_user(create_date); + +COMMENT ON TABLE sys_user IS '用户管理'; +COMMENT ON COLUMN sys_user.id IS 'id'; +COMMENT ON COLUMN sys_user.username IS '用户名'; +COMMENT ON COLUMN sys_user.password IS '密码'; +COMMENT ON COLUMN sys_user.real_name IS '姓名'; +COMMENT ON COLUMN sys_user.head_url IS '头像'; +COMMENT ON COLUMN sys_user.gender IS '性别 0:男 1:女 2:保密'; +COMMENT ON COLUMN sys_user.email IS '邮箱'; +COMMENT ON COLUMN sys_user.mobile IS '手机号'; +COMMENT ON COLUMN sys_user.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_user.super_admin IS '超级管理员 0:否 1:是'; +COMMENT ON COLUMN sys_user.status IS '状态 0:停用 1:正常'; +COMMENT ON COLUMN sys_user.creator IS '创建者'; +COMMENT ON COLUMN sys_user.create_date IS '创建时间'; +COMMENT ON COLUMN sys_user.updater IS '更新者'; +COMMENT ON COLUMN sys_user.update_date IS '更新时间'; + + +CREATE TABLE sys_dept ( + id int8 NOT NULL, + pid int8, + pids varchar(500), + name varchar(50), + sort int, + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); +CREATE INDEX idx_sys_dept_pid on sys_dept(pid); +CREATE INDEX idx_sys_dept_idx_sort on sys_dept(sort); + +COMMENT ON TABLE sys_dept IS '部门管理'; +COMMENT ON COLUMN sys_dept.id IS 'id'; +COMMENT ON COLUMN sys_dept.pid IS '上级ID'; +COMMENT ON COLUMN sys_dept.pids IS '所有上级ID,用逗号分开'; +COMMENT ON COLUMN sys_dept.name IS '部门名称'; +COMMENT ON COLUMN sys_dept.sort IS '排序'; +COMMENT ON COLUMN sys_dept.creator IS '创建者'; +COMMENT ON COLUMN sys_dept.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dept.updater IS '更新者'; +COMMENT ON COLUMN sys_dept.update_date IS '更新时间'; + + +create table sys_role +( + id int8 NOT NULL, + name varchar(50), + remark varchar(100), + dept_id int8, + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); + +CREATE INDEX idx_sys_role_dept_id on sys_role(dept_id); + +COMMENT ON TABLE sys_role IS '角色管理'; +COMMENT ON COLUMN sys_role.id IS 'id'; +COMMENT ON COLUMN sys_role.name IS '角色名称'; +COMMENT ON COLUMN sys_role.remark IS '备注'; +COMMENT ON COLUMN sys_role.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_role.creator IS '创建者'; +COMMENT ON COLUMN sys_role.create_date IS '创建时间'; +COMMENT ON COLUMN sys_role.updater IS '更新者'; +COMMENT ON COLUMN sys_role.update_date IS '更新时间'; + + +create table sys_menu +( + id int8 NOT NULL, + pid int8, + name varchar(200), + url varchar(200), + permissions varchar(500), + menu_type int, + icon varchar(50), + sort int, + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); + +CREATE INDEX idx_sys_menu_pid on sys_menu(pid); +CREATE INDEX idx_sys_menu_sort on sys_menu(sort); + +COMMENT ON TABLE sys_menu IS '菜单管理'; +COMMENT ON COLUMN sys_menu.id IS 'id'; +COMMENT ON COLUMN sys_menu.pid IS '上级ID,一级菜单为0'; +COMMENT ON COLUMN sys_menu.name IS '名称'; +COMMENT ON COLUMN sys_menu.url IS '菜单URL'; +COMMENT ON COLUMN sys_menu.permissions IS '授权(多个用逗号分隔,如:sys:user:list,sys:user:save)'; +COMMENT ON COLUMN sys_menu.menu_type IS '类型 0:菜单 1:按钮'; +COMMENT ON COLUMN sys_menu.icon IS '菜单图标'; +COMMENT ON COLUMN sys_menu.sort IS '排序'; +COMMENT ON COLUMN sys_menu.creator IS '创建者'; +COMMENT ON COLUMN sys_menu.create_date IS '创建时间'; +COMMENT ON COLUMN sys_menu.updater IS '更新者'; +COMMENT ON COLUMN sys_menu.update_date IS '更新时间'; + + +create table sys_role_user +( + id int8 NOT NULL, + role_id int8, + user_id int8, + creator int8, + create_date timestamp, + primary key (id) +); + +CREATE INDEX idx_sys_role_user_role_id on sys_role_user(role_id); +CREATE INDEX idx_sys_role_user_user_id on sys_role_user(user_id); + +COMMENT ON TABLE sys_role_user IS '角色用户关系'; +COMMENT ON COLUMN sys_role_user.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_user.user_id IS '用户ID'; +COMMENT ON COLUMN sys_role_user.creator IS '创建者'; +COMMENT ON COLUMN sys_role_user.create_date IS '创建时间'; + + +create table sys_role_menu +( + id int8 NOT NULL, + role_id int8, + menu_id int8, + creator int8, + create_date timestamp, + primary key (id) +); + +CREATE INDEX idx_sys_role_menu_role_id on sys_role_menu(role_id); +CREATE INDEX idx_sys_role_menu_menu_id on sys_role_menu(menu_id); + +COMMENT ON TABLE sys_role_menu IS '角色菜单关系'; +COMMENT ON COLUMN sys_role_menu.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_menu.menu_id IS '菜单ID'; +COMMENT ON COLUMN sys_role_menu.creator IS '创建者'; +COMMENT ON COLUMN sys_role_menu.create_date IS '创建时间'; + + +create table sys_role_data_scope +( + id int8 NOT NULL, + role_id int8, + dept_id int8, + creator int8, + create_date timestamp, + primary key (id) +); +CREATE INDEX idx_data_scope_role_id on sys_role_data_scope(role_id); + +COMMENT ON TABLE sys_role_data_scope IS '角色数据权限'; +COMMENT ON COLUMN sys_role_data_scope.role_id IS '角色ID'; +COMMENT ON COLUMN sys_role_data_scope.dept_id IS '部门ID'; +COMMENT ON COLUMN sys_role_data_scope.creator IS '创建者'; +COMMENT ON COLUMN sys_role_data_scope.create_date IS '创建时间'; + + +create table sys_params +( + id int8 NOT NULL, + param_code varchar(32), + param_value varchar(2000), + param_type int DEFAULT 1 NOT NULL, + remark varchar(200), + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_params_param_code on sys_params(param_code); +CREATE INDEX idx_sys_params_create_date on sys_params(create_date); + +COMMENT ON TABLE sys_params IS '参数管理'; +COMMENT ON COLUMN sys_params.param_code IS '参数编码'; +COMMENT ON COLUMN sys_params.param_value IS '参数值'; +COMMENT ON COLUMN sys_params.param_type IS '类型 0:系统参数 1:非系统参数'; +COMMENT ON COLUMN sys_params.remark IS '备注'; +COMMENT ON COLUMN sys_params.creator IS '创建者'; +COMMENT ON COLUMN sys_params.create_date IS '创建时间'; +COMMENT ON COLUMN sys_params.updater IS '更新者'; +COMMENT ON COLUMN sys_params.update_date IS '更新时间'; + + +create table sys_dict_type +( + id int8 NOT NULL, + dict_type varchar(100), + dict_name varchar(255), + remark varchar(255), + sort int, + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_dict_type_dict_type on sys_dict_type(dict_type); + +COMMENT ON TABLE sys_dict_type IS '字典类型'; +COMMENT ON COLUMN sys_dict_type.id IS 'id'; +COMMENT ON COLUMN sys_dict_type.dict_type IS '字典类型'; +COMMENT ON COLUMN sys_dict_type.dict_name IS '字典名称'; +COMMENT ON COLUMN sys_dict_type.remark IS '备注'; +COMMENT ON COLUMN sys_dict_type.sort IS '排序'; +COMMENT ON COLUMN sys_dict_type.creator IS '创建者'; +COMMENT ON COLUMN sys_dict_type.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dict_type.updater IS '更新者'; +COMMENT ON COLUMN sys_dict_type.update_date IS '更新时间'; + +create table sys_dict_data +( + id int8 NOT NULL, + dict_type_id int8 NOT NULL, + dict_label varchar(255), + dict_value varchar(255), + remark varchar(255), + sort int, + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + primary key (id) +); +CREATE INDEX idx_sys_dict_data_sort on sys_dict_data(sort); +CREATE UNIQUE INDEX uk_dict_type_value on sys_dict_data(dict_type_id, dict_value); + +COMMENT ON TABLE sys_dict_data IS '字典数据'; +COMMENT ON COLUMN sys_dict_data.id IS 'id'; +COMMENT ON COLUMN sys_dict_data.dict_type_id IS '字典类型ID'; +COMMENT ON COLUMN sys_dict_data.dict_label IS '字典标签'; +COMMENT ON COLUMN sys_dict_data.dict_value IS '字典值'; +COMMENT ON COLUMN sys_dict_data.remark IS '备注'; +COMMENT ON COLUMN sys_dict_data.sort IS '排序'; +COMMENT ON COLUMN sys_dict_data.creator IS '创建者'; +COMMENT ON COLUMN sys_dict_data.create_date IS '创建时间'; +COMMENT ON COLUMN sys_dict_data.updater IS '更新者'; +COMMENT ON COLUMN sys_dict_data.update_date IS '更新时间'; + + +create table sys_log_login +( + id int8 NOT NULL, + operation int, + status int, + user_agent varchar(500), + ip varchar(32), + creator_name varchar(50), + creator int8, + create_date timestamp, + primary key (id) +); +CREATE INDEX idx_login_status on sys_log_login(status); +CREATE INDEX idx_login_create_date on sys_log_login(create_date); + +COMMENT ON TABLE sys_log_login IS '登录日志'; +COMMENT ON COLUMN sys_log_login.id IS 'id'; +COMMENT ON COLUMN sys_log_login.operation IS '用户操作 0:用户登录 1:用户退出'; +COMMENT ON COLUMN sys_log_login.status IS '状态 0:失败 1:成功 2:账号已锁定'; +COMMENT ON COLUMN sys_log_login.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_login.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_login.creator_name IS '用户名'; +COMMENT ON COLUMN sys_log_login.creator IS '创建者'; +COMMENT ON COLUMN sys_log_login.create_date IS '创建时间'; + + +create table sys_log_operation +( + id int8 NOT NULL, + operation varchar(50), + request_uri varchar(200), + request_method varchar(20), + request_params text, + request_time int, + user_agent varchar(500), + ip varchar(32), + status int, + creator_name varchar(50), + creator int8, + create_date timestamp, + primary key (id) +); +CREATE INDEX idx_operation_create_date on sys_log_operation(create_date); + +COMMENT ON TABLE sys_log_operation IS '操作日志'; +COMMENT ON COLUMN sys_log_operation.id IS 'id'; +COMMENT ON COLUMN sys_log_operation.operation IS '用户操作'; +COMMENT ON COLUMN sys_log_operation.request_uri IS '请求URI'; +COMMENT ON COLUMN sys_log_operation.request_method IS '请求方式'; +COMMENT ON COLUMN sys_log_operation.request_params IS '请求参数'; +COMMENT ON COLUMN sys_log_operation.request_time IS '请求时长(毫秒)'; +COMMENT ON COLUMN sys_log_operation.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_operation.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_operation.status IS '状态 0:失败 1:成功'; +COMMENT ON COLUMN sys_log_operation.creator_name IS '用户名'; +COMMENT ON COLUMN sys_log_operation.creator IS '创建者'; +COMMENT ON COLUMN sys_log_operation.create_date IS '创建时间'; + + +create table sys_log_error +( + id int8 NOT NULL, + request_uri varchar(200), + request_method varchar(20), + request_params text, + user_agent varchar(500), + ip varchar(32), + error_info text, + creator int8, + create_date timestamp, + primary key (id) +); +CREATE INDEX idx_error_create_date on sys_log_error(create_date); + +COMMENT ON TABLE sys_log_error IS '异常日志'; +COMMENT ON COLUMN sys_log_error.id IS 'id'; +COMMENT ON COLUMN sys_log_error.request_uri IS '请求URI'; +COMMENT ON COLUMN sys_log_error.request_method IS '请求方式'; +COMMENT ON COLUMN sys_log_error.request_params IS '请求参数'; +COMMENT ON COLUMN sys_log_error.user_agent IS '用户代理'; +COMMENT ON COLUMN sys_log_error.ip IS '操作IP'; +COMMENT ON COLUMN sys_log_error.error_info IS '异常信息'; +COMMENT ON COLUMN sys_log_error.creator IS '创建者'; +COMMENT ON COLUMN sys_log_error.create_date IS '创建时间'; + + + +CREATE TABLE sys_oss ( + id int8 NOT NULL, + url varchar(200), + creator int8, + create_date timestamp, + PRIMARY KEY (id) +); +CREATE INDEX idx_sys_oss_create_date on sys_oss(create_date); + +COMMENT ON TABLE sys_oss IS '文件上传'; +COMMENT ON COLUMN sys_oss.id IS 'id'; +COMMENT ON COLUMN sys_oss.url IS 'URL地址'; +COMMENT ON COLUMN sys_oss.creator IS '创建者'; +COMMENT ON COLUMN sys_oss.create_date IS '创建时间'; + + +CREATE TABLE schedule_job ( + id int8 NOT NULL, + bean_name varchar(200), + params varchar(2000), + cron_expression varchar(100), + status int, + remark varchar(255), + creator int8, + create_date timestamp, + updater int8, + update_date timestamp, + PRIMARY KEY (id) +); + +CREATE INDEX idx_schedule_job_create_date on schedule_job(create_date); + +COMMENT ON TABLE schedule_job IS '定时任务'; +COMMENT ON COLUMN schedule_job.id IS 'id'; +COMMENT ON COLUMN schedule_job.bean_name IS 'spring bean名称'; +COMMENT ON COLUMN schedule_job.params IS '参数'; +COMMENT ON COLUMN schedule_job.cron_expression IS 'cron表达式'; +COMMENT ON COLUMN schedule_job.status IS '任务状态 0:暂停 1:正常'; +COMMENT ON COLUMN schedule_job.remark IS '备注'; +COMMENT ON COLUMN schedule_job.creator IS '创建者'; +COMMENT ON COLUMN schedule_job.create_date IS '创建时间'; +COMMENT ON COLUMN schedule_job.updater IS '更新者'; +COMMENT ON COLUMN schedule_job.update_date IS '更新时间'; + + +CREATE TABLE schedule_job_log ( + id int8 NOT NULL, + job_id int8 NOT NULL, + bean_name varchar(200), + params varchar(2000), + status int, + error varchar(2000), + times int, + create_date timestamp, + PRIMARY KEY (id) +); + +CREATE INDEX idx_job_log_job_id on schedule_job_log(job_id); +CREATE INDEX idx_job_log_create_date on schedule_job_log(create_date); + +COMMENT ON TABLE schedule_job_log IS '定时任务日志'; +COMMENT ON COLUMN schedule_job_log.id IS 'id'; +COMMENT ON COLUMN schedule_job_log.bean_name IS 'spring bean名称'; +COMMENT ON COLUMN schedule_job_log.params IS '参数'; +COMMENT ON COLUMN schedule_job_log.status IS '任务状态 0:失败 1:成功'; +COMMENT ON COLUMN schedule_job_log.error IS '失败信息'; +COMMENT ON COLUMN schedule_job_log.times IS '耗时(单位:毫秒)'; +COMMENT ON COLUMN schedule_job.create_date IS '创建时间'; + + +CREATE TABLE sys_user_token ( + id int8 NOT NULL, + user_id int8, + token varchar(100), + expire_date timestamp, + update_date timestamp, + create_date timestamp, + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX uk_sys_user_token_user_id on sys_user_token(user_id); +CREATE UNIQUE INDEX uk_sys_user_token on sys_user_token(token); + +COMMENT ON TABLE sys_user_token IS '系统用户Token'; +COMMENT ON COLUMN sys_user_token.id IS 'id'; +COMMENT ON COLUMN sys_user_token.user_id IS '用户id'; +COMMENT ON COLUMN sys_user_token.token IS '用户token'; +COMMENT ON COLUMN sys_user_token.expire_date IS '过期时间'; +COMMENT ON COLUMN sys_user_token.update_date IS '更新时间'; +COMMENT ON COLUMN sys_user_token.create_date IS '创建时间'; + + + +-- 初始数据 +INSERT INTO sys_user(id, username, password, real_name, gender, email, mobile, status, dept_id, super_admin, creator, create_date, updater, update_date) VALUES (1067246875800000001, 'admin', '$2a$10$012Kx2ba5jzqr9gLlG4MX.bnQJTD9UWqF57XDo2N3.fPtLne02u/m', '管理员', 0, 'root@renren.io', '13612345678', 1, null, 1, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000002, 0, '权限管理', NULL, NULL, 0, 'icon-safetycertificate', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000003, 1067246875800000055, '新增', NULL, 'sys:user:save,sys:dept:list,sys:role:list', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000004, 1067246875800000055, '修改', NULL, 'sys:user:update,sys:dept:list,sys:role:list', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000005, 1067246875800000055, '删除', NULL, 'sys:user:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000006, 1067246875800000055, '导出', NULL, 'sys:user:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000007, 1067246875800000002, '角色管理', 'sys/role', NULL, 0, 'icon-team', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000008, 1067246875800000007, '查看', NULL, 'sys:role:page,sys:role:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000009, 1067246875800000007, '新增', NULL, 'sys:role:save,sys:menu:select,sys:dept:list', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000010, 1067246875800000007, '修改', NULL, 'sys:role:update,sys:menu:select,sys:dept:list', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000011, 1067246875800000007, '删除', NULL, 'sys:role:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000012, 1067246875800000002, '部门管理', 'sys/dept', NULL, 0, 'icon-apartment', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000014, 1067246875800000012, '查看', NULL, 'sys:dept:list,sys:dept:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000015, 1067246875800000012, '新增', NULL, 'sys:dept:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000016, 1067246875800000012, '修改', NULL, 'sys:dept:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000017, 1067246875800000012, '删除', NULL, 'sys:dept:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000025, 1067246875800000035, '菜单管理', 'sys/menu', NULL, 0, 'icon-unorderedlist', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000026, 1067246875800000025, '查看', NULL, 'sys:menu:list,sys:menu:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000027, 1067246875800000025, '新增', NULL, 'sys:menu:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000028, 1067246875800000025, '修改', NULL, 'sys:menu:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000029, 1067246875800000025, '删除', NULL, 'sys:menu:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000030, 1067246875800000035, '定时任务', 'job/schedule', NULL, 0, 'icon-dashboard', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000031, 1067246875800000030, '查看', NULL, 'sys:schedule:page,sys:schedule:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000032, 1067246875800000030, '新增', NULL, 'sys:schedule:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000033, 1067246875800000030, '修改', NULL, 'sys:schedule:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000034, 1067246875800000030, '删除', NULL, 'sys:schedule:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000035, 0, '系统设置', NULL, NULL, 0, 'icon-setting', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000036, 1067246875800000030, '暂停', NULL, 'sys:schedule:pause', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000037, 1067246875800000030, '恢复', NULL, 'sys:schedule:resume', 1, NULL, 5, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000038, 1067246875800000030, '立即执行', NULL, 'sys:schedule:run', 1, NULL, 6, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000039, 1067246875800000030, '日志列表', NULL, 'sys:schedule:log', 1, NULL, 7, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000040, 1067246875800000035, '参数管理', 'sys/params', '', 0, 'icon-fileprotect', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000041, 1067246875800000035, '字典管理', 'sys/dict-type', NULL, 0, 'icon-golden-fill', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000042, 1067246875800000041, '查看', NULL, 'sys:dict:page,sys:dict:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000043, 1067246875800000041, '新增', NULL, 'sys:dict:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000044, 1067246875800000041, '修改', NULL, 'sys:dict:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000045, 1067246875800000041, '删除', NULL, 'sys:dict:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000046, 0, '日志管理', NULL, NULL, 0, 'icon-container', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000047, 1067246875800000035, '文件上传', 'oss/oss', 'sys:oss:all', 0, 'icon-upload', 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000048, 1067246875800000046, '登录日志', 'sys/log-login', 'sys:log:login', 0, 'icon-filedone', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000049, 1067246875800000046, '操作日志', 'sys/log-operation', 'sys:log:operation', 0, 'icon-solution', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000050, 1067246875800000046, '异常日志', 'sys/log-error', 'sys:log:error', 0, 'icon-file-exception', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000051, 1067246875800000053, 'SQL监控', '{{ApiUrl}}/druid/sql.html', NULL, 0, 'icon-database', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000053, 0, '系统监控', NULL, NULL, 0, 'icon-desktop', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000055, 1067246875800000002, '用户管理', 'sys/user', NULL, 0, 'icon-user', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000056, 1067246875800000055, '查看', NULL, 'sys:user:page,sys:user:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000057, 1067246875800000040, '新增', NULL, 'sys:params:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000058, 1067246875800000040, '导出', NULL, 'sys:params:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000059, 1067246875800000040, '查看', '', 'sys:params:page,sys:params:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000060, 1067246875800000040, '修改', NULL, 'sys:params:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000061, 1067246875800000040, '删除', '', 'sys:params:delete', 1, '', 3, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1156748733921165314, 1067246875800000053, '接口文档', '{{ApiUrl}}/doc.html', '', 0, 'icon-file-word', 1, 1067246875800000001, now(), 1067246875800000001, now()); + + +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000062, 1067246875800000063, '1067246875800000066,1067246875800000063', '技术部', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000063, 1067246875800000066, '1067246875800000066', '长沙分公司', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000064, 1067246875800000066, '1067246875800000066', '上海分公司', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000065, 1067246875800000064, '1067246875800000066,1067246875800000064', '市场部', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000066, 0, '0', '人人开源集团', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000067, 1067246875800000064, '1067246875800000066,1067246875800000064', '销售部', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000068, 1067246875800000063, '1067246875800000066,1067246875800000063', '产品部', 1, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1160061077912858625, 'gender', '性别', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061112075464705, 1160061077912858625, '男', '0', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061146967879681, 1160061077912858625, '女', '1', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061190127267841, 1160061077912858625, '保密', '2', '', 2, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1225813644059140097, 'notice_type', '站内通知-类型', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814069634195457, 1225813644059140097, '公告', '0', '', 0, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814107559092225, 1225813644059140097, '会议', '1', '', 1, 1067246875800000001, now(), 1067246875800000001, now()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814271879340034, 1225813644059140097, '其他', '2', '', 2, 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO sys_params(id, param_code, param_value, param_type, remark, creator, create_date, updater, update_date) VALUES (1067246875800000073, 'CLOUD_STORAGE_CONFIG_KEY', '{"type":1,"qiniuDomain":"http://test.oss.renren.io","qiniuPrefix":"upload","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","qiniuBucketName":"renren-oss","aliyunDomain":"","aliyunPrefix":"","aliyunEndPoint":"","aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qcloudBucketName":""}', '0', '云存储配置信息', 1067246875800000001, now(), 1067246875800000001, now()); + +INSERT INTO schedule_job (id, bean_name, params, cron_expression, status, remark, creator, create_date, updater, update_date) VALUES (1067246875800000076, 'testTask', 'renren', '0 0/30 * * * ?', 0, '有参测试,多个参数使用json', 1067246875800000001, now(), 1067246875800000001, now()); + + + +-- quartz自带表结构 +CREATE TABLE qrtz_job_details +( + SCHED_NAME VARCHAR(120) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + JOB_CLASS_NAME VARCHAR(250) NOT NULL, + IS_DURABLE BOOL NOT NULL, + IS_NONCONCURRENT BOOL NOT NULL, + IS_UPDATE_DATA BOOL NOT NULL, + REQUESTS_RECOVERY BOOL NOT NULL, + JOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) +); + +CREATE TABLE qrtz_triggers +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + NEXT_FIRE_TIME BIGINT NULL, + PREV_FIRE_TIME BIGINT NULL, + PRIORITY INTEGER NULL, + TRIGGER_STATE VARCHAR(16) NOT NULL, + TRIGGER_TYPE VARCHAR(8) NOT NULL, + START_TIME BIGINT NOT NULL, + END_TIME BIGINT NULL, + CALENDAR_NAME VARCHAR(200) NULL, + MISFIRE_INSTR SMALLINT NULL, + JOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) + REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) +); + +CREATE TABLE qrtz_simple_triggers +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + REPEAT_COUNT BIGINT NOT NULL, + REPEAT_INTERVAL BIGINT NOT NULL, + TIMES_TRIGGERED BIGINT NOT NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); + +CREATE TABLE qrtz_cron_triggers +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + CRON_EXPRESSION VARCHAR(120) NOT NULL, + TIME_ZONE_ID VARCHAR(80), + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); + +CREATE TABLE qrtz_simprop_triggers +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + STR_PROP_1 VARCHAR(512) NULL, + STR_PROP_2 VARCHAR(512) NULL, + STR_PROP_3 VARCHAR(512) NULL, + INT_PROP_1 INT NULL, + INT_PROP_2 INT NULL, + LONG_PROP_1 BIGINT NULL, + LONG_PROP_2 BIGINT NULL, + DEC_PROP_1 NUMERIC(13,4) NULL, + DEC_PROP_2 NUMERIC(13,4) NULL, + BOOL_PROP_1 BOOL NULL, + BOOL_PROP_2 BOOL NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); + +CREATE TABLE qrtz_blob_triggers +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + BLOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); + +CREATE TABLE qrtz_calendars +( + SCHED_NAME VARCHAR(120) NOT NULL, + CALENDAR_NAME VARCHAR(200) NOT NULL, + CALENDAR BYTEA NOT NULL, + PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) +); + + +CREATE TABLE qrtz_paused_trigger_grps +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) +); + +CREATE TABLE qrtz_fired_triggers +( + SCHED_NAME VARCHAR(120) NOT NULL, + ENTRY_ID VARCHAR(95) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + FIRED_TIME BIGINT NOT NULL, + SCHED_TIME BIGINT NOT NULL, + PRIORITY INTEGER NOT NULL, + STATE VARCHAR(16) NOT NULL, + JOB_NAME VARCHAR(200) NULL, + JOB_GROUP VARCHAR(200) NULL, + IS_NONCONCURRENT BOOL NULL, + REQUESTS_RECOVERY BOOL NULL, + PRIMARY KEY (SCHED_NAME,ENTRY_ID) +); + +CREATE TABLE qrtz_scheduler_state +( + SCHED_NAME VARCHAR(120) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + LAST_CHECKIN_TIME BIGINT NOT NULL, + CHECKIN_INTERVAL BIGINT NOT NULL, + PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) +); + +CREATE TABLE qrtz_locks +( + SCHED_NAME VARCHAR(120) NOT NULL, + LOCK_NAME VARCHAR(40) NOT NULL, + PRIMARY KEY (SCHED_NAME,LOCK_NAME) +); + +create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); +create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); + +create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); +create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); +create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); +create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); +create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); +create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); +create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); +create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); +create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); + +create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); +create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); +create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); +create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); +create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); +create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP); + + +commit; diff --git a/renren-admin/db/sqlserver.sql b/renren-admin/db/sqlserver.sql new file mode 100644 index 0000000..0d40be7 --- /dev/null +++ b/renren-admin/db/sqlserver.sql @@ -0,0 +1,674 @@ +CREATE TABLE sys_user ( + id bigint NOT NULL, + username varchar(50) NOT NULL, + password varchar(100), + real_name varchar(50), + head_url varchar(200), + gender int, + email varchar(100), + mobile varchar(100), + dept_id bigint, + super_admin int, + status int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); + +CREATE UNIQUE INDEX uk_sys_user_username on sys_user(username); +CREATE INDEX idx_sys_user_create_date on sys_user(create_date); + + +CREATE TABLE sys_dept ( + id bigint NOT NULL, + pid bigint, + pids varchar(500), + name varchar(50), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE INDEX idx_sys_dept_pid on sys_dept(pid); +CREATE INDEX idx_sys_dept_idx_sort on sys_dept(sort); + + +create table sys_role +( + id bigint NOT NULL, + name varchar(50), + remark varchar(100), + dept_id bigint, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_role_dept_id on sys_role(dept_id); + + +create table sys_menu +( + id bigint NOT NULL, + pid bigint, + name varchar(200), + url varchar(200), + permissions varchar(500), + menu_type int, + icon varchar(50), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_menu_pid on sys_menu(pid); +CREATE INDEX idx_sys_menu_sort on sys_menu(sort); + + +create table sys_role_user +( + id bigint NOT NULL, + role_id bigint, + user_id bigint, + creator bigint, + create_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_role_user_role_id on sys_role_user(role_id); +CREATE INDEX idx_sys_role_user_user_id on sys_role_user(user_id); + + +create table sys_role_menu +( + id bigint NOT NULL, + role_id bigint, + menu_id bigint, + creator bigint, + create_date datetime, + primary key (id) +); + +CREATE INDEX idx_sys_role_menu_role_id on sys_role_menu(role_id); +CREATE INDEX idx_sys_role_menu_menu_id on sys_role_menu(menu_id); + + +create table sys_role_data_scope +( + id bigint NOT NULL, + role_id bigint, + dept_id bigint, + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_data_scope_role_id on sys_role_data_scope(role_id); + + +create table sys_params +( + id bigint NOT NULL, + param_code varchar(32), + param_value varchar(2000), + param_type int DEFAULT 1 NOT NULL, + remark varchar(200), + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_params_param_code on sys_params(param_code); +CREATE INDEX idx_sys_params_create_date on sys_params(create_date); + + +create table sys_dict_type +( + id bigint NOT NULL, + dict_type varchar(100), + dict_name varchar(255), + remark varchar(255), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE UNIQUE INDEX uk_sys_dict_type_dict_type on sys_dict_type(dict_type); + + +create table sys_dict_data +( + id bigint NOT NULL, + dict_type_id bigint NOT NULL, + dict_label varchar(255), + dict_value varchar(255), + remark varchar(255), + sort int, + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + primary key (id) +); +CREATE INDEX idx_sys_dict_data_sort on sys_dict_data(sort); +CREATE UNIQUE INDEX uk_dict_type_value on sys_dict_data(dict_type_id, dict_value); + + +create table sys_log_login +( + id bigint NOT NULL, + operation int, + status int, + user_agent varchar(500), + ip varchar(32), + creator_name varchar(50), + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_login_status on sys_log_login(status); +CREATE INDEX idx_login_create_date on sys_log_login(create_date); + + +create table sys_log_operation +( + id bigint NOT NULL, + operation varchar(50), + request_uri varchar(200), + request_method varchar(20), + request_params text, + request_time int, + user_agent varchar(500), + ip varchar(32), + status int, + creator_name varchar(50), + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_operation_create_date on sys_log_operation(create_date); + + +create table sys_log_error +( + id bigint NOT NULL, + request_uri varchar(200), + request_method varchar(20), + request_params text, + user_agent varchar(500), + ip varchar(32), + error_info text, + creator bigint, + create_date datetime, + primary key (id) +); +CREATE INDEX idx_error_create_date on sys_log_error(create_date); + + +CREATE TABLE sys_oss ( + id bigint NOT NULL, + url varchar(200), + creator bigint, + create_date datetime, + PRIMARY KEY (id) +); +CREATE INDEX idx_sys_oss_create_date on sys_oss(create_date); + + +CREATE TABLE schedule_job ( + id bigint NOT NULL, + bean_name varchar(200), + params varchar(2000), + cron_expression varchar(100), + status int, + remark varchar(255), + creator bigint, + create_date datetime, + updater bigint, + update_date datetime, + PRIMARY KEY (id) +); + +CREATE INDEX idx_schedule_job_create_date on schedule_job(create_date); + + +CREATE TABLE schedule_job_log ( + id bigint NOT NULL, + job_id bigint NOT NULL, + bean_name varchar(200), + params varchar(2000), + status int, + error varchar(2000), + times int, + create_date datetime, + PRIMARY KEY (id) +); + +CREATE INDEX idx_job_log_job_id on schedule_job_log(job_id); +CREATE INDEX idx_job_log_create_date on schedule_job_log(create_date); + + +CREATE TABLE sys_user_token ( + id bigint NOT NULL, + user_id bigint, + token varchar(100), + expire_date datetime, + update_date datetime, + create_date datetime, + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX uk_sys_user_token_user_id on sys_user_token(user_id); +CREATE UNIQUE INDEX uk_sys_user_token on sys_user_token(token); + + + +-- 初始数据 +INSERT INTO sys_user(id, username, password, real_name, gender, email, mobile, status, dept_id, super_admin, creator, create_date, updater, update_date) VALUES (1067246875800000001, 'admin', '$2a$10$012Kx2ba5jzqr9gLlG4MX.bnQJTD9UWqF57XDo2N3.fPtLne02u/m', '管理员', 0, 'root@renren.io', '13612345678', 1, null, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); + +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000002, 0, '权限管理', NULL, NULL, 0, 'icon-safetycertificate', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000003, 1067246875800000055, '新增', NULL, 'sys:user:save,sys:dept:list,sys:role:list', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000004, 1067246875800000055, '修改', NULL, 'sys:user:update,sys:dept:list,sys:role:list', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000005, 1067246875800000055, '删除', NULL, 'sys:user:delete', 1, NULL, 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000006, 1067246875800000055, '导出', NULL, 'sys:user:export', 1, NULL, 4, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000007, 1067246875800000002, '角色管理', 'sys/role', NULL, 0, 'icon-team', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000008, 1067246875800000007, '查看', NULL, 'sys:role:page,sys:role:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000009, 1067246875800000007, '新增', NULL, 'sys:role:save,sys:menu:select,sys:dept:list', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000010, 1067246875800000007, '修改', NULL, 'sys:role:update,sys:menu:select,sys:dept:list', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000011, 1067246875800000007, '删除', NULL, 'sys:role:delete', 1, NULL, 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000012, 1067246875800000002, '部门管理', 'sys/dept', NULL, 0, 'icon-apartment', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000014, 1067246875800000012, '查看', NULL, 'sys:dept:list,sys:dept:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000015, 1067246875800000012, '新增', NULL, 'sys:dept:save', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000016, 1067246875800000012, '修改', NULL, 'sys:dept:update', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000017, 1067246875800000012, '删除', NULL, 'sys:dept:delete', 1, NULL, 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000025, 1067246875800000035, '菜单管理', 'sys/menu', NULL, 0, 'icon-unorderedlist', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000026, 1067246875800000025, '查看', NULL, 'sys:menu:list,sys:menu:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000027, 1067246875800000025, '新增', NULL, 'sys:menu:save', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000028, 1067246875800000025, '修改', NULL, 'sys:menu:update', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000029, 1067246875800000025, '删除', NULL, 'sys:menu:delete', 1, NULL, 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000030, 1067246875800000035, '定时任务', 'job/schedule', NULL, 0, 'icon-dashboard', 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000031, 1067246875800000030, '查看', NULL, 'sys:schedule:page,sys:schedule:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000032, 1067246875800000030, '新增', NULL, 'sys:schedule:save', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000033, 1067246875800000030, '修改', NULL, 'sys:schedule:update', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000034, 1067246875800000030, '删除', NULL, 'sys:schedule:delete', 1, NULL, 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000035, 0, '系统设置', NULL, NULL, 0, 'icon-setting', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000036, 1067246875800000030, '暂停', NULL, 'sys:schedule:pause', 1, NULL, 4, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000037, 1067246875800000030, '恢复', NULL, 'sys:schedule:resume', 1, NULL, 5, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000038, 1067246875800000030, '立即执行', NULL, 'sys:schedule:run', 1, NULL, 6, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000039, 1067246875800000030, '日志列表', NULL, 'sys:schedule:log', 1, NULL, 7, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000040, 1067246875800000035, '参数管理', 'sys/params', '', 0, 'icon-fileprotect', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000041, 1067246875800000035, '字典管理', 'sys/dict-type', NULL, 0, 'icon-golden-fill', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000042, 1067246875800000041, '查看', NULL, 'sys:dict:page,sys:dict:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000043, 1067246875800000041, '新增', NULL, 'sys:dict:save', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000044, 1067246875800000041, '修改', NULL, 'sys:dict:update', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000045, 1067246875800000041, '删除', NULL, 'sys:dict:delete', 1, NULL, 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000046, 0, '日志管理', NULL, NULL, 0, 'icon-container', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000047, 1067246875800000035, '文件上传', 'oss/oss', 'sys:oss:all', 0, 'icon-upload', 4, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000048, 1067246875800000046, '登录日志', 'sys/log-login', 'sys:log:login', 0, 'icon-filedone', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000049, 1067246875800000046, '操作日志', 'sys/log-operation', 'sys:log:operation', 0, 'icon-solution', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000050, 1067246875800000046, '异常日志', 'sys/log-error', 'sys:log:error', 0, 'icon-file-exception', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000051, 1067246875800000053, 'SQL监控', '{{ApiUrl}}/druid/sql.html', NULL, 0, 'icon-database', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000053, 0, '系统监控', NULL, NULL, 0, 'icon-desktop', 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000055, 1067246875800000002, '用户管理', 'sys/user', NULL, 0, 'icon-user', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000056, 1067246875800000055, '查看', NULL, 'sys:user:page,sys:user:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000057, 1067246875800000040, '新增', NULL, 'sys:params:save', 1, NULL, 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000058, 1067246875800000040, '导出', NULL, 'sys:params:export', 1, NULL, 4, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000059, 1067246875800000040, '查看', '', 'sys:params:page,sys:params:info', 1, NULL, 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000060, 1067246875800000040, '修改', NULL, 'sys:params:update', 1, NULL, 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1067246875800000061, 1067246875800000040, '删除', '', 'sys:params:delete', 1, '', 3, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_menu (id, pid, name, url, permissions, menu_type, icon, sort, creator, create_date, updater, update_date) VALUES (1156748733921165314, 1067246875800000053, '接口文档', '{{ApiUrl}}/doc.html', '', 0, 'icon-file-word', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); + + +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000062, 1067246875800000063, '1067246875800000066,1067246875800000063', '技术部', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000063, 1067246875800000066, '1067246875800000066', '长沙分公司', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000064, 1067246875800000066, '1067246875800000066', '上海分公司', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000065, 1067246875800000064, '1067246875800000066,1067246875800000064', '市场部', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000066, 0, '0', '人人开源集团', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000067, 1067246875800000064, '1067246875800000066,1067246875800000064', '销售部', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dept(id, pid, pids, name, sort, creator, create_date, updater, update_date) VALUES (1067246875800000068, 1067246875800000063, '1067246875800000066,1067246875800000063', '产品部', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); + +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1160061077912858625, 'gender', '性别', '', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061112075464705, 1160061077912858625, '男', '0', '', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061146967879681, 1160061077912858625, '女', '1', '', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1160061190127267841, 1160061077912858625, '保密', '2', '', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_type(id, dict_type, dict_name, remark, sort, creator, create_date, updater, update_date) VALUES (1225813644059140097, 'notice_type', '站内通知-类型', '', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814069634195457, 1225813644059140097, '公告', '0', '', 0, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814107559092225, 1225813644059140097, '会议', '1', '', 1, 1067246875800000001, getdate(), 1067246875800000001, getdate()); +INSERT INTO sys_dict_data(id, dict_type_id, dict_label, dict_value, remark, sort, creator, create_date, updater, update_date) VALUES (1225814271879340034, 1225813644059140097, '其他', '2', '', 2, 1067246875800000001, getdate(), 1067246875800000001, getdate()); + +INSERT INTO sys_params(id, param_code, param_value, param_type, remark, creator, create_date, updater, update_date) VALUES (1067246875800000073, 'CLOUD_STORAGE_CONFIG_KEY', '{"type":1,"qiniuDomain":"http://test.oss.renren.io","qiniuPrefix":"upload","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","qiniuBucketName":"renren-oss","aliyunDomain":"","aliyunPrefix":"","aliyunEndPoint":"","aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qcloudBucketName":""}', '0', '云存储配置信息', 1067246875800000001, getdate(), 1067246875800000001, getdate()); + +INSERT INTO schedule_job (id, bean_name, params, cron_expression, status, remark, creator, create_date, updater, update_date) VALUES (1067246875800000076, 'testTask', 'renren', '0 0/30 * * * ?', 0, '有参测试,多个参数使用json', 1067246875800000001, getdate(), 1067246875800000001, getdate()); + + +-- quartz自带表结构 +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1) + ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1) + ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1) + ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1) + ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_CALENDARS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_LOCKS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_JOB_DETAILS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] +GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1) + DROP TABLE [dbo].[QRTZ_TRIGGERS] +GO + +CREATE TABLE [dbo].[QRTZ_CALENDARS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [CALENDAR_NAME] [VARCHAR] (200) NOT NULL , + [CALENDAR] [IMAGE] NOT NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [TRIGGER_NAME] [VARCHAR] (200) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL , + [CRON_EXPRESSION] [VARCHAR] (120) NOT NULL , + [TIME_ZONE_ID] [VARCHAR] (80) +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [ENTRY_ID] [VARCHAR] (95) NOT NULL , + [TRIGGER_NAME] [VARCHAR] (200) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL , + [INSTANCE_NAME] [VARCHAR] (200) NOT NULL , + [FIRED_TIME] [BIGINT] NOT NULL , + [SCHED_TIME] [BIGINT] NOT NULL , + [PRIORITY] [INTEGER] NOT NULL , + [STATE] [VARCHAR] (16) NOT NULL, + [JOB_NAME] [VARCHAR] (200) NULL , + [JOB_GROUP] [VARCHAR] (200) NULL , + [IS_NONCONCURRENT] [VARCHAR] (1) NULL , + [REQUESTS_RECOVERY] [VARCHAR] (1) NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [INSTANCE_NAME] [VARCHAR] (200) NOT NULL , + [LAST_CHECKIN_TIME] [BIGINT] NOT NULL , + [CHECKIN_INTERVAL] [BIGINT] NOT NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_LOCKS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [LOCK_NAME] [VARCHAR] (40) NOT NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [JOB_NAME] [VARCHAR] (200) NOT NULL , + [JOB_GROUP] [VARCHAR] (200) NOT NULL , + [DESCRIPTION] [VARCHAR] (250) NULL , + [JOB_CLASS_NAME] [VARCHAR] (250) NOT NULL , + [IS_DURABLE] [VARCHAR] (1) NOT NULL , + [IS_NONCONCURRENT] [VARCHAR] (1) NOT NULL , + [IS_UPDATE_DATA] [VARCHAR] (1) NOT NULL , + [REQUESTS_RECOVERY] [VARCHAR] (1) NOT NULL , + [JOB_DATA] [IMAGE] NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [TRIGGER_NAME] [VARCHAR] (200) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL , + [REPEAT_COUNT] [BIGINT] NOT NULL , + [REPEAT_INTERVAL] [BIGINT] NOT NULL , + [TIMES_TRIGGERED] [BIGINT] NOT NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [TRIGGER_NAME] [VARCHAR] (200) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL , + [STR_PROP_1] [VARCHAR] (512) NULL, + [STR_PROP_2] [VARCHAR] (512) NULL, + [STR_PROP_3] [VARCHAR] (512) NULL, + [INT_PROP_1] [INT] NULL, + [INT_PROP_2] [INT] NULL, + [LONG_PROP_1] [BIGINT] NULL, + [LONG_PROP_2] [BIGINT] NULL, + [DEC_PROP_1] [NUMERIC] (13,4) NULL, + [DEC_PROP_2] [NUMERIC] (13,4) NULL, + [BOOL_PROP_1] [VARCHAR] (1) NULL, + [BOOL_PROP_2] [VARCHAR] (1) NULL, +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [TRIGGER_NAME] [VARCHAR] (200) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL , + [BLOB_DATA] [IMAGE] NULL +) ON [PRIMARY] +GO + +CREATE TABLE [dbo].[QRTZ_TRIGGERS] ( + [SCHED_NAME] [VARCHAR] (120) NOT NULL , + [TRIGGER_NAME] [VARCHAR] (200) NOT NULL , + [TRIGGER_GROUP] [VARCHAR] (200) NOT NULL , + [JOB_NAME] [VARCHAR] (200) NOT NULL , + [JOB_GROUP] [VARCHAR] (200) NOT NULL , + [DESCRIPTION] [VARCHAR] (250) NULL , + [NEXT_FIRE_TIME] [BIGINT] NULL , + [PREV_FIRE_TIME] [BIGINT] NULL , + [PRIORITY] [INTEGER] NULL , + [TRIGGER_STATE] [VARCHAR] (16) NOT NULL , + [TRIGGER_TYPE] [VARCHAR] (8) NOT NULL , + [START_TIME] [BIGINT] NOT NULL , + [END_TIME] [BIGINT] NULL , + [CALENDAR_NAME] [VARCHAR] (200) NULL , + [MISFIRE_INSTR] [SMALLINT] NULL , + [JOB_DATA] [IMAGE] NULL +) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [CALENDAR_NAME] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [ENTRY_ID] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [TRIGGER_GROUP] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [INSTANCE_NAME] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [LOCK_NAME] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [JOB_NAME], + [JOB_GROUP] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD + CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY CLUSTERED + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD + CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) REFERENCES [dbo].[QRTZ_TRIGGERS] ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON DELETE CASCADE +GO + +ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD + CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) REFERENCES [dbo].[QRTZ_TRIGGERS] ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON DELETE CASCADE +GO + +ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD + CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY + ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) REFERENCES [dbo].[QRTZ_TRIGGERS] ( + [SCHED_NAME], + [TRIGGER_NAME], + [TRIGGER_GROUP] + ) ON DELETE CASCADE +GO + +ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD + CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY + ( + [SCHED_NAME], + [JOB_NAME], + [JOB_GROUP] + ) REFERENCES [dbo].[QRTZ_JOB_DETAILS] ( + [SCHED_NAME], + [JOB_NAME], + [JOB_GROUP] + ) +GO \ No newline at end of file diff --git a/renren-admin/pom.xml b/renren-admin/pom.xml new file mode 100644 index 0000000..ccbd17d --- /dev/null +++ b/renren-admin/pom.xml @@ -0,0 +1,128 @@ + + + io.renren + renren-security + 5.5.0 + + 4.0.0 + renren-admin + jar + renren-admin + + + 2.5.2 + 2.1.0 + 1.6.2 + 3.2.1 + 7.2.27 + 2.8.3 + 3.2.2 + 5.4.4 + + + + + io.renren + renren-common + 5.5.0 + + + io.renren + renren-dynamic-datasource + 5.5.0 + + + org.springframework.boot + spring-boot-starter-quartz + + + org.apache.shiro + shiro-spring + jakarta + ${shiro.version} + + + + org.apache.shiro + shiro-core + + + org.apache.shiro + shiro-web + + + + + + org.apache.shiro + shiro-core + jakarta + ${shiro.version} + + + org.apache.shiro + shiro-web + jakarta + ${shiro.version} + + + org.apache.shiro + shiro-core + + + + + com.github.whvcse + easy-captcha + ${captcha.version} + + + com.alibaba + easyexcel + ${easyexcel.version} + + + com.qiniu + qiniu-java-sdk + ${qiniu.version} + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun.oss.version} + + + com.aliyun + aliyun-java-sdk-core + ${aliyun.core.version} + + + com.qcloud + cos_api + ${qcloud.cos.version} + + + org.slf4j + slf4j-log4j12 + + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + diff --git a/renren-admin/src/main/java/io/renren/AdminApplication.java b/renren-admin/src/main/java/io/renren/AdminApplication.java new file mode 100644 index 0000000..422a37e --- /dev/null +++ b/renren-admin/src/main/java/io/renren/AdminApplication.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + + +/** + * renren-admin + * + * @author Mark sunlightcs@gmail.com + */ +@SpringBootApplication +public class AdminApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(AdminApplication.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(AdminApplication.class); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/annotation/DataFilter.java b/renren-admin/src/main/java/io/renren/common/annotation/DataFilter.java new file mode 100644 index 0000000..108c7d0 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/annotation/DataFilter.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.annotation; + +import java.lang.annotation.*; + +/** + * 数据过滤注解 + * + * @author Mark sunlightcs@gmail.com + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataFilter { + /** + * 表的别名 + */ + String tableAlias() default ""; + + /** + * 用户ID + */ + String userId() default "creator"; + + /** + * 部门ID + */ + String deptId() default "dept_id"; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/annotation/LogOperation.java b/renren-admin/src/main/java/io/renren/common/annotation/LogOperation.java new file mode 100644 index 0000000..067a73e --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/annotation/LogOperation.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 操作日志注解 + * + * @author Mark sunlightcs@gmail.com + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface LogOperation { + + String value() default ""; +} diff --git a/renren-admin/src/main/java/io/renren/common/aspect/DataFilterAspect.java b/renren-admin/src/main/java/io/renren/common/aspect/DataFilterAspect.java new file mode 100644 index 0000000..597393f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/aspect/DataFilterAspect.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.aspect; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.qiniu.util.StringUtils; +import io.renren.common.annotation.DataFilter; +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.interceptor.DataScope; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.enums.SuperAdminEnum; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +/** + * 数据过滤,切面处理类 + * + * @author Mark sunlightcs@gmail.com + */ +@Aspect +@Component +public class DataFilterAspect { + + @Pointcut("@annotation(io.renren.common.annotation.DataFilter)") + public void dataFilterCut() { + + } + + @Before("dataFilterCut()") + public void dataFilter(JoinPoint point) { + Object params = point.getArgs()[0]; + if (params != null && params instanceof Map) { + UserDetail user = SecurityUser.getUser(); + + //如果是超级管理员,则不进行数据过滤 + if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) { + return; + } + + try { + //否则进行数据过滤 + Map map = (Map) params; + String sqlFilter = getSqlFilter(user, point); + map.put(Constant.SQL_FILTER, new DataScope(sqlFilter)); + } catch (Exception e) { + + } + + return; + } + + throw new RenException(ErrorCode.DATA_SCOPE_PARAMS_ERROR); + } + + /** + * 获取数据过滤的SQL + */ + private String getSqlFilter(UserDetail user, JoinPoint point) throws Exception { + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = point.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes()); + DataFilter dataFilter = method.getAnnotation(DataFilter.class); + + //获取表的别名 + String tableAlias = dataFilter.tableAlias(); + if (StrUtil.isNotBlank(tableAlias)) { + tableAlias += "."; + } + + StringBuilder sqlFilter = new StringBuilder(); + sqlFilter.append(" ("); + + //部门ID列表 + List deptIdList = user.getDeptIdList(); + if (CollUtil.isNotEmpty(deptIdList)) { + sqlFilter.append(tableAlias).append(dataFilter.deptId()); + + sqlFilter.append(" in(").append(StringUtils.join(deptIdList, ",")).append(")"); + } + + //查询本人数据 + if (CollUtil.isNotEmpty(deptIdList)) { + sqlFilter.append(" or "); + } + sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getId()); + + sqlFilter.append(")"); + + return sqlFilter.toString(); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/aspect/LogOperationAspect.java b/renren-admin/src/main/java/io/renren/common/aspect/LogOperationAspect.java new file mode 100644 index 0000000..705009c --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/aspect/LogOperationAspect.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.aspect; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.utils.HttpContextUtils; +import io.renren.common.utils.IpUtils; +import io.renren.common.utils.JsonUtils; +import io.renren.modules.log.entity.SysLogOperationEntity; +import io.renren.modules.log.enums.OperationStatusEnum; +import io.renren.modules.log.service.SysLogOperationService; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import jakarta.servlet.http.HttpServletRequest; +import lombok.AllArgsConstructor; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +/** + * 操作日志,切面处理类 + * + * @author Mark sunlightcs@gmail.com + */ +@Aspect +@Component +@AllArgsConstructor +public class LogOperationAspect { + private final SysLogOperationService sysLogOperationService; + + @Pointcut("@annotation(io.renren.common.annotation.LogOperation)") + public void logPointCut() { + + } + + @Around("logPointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable { + long beginTime = System.currentTimeMillis(); + try { + //执行方法 + Object result = point.proceed(); + + //执行时长(毫秒) + long time = System.currentTimeMillis() - beginTime; + //保存日志 + saveLog(point, time, OperationStatusEnum.SUCCESS.value()); + + return result; + } catch (Exception e) { + //执行时长(毫秒) + long time = System.currentTimeMillis() - beginTime; + //保存日志 + saveLog(point, time, OperationStatusEnum.FAIL.value()); + + throw e; + } + } + + private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status) throws Exception { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes()); + LogOperation annotation = method.getAnnotation(LogOperation.class); + + SysLogOperationEntity log = new SysLogOperationEntity(); + if (annotation != null) { + //注解上的描述 + log.setOperation(annotation.value()); + } + + //登录用户信息 + UserDetail user = SecurityUser.getUser(); + if (user != null) { + log.setCreatorName(user.getUsername()); + } + + log.setStatus(status); + log.setRequestTime((int) time); + + //请求相关信息 + HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); + log.setIp(IpUtils.getIpAddr(request)); + log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); + log.setRequestUri(request.getRequestURI()); + log.setRequestMethod(request.getMethod()); + + //请求参数 + Object[] args = joinPoint.getArgs(); + try { + String params = JsonUtils.toJsonString(args[0]); + log.setRequestParams(params); + } catch (Exception e) { + + } + + //保存到DB + sysLogOperationService.save(log); + } +} diff --git a/renren-admin/src/main/java/io/renren/common/config/MybatisPlusConfig.java b/renren-admin/src/main/java/io/renren/common/config/MybatisPlusConfig.java new file mode 100644 index 0000000..68e3fba --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/config/MybatisPlusConfig.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import io.renren.common.interceptor.DataFilterInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * mybatis-plus配置 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Configuration +public class MybatisPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); + // 数据权限 + mybatisPlusInterceptor.addInnerInterceptor(new DataFilterInterceptor()); + // 分页插件 + mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + // 乐观锁 + mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + // 防止全表更新与删除 + mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + + return mybatisPlusInterceptor; + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/config/SwaggerConfig.java b/renren-admin/src/main/java/io/renren/common/config/SwaggerConfig.java new file mode 100644 index 0000000..283d643 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/config/SwaggerConfig.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.config; + +import io.renren.common.constant.Constant; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * Swagger配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class SwaggerConfig { + @Bean + public OpenAPI createRestApi() { + return new OpenAPI() + .info(apiInfo()) + .security(security()); + } + + private Info apiInfo() { + return new Info() + .title("人人开源") + .description("renren-admin文档") + .version("5.x"); + } + + private List security() { + SecurityRequirement key = new SecurityRequirement(); + key.addList(Constant.TOKEN_HEADER, Constant.TOKEN_HEADER); + + List list = new ArrayList<>(); + list.add(key); + return list; + } +} diff --git a/renren-admin/src/main/java/io/renren/common/exception/RenExceptionHandler.java b/renren-admin/src/main/java/io/renren/common/exception/RenExceptionHandler.java new file mode 100644 index 0000000..6bcc92e --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/exception/RenExceptionHandler.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.exception; + +import cn.hutool.core.map.MapUtil; +import io.renren.common.utils.HttpContextUtils; +import io.renren.common.utils.IpUtils; +import io.renren.common.utils.JsonUtils; +import io.renren.common.utils.Result; +import io.renren.modules.log.entity.SysLogErrorEntity; +import io.renren.modules.log.service.SysLogErrorService; +import jakarta.servlet.http.HttpServletRequest; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.Map; + + +/** + * 异常处理器 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Slf4j +@RestControllerAdvice +@AllArgsConstructor +public class RenExceptionHandler { + private final SysLogErrorService sysLogErrorService; + + /** + * 处理自定义异常 + */ + @ExceptionHandler(RenException.class) + public Result handleRenException(RenException ex) { + Result result = new Result(); + result.error(ex.getCode(), ex.getMsg()); + + return result; + } + + @ExceptionHandler(DuplicateKeyException.class) + public Result handleDuplicateKeyException(DuplicateKeyException ex) { + Result result = new Result(); + result.error(ErrorCode.DB_RECORD_EXISTS); + + return result; + } + + @ExceptionHandler(Exception.class) + public Result handleException(Exception ex) { + log.error(ex.getMessage(), ex); + + saveLog(ex); + + return new Result().error(); + } + + /** + * 保存异常日志 + */ + private void saveLog(Exception ex) { + SysLogErrorEntity log = new SysLogErrorEntity(); + + //请求相关信息 + HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); + log.setIp(IpUtils.getIpAddr(request)); + log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); + log.setRequestUri(request.getRequestURI()); + log.setRequestMethod(request.getMethod()); + Map params = HttpContextUtils.getParameterMap(request); + if (MapUtil.isNotEmpty(params)) { + log.setRequestParams(JsonUtils.toJsonString(params)); + } + + //异常信息 + log.setErrorInfo(ExceptionUtils.getErrorStackTrace(ex)); + + //保存 + sysLogErrorService.save(log); + } +} diff --git a/renren-admin/src/main/java/io/renren/common/handler/FieldMetaObjectHandler.java b/renren-admin/src/main/java/io/renren/common/handler/FieldMetaObjectHandler.java new file mode 100644 index 0000000..b325e5d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/handler/FieldMetaObjectHandler.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * 公共字段,自动填充值 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +public class FieldMetaObjectHandler implements MetaObjectHandler { + private final static String CREATE_DATE = "createDate"; + private final static String CREATOR = "creator"; + private final static String UPDATE_DATE = "updateDate"; + private final static String UPDATER = "updater"; + private final static String DEPT_ID = "deptId"; + + @Override + public void insertFill(MetaObject metaObject) { + UserDetail user = SecurityUser.getUser(); + Date date = new Date(); + + //创建者 + strictInsertFill(metaObject, CREATOR, Long.class, user.getId()); + //创建时间 + strictInsertFill(metaObject, CREATE_DATE, Date.class, date); + + //创建者所属部门 + strictInsertFill(metaObject, DEPT_ID, Long.class, user.getDeptId()); + + //更新者 + strictInsertFill(metaObject, UPDATER, Long.class, user.getId()); + //更新时间 + strictInsertFill(metaObject, UPDATE_DATE, Date.class, date); + } + + @Override + public void updateFill(MetaObject metaObject) { + //更新者 + strictUpdateFill(metaObject, UPDATER, Long.class, SecurityUser.getUserId()); + //更新时间 + strictUpdateFill(metaObject, UPDATE_DATE, Date.class, new Date()); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/interceptor/DataFilterInterceptor.java b/renren-admin/src/main/java/io/renren/common/interceptor/DataFilterInterceptor.java new file mode 100644 index 0000000..87cb0b2 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/interceptor/DataFilterInterceptor.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.interceptor; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.PluginUtils; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import java.util.Map; + +/** + * 数据过滤 + * + * @author Mark sunlightcs@gmail.com + */ +public class DataFilterInterceptor implements InnerInterceptor { + + @Override + public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { + DataScope scope = getDataScope(parameter); + // 不进行数据过滤 + if(scope == null || StrUtil.isBlank(scope.getSqlFilter())){ + return; + } + + // 拼接新SQL + String buildSql = getSelect(boundSql.getSql(), scope); + + // 重写SQL + PluginUtils.mpBoundSql(boundSql).sql(buildSql); + } + + private DataScope getDataScope(Object parameter){ + if (parameter == null){ + return null; + } + + // 判断参数里是否有DataScope对象 + if (parameter instanceof Map) { + Map parameterMap = (Map) parameter; + for (Map.Entry entry : parameterMap.entrySet()) { + if (entry.getValue() != null && entry.getValue() instanceof DataScope) { + return (DataScope) entry.getValue(); + } + } + } else if (parameter instanceof DataScope) { + return (DataScope) parameter; + } + + return null; + } + + private String getSelect(String buildSql, DataScope scope){ + try { + Select select = (Select) CCJSqlParserUtil.parse(buildSql); + PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); + + Expression expression = plainSelect.getWhere(); + if(expression == null){ + plainSelect.setWhere(new StringValue(scope.getSqlFilter())); + }else{ + AndExpression andExpression = new AndExpression(expression, new StringValue(scope.getSqlFilter())); + plainSelect.setWhere(andExpression); + } + + return select.toString().replaceAll("'", ""); + }catch (JSQLParserException e){ + return buildSql; + } + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/interceptor/DataScope.java b/renren-admin/src/main/java/io/renren/common/interceptor/DataScope.java new file mode 100644 index 0000000..11acdd2 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/interceptor/DataScope.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.interceptor; + +/** + * 数据范围 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class DataScope { + private String sqlFilter; + + public DataScope(String sqlFilter) { + this.sqlFilter = sqlFilter; + } + + public String getSqlFilter() { + return sqlFilter; + } + + public void setSqlFilter(String sqlFilter) { + this.sqlFilter = sqlFilter; + } + + @Override + public String toString() { + return this.sqlFilter; + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/common/utils/ExcelUtils.java b/renren-admin/src/main/java/io/renren/common/utils/ExcelUtils.java new file mode 100644 index 0000000..ada0a28 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/utils/ExcelUtils.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.converters.longconverter.LongStringConverter; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.BeanUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * excel工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class ExcelUtils { + + /** + * Excel导出 + * + * @param response response + * @param fileName 文件名 + * @param sheetName sheetName + * @param list 数据List + * @param pojoClass 对象Class + */ + public static void exportExcel(HttpServletResponse response, String fileName, String sheetName, List list, + Class pojoClass) throws IOException { + if (StrUtil.isBlank(fileName)) { + //当前日期 + fileName = DateUtils.format(new Date()); + } + + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("UTF-8"); + fileName = URLUtil.encode(fileName, StandardCharsets.UTF_8); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + EasyExcel.write(response.getOutputStream(), pojoClass).registerConverter(new LongStringConverter()).sheet(sheetName).doWrite(list); + } + + /** + * Excel导出,先sourceList转换成List,再导出 + * + * @param response response + * @param fileName 文件名 + * @param sheetName sheetName + * @param sourceList 原数据List + * @param targetClass 目标对象Class + */ + public static void exportExcelToTarget(HttpServletResponse response, String fileName, String sheetName, List sourceList, + Class targetClass) throws Exception { + List targetList = new ArrayList<>(sourceList.size()); + for (Object source : sourceList) { + Object target = targetClass.newInstance(); + BeanUtils.copyProperties(source, target); + targetList.add(target); + } + + exportExcel(response, fileName, sheetName, targetList, targetClass); + } + +} diff --git a/renren-admin/src/main/java/io/renren/common/validator/group/AliyunGroup.java b/renren-admin/src/main/java/io/renren/common/validator/group/AliyunGroup.java new file mode 100644 index 0000000..d8e7b5c --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/validator/group/AliyunGroup.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + +/** + * 阿里云 + * + * @author Mark sunlightcs@gmail.com + */ +public interface AliyunGroup { +} diff --git a/renren-admin/src/main/java/io/renren/common/validator/group/QcloudGroup.java b/renren-admin/src/main/java/io/renren/common/validator/group/QcloudGroup.java new file mode 100644 index 0000000..376e988 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/validator/group/QcloudGroup.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + +/** + * 腾讯云 + * + * @author Mark sunlightcs@gmail.com + */ +public interface QcloudGroup { +} diff --git a/renren-admin/src/main/java/io/renren/common/validator/group/QiniuGroup.java b/renren-admin/src/main/java/io/renren/common/validator/group/QiniuGroup.java new file mode 100644 index 0000000..542018b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/validator/group/QiniuGroup.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + +/** + * 七牛 + * + * @author Mark sunlightcs@gmail.com + */ +public interface QiniuGroup { +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/config/ScheduleConfig.java b/renren-admin/src/main/java/io/renren/modules/job/config/ScheduleConfig.java new file mode 100644 index 0000000..abeeaa3 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/config/ScheduleConfig.java @@ -0,0 +1,66 @@ +///** +// * Copyright (c) 2018 人人开源 All rights reserved. +// * +// * https://www.renren.io +// * +// * 版权所有,侵权必究! +// */ +// +//package io.renren.modules.job.config; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.scheduling.quartz.SchedulerFactoryBean; +// +//import javax.sql.DataSource; +//import java.util.Properties; +// +///** +// * 定时任务配置(备注:集群需要打开注释) +// * +// * @author Mark sunlightcs@gmail.com +// */ +//@Configuration +//public class ScheduleConfig { +// +// @Bean +// public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) { +// SchedulerFactoryBean factory = new SchedulerFactoryBean(); +// factory.setDataSource(dataSource); +// +// //quartz参数 +// Properties prop = new Properties(); +// prop.put("org.quartz.scheduler.instanceName", "RenrenScheduler"); +// prop.put("org.quartz.scheduler.instanceId", "AUTO"); +// //线程池配置 +// prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); +// prop.put("org.quartz.threadPool.threadCount", "20"); +// prop.put("org.quartz.threadPool.threadPriority", "5"); +// //JobStore配置 +// prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore"); +// //集群配置 +// prop.put("org.quartz.jobStore.isClustered", "true"); +// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); +// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); +// +// prop.put("org.quartz.jobStore.misfireThreshold", "12000"); +// prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); +// prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); +// +// //PostgreSQL数据库,需要打开此注释 +// //prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate"); +// +// factory.setQuartzProperties(prop); +// +// factory.setSchedulerName("RenrenScheduler"); +// //延时启动 +// factory.setStartupDelay(30); +// factory.setApplicationContextSchedulerContextKey("applicationContextKey"); +// //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 +// factory.setOverwriteExistingJobs(true); +// //设置自动启动,默认为true +// factory.setAutoStartup(true); +// +// return factory; +// } +//} diff --git a/renren-admin/src/main/java/io/renren/modules/job/controller/ScheduleJobController.java b/renren-admin/src/main/java/io/renren/modules/job/controller/ScheduleJobController.java new file mode 100644 index 0000000..f52e8b8 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/controller/ScheduleJobController.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.job.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.Result; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.job.dto.ScheduleJobDTO; +import io.renren.modules.job.service.ScheduleJobService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 定时任务 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/sys/schedule") +@Tag(name = "定时任务") +@AllArgsConstructor +public class ScheduleJobController { + private final ScheduleJobService scheduleJobService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "beanName", description = "beanName", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:schedule:page") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = scheduleJobService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:schedule:info") + public Result info(@PathVariable("id") Long id) { + ScheduleJobDTO schedule = scheduleJobService.get(id); + + return new Result().ok(schedule); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:schedule:save") + public Result save(@RequestBody ScheduleJobDTO dto) { + ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); + + scheduleJobService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:schedule:update") + public Result update(@RequestBody ScheduleJobDTO dto) { + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + scheduleJobService.update(dto); + + return new Result(); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:schedule:delete") + public Result delete(@RequestBody Long[] ids) { + scheduleJobService.deleteBatch(ids); + + return new Result(); + } + + @PutMapping("/run") + @Operation(summary = "立即执行") + @LogOperation("立即执行") + @RequiresPermissions("sys:schedule:run") + public Result run(@RequestBody Long[] ids) { + scheduleJobService.run(ids); + + return new Result(); + } + + @PutMapping("/pause") + @Operation(summary = "暂停") + @LogOperation("暂停") + @RequiresPermissions("sys:schedule:pause") + public Result pause(@RequestBody Long[] ids) { + scheduleJobService.pause(ids); + + return new Result(); + } + + @PutMapping("/resume") + @Operation(summary = "恢复") + @LogOperation("恢复") + @RequiresPermissions("sys:schedule:resume") + public Result resume(@RequestBody Long[] ids) { + scheduleJobService.resume(ids); + + return new Result(); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/controller/ScheduleJobLogController.java b/renren-admin/src/main/java/io/renren/modules/job/controller/ScheduleJobLogController.java new file mode 100644 index 0000000..d97ea4e --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/controller/ScheduleJobLogController.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.job.controller; + +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.Result; +import io.renren.modules.job.dto.ScheduleJobLogDTO; +import io.renren.modules.job.service.ScheduleJobLogService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 定时任务日志 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/sys/scheduleLog") +@Tag(name = "定时任务日志") +@AllArgsConstructor +public class ScheduleJobLogController { + private final ScheduleJobLogService scheduleJobLogService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "jobId", description = "jobId", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:schedule:log") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = scheduleJobLogService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:schedule:log") + public Result info(@PathVariable("id") Long id) { + ScheduleJobLogDTO log = scheduleJobLogService.get(id); + + return new Result().ok(log); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/dao/ScheduleJobDao.java b/renren-admin/src/main/java/io/renren/modules/job/dao/ScheduleJobDao.java new file mode 100644 index 0000000..c5e6f91 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/dao/ScheduleJobDao.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.job.entity.ScheduleJobEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Map; + +/** + * 定时任务 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface ScheduleJobDao extends BaseDao { + + /** + * 批量更新状态 + */ + int updateBatch(Map map); +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/dao/ScheduleJobLogDao.java b/renren-admin/src/main/java/io/renren/modules/job/dao/ScheduleJobLogDao.java new file mode 100644 index 0000000..9c46eb3 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/dao/ScheduleJobLogDao.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.job.entity.ScheduleJobLogEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 定时任务日志 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface ScheduleJobLogDao extends BaseDao { + +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/dto/ScheduleJobDTO.java b/renren-admin/src/main/java/io/renren/modules/job/dto/ScheduleJobDTO.java new file mode 100644 index 0000000..4f1985b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/dto/ScheduleJobDTO.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; +import org.hibernate.validator.constraints.Range; + +import java.io.Serializable; +import java.util.Date; + +/** + * 定时任务 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "定时任务") +public class ScheduleJobDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "spring bean名称") + @NotBlank(message = "{schedule.bean.require}", groups = DefaultGroup.class) + private String beanName; + + @Schema(title = "参数") + private String params; + + @Schema(title = "cron表达式") + @NotBlank(message = "{schedule.cron.require}", groups = DefaultGroup.class) + private String cronExpression; + + @Schema(title = "任务状态 0:暂停 1:正常") + @Range(min=0, max=1, message = "{schedule.status.range}", groups = DefaultGroup.class) + private Integer status; + + @Schema(title = "备注") + private String remark; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date createDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/dto/ScheduleJobLogDTO.java b/renren-admin/src/main/java/io/renren/modules/job/dto/ScheduleJobLogDTO.java new file mode 100644 index 0000000..1f2a964 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/dto/ScheduleJobLogDTO.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 定时任务日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "定时任务日志") +public class ScheduleJobLogDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + private Long id; + + @Schema(title = "任务id") + private Long jobId; + + @Schema(title = "spring bean名称") + private String beanName; + + @Schema(title = "参数") + private String params; + + @Schema(title = "任务状态 0:失败 1:成功") + private Integer status; + + @Schema(title = "失败信息") + private String error; + + @Schema(title = "耗时(单位:毫秒)") + private Integer times; + + @Schema(title = "创建时间") + private Date createDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/entity/ScheduleJobEntity.java b/renren-admin/src/main/java/io/renren/modules/job/entity/ScheduleJobEntity.java new file mode 100644 index 0000000..7c584bd --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/entity/ScheduleJobEntity.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 定时任务 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("schedule_job") +public class ScheduleJobEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * spring bean名称 + */ + private String beanName; + /** + * 参数 + */ + private String params; + /** + * cron表达式 + */ + private String cronExpression; + /** + * 任务状态 0:暂停 1:正常 + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/entity/ScheduleJobLogEntity.java b/renren-admin/src/main/java/io/renren/modules/job/entity/ScheduleJobLogEntity.java new file mode 100644 index 0000000..0d4c9eb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/entity/ScheduleJobLogEntity.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 定时任务日志 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@TableName("schedule_job_log") +public class ScheduleJobLogEntity implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId + private Long id; + /** + * 任务id + */ + private Long jobId; + /** + * spring bean名称 + */ + private String beanName; + /** + * 参数 + */ + private String params; + /** + * 任务状态 0:失败 1:成功 + */ + private Integer status; + /** + * 失败信息 + */ + private String error; + /** + * 耗时(单位:毫秒) + */ + private Integer times; + /** + * 创建时间 + */ + private Date createDate; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/init/JobCommandLineRunner.java b/renren-admin/src/main/java/io/renren/modules/job/init/JobCommandLineRunner.java new file mode 100644 index 0000000..a26d663 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/init/JobCommandLineRunner.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.job.init; + +import io.renren.modules.job.dao.ScheduleJobDao; +import io.renren.modules.job.entity.ScheduleJobEntity; +import io.renren.modules.job.utils.ScheduleUtils; +import lombok.AllArgsConstructor; +import org.quartz.CronTrigger; +import org.quartz.Scheduler; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 初始化定时任务数据 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +@AllArgsConstructor +public class JobCommandLineRunner implements CommandLineRunner { + private final Scheduler scheduler; + private final ScheduleJobDao scheduleJobDao; + + @Override + public void run(String... args) { + List scheduleJobList = scheduleJobDao.selectList(null); + for (ScheduleJobEntity scheduleJob : scheduleJobList) { + CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId()); + //如果不存在,则创建 + if (cronTrigger == null) { + ScheduleUtils.createScheduleJob(scheduler, scheduleJob); + } else { + ScheduleUtils.updateScheduleJob(scheduler, scheduleJob); + } + } + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/service/ScheduleJobLogService.java b/renren-admin/src/main/java/io/renren/modules/job/service/ScheduleJobLogService.java new file mode 100644 index 0000000..8c4e5bb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/service/ScheduleJobLogService.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.job.dto.ScheduleJobLogDTO; +import io.renren.modules.job.entity.ScheduleJobLogEntity; + +import java.util.Map; + +/** + * 定时任务日志 + * + * @author Mark sunlightcs@gmail.com + */ +public interface ScheduleJobLogService extends BaseService { + + PageData page(Map params); + + ScheduleJobLogDTO get(Long id); +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/service/ScheduleJobService.java b/renren-admin/src/main/java/io/renren/modules/job/service/ScheduleJobService.java new file mode 100644 index 0000000..970f8c8 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/service/ScheduleJobService.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.job.dto.ScheduleJobDTO; +import io.renren.modules.job.entity.ScheduleJobEntity; + +import java.util.Map; + +/** + * 定时任务 + * + * @author Mark sunlightcs@gmail.com + */ +public interface ScheduleJobService extends BaseService { + + PageData page(Map params); + + ScheduleJobDTO get(Long id); + + /** + * 保存定时任务 + */ + void save(ScheduleJobDTO dto); + + /** + * 更新定时任务 + */ + void update(ScheduleJobDTO dto); + + /** + * 批量删除定时任务 + */ + void deleteBatch(Long[] ids); + + /** + * 批量更新定时任务状态 + */ + int updateBatch(Long[] ids, int status); + + /** + * 立即执行 + */ + void run(Long[] ids); + + /** + * 暂停运行 + */ + void pause(Long[] ids); + + /** + * 恢复运行 + */ + void resume(Long[] ids); +} diff --git a/renren-admin/src/main/java/io/renren/modules/job/service/impl/ScheduleJobLogServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/job/service/impl/ScheduleJobLogServiceImpl.java new file mode 100644 index 0000000..4196c9f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/service/impl/ScheduleJobLogServiceImpl.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.job.dao.ScheduleJobLogDao; +import io.renren.modules.job.dto.ScheduleJobLogDTO; +import io.renren.modules.job.entity.ScheduleJobLogEntity; +import io.renren.modules.job.service.ScheduleJobLogService; +import cn.hutool.core.util.StrUtil; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service +public class ScheduleJobLogServiceImpl extends BaseServiceImpl implements ScheduleJobLogService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + return getPageData(page, ScheduleJobLogDTO.class); + } + + private QueryWrapper getWrapper(Map params){ + String jobId = (String)params.get("jobId"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(StrUtil.isNotBlank(jobId), "job_id", jobId); + + return wrapper; + } + + @Override + public ScheduleJobLogDTO get(Long id) { + ScheduleJobLogEntity entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, ScheduleJobLogDTO.class); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/service/impl/ScheduleJobServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/job/service/impl/ScheduleJobServiceImpl.java new file mode 100644 index 0000000..66f018d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/service/impl/ScheduleJobServiceImpl.java @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.job.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.job.dao.ScheduleJobDao; +import io.renren.modules.job.dto.ScheduleJobDTO; +import io.renren.modules.job.entity.ScheduleJobEntity; +import io.renren.modules.job.service.ScheduleJobService; +import io.renren.modules.job.utils.ScheduleUtils; +import lombok.AllArgsConstructor; +import org.quartz.Scheduler; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +@Service +@AllArgsConstructor +public class ScheduleJobServiceImpl extends BaseServiceImpl implements ScheduleJobService { + private final Scheduler scheduler; + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + return getPageData(page, ScheduleJobDTO.class); + } + + @Override + public ScheduleJobDTO get(Long id) { + ScheduleJobEntity entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, ScheduleJobDTO.class); + } + + private QueryWrapper getWrapper(Map params) { + String beanName = (String) params.get("beanName"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.like(StrUtil.isNotBlank(beanName), "bean_name", beanName); + + return wrapper; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(ScheduleJobDTO dto) { + ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class); + + entity.setStatus(Constant.ScheduleStatus.NORMAL.getValue()); + this.insert(entity); + + ScheduleUtils.createScheduleJob(scheduler, entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(ScheduleJobDTO dto) { + ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class); + + ScheduleUtils.updateScheduleJob(scheduler, entity); + + this.updateById(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteBatch(Long[] ids) { + for (Long id : ids) { + ScheduleUtils.deleteScheduleJob(scheduler, id); + } + + //删除数据 + this.deleteBatchIds(Arrays.asList(ids)); + } + + @Override + public int updateBatch(Long[] ids, int status) { + Map map = new HashMap<>(2); + map.put("ids", ids); + map.put("status", status); + return baseDao.updateBatch(map); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void run(Long[] ids) { + for (Long id : ids) { + ScheduleUtils.run(scheduler, this.selectById(id)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void pause(Long[] ids) { + for (Long id : ids) { + ScheduleUtils.pauseJob(scheduler, id); + } + + updateBatch(ids, Constant.ScheduleStatus.PAUSE.getValue()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void resume(Long[] ids) { + for (Long id : ids) { + ScheduleUtils.resumeJob(scheduler, id); + } + + updateBatch(ids, Constant.ScheduleStatus.NORMAL.getValue()); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/task/ITask.java b/renren-admin/src/main/java/io/renren/modules/job/task/ITask.java new file mode 100644 index 0000000..c6e09b9 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/task/ITask.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.task; + +/** + * 定时任务接口,所有定时任务都要实现该接口 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface ITask { + + /** + * 执行定时任务接口 + * + * @param params 参数,多参数使用JSON数据 + */ + void run(String params); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/task/TestTask.java b/renren-admin/src/main/java/io/renren/modules/job/task/TestTask.java new file mode 100644 index 0000000..7dc12ea --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/task/TestTask.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.task; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * 测试定时任务(演示Demo,可删除) + * + * testTask为spring bean的名称 + * + * @author Mark sunlightcs@gmail.com + */ +@Component("testTask") +public class TestTask implements ITask{ + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void run(String params){ + logger.debug("TestTask定时任务正在执行,参数为:{}", params); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/utils/ScheduleJob.java b/renren-admin/src/main/java/io/renren/modules/job/utils/ScheduleJob.java new file mode 100644 index 0000000..257ba18 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/utils/ScheduleJob.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.utils; + +import io.renren.common.constant.Constant; +import io.renren.common.exception.ExceptionUtils; +import io.renren.common.utils.SpringContextUtils; +import io.renren.modules.job.entity.ScheduleJobEntity; +import io.renren.modules.job.entity.ScheduleJobLogEntity; +import io.renren.modules.job.service.ScheduleJobLogService; +import org.quartz.JobExecutionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.lang.reflect.Method; +import java.util.Date; + + +/** + * 定时任务 + * + * @author Mark sunlightcs@gmail.com + */ +public class ScheduleJob extends QuartzJobBean { + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + protected void executeInternal(JobExecutionContext context) { + ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap(). + get(ScheduleUtils.JOB_PARAM_KEY); + + //数据库保存执行记录 + ScheduleJobLogEntity log = new ScheduleJobLogEntity(); + log.setJobId(scheduleJob.getId()); + log.setBeanName(scheduleJob.getBeanName()); + log.setParams(scheduleJob.getParams()); + log.setCreateDate(new Date()); + + //任务开始时间 + long startTime = System.currentTimeMillis(); + + try { + //执行任务 + logger.info("任务准备执行,任务ID:{}", scheduleJob.getId()); + Object target = SpringContextUtils.getBean(scheduleJob.getBeanName()); + Method method = target.getClass().getDeclaredMethod("run", String.class); + method.invoke(target, scheduleJob.getParams()); + + //任务执行总时长 + long times = System.currentTimeMillis() - startTime; + log.setTimes((int)times); + //任务状态 + log.setStatus(Constant.SUCCESS); + + logger.info("任务执行完毕,任务ID:{} 总共耗时:{} 毫秒", scheduleJob.getId(), times); + } catch (Exception e) { + logger.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e); + + //任务执行总时长 + long times = System.currentTimeMillis() - startTime; + log.setTimes((int)times); + + //任务状态 + log.setStatus(Constant.FAIL); + log.setError(ExceptionUtils.getErrorStackTrace(e)); + }finally { + //获取spring bean + ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class); + scheduleJobLogService.insert(log); + } + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/job/utils/ScheduleUtils.java b/renren-admin/src/main/java/io/renren/modules/job/utils/ScheduleUtils.java new file mode 100644 index 0000000..7e141b9 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/job/utils/ScheduleUtils.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.job.utils; + +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.modules.job.entity.ScheduleJobEntity; +import org.quartz.*; + +/** + * 定时任务工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class ScheduleUtils { + private final static String JOB_NAME = "TASK_"; + /** + * 任务调度参数key + */ + public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY"; + + /** + * 获取触发器key + */ + public static TriggerKey getTriggerKey(Long jobId) { + return TriggerKey.triggerKey(JOB_NAME + jobId); + } + + /** + * 获取jobKey + */ + public static JobKey getJobKey(Long jobId) { + return JobKey.jobKey(JOB_NAME + jobId); + } + + /** + * 获取表达式触发器 + */ + public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) { + try { + return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId)); + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } + + /** + * 创建定时任务 + */ + public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) { + try { + //构建job信息 + JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getId())).build(); + + //表达式调度构建器 + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()) + .withMisfireHandlingInstructionDoNothing(); + + //按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build(); + + //放入参数,运行时的方法可以获取 + jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob); + + scheduler.scheduleJob(jobDetail, trigger); + + //暂停任务 + if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){ + pauseJob(scheduler, scheduleJob.getId()); + } + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } + + /** + * 更新定时任务 + */ + public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) { + try { + TriggerKey triggerKey = getTriggerKey(scheduleJob.getId()); + + //表达式调度构建器 + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()) + .withMisfireHandlingInstructionDoNothing(); + + CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId()); + + //按新的cronExpression表达式重新构建trigger + trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); + + //参数 + trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob); + + scheduler.rescheduleJob(triggerKey, trigger); + + //暂停任务 + if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){ + pauseJob(scheduler, scheduleJob.getId()); + } + + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } + + /** + * 立即执行任务 + */ + public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) { + try { + //参数 + JobDataMap dataMap = new JobDataMap(); + dataMap.put(JOB_PARAM_KEY, scheduleJob); + + scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap); + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } + + /** + * 暂停任务 + */ + public static void pauseJob(Scheduler scheduler, Long jobId) { + try { + scheduler.pauseJob(getJobKey(jobId)); + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } + + /** + * 恢复任务 + */ + public static void resumeJob(Scheduler scheduler, Long jobId) { + try { + scheduler.resumeJob(getJobKey(jobId)); + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } + + /** + * 删除定时任务 + */ + public static void deleteScheduleJob(Scheduler scheduler, Long jobId) { + try { + scheduler.deleteJob(getJobKey(jobId)); + } catch (SchedulerException e) { + throw new RenException(ErrorCode.JOB_ERROR, e); + } + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogErrorController.java b/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogErrorController.java new file mode 100644 index 0000000..e02266b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogErrorController.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.ExcelUtils; +import io.renren.common.utils.Result; +import io.renren.modules.log.dto.SysLogErrorDTO; +import io.renren.modules.log.excel.SysLogErrorExcel; +import io.renren.modules.log.service.SysLogErrorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; + + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@RestController +@RequestMapping("sys/log/error") +@Tag(name = "异常日志") +@AllArgsConstructor +public class SysLogErrorController { + private final SysLogErrorService sysLogErrorService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:log:error") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysLogErrorService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("export") + @Operation(summary = "导出") + @LogOperation("导出") + @RequiresPermissions("sys:log:error") + public void export(@Parameter(hidden = true) @RequestParam Map params, HttpServletResponse response) throws Exception { + List list = sysLogErrorService.list(params); + + ExcelUtils.exportExcelToTarget(response, null, "异常日志", list, SysLogErrorExcel.class); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogLoginController.java b/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogLoginController.java new file mode 100644 index 0000000..b7dd76d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogLoginController.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.ExcelUtils; +import io.renren.common.utils.Result; +import io.renren.modules.log.dto.SysLogLoginDTO; +import io.renren.modules.log.excel.SysLogLoginExcel; +import io.renren.modules.log.service.SysLogLoginService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; + + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@RestController +@RequestMapping("sys/log/login") +@Tag(name = "登录日志") +@AllArgsConstructor +public class SysLogLoginController { + private final SysLogLoginService sysLogLoginService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "status", description = "状态 0:失败 1:成功 2:账号已锁定", in = ParameterIn.QUERY, ref = "int"), + @Parameter(name = "creatorName", description = "用户名", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:log:login") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysLogLoginService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("export") + @Operation(summary = "导出") + @LogOperation("导出") + @Parameters({ + @Parameter(name = "status", description = "状态 0:失败 1:成功 2:账号已锁定", in = ParameterIn.QUERY, ref = "int"), + @Parameter(name = "creatorName", description = "用户名", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:log:login") + public void export(@Parameter(hidden = true) @RequestParam Map params, HttpServletResponse response) throws Exception { + List list = sysLogLoginService.list(params); + + ExcelUtils.exportExcelToTarget(response, null, "登录日志", list, SysLogLoginExcel.class); + + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogOperationController.java b/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogOperationController.java new file mode 100644 index 0000000..eb9c15f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/controller/SysLogOperationController.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.ExcelUtils; +import io.renren.common.utils.Result; +import io.renren.modules.log.dto.SysLogOperationDTO; +import io.renren.modules.log.excel.SysLogOperationExcel; +import io.renren.modules.log.service.SysLogOperationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; + + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@RestController +@RequestMapping("sys/log/operation") +@Tag(name = "操作日志") +@AllArgsConstructor +public class SysLogOperationController { + private final SysLogOperationService sysLogOperationService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "status", description = "状态 0:失败 1:成功", in = ParameterIn.QUERY, ref = "int") + }) + @RequiresPermissions("sys:log:operation") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysLogOperationService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("export") + @Operation(summary = "导出") + @LogOperation("导出") + @RequiresPermissions("sys:log:operation") + public void export(@Parameter(hidden = true) @RequestParam Map params, HttpServletResponse response) throws Exception { + List list = sysLogOperationService.list(params); + + ExcelUtils.exportExcelToTarget(response, null, "操作日志", list, SysLogOperationExcel.class); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogErrorDao.java b/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogErrorDao.java new file mode 100644 index 0000000..cf7e397 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogErrorDao.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.log.entity.SysLogErrorEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Mapper +public interface SysLogErrorDao extends BaseDao { + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogLoginDao.java b/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogLoginDao.java new file mode 100644 index 0000000..3ed5087 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogLoginDao.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.log.entity.SysLogLoginEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Mapper +public interface SysLogLoginDao extends BaseDao { + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogOperationDao.java b/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogOperationDao.java new file mode 100644 index 0000000..5be96ca --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/dao/SysLogOperationDao.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.log.entity.SysLogOperationEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Mapper +public interface SysLogOperationDao extends BaseDao { + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogErrorDTO.java b/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogErrorDTO.java new file mode 100644 index 0000000..597fd04 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogErrorDTO.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.renren.common.utils.DateUtils; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(description = "异常日志") +public class SysLogErrorDTO implements Serializable { + + @Schema(description = "id") + private Long id; + @Schema(description = "请求URI") + private String requestUri; + @Schema(description = "请求方式") + private String requestMethod; + @Schema(description = "请求参数") + private String requestParams; + @Schema(description = "用户代理") + private String userAgent; + @Schema(description = "操作IP") + private String ip; + @Schema(description = "异常信息") + private String errorInfo; + @Schema(description = "创建时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date createDate; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogLoginDTO.java b/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogLoginDTO.java new file mode 100644 index 0000000..91ec1d7 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogLoginDTO.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.renren.common.utils.DateUtils; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(description = "登录日志") +public class SysLogLoginDTO implements Serializable { + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户操作 0:用户登录 1:用户退出") + private Integer operation; + + @Schema(description = "状态 0:失败 1:成功 2:账号已锁定") + private Integer status; + + @Schema(description = "用户代理") + private String userAgent; + + @Schema(description = "操作IP") + private String ip; + + @Schema(description = "用户名") + private String creatorName; + + @Schema(description = "创建时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date createDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogOperationDTO.java b/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogOperationDTO.java new file mode 100644 index 0000000..ba4f819 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/dto/SysLogOperationDTO.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.renren.common.utils.DateUtils; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(description = "操作日志") +public class SysLogOperationDTO implements Serializable { + @Schema(description = "id") + private Long id; + + @Schema(description = "用户操作") + private String operation; + + @Schema(description = "请求URI") + private String requestUri; + + @Schema(description = "请求方式") + private String requestMethod; + + @Schema(description = "请求参数") + private String requestParams; + + @Schema(description = "请求时长(毫秒)") + private Integer requestTime; + + @Schema(description = "用户代理") + private String userAgent; + + @Schema(description = "操作IP") + private String ip; + + @Schema(description = "状态 0:失败 1:成功") + private Integer status; + + @Schema(description = "用户名") + private String creatorName; + + @Schema(description = "创建时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date createDate; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogErrorEntity.java b/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogErrorEntity.java new file mode 100644 index 0000000..b14a970 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogErrorEntity.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_log_error") +public class SysLogErrorEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 请求URI + */ + private String requestUri; + /** + * 请求方式 + */ + private String requestMethod; + /** + * 请求参数 + */ + private String requestParams; + /** + * 用户代理 + */ + private String userAgent; + /** + * 操作IP + */ + private String ip; + /** + * 异常信息 + */ + private String errorInfo; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogLoginEntity.java b/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogLoginEntity.java new file mode 100644 index 0000000..2be0651 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogLoginEntity.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_log_login") +public class SysLogLoginEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 用户操作 0:用户登录 1:用户退出 + */ + private Integer operation; + /** + * 状态 0:失败 1:成功 2:账号已锁定 + */ + private Integer status; + /** + * 用户代理 + */ + private String userAgent; + /** + * 操作IP + */ + private String ip; + /** + * 用户名 + */ + private String creatorName; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogOperationEntity.java b/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogOperationEntity.java new file mode 100644 index 0000000..ac1ce1e --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/entity/SysLogOperationEntity.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_log_operation") +public class SysLogOperationEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 用户操作 + */ + private String operation; + /** + * 请求URI + */ + private String requestUri; + /** + * 请求方式 + */ + private String requestMethod; + /** + * 请求参数 + */ + private String requestParams; + /** + * 请求时长(毫秒) + */ + private Integer requestTime; + /** + * 用户代理 + */ + private String userAgent; + /** + * 操作IP + */ + private String ip; + /** + * 状态 0:失败 1:成功 + */ + private Integer status; + /** + * 用户名 + */ + private String creatorName; +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/enums/LoginOperationEnum.java b/renren-admin/src/main/java/io/renren/modules/log/enums/LoginOperationEnum.java new file mode 100644 index 0000000..a130c96 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/enums/LoginOperationEnum.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.enums; + +/** + * 登录操作枚举 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public enum LoginOperationEnum { + /** + * 用户登录 + */ + LOGIN(0), + /** + * 用户退出 + */ + LOGOUT(1); + + private int value; + + LoginOperationEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/enums/LoginStatusEnum.java b/renren-admin/src/main/java/io/renren/modules/log/enums/LoginStatusEnum.java new file mode 100644 index 0000000..0292db3 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/enums/LoginStatusEnum.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.enums; + +/** + * 登录状态枚举 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public enum LoginStatusEnum { + /** + * 失败 + */ + FAIL(0), + /** + * 成功 + */ + SUCCESS(1), + /** + * 账号已锁定 + */ + LOCK(2); + + private int value; + + LoginStatusEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/enums/OperationStatusEnum.java b/renren-admin/src/main/java/io/renren/modules/log/enums/OperationStatusEnum.java new file mode 100644 index 0000000..366e5fa --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/enums/OperationStatusEnum.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.enums; + +/** + * 操作状态枚举 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public enum OperationStatusEnum { + /** + * 失败 + */ + FAIL(0), + /** + * 成功 + */ + SUCCESS(1); + + private int value; + + OperationStatusEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogErrorExcel.java b/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogErrorExcel.java new file mode 100644 index 0000000..47cac98 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogErrorExcel.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import lombok.Data; + +import java.util.Date; + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@ContentRowHeight(20) +@HeadRowHeight(20) +@ColumnWidth(25) +public class SysLogErrorExcel { + @ExcelProperty("请求URI") + private String requestUri; + + @ExcelProperty("请求方式") + private String requestMethod; + + @ExcelProperty("请求参数") + private String requestParams; + + @ExcelProperty("User-Agent") + private String userAgent; + + @ExcelProperty("操作IP") + private String ip; + + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty("创建时间") + private Date createDate; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogLoginExcel.java b/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogLoginExcel.java new file mode 100644 index 0000000..2b42f31 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogLoginExcel.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import io.renren.modules.log.excel.converter.SysLogOperationConverter; +import io.renren.modules.log.excel.converter.SysLogStatusConverter; +import lombok.Data; + +import java.util.Date; + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@ContentRowHeight(20) +@HeadRowHeight(20) +@ColumnWidth(25) +public class SysLogLoginExcel { + @ExcelProperty(value = "操作类型", converter = SysLogOperationConverter.class) + private Integer operation; + + @ExcelProperty(value = "状态", converter = SysLogStatusConverter.class) + private Integer status; + + @ExcelProperty("User-Agent") + private String userAgent; + + @ExcelProperty("操作IP") + private String ip; + + @ExcelProperty("用户名") + private String creatorName; + + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty("创建时间") + private Date createDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogOperationExcel.java b/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogOperationExcel.java new file mode 100644 index 0000000..1ae8b9d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/excel/SysLogOperationExcel.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.log.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import lombok.Data; + +import java.util.Date; + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@ContentRowHeight(20) +@HeadRowHeight(20) +@ColumnWidth(25) +public class SysLogOperationExcel { + @ExcelProperty("用户操作") + private String operation; + + @ExcelProperty("请求URI") + private String requestUri; + + @ExcelProperty("请求方式") + private String requestMethod; + + @ExcelProperty("请求参数") + private String requestParams; + + @ExcelProperty("请求时长(毫秒)") + private Integer requestTime; + + @ExcelProperty("User-Agent") + private String userAgent; + + @ExcelProperty("操作IP") + private String ip; + + @ExcelProperty("状态") + private Integer status; + + @ExcelProperty("用户名") + private String creatorName; + + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty("创建时间") + private Date createDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/excel/converter/SysLogOperationConverter.java b/renren-admin/src/main/java/io/renren/modules/log/excel/converter/SysLogOperationConverter.java new file mode 100644 index 0000000..195ea6f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/excel/converter/SysLogOperationConverter.java @@ -0,0 +1,40 @@ +package io.renren.modules.log.excel.converter; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +public class SysLogOperationConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Integer.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if(cellData.getStringValue().equals("用户登录")){ + return 0; + }else{ + return 1; + } + } + + @Override + public WriteCellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if(value == 0){ + return new WriteCellData<>("用户登录"); + }else{ + return new WriteCellData<>("用户退出"); + } + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/excel/converter/SysLogStatusConverter.java b/renren-admin/src/main/java/io/renren/modules/log/excel/converter/SysLogStatusConverter.java new file mode 100644 index 0000000..32d3037 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/excel/converter/SysLogStatusConverter.java @@ -0,0 +1,48 @@ +package io.renren.modules.log.excel.converter; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +public class SysLogStatusConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Integer.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if(cellData.getStringValue().equals("失败")){ + return 0; + }else if(cellData.getStringValue().equals("成功")){ + return 1; + }else if(cellData.getStringValue().equals("账号已锁定")){ + return 2; + }else{ + return -1; + } + } + + @Override + public WriteCellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if(value == 0){ + return new WriteCellData<>("失败"); + }else if(value == 1){ + return new WriteCellData<>("成功"); + }else if(value == 2){ + return new WriteCellData<>("账号已锁定"); + }else{ + return new WriteCellData<>("未知"); + } + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/log/service/SysLogErrorService.java b/renren-admin/src/main/java/io/renren/modules/log/service/SysLogErrorService.java new file mode 100644 index 0000000..7ac9f66 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/service/SysLogErrorService.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.service; + + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.log.dto.SysLogErrorDTO; +import io.renren.modules.log.entity.SysLogErrorEntity; + +import java.util.List; +import java.util.Map; + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface SysLogErrorService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + void save(SysLogErrorEntity entity); + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/service/SysLogLoginService.java b/renren-admin/src/main/java/io/renren/modules/log/service/SysLogLoginService.java new file mode 100644 index 0000000..39ed28d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/service/SysLogLoginService.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.log.dto.SysLogLoginDTO; +import io.renren.modules.log.entity.SysLogLoginEntity; + +import java.util.List; +import java.util.Map; + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface SysLogLoginService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + void save(SysLogLoginEntity entity); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/service/SysLogOperationService.java b/renren-admin/src/main/java/io/renren/modules/log/service/SysLogOperationService.java new file mode 100644 index 0000000..5c7983e --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/service/SysLogOperationService.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.log.dto.SysLogOperationDTO; +import io.renren.modules.log.entity.SysLogOperationEntity; + +import java.util.List; +import java.util.Map; + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface SysLogOperationService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + void save(SysLogOperationEntity entity); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogErrorServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogErrorServiceImpl.java new file mode 100644 index 0000000..b249ae7 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogErrorServiceImpl.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.log.dao.SysLogErrorDao; +import io.renren.modules.log.dto.SysLogErrorDTO; +import io.renren.modules.log.entity.SysLogErrorEntity; +import io.renren.modules.log.service.SysLogErrorService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + * 异常日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Service +public class SysLogErrorServiceImpl extends BaseServiceImpl implements SysLogErrorService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + + return getPageData(page, SysLogErrorDTO.class); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, SysLogErrorDTO.class); + } + + private QueryWrapper getWrapper(Map params){ + QueryWrapper wrapper = new QueryWrapper<>(); + return wrapper; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysLogErrorEntity entity) { + insert(entity); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogLoginServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogLoginServiceImpl.java new file mode 100644 index 0000000..1b46ddc --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogLoginServiceImpl.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.log.dao.SysLogLoginDao; +import io.renren.modules.log.dto.SysLogLoginDTO; +import io.renren.modules.log.entity.SysLogLoginEntity; +import io.renren.modules.log.service.SysLogLoginService; +import cn.hutool.core.util.StrUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + * 登录日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Service +public class SysLogLoginServiceImpl extends BaseServiceImpl implements SysLogLoginService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + + return getPageData(page, SysLogLoginDTO.class); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, SysLogLoginDTO.class); + } + + private QueryWrapper getWrapper(Map params){ + String status = (String) params.get("status"); + String creatorName = (String) params.get("creatorName"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(StrUtil.isNotBlank(status), "status", status); + wrapper.like(StrUtil.isNotBlank(creatorName), "creator_name", creatorName); + + return wrapper; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysLogLoginEntity entity) { + insert(entity); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogOperationServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogOperationServiceImpl.java new file mode 100644 index 0000000..6398fcb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/log/service/impl/SysLogOperationServiceImpl.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.log.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.log.dao.SysLogOperationDao; +import io.renren.modules.log.dto.SysLogOperationDTO; +import io.renren.modules.log.entity.SysLogOperationEntity; +import io.renren.modules.log.service.SysLogOperationService; +import cn.hutool.core.util.StrUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + * 操作日志 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Service +public class SysLogOperationServiceImpl extends BaseServiceImpl implements SysLogOperationService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + + return getPageData(page, SysLogOperationDTO.class); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, SysLogOperationDTO.class); + } + + private QueryWrapper getWrapper(Map params){ + String status = (String) params.get("status"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(StrUtil.isNotBlank(status), "status", status); + + return wrapper; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysLogOperationEntity entity) { + insert(entity); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/AbstractCloudStorageService.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/AbstractCloudStorageService.java new file mode 100644 index 0000000..9203835 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/AbstractCloudStorageService.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.cloud; + +import io.renren.common.utils.DateUtils; +import cn.hutool.core.util.StrUtil; + +import java.io.InputStream; +import java.util.Date; +import java.util.UUID; + +/** + * 云存储(支持七牛、阿里云、腾讯云) + * + * @author Mark sunlightcs@gmail.com + */ +public abstract class AbstractCloudStorageService { + /** 云存储配置信息 */ + CloudStorageConfig config; + + /** + * 文件路径 + * @param prefix 前缀 + * @param suffix 后缀 + * @return 返回上传路径 + */ + public String getPath(String prefix, String suffix) { + //生成uuid + String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + //文件路径 + String path = DateUtils.format(new Date(), "yyyyMMdd") + "/" + uuid; + + if(StrUtil.isNotBlank(prefix)){ + path = prefix + "/" + path; + } + + return path + "." + suffix; + } + + /** + * 文件上传 + * @param data 文件字节数组 + * @param path 文件路径,包含文件名 + * @return 返回http地址 + */ + public abstract String upload(byte[] data, String path); + + /** + * 文件上传 + * @param data 文件字节数组 + * @param suffix 后缀 + * @return 返回http地址 + */ + public abstract String uploadSuffix(byte[] data, String suffix); + + /** + * 文件上传 + * @param inputStream 字节流 + * @param path 文件路径,包含文件名 + * @return 返回http地址 + */ + public abstract String upload(InputStream inputStream, String path); + + /** + * 文件上传 + * @param inputStream 字节流 + * @param suffix 后缀 + * @return 返回http地址 + */ + public abstract String uploadSuffix(InputStream inputStream, String suffix); + +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/AliyunCloudStorageService.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/AliyunCloudStorageService.java new file mode 100644 index 0000000..9754dbb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/AliyunCloudStorageService.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.cloud; + +import com.aliyun.oss.OSSClient; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * 阿里云存储 + * + * @author Mark sunlightcs@gmail.com + */ +public class AliyunCloudStorageService extends AbstractCloudStorageService { + + public AliyunCloudStorageService(CloudStorageConfig config){ + this.config = config; + } + + @Override + public String upload(byte[] data, String path) { + return upload(new ByteArrayInputStream(data), path); + } + + @Override + public String upload(InputStream inputStream, String path) { + OSSClient client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(), + config.getAliyunAccessKeySecret()); + try { + client.putObject(config.getAliyunBucketName(), path, inputStream); + client.shutdown(); + } catch (Exception e){ + throw new RenException(ErrorCode.OSS_UPLOAD_FILE_ERROR, e, ""); + } + + return config.getAliyunDomain() + "/" + path; + } + + @Override + public String uploadSuffix(byte[] data, String suffix) { + return upload(data, getPath(config.getAliyunPrefix(), suffix)); + } + + @Override + public String uploadSuffix(InputStream inputStream, String suffix) { + return upload(inputStream, getPath(config.getAliyunPrefix(), suffix)); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java new file mode 100644 index 0000000..0fe557f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.cloud; + +import io.renren.common.validator.group.AliyunGroup; +import io.renren.common.validator.group.QcloudGroup; +import io.renren.common.validator.group.QiniuGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Range; +import org.hibernate.validator.constraints.URL; + +import java.io.Serializable; + +/** + * 云存储配置信息 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "云存储配置信息") +public class CloudStorageConfig implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "类型 1:七牛 2:阿里云 3:腾讯云 ") + @Range(min = 1, max = 6, message = "{oss.type.range}") + private Integer type; + + @Schema(title = "七牛绑定的域名") + @NotBlank(message = "{qiniu.domain.require}", groups = QiniuGroup.class) + @URL(message = "{qiniu.domain.url}", groups = QiniuGroup.class) + private String qiniuDomain; + + @Schema(title = "七牛路径前缀") + private String qiniuPrefix; + + @Schema(title = "七牛ACCESS_KEY") + @NotBlank(message = "{qiniu.accesskey.require}", groups = QiniuGroup.class) + private String qiniuAccessKey; + + @Schema(title = "七牛SECRET_KEY") + @NotBlank(message = "{qiniu.secretkey.require}", groups = QiniuGroup.class) + private String qiniuSecretKey; + + @Schema(title = "七牛存储空间名") + @NotBlank(message = "{qiniu.bucketName.require}", groups = QiniuGroup.class) + private String qiniuBucketName; + + @Schema(title = "阿里云绑定的域名") + @NotBlank(message = "{aliyun.domain.require}", groups = AliyunGroup.class) + @URL(message = "{aliyun.domain.url}", groups = AliyunGroup.class) + private String aliyunDomain; + + @Schema(title = "阿里云路径前缀") + private String aliyunPrefix; + + @Schema(title = "阿里云EndPoint") + @NotBlank(message = "{aliyun.endPoint.require}", groups = AliyunGroup.class) + private String aliyunEndPoint; + + @Schema(title = "阿里云AccessKeyId") + @NotBlank(message = "{aliyun.accesskeyid.require}", groups = AliyunGroup.class) + private String aliyunAccessKeyId; + + @Schema(title = "阿里云AccessKeySecret") + @NotBlank(message = "{aliyun.accesskeysecret.require}", groups = AliyunGroup.class) + private String aliyunAccessKeySecret; + + @Schema(title = "阿里云BucketName") + @NotBlank(message = "{aliyun.bucketName.require}", groups = AliyunGroup.class) + private String aliyunBucketName; + + @Schema(title = "腾讯云绑定的域名") + @NotBlank(message = "{qcloud.domain.require}", groups = QcloudGroup.class) + @URL(message = "{qcloud.domain.url}", groups = QcloudGroup.class) + private String qcloudDomain; + + @Schema(title = "腾讯云路径前缀") + private String qcloudPrefix; + + @Schema(title = "腾讯云AppId") + @NotNull(message = "{qcloud.appid.require}", groups = QcloudGroup.class) + private Integer qcloudAppId; + + @Schema(title = "腾讯云SecretId") + @NotBlank(message = "{qcloud.secretId.require}", groups = QcloudGroup.class) + private String qcloudSecretId; + + @Schema(title = "腾讯云SecretKey") + @NotBlank(message = "{qcloud.secretkey.require}", groups = QcloudGroup.class) + private String qcloudSecretKey; + + @Schema(title = "腾讯云BucketName") + @NotBlank(message = "{qcloud.bucketName.require}", groups = QcloudGroup.class) + private String qcloudBucketName; + + @Schema(title = "腾讯云COS所属地区") + @NotBlank(message = "{qcloud.region.require}", groups = QcloudGroup.class) + private String qcloudRegion; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java new file mode 100644 index 0000000..f7d5bd5 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.cloud; + +import io.renren.common.constant.Constant; +import io.renren.common.utils.SpringContextUtils; +import io.renren.modules.sys.service.SysParamsService; + +/** + * 文件上传Factory + * @author Mark sunlightcs@gmail.com + */ +public final class OSSFactory { + private static SysParamsService sysParamsService; + + static { + OSSFactory.sysParamsService = SpringContextUtils.getBean(SysParamsService.class); + } + + public static AbstractCloudStorageService build(){ + //获取云存储配置信息 + CloudStorageConfig config = sysParamsService.getValueObject(Constant.CLOUD_STORAGE_CONFIG_KEY, CloudStorageConfig.class); + + if(config.getType() == Constant.CloudService.QINIU.getValue()){ + return new QiniuCloudStorageService(config); + }else if(config.getType() == Constant.CloudService.ALIYUN.getValue()){ + return new AliyunCloudStorageService(config); + }else if(config.getType() == Constant.CloudService.QCLOUD.getValue()){ + return new QcloudCloudStorageService(config); + } + + return null; + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/QcloudCloudStorageService.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/QcloudCloudStorageService.java new file mode 100644 index 0000000..80d05d6 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/QcloudCloudStorageService.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.cloud; + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.model.ObjectMetadata; +import com.qcloud.cos.model.PutObjectRequest; +import com.qcloud.cos.model.PutObjectResult; +import com.qcloud.cos.region.Region; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * 腾讯云存储 + * + * @author Mark sunlightcs@gmail.com + */ +public class QcloudCloudStorageService extends AbstractCloudStorageService { + private COSCredentials credentials; + private ClientConfig clientConfig; + + public QcloudCloudStorageService(CloudStorageConfig config){ + this.config = config; + + //初始化 + init(); + } + + private void init(){ + //1、初始化用户身份信息(secretId, secretKey) + credentials = new BasicCOSCredentials(config.getQcloudSecretId(), config.getQcloudSecretKey()); + + //2、设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224 + clientConfig = new ClientConfig(new Region(config.getQcloudRegion())); + } + + @Override + public String upload(byte[] data, String path) { + return upload(new ByteArrayInputStream(data), path); + } + + @Override + public String upload(InputStream inputStream, String path) { + try { + COSClient client = new COSClient(credentials, clientConfig); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(inputStream.available()); + String bucketName = config.getQcloudBucketName() +"-"+ config.getQcloudAppId(); + PutObjectRequest request = new PutObjectRequest(bucketName, path, inputStream, metadata); + PutObjectResult result = client.putObject(request); + + client.shutdown(); + if(result.getETag() == null){ + throw new RenException(ErrorCode.OSS_UPLOAD_FILE_ERROR, ""); + } + } catch (IOException e) { + throw new RenException(ErrorCode.OSS_UPLOAD_FILE_ERROR, e, ""); + } + + return config.getQcloudDomain() + "/" + path; + } + + @Override + public String uploadSuffix(byte[] data, String suffix) { + return upload(data, getPath(config.getQcloudPrefix(), suffix)); + } + + @Override + public String uploadSuffix(InputStream inputStream, String suffix) { + return upload(inputStream, getPath(config.getQcloudPrefix(), suffix)); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/QiniuCloudStorageService.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/QiniuCloudStorageService.java new file mode 100644 index 0000000..2ddc485 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/QiniuCloudStorageService.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.cloud; + +import com.qiniu.http.Response; +import com.qiniu.storage.Configuration; +import com.qiniu.storage.Region; +import com.qiniu.storage.UploadManager; +import com.qiniu.util.Auth; +import com.qiniu.util.IOUtils; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * 七牛云存储 + * + * @author Mark sunlightcs@gmail.com + */ +public class QiniuCloudStorageService extends AbstractCloudStorageService { + private UploadManager uploadManager; + private String token; + + public QiniuCloudStorageService(CloudStorageConfig config) { + this.config = config; + + //初始化 + init(); + } + + private void init() { + uploadManager = new UploadManager(new Configuration(Region.autoRegion())); + token = Auth.create(config.getQiniuAccessKey(), config.getQiniuSecretKey()). + uploadToken(config.getQiniuBucketName()); + + } + + @Override + public String upload(byte[] data, String path) { + try { + Response res = uploadManager.put(data, path, token); + if (!res.isOK()) { + throw new RenException(ErrorCode.OSS_UPLOAD_FILE_ERROR, res.toString()); + } + } catch (Exception e) { + throw new RenException(ErrorCode.OSS_UPLOAD_FILE_ERROR, e, ""); + } + + return config.getQiniuDomain() + "/" + path; + } + + @Override + public String upload(InputStream inputStream, String path) { + try { + byte[] data = IOUtils.toByteArray(inputStream); + return this.upload(data, path); + } catch (IOException e) { + throw new RenException(ErrorCode.OSS_UPLOAD_FILE_ERROR, e, ""); + } + } + + @Override + public String uploadSuffix(byte[] data, String suffix) { + return upload(data, getPath(config.getQiniuPrefix(), suffix)); + } + + @Override + public String uploadSuffix(InputStream inputStream, String suffix) { + return upload(inputStream, getPath(config.getQiniuPrefix(), suffix)); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java b/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java new file mode 100644 index 0000000..b08cd23 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.controller; + +import cn.hutool.core.io.file.FileNameUtil; +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.page.PageData; +import io.renren.common.utils.JsonUtils; +import io.renren.common.utils.Result; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.AliyunGroup; +import io.renren.common.validator.group.QcloudGroup; +import io.renren.common.validator.group.QiniuGroup; +import io.renren.modules.oss.cloud.CloudStorageConfig; +import io.renren.modules.oss.cloud.OSSFactory; +import io.renren.modules.oss.entity.SysOssEntity; +import io.renren.modules.oss.service.SysOssService; +import io.renren.modules.sys.service.SysParamsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 文件上传 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("sys/oss") +@Tag(name = "文件上传") +@AllArgsConstructor +public class SysOssController { + private final SysOssService sysOssService; + private final SysParamsService sysParamsService; + + private final static String KEY = Constant.CLOUD_STORAGE_CONFIG_KEY; + + @GetMapping("page") + @Operation(summary = "分页") + @RequiresPermissions("sys:oss:all") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysOssService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("info") + @Operation(summary = "云存储配置信息") + @RequiresPermissions("sys:oss:all") + public Result info() { + CloudStorageConfig config = sysParamsService.getValueObject(KEY, CloudStorageConfig.class); + + return new Result().ok(config); + } + + @PostMapping + @Operation(summary = "保存云存储配置信息") + @LogOperation("保存云存储配置信息") + @RequiresPermissions("sys:oss:all") + public Result saveConfig(@RequestBody CloudStorageConfig config) { + //校验类型 + ValidatorUtils.validateEntity(config); + + if (config.getType() == Constant.CloudService.QINIU.getValue()) { + //校验七牛数据 + ValidatorUtils.validateEntity(config, QiniuGroup.class); + } else if (config.getType() == Constant.CloudService.ALIYUN.getValue()) { + //校验阿里云数据 + ValidatorUtils.validateEntity(config, AliyunGroup.class); + } else if (config.getType() == Constant.CloudService.QCLOUD.getValue()) { + //校验腾讯云数据 + ValidatorUtils.validateEntity(config, QcloudGroup.class); + } + + sysParamsService.updateValueByCode(KEY, JsonUtils.toJsonString(config)); + + return new Result(); + } + + @PostMapping("upload") + @Operation(summary = "上传文件") + @RequiresPermissions("sys:oss:all") + public Result> upload(@RequestParam("file") MultipartFile file) throws Exception { + if (file.isEmpty()) { + return new Result>().error(ErrorCode.UPLOAD_FILE_EMPTY); + } + + //上传文件 + String suffix = FileNameUtil.getSuffix(file.getOriginalFilename()); + String url = OSSFactory.build().uploadSuffix(file.getBytes(), suffix); + + //保存文件信息 + SysOssEntity ossEntity = new SysOssEntity(); + ossEntity.setUrl(url); + ossEntity.setCreateDate(new Date()); + sysOssService.insert(ossEntity); + + Map data = new HashMap<>(1); + data.put("src", url); + + return new Result>().ok(data); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:oss:all") + public Result delete(@RequestBody Long[] ids) { + sysOssService.deleteBatchIds(Arrays.asList(ids)); + + return new Result(); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/dao/SysOssDao.java b/renren-admin/src/main/java/io/renren/modules/oss/dao/SysOssDao.java new file mode 100644 index 0000000..0b164b0 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/dao/SysOssDao.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.oss.entity.SysOssEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 文件上传 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysOssDao extends BaseDao { + +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/entity/SysOssEntity.java b/renren-admin/src/main/java/io/renren/modules/oss/entity/SysOssEntity.java new file mode 100644 index 0000000..af6601a --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/entity/SysOssEntity.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 文件上传 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_oss") +public class SysOssEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * URL地址 + */ + private String url; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/oss/service/SysOssService.java b/renren-admin/src/main/java/io/renren/modules/oss/service/SysOssService.java new file mode 100644 index 0000000..46736ef --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/service/SysOssService.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.oss.entity.SysOssEntity; + +import java.util.Map; + +/** + * 文件上传 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysOssService extends BaseService { + + PageData page(Map params); +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/service/impl/SysOssServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/oss/service/impl/SysOssServiceImpl.java new file mode 100644 index 0000000..04437e7 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/service/impl/SysOssServiceImpl.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.oss.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.modules.oss.dao.SysOssDao; +import io.renren.modules.oss.entity.SysOssEntity; +import io.renren.modules.oss.service.SysOssService; +import org.springframework.stereotype.Service; + +import java.util.Map; + + +@Service +public class SysOssServiceImpl extends BaseServiceImpl implements SysOssService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + new QueryWrapper<>() + ); + return getPageData(page, SysOssEntity.class); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/config/FilterConfig.java b/renren-admin/src/main/java/io/renren/modules/security/config/FilterConfig.java new file mode 100644 index 0000000..e2b7126 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/config/FilterConfig.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.config; + +import io.renren.common.xss.XssFilter; +import jakarta.servlet.DispatcherType; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.DelegatingFilterProxy; + + +/** + * Filter配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class FilterConfig { + + @Bean + public FilterRegistrationBean shiroFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new DelegatingFilterProxy("shiroFilter")); + //该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 + registration.addInitParameter("targetFilterLifecycle", "true"); + registration.setEnabled(true); + registration.setOrder(Integer.MAX_VALUE - 1); + registration.addUrlPatterns("/*"); + return registration; + } + + @Bean + public FilterRegistrationBean xssFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns("/*"); + registration.setName("xssFilter"); + registration.setOrder(Integer.MAX_VALUE); + return registration; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/config/ShiroConfig.java b/renren-admin/src/main/java/io/renren/modules/security/config/ShiroConfig.java new file mode 100644 index 0000000..020dda8 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/config/ShiroConfig.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.config; + +import io.renren.modules.security.oauth2.Oauth2Filter; +import io.renren.modules.security.oauth2.Oauth2Realm; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.session.mgt.SessionManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import jakarta.servlet.Filter; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Shiro的配置文件 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class ShiroConfig { + + @Bean + public DefaultWebSessionManager sessionManager(){ + DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); + sessionManager.setSessionValidationSchedulerEnabled(false); + sessionManager.setSessionIdUrlRewritingEnabled(false); + + return sessionManager; + } + + @Bean("securityManager") + public SecurityManager securityManager(Oauth2Realm oAuth2Realm, SessionManager sessionManager) { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + securityManager.setRealm(oAuth2Realm); + securityManager.setSessionManager(sessionManager); + securityManager.setRememberMeManager(null); + return securityManager; + } + + @Bean("shiroFilter") + public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { + ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); + shiroFilter.setSecurityManager(securityManager); + + //oauth过滤 + Map filters = new HashMap<>(); + filters.put("oauth2", new Oauth2Filter()); + shiroFilter.setFilters(filters); + + Map filterMap = new LinkedHashMap<>(); + filterMap.put("/webjars/**", "anon"); + filterMap.put("/druid/**", "anon"); + filterMap.put("/login", "anon"); + filterMap.put("/swagger/**", "anon"); + filterMap.put("/v3/api-docs/**", "anon"); + filterMap.put("/doc.html", "anon"); + filterMap.put("/swagger-resources/**", "anon"); + filterMap.put("/captcha", "anon"); + filterMap.put("/favicon.ico", "anon"); + filterMap.put("/", "anon"); + filterMap.put("/**", "oauth2"); + shiroFilter.setFilterChainDefinitionMap(filterMap); + + return shiroFilter; + } + + @Bean("lifecycleBeanPostProcessor") + public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { + AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); + advisor.setSecurityManager(securityManager); + return advisor; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/config/WebMvcConfig.java b/renren-admin/src/main/java/io/renren/modules/security/config/WebMvcConfig.java new file mode 100644 index 0000000..3d72df9 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/config/WebMvcConfig.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.security.config; + +import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import tools.jackson.databind.DeserializationFeature; +import tools.jackson.databind.cfg.DateTimeFeature; +import tools.jackson.databind.ext.javatime.deser.LocalDateDeserializer; +import tools.jackson.databind.ext.javatime.deser.LocalDateTimeDeserializer; +import tools.jackson.databind.ext.javatime.deser.LocalTimeDeserializer; +import tools.jackson.databind.ext.javatime.ser.LocalDateSerializer; +import tools.jackson.databind.ext.javatime.ser.LocalDateTimeSerializer; +import tools.jackson.databind.ext.javatime.ser.LocalTimeSerializer; +import tools.jackson.databind.module.SimpleModule; +import tools.jackson.databind.ser.std.ToStringSerializer; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") + .maxAge(3600); + } + + @Bean + public SimpleModule customSerializerModule() { + SimpleModule module = new SimpleModule("CustomSerializerModule"); + + // 日期时间序列化 + module.addSerializer(LocalDateTime.class, + new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + module.addSerializer(LocalDate.class, + new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + module.addSerializer(LocalTime.class, + new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); + + // 日期时间反序列化 + module.addDeserializer(LocalDateTime.class, + new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + module.addDeserializer(LocalDate.class, + new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + module.addDeserializer(LocalTime.class, + new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); + + // Long 类型序列化为 String,解决前端 js 精度丢失问题 + module.addSerializer(Long.class, ToStringSerializer.instance); + module.addSerializer(Long.TYPE, ToStringSerializer.instance); + + return module; + } + + /** + * 自定义 JsonMapper 构建器配置 + */ + @Bean + public JsonMapperBuilderCustomizer jsonMapperBuilderCustomizer() { + return builder -> builder + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/controller/LoginController.java b/renren-admin/src/main/java/io/renren/modules/security/controller/LoginController.java new file mode 100644 index 0000000..017b430 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/controller/LoginController.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.security.controller; + +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.utils.IpUtils; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.modules.log.entity.SysLogLoginEntity; +import io.renren.modules.log.enums.LoginOperationEnum; +import io.renren.modules.log.enums.LoginStatusEnum; +import io.renren.modules.log.service.SysLogLoginService; +import io.renren.modules.security.dto.LoginDTO; +import io.renren.modules.security.password.PasswordUtils; +import io.renren.modules.security.service.CaptchaService; +import io.renren.modules.security.service.SysUserTokenService; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dto.SysUserDTO; +import io.renren.modules.sys.enums.UserStatusEnum; +import io.renren.modules.sys.service.SysUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.Date; + +/** + * 登录 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@Tag(name = "登录管理") +@AllArgsConstructor +public class LoginController { + private final SysUserService sysUserService; + private final SysUserTokenService sysUserTokenService; + private final CaptchaService captchaService; + private final SysLogLoginService sysLogLoginService; + + @GetMapping("captcha") + @Operation(summary = "验证码") + @Parameter(in = ParameterIn.QUERY, ref = "string", name = "uuid", required = true) + public void captcha(HttpServletResponse response, String uuid) throws IOException { + //uuid不能为空 + AssertUtils.isBlank(uuid, ErrorCode.IDENTIFIER_NOT_NULL); + + //生成验证码 + captchaService.create(response, uuid); + } + + @PostMapping("login") + @Operation(summary = "登录") + public Result login(HttpServletRequest request, @RequestBody LoginDTO login) { + //效验数据 + ValidatorUtils.validateEntity(login); + + //验证码是否正确 + boolean flag = captchaService.validate(login.getUuid(), login.getCaptcha()); + if (!flag) { + return new Result().error(ErrorCode.CAPTCHA_ERROR); + } + + //用户信息 + SysUserDTO user = sysUserService.getByUsername(login.getUsername()); + + SysLogLoginEntity log = new SysLogLoginEntity(); + log.setOperation(LoginOperationEnum.LOGIN.value()); + log.setCreateDate(new Date()); + log.setIp(IpUtils.getIpAddr(request)); + log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); + + //用户不存在 + if (user == null) { + log.setStatus(LoginStatusEnum.FAIL.value()); + log.setCreatorName(login.getUsername()); + sysLogLoginService.save(log); + + throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); + } + + //密码错误 + if (!PasswordUtils.matches(login.getPassword(), user.getPassword())) { + log.setStatus(LoginStatusEnum.FAIL.value()); + log.setCreator(user.getId()); + log.setCreatorName(user.getUsername()); + sysLogLoginService.save(log); + + throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); + } + + //账号停用 + if (user.getStatus() == UserStatusEnum.DISABLE.value()) { + log.setStatus(LoginStatusEnum.LOCK.value()); + log.setCreator(user.getId()); + log.setCreatorName(user.getUsername()); + sysLogLoginService.save(log); + + throw new RenException(ErrorCode.ACCOUNT_DISABLE); + } + + //登录成功 + log.setStatus(LoginStatusEnum.SUCCESS.value()); + log.setCreator(user.getId()); + log.setCreatorName(user.getUsername()); + sysLogLoginService.save(log); + + return sysUserTokenService.createToken(user.getId()); + } + + @PostMapping("logout") + @Operation(summary = "退出") + public Result logout(HttpServletRequest request) { + UserDetail user = SecurityUser.getUser(); + + //退出 + sysUserTokenService.logout(user.getId()); + + //用户信息 + SysLogLoginEntity log = new SysLogLoginEntity(); + log.setOperation(LoginOperationEnum.LOGOUT.value()); + log.setIp(IpUtils.getIpAddr(request)); + log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); + log.setIp(IpUtils.getIpAddr(request)); + log.setStatus(LoginStatusEnum.SUCCESS.value()); + log.setCreator(user.getId()); + log.setCreatorName(user.getUsername()); + log.setCreateDate(new Date()); + sysLogLoginService.save(log); + + return new Result(); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/dao/SysUserTokenDao.java b/renren-admin/src/main/java/io/renren/modules/security/dao/SysUserTokenDao.java new file mode 100644 index 0000000..154b130 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/dao/SysUserTokenDao.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.security.entity.SysUserTokenEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 系统用户Token + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysUserTokenDao extends BaseDao { + + SysUserTokenEntity getByToken(String token); + + SysUserTokenEntity getByUserId(Long userId); + + void updateToken(@Param("userId") Long userId, @Param("token") String token); +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/dto/LoginDTO.java b/renren-admin/src/main/java/io/renren/modules/security/dto/LoginDTO.java new file mode 100644 index 0000000..50422b3 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/dto/LoginDTO.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 登录表单 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "登录表单") +public class LoginDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "用户名", required = true) + @NotBlank(message="{sysuser.username.require}") + private String username; + + @Schema(title = "密码") + @NotBlank(message="{sysuser.password.require}") + private String password; + + @Schema(title = "验证码") + @NotBlank(message="{sysuser.captcha.require}") + private String captcha; + + @Schema(title = "唯一标识") + @NotBlank(message="{sysuser.uuid.require}") + private String uuid; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/entity/SysUserTokenEntity.java b/renren-admin/src/main/java/io/renren/modules/security/entity/SysUserTokenEntity.java new file mode 100644 index 0000000..8011c82 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/entity/SysUserTokenEntity.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 系统用户Token + */ +@Data +@TableName("sys_user_token") +public class SysUserTokenEntity implements Serializable { + private static final long serialVersionUID = 1L; + /** + * id + */ + @TableId + private Long id; + /** + * 用户ID + */ + private Long userId; + /** + * 用户token + */ + private String token; + /** + * 过期时间 + */ + private Date expireDate; + /** + * 更新时间 + */ + private Date updateDate; + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createDate; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Filter.java b/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Filter.java new file mode 100644 index 0000000..8e3f162 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Filter.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.security.oauth2; + +import cn.hutool.core.util.StrUtil; +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.utils.HttpContextUtils; +import io.renren.common.utils.JsonUtils; +import io.renren.common.utils.Result; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.web.filter.authc.AuthenticatingFilter; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.io.IOException; + +/** + * oauth2过滤器 + * + * @author Mark sunlightcs@gmail.com + */ +public class Oauth2Filter extends AuthenticatingFilter { + + @Override + protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception { + //获取请求token + String token = getRequestToken((HttpServletRequest) request); + + if (StrUtil.isBlank(token)) { + return null; + } + + return new Oauth2Token(token); + } + + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { + if (((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())) { + return true; + } + + return false; + } + + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + //获取请求token,如果token不存在,直接返回401 + String token = getRequestToken((HttpServletRequest) request); + if (StrUtil.isBlank(token)) { + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setContentType("application/json;charset=utf-8"); + httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); + httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin()); + + String json = JsonUtils.toJsonString(new Result().error(ErrorCode.UNAUTHORIZED)); + + httpResponse.getWriter().print(json); + + return false; + } + + return executeLogin(request, response); + } + + @Override + protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setContentType("application/json;charset=utf-8"); + httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); + httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin()); + try { + //处理登录失败的异常 + Throwable throwable = e.getCause() == null ? e : e.getCause(); + Result r = new Result().error(HttpStatus.UNAUTHORIZED.value(), throwable.getMessage()); + + String json = JsonUtils.toJsonString(r); + httpResponse.getWriter().print(json); + } catch (IOException e1) { + + } + + return false; + } + + /** + * 获取请求的token + */ + private String getRequestToken(HttpServletRequest httpRequest) { + //从header中获取token + String token = httpRequest.getHeader(Constant.TOKEN_HEADER); + + //如果header中不存在token,则从参数中获取token + if (StrUtil.isBlank(token)) { + token = httpRequest.getParameter(Constant.TOKEN_HEADER); + } + + return token; + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Realm.java b/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Realm.java new file mode 100644 index 0000000..6df453a --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Realm.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.security.oauth2; + +import io.renren.common.exception.ErrorCode; +import io.renren.common.utils.ConvertUtils; +import io.renren.common.utils.MessageUtils; +import io.renren.modules.security.entity.SysUserTokenEntity; +import io.renren.modules.security.service.ShiroService; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.entity.SysUserEntity; +import lombok.AllArgsConstructor; +import org.apache.shiro.authc.*; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Set; + +/** + * 认证 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +@AllArgsConstructor +public class Oauth2Realm extends AuthorizingRealm { + private final ShiroService shiroService; + + @Override + public boolean supports(AuthenticationToken token) { + return token instanceof Oauth2Token; + } + + /** + * 授权(验证权限时调用) + */ + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + UserDetail user = (UserDetail) principals.getPrimaryPrincipal(); + + //用户权限列表 + Set permsSet = shiroService.getUserPermissions(user); + + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + info.setStringPermissions(permsSet); + return info; + } + + /** + * 认证(登录时调用) + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + String accessToken = (String) token.getPrincipal(); + + //根据accessToken,查询用户信息 + SysUserTokenEntity tokenEntity = shiroService.getByToken(accessToken); + //token失效 + if (tokenEntity == null || tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()) { + throw new IncorrectCredentialsException(MessageUtils.getMessage(ErrorCode.TOKEN_INVALID)); + } + + //查询用户信息 + SysUserEntity userEntity = shiroService.getUser(tokenEntity.getUserId()); + + //转换成UserDetail对象 + UserDetail userDetail = ConvertUtils.sourceToTarget(userEntity, UserDetail.class); + + //获取用户对应的部门数据权限 + List deptIdList = shiroService.getDataScopeList(userDetail.getId()); + userDetail.setDeptIdList(deptIdList); + + //账号锁定 + if (userDetail.getStatus() == 0) { + throw new LockedAccountException(MessageUtils.getMessage(ErrorCode.ACCOUNT_LOCK)); + } + + SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userDetail, accessToken, getName()); + return info; + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Token.java b/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Token.java new file mode 100644 index 0000000..f6be31d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/oauth2/Oauth2Token.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.oauth2; + +import org.apache.shiro.authc.AuthenticationToken; + +/** + * token + * + * @author Mark sunlightcs@gmail.com + */ +public class Oauth2Token implements AuthenticationToken { + private String token; + + public Oauth2Token(String token){ + this.token = token; + } + + @Override + public String getPrincipal() { + return token; + } + + @Override + public Object getCredentials() { + return token; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/oauth2/TokenGenerator.java b/renren-admin/src/main/java/io/renren/modules/security/oauth2/TokenGenerator.java new file mode 100644 index 0000000..13d0014 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/oauth2/TokenGenerator.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.oauth2; + +import io.renren.common.exception.RenException; + +import java.security.MessageDigest; +import java.util.UUID; + +/** + * 生成token + * + * @author Mark sunlightcs@gmail.com + */ +public class TokenGenerator { + + public static String generateValue() { + return generateValue(UUID.randomUUID().toString()); + } + + private static final char[] HEX_CODE = "0123456789abcdef".toCharArray(); + + public static String toHexString(byte[] data) { + if(data == null) { + return null; + } + StringBuilder r = new StringBuilder(data.length*2); + for ( byte b : data) { + r.append(HEX_CODE[(b >> 4) & 0xF]); + r.append(HEX_CODE[(b & 0xF)]); + } + return r.toString(); + } + + public static String generateValue(String param) { + try { + MessageDigest algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(param.getBytes()); + byte[] messageDigest = algorithm.digest(); + return toHexString(messageDigest); + } catch (Exception e) { + throw new RenException("token invalid", e); + } + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/password/BCrypt.java b/renren-admin/src/main/java/io/renren/modules/security/password/BCrypt.java new file mode 100644 index 0000000..1383c38 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/password/BCrypt.java @@ -0,0 +1,662 @@ +package io.renren.modules.security.password; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.security.SecureRandom; + +/** + * BCrypt implements OpenBSD-style Blowfish password hashing using the scheme described in + * "A Future-Adaptable Password Scheme" by Niels Provos and David Mazieres. + *

+ * This password hashing system tries to thwart off-line password cracking using a + * computationally-intensive hashing algorithm, based on Bruce Schneier's Blowfish cipher. + * The work factor of the algorithm is parameterised, so it can be increased as computers + * get faster. + *

+ * Usage is really simple. To hash a password for the first time, call the hashpw method + * with a random salt, like this: + *

+ * + * String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt());
+ *
+ *

+ * To check whether a plaintext password matches one that has been hashed previously, use + * the checkpw method: + *

+ * + * if (BCrypt.checkpw(candidate_password, stored_hash))
+ *     System.out.println("It matches");
+ * else
+ *     System.out.println("It does not match");
+ *
+ *

+ * The gensalt() method takes an optional parameter (log_rounds) that determines the + * computational complexity of the hashing: + *

+ * + * String strong_salt = BCrypt.gensalt(10)
+ * String stronger_salt = BCrypt.gensalt(12)
+ *
+ *

+ * The amount of work increases exponentially (2**log_rounds), so each increment is twice + * as much work. The default log_rounds is 10, and the valid range is 4 to 31. + * + * @author Damien Miller + */ +public class BCrypt { + // BCrypt parameters + + private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10; + private static final int BCRYPT_SALT_LEN = 16; + // Blowfish parameters + private static final int BLOWFISH_NUM_ROUNDS = 16; + // Initial contents of key schedule + private static final int P_orig[] = { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, + 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b }; + private static final int S_orig[] = { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, + 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, + 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, + 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, + 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, + 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, + 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, + 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, + 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, + 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, + 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, + 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, + 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, + 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, + 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, + 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, + 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, + 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, + 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, + 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, + 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, + 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, + 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, + 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, + 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, + 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, + 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, + 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, + 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, + 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, + 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, + 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, + 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, + 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, + 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, + 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, + 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, + 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, + 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, + 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, + 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, + 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, + 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, + 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, + 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, + 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, + 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, + 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, + 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, + 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, + 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, + 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, + 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, + 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, + 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, + 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, + 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, + 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, + 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, + 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, + 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, + 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, + 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, + 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, + 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 }; + // bcrypt IV: "OrpheanBeholderScryDoubt" + static private final int bf_crypt_ciphertext[] = { 0x4f727068, 0x65616e42, + 0x65686f6c, 0x64657253, 0x63727944, 0x6f756274 }; + // Table for Base64 encoding + static private final char base64_code[] = { '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + // Table for Base64 decoding + static private final byte index_64[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1 }; + static final int MIN_LOG_ROUNDS = 4; + static final int MAX_LOG_ROUNDS = 31; + // Expanded Blowfish key + private int P[]; + private int S[]; + + /** + * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note + * that this is not compatible with the standard MIME-base64 + * encoding. + * + * @param d the byte array to encode + * @param len the number of bytes to encode + * @param rs the destination buffer for the base64-encoded string + * @exception IllegalArgumentException if the length is invalid + */ + static void encode_base64(byte d[], int len, StringBuilder rs) + throws IllegalArgumentException { + int off = 0; + int c1, c2; + + if (len <= 0 || len > d.length) { + throw new IllegalArgumentException("Invalid len"); + } + + while (off < len) { + c1 = d[off++] & 0xff; + rs.append(base64_code[(c1 >> 2) & 0x3f]); + c1 = (c1 & 0x03) << 4; + if (off >= len) { + rs.append(base64_code[c1 & 0x3f]); + break; + } + c2 = d[off++] & 0xff; + c1 |= (c2 >> 4) & 0x0f; + rs.append(base64_code[c1 & 0x3f]); + c1 = (c2 & 0x0f) << 2; + if (off >= len) { + rs.append(base64_code[c1 & 0x3f]); + break; + } + c2 = d[off++] & 0xff; + c1 |= (c2 >> 6) & 0x03; + rs.append(base64_code[c1 & 0x3f]); + rs.append(base64_code[c2 & 0x3f]); + } + } + + /** + * Look up the 3 bits base64-encoded by the specified character, range-checking + * against conversion table + * @param x the base64-encoded value + * @return the decoded value of x + */ + private static byte char64(char x) { + if (x > index_64.length) { + return -1; + } + return index_64[x]; + } + + /** + * Decode a string encoded using bcrypt's base64 scheme to a byte array. Note that + * this is *not* compatible with the standard MIME-base64 encoding. + * @param s the string to decode + * @param maxolen the maximum number of bytes to decode + * @return an array containing the decoded bytes + * @throws IllegalArgumentException if maxolen is invalid + */ + static byte[] decode_base64(String s, int maxolen) throws IllegalArgumentException { + ByteArrayOutputStream out = new ByteArrayOutputStream(maxolen); + int off = 0, slen = s.length(), olen = 0; + byte c1, c2, c3, c4, o; + + if (maxolen <= 0) { + throw new IllegalArgumentException("Invalid maxolen"); + } + + while (off < slen - 1 && olen < maxolen) { + c1 = char64(s.charAt(off++)); + c2 = char64(s.charAt(off++)); + if (c1 == -1 || c2 == -1) { + break; + } + o = (byte) (c1 << 2); + o |= (c2 & 0x30) >> 4; + out.write(o); + if (++olen >= maxolen || off >= slen) { + break; + } + c3 = char64(s.charAt(off++)); + if (c3 == -1) { + break; + } + o = (byte) ((c2 & 0x0f) << 4); + o |= (c3 & 0x3c) >> 2; + out.write(o); + if (++olen >= maxolen || off >= slen) { + break; + } + c4 = char64(s.charAt(off++)); + o = (byte) ((c3 & 0x03) << 6); + o |= c4; + out.write(o); + ++olen; + } + + return out.toByteArray(); + } + + /** + * Blowfish encipher a single 64-bit block encoded as two 32-bit halves + * @param lr an array containing the two 32-bit half blocks + * @param off the position in the array of the blocks + */ + private final void encipher(int lr[], int off) { + int i, n, l = lr[off], r = lr[off + 1]; + + l ^= P[0]; + for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) { + // Feistel substitution on left word + n = S[(l >> 24) & 0xff]; + n += S[0x100 | ((l >> 16) & 0xff)]; + n ^= S[0x200 | ((l >> 8) & 0xff)]; + n += S[0x300 | (l & 0xff)]; + r ^= n ^ P[++i]; + + // Feistel substitution on right word + n = S[(r >> 24) & 0xff]; + n += S[0x100 | ((r >> 16) & 0xff)]; + n ^= S[0x200 | ((r >> 8) & 0xff)]; + n += S[0x300 | (r & 0xff)]; + l ^= n ^ P[++i]; + } + lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1]; + lr[off + 1] = l; + } + + /** + * Cycically extract a word of key material + * @param data the string to extract the data from + * @param offp a "pointer" (as a one-entry array) to the current offset into data + * @return the next word of material from data + */ + private static int streamtoword(byte data[], int offp[]) { + int i; + int word = 0; + int off = offp[0]; + + for (i = 0; i < 4; i++) { + word = (word << 8) | (data[off] & 0xff); + off = (off + 1) % data.length; + } + + offp[0] = off; + return word; + } + + /** + * Initialise the Blowfish key schedule + */ + private void init_key() { + P = (int[]) P_orig.clone(); + S = (int[]) S_orig.clone(); + } + + /** + * Key the Blowfish cipher + * @param key an array containing the key + */ + private void key(byte key[]) { + int i; + int koffp[] = { 0 }; + int lr[] = { 0, 0 }; + int plen = P.length, slen = S.length; + + for (i = 0; i < plen; i++) { + P[i] = P[i] ^ streamtoword(key, koffp); + } + + for (i = 0; i < plen; i += 2) { + encipher(lr, 0); + P[i] = lr[0]; + P[i + 1] = lr[1]; + } + + for (i = 0; i < slen; i += 2) { + encipher(lr, 0); + S[i] = lr[0]; + S[i + 1] = lr[1]; + } + } + + /** + * Perform the "enhanced key schedule" step described by Provos and Mazieres in + * "A Future-Adaptable Password Scheme" http://www.openbsd.org/papers/bcrypt-paper.ps + * @param data salt information + * @param key password information + */ + private void ekskey(byte data[], byte key[]) { + int i; + int koffp[] = { 0 }, doffp[] = { 0 }; + int lr[] = { 0, 0 }; + int plen = P.length, slen = S.length; + + for (i = 0; i < plen; i++) { + P[i] = P[i] ^ streamtoword(key, koffp); + } + + for (i = 0; i < plen; i += 2) { + lr[0] ^= streamtoword(data, doffp); + lr[1] ^= streamtoword(data, doffp); + encipher(lr, 0); + P[i] = lr[0]; + P[i + 1] = lr[1]; + } + + for (i = 0; i < slen; i += 2) { + lr[0] ^= streamtoword(data, doffp); + lr[1] ^= streamtoword(data, doffp); + encipher(lr, 0); + S[i] = lr[0]; + S[i + 1] = lr[1]; + } + } + + static long roundsForLogRounds(int log_rounds) { + if (log_rounds < 4 || log_rounds > 31) { + throw new IllegalArgumentException("Bad number of rounds"); + } + return 1L << log_rounds; + } + + /** + * Perform the central password hashing step in the bcrypt scheme + * @param password the password to hash + * @param salt the binary salt to hash with the password + * @param log_rounds the binary logarithm of the number of rounds of hashing to apply + * @return an array containing the binary hashed password + */ + private byte[] crypt_raw(byte password[], byte salt[], int log_rounds) { + int cdata[] = (int[]) bf_crypt_ciphertext.clone(); + int clen = cdata.length; + byte ret[]; + + long rounds = roundsForLogRounds(log_rounds); + + init_key(); + ekskey(salt, password); + for (long i = 0; i < rounds; i++) { + key(password); + key(salt); + } + + for (int i = 0; i < 64; i++) { + for (int j = 0; j < (clen >> 1); j++) { + encipher(cdata, j << 1); + } + } + + ret = new byte[clen * 4]; + for (int i = 0, j = 0; i < clen; i++) { + ret[j++] = (byte) ((cdata[i] >> 24) & 0xff); + ret[j++] = (byte) ((cdata[i] >> 16) & 0xff); + ret[j++] = (byte) ((cdata[i] >> 8) & 0xff); + ret[j++] = (byte) (cdata[i] & 0xff); + } + return ret; + } + + /** + * Hash a password using the OpenBSD bcrypt scheme + * @param password the password to hash + * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt) + * @return the hashed password + * @throws IllegalArgumentException if invalid salt is passed + */ + public static String hashpw(String password, String salt) throws IllegalArgumentException { + BCrypt B; + String real_salt; + byte passwordb[], saltb[], hashed[]; + char minor = (char) 0; + int rounds, off = 0; + StringBuilder rs = new StringBuilder(); + + if (salt == null) { + throw new IllegalArgumentException("salt cannot be null"); + } + + int saltLength = salt.length(); + + if (saltLength < 28) { + throw new IllegalArgumentException("Invalid salt"); + } + + if (salt.charAt(0) != '$' || salt.charAt(1) != '2') { + throw new IllegalArgumentException("Invalid salt version"); + } + if (salt.charAt(2) == '$') { + off = 3; + } + else { + minor = salt.charAt(2); + if (minor != 'a' || salt.charAt(3) != '$') { + throw new IllegalArgumentException("Invalid salt revision"); + } + off = 4; + } + + if (saltLength - off < 25) { + throw new IllegalArgumentException("Invalid salt"); + } + + // Extract number of rounds + if (salt.charAt(off + 2) > '$') { + throw new IllegalArgumentException("Missing salt rounds"); + } + rounds = Integer.parseInt(salt.substring(off, off + 2)); + + real_salt = salt.substring(off + 3, off + 25); + try { + passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8"); + } + catch (UnsupportedEncodingException uee) { + throw new AssertionError("UTF-8 is not supported"); + } + + saltb = decode_base64(real_salt, BCRYPT_SALT_LEN); + + B = new BCrypt(); + hashed = B.crypt_raw(passwordb, saltb, rounds); + + rs.append("$2"); + if (minor >= 'a') { + rs.append(minor); + } + rs.append("$"); + if (rounds < 10) { + rs.append("0"); + } + rs.append(rounds); + rs.append("$"); + encode_base64(saltb, saltb.length, rs); + encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs); + return rs.toString(); + } + + /** + * Generate a salt for use with the BCrypt.hashpw() method + * @param log_rounds the log2 of the number of rounds of hashing to apply - the work + * factor therefore increases as 2**log_rounds. Minimum 4, maximum 31. + * @param random an instance of SecureRandom to use + * @return an encoded salt value + */ + public static String gensalt(int log_rounds, SecureRandom random) { + if (log_rounds < MIN_LOG_ROUNDS || log_rounds > MAX_LOG_ROUNDS) { + throw new IllegalArgumentException("Bad number of rounds"); + } + StringBuilder rs = new StringBuilder(); + byte rnd[] = new byte[BCRYPT_SALT_LEN]; + + random.nextBytes(rnd); + + rs.append("$2a$"); + if (log_rounds < 10) { + rs.append("0"); + } + rs.append(log_rounds); + rs.append("$"); + encode_base64(rnd, rnd.length, rs); + return rs.toString(); + } + + /** + * Generate a salt for use with the BCrypt.hashpw() method + * @param log_rounds the log2 of the number of rounds of hashing to apply - the work + * factor therefore increases as 2**log_rounds. Minimum 4, maximum 31. + * @return an encoded salt value + */ + public static String gensalt(int log_rounds) { + return gensalt(log_rounds, new SecureRandom()); + } + + /** + * Generate a salt for use with the BCrypt.hashpw() method, selecting a reasonable + * default for the number of hashing rounds to apply + * @return an encoded salt value + */ + public static String gensalt() { + return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS); + } + + /** + * Check that a plaintext password matches a previously hashed one + * @param plaintext the plaintext password to verify + * @param hashed the previously-hashed password + * @return true if the passwords match, false otherwise + */ + public static boolean checkpw(String plaintext, String hashed) { + return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed)); + } + + static boolean equalsNoEarlyReturn(String a, String b) { + char[] caa = a.toCharArray(); + char[] cab = b.toCharArray(); + + if (caa.length != cab.length) { + return false; + } + + byte ret = 0; + for (int i = 0; i < caa.length; i++) { + ret |= caa[i] ^ cab[i]; + } + return ret == 0; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/password/BCryptPasswordEncoder.java b/renren-admin/src/main/java/io/renren/modules/security/password/BCryptPasswordEncoder.java new file mode 100644 index 0000000..d27be66 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/password/BCryptPasswordEncoder.java @@ -0,0 +1,82 @@ +package io.renren.modules.security.password; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.security.SecureRandom; +import java.util.regex.Pattern; + +/** + * Implementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients + * can optionally supply a "strength" (a.k.a. log rounds in BCrypt) and a SecureRandom + * instance. The larger the strength parameter the more work will have to be done + * (exponentially) to hash the passwords. The default value is 10. + * + * @author Dave Syer + * + */ +public class BCryptPasswordEncoder implements PasswordEncoder { + private Pattern BCRYPT_PATTERN = Pattern + .compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}"); + private final Log logger = LogFactory.getLog(getClass()); + + private final int strength; + + private final SecureRandom random; + + public BCryptPasswordEncoder() { + this(-1); + } + + /** + * @param strength the log rounds to use, between 4 and 31 + */ + public BCryptPasswordEncoder(int strength) { + this(strength, null); + } + + /** + * @param strength the log rounds to use, between 4 and 31 + * @param random the secure random instance to use + * + */ + public BCryptPasswordEncoder(int strength, SecureRandom random) { + if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) { + throw new IllegalArgumentException("Bad strength"); + } + this.strength = strength; + this.random = random; + } + + @Override + public String encode(CharSequence rawPassword) { + String salt; + if (strength > 0) { + if (random != null) { + salt = BCrypt.gensalt(strength, random); + } + else { + salt = BCrypt.gensalt(strength); + } + } + else { + salt = BCrypt.gensalt(); + } + return BCrypt.hashpw(rawPassword.toString(), salt); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + if (encodedPassword == null || encodedPassword.length() == 0) { + logger.warn("Empty encoded password"); + return false; + } + + if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) { + logger.warn("Encoded password does not look like BCrypt"); + return false; + } + + return BCrypt.checkpw(rawPassword.toString(), encodedPassword); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/password/PasswordEncoder.java b/renren-admin/src/main/java/io/renren/modules/security/password/PasswordEncoder.java new file mode 100644 index 0000000..3b746e6 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/password/PasswordEncoder.java @@ -0,0 +1,30 @@ +package io.renren.modules.security.password; + +/** + * Service interface for encoding passwords. + * + * The preferred implementation is {@code BCryptPasswordEncoder}. + * + * @author Keith Donald + */ +public interface PasswordEncoder { + + /** + * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or + * greater hash combined with an 8-byte or greater randomly generated salt. + */ + String encode(CharSequence rawPassword); + + /** + * Verify the encoded password obtained from storage matches the submitted raw + * password after it too is encoded. Returns true if the passwords match, false if + * they do not. The stored password itself is never decoded. + * + * @param rawPassword the raw password to encode and match + * @param encodedPassword the encoded password from storage to compare with + * @return true if the raw password, after encoding, matches the encoded password from + * storage + */ + boolean matches(CharSequence rawPassword, String encodedPassword); + +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/password/PasswordUtils.java b/renren-admin/src/main/java/io/renren/modules/security/password/PasswordUtils.java new file mode 100644 index 0000000..be12fa6 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/password/PasswordUtils.java @@ -0,0 +1,58 @@ +/** + * Copyright 2018 人人开源 https://www.renren.io + *

+ * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.renren.modules.security.password; + +/** + * 密码工具类 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class PasswordUtils { + private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + + /** + * 加密 + * @param str 字符串 + * @return 返回加密字符串 + */ + public static String encode(String str){ + return passwordEncoder.encode(str); + } + + + /** + * 比较密码是否相等 + * @param str 明文密码 + * @param password 加密后密码 + * @return true:成功 false:失败 + */ + public static boolean matches(String str, String password){ + return passwordEncoder.matches(str, password); + } + + + public static void main(String[] args) { + String str = "admin"; + String password = encode(str); + + System.out.println(password); + System.out.println(matches(str, password)); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/service/CaptchaService.java b/renren-admin/src/main/java/io/renren/modules/security/service/CaptchaService.java new file mode 100644 index 0000000..07ef78d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/service/CaptchaService.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.service; + +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; + +/** + * 验证码 + * + * @author Mark sunlightcs@gmail.com + */ +public interface CaptchaService { + + /** + * 图片验证码 + */ + void create(HttpServletResponse response, String uuid) throws IOException; + + /** + * 验证码效验 + * @param uuid uuid + * @param code 验证码 + * @return true:成功 false:失败 + */ + boolean validate(String uuid, String code); +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/service/ShiroService.java b/renren-admin/src/main/java/io/renren/modules/security/service/ShiroService.java new file mode 100644 index 0000000..3705332 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/service/ShiroService.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.service; + +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.entity.SysUserEntity; +import io.renren.modules.security.entity.SysUserTokenEntity; + +import java.util.List; +import java.util.Set; + +/** + * shiro相关接口 + * + * @author Mark sunlightcs@gmail.com + */ +public interface ShiroService { + /** + * 获取用户权限列表 + */ + Set getUserPermissions(UserDetail user); + + SysUserTokenEntity getByToken(String token); + + /** + * 根据用户ID,查询用户 + * @param userId + */ + SysUserEntity getUser(Long userId); + + /** + * 获取用户对应的部门数据权限 + * @param userId 用户ID + * @return 返回部门ID列表 + */ + List getDataScopeList(Long userId); +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/service/SysUserTokenService.java b/renren-admin/src/main/java/io/renren/modules/security/service/SysUserTokenService.java new file mode 100644 index 0000000..881493c --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/service/SysUserTokenService.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.service; + +import io.renren.common.service.BaseService; +import io.renren.common.utils.Result; +import io.renren.modules.security.entity.SysUserTokenEntity; + +/** + * 用户Token + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysUserTokenService extends BaseService { + + /** + * 生成token + * @param userId 用户ID + */ + Result createToken(Long userId); + + /** + * 退出,修改token值 + * @param userId 用户ID + */ + void logout(Long userId); + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/service/impl/CaptchaServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/security/service/impl/CaptchaServiceImpl.java new file mode 100644 index 0000000..9c60ad2 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/service/impl/CaptchaServiceImpl.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.security.service.impl; + +import cn.hutool.cache.Cache; +import cn.hutool.cache.CacheUtil; +import com.wf.captcha.SpecCaptcha; +import com.wf.captcha.base.Captcha; +import io.renren.common.redis.RedisKeys; +import io.renren.common.redis.RedisUtils; +import io.renren.modules.security.service.CaptchaService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.IOException; + +/** + * 验证码 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class CaptchaServiceImpl implements CaptchaService { + @Resource + private RedisUtils redisUtils; + @Value("${renren.redis.open: false}") + private boolean open; + /** + * Local Cache 5分钟过期 + */ + Cache localCache = CacheUtil.newLRUCache(1000, 1000 * 60 * 5); + + @Override + public void create(HttpServletResponse response, String uuid) throws IOException { + response.setContentType("image/gif"); + response.setHeader("Pragma", "No-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + + //生成验证码 + SpecCaptcha captcha = new SpecCaptcha(150, 40); + captcha.setLen(5); + captcha.setCharType(Captcha.TYPE_DEFAULT); + captcha.out(response.getOutputStream()); + + //保存到缓存 + setCache(uuid, captcha.text()); + } + + @Override + public boolean validate(String uuid, String code) { + //获取验证码 + String captcha = getCache(uuid); + + //效验成功 + if (code.equalsIgnoreCase(captcha)) { + return true; + } + + return false; + } + + private void setCache(String key, String value) { + if (open) { + key = RedisKeys.getCaptchaKey(key); + redisUtils.set(key, value, 300); + } else { + localCache.put(key, value); + } + } + + private String getCache(String key) { + if (open) { + key = RedisKeys.getCaptchaKey(key); + String captcha = (String) redisUtils.get(key); + //删除验证码 + if (captcha != null) { + redisUtils.delete(key); + } + + return captcha; + } + + String captcha = localCache.get(key); + //删除验证码 + if (captcha != null) { + localCache.remove(key); + } + return captcha; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/security/service/impl/ShiroServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/security/service/impl/ShiroServiceImpl.java new file mode 100644 index 0000000..fa78068 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/service/impl/ShiroServiceImpl.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.security.service.impl; + +import cn.hutool.core.util.StrUtil; +import io.renren.modules.security.dao.SysUserTokenDao; +import io.renren.modules.security.entity.SysUserTokenEntity; +import io.renren.modules.security.service.ShiroService; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dao.SysMenuDao; +import io.renren.modules.sys.dao.SysRoleDataScopeDao; +import io.renren.modules.sys.dao.SysUserDao; +import io.renren.modules.sys.entity.SysUserEntity; +import io.renren.modules.sys.enums.SuperAdminEnum; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Service +@AllArgsConstructor +public class ShiroServiceImpl implements ShiroService { + private final SysMenuDao sysMenuDao; + private final SysUserDao sysUserDao; + private final SysUserTokenDao sysUserTokenDao; + private final SysRoleDataScopeDao sysRoleDataScopeDao; + + @Override + public Set getUserPermissions(UserDetail user) { + //系统管理员,拥有最高权限 + List permissionsList; + if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) { + permissionsList = sysMenuDao.getPermissionsList(); + } else { + permissionsList = sysMenuDao.getUserPermissionsList(user.getId()); + } + + //用户权限列表 + Set permsSet = new HashSet<>(); + for (String permissions : permissionsList) { + if (StrUtil.isBlank(permissions)) { + continue; + } + permsSet.addAll(Arrays.asList(permissions.trim().split(","))); + } + + return permsSet; + } + + @Override + public SysUserTokenEntity getByToken(String token) { + return sysUserTokenDao.getByToken(token); + } + + @Override + public SysUserEntity getUser(Long userId) { + return sysUserDao.selectById(userId); + } + + @Override + public List getDataScopeList(Long userId) { + return sysRoleDataScopeDao.getDataScopeList(userId); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/service/impl/SysUserTokenServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/security/service/impl/SysUserTokenServiceImpl.java new file mode 100644 index 0000000..65b5c60 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/service/impl/SysUserTokenServiceImpl.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.service.impl; + +import io.renren.common.constant.Constant; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.modules.security.oauth2.TokenGenerator; +import io.renren.common.utils.Result; +import io.renren.modules.security.dao.SysUserTokenDao; +import io.renren.modules.security.entity.SysUserTokenEntity; +import io.renren.modules.security.service.SysUserTokenService; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Service +public class SysUserTokenServiceImpl extends BaseServiceImpl implements SysUserTokenService { + /** + * 12小时后过期 + */ + private final static int EXPIRE = 3600 * 12; + + @Override + public Result createToken(Long userId) { + //用户token + String token; + + //当前时间 + Date now = new Date(); + //过期时间 + Date expireTime = new Date(now.getTime() + EXPIRE * 1000); + + //判断是否生成过token + SysUserTokenEntity tokenEntity = baseDao.getByUserId(userId); + if(tokenEntity == null){ + //生成一个token + token = TokenGenerator.generateValue(); + + tokenEntity = new SysUserTokenEntity(); + tokenEntity.setUserId(userId); + tokenEntity.setToken(token); + tokenEntity.setUpdateDate(now); + tokenEntity.setExpireDate(expireTime); + + //保存token + this.insert(tokenEntity); + }else{ + //判断token是否过期 + if(tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()){ + //token过期,重新生成token + token = TokenGenerator.generateValue(); + }else { + token = tokenEntity.getToken(); + } + + tokenEntity.setToken(token); + tokenEntity.setUpdateDate(now); + tokenEntity.setExpireDate(expireTime); + + //更新token + this.updateById(tokenEntity); + } + + Map map = new HashMap<>(2); + map.put(Constant.TOKEN_HEADER, token); + map.put("expire", EXPIRE); + return new Result().ok(map); + } + + @Override + public void logout(Long userId) { + //生成一个token + String token = TokenGenerator.generateValue(); + + //修改token + baseDao.updateToken(userId, token); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/user/SecurityUser.java b/renren-admin/src/main/java/io/renren/modules/security/user/SecurityUser.java new file mode 100644 index 0000000..2336337 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/user/SecurityUser.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.user; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; + +/** + * 用户 + * + * @author Mark sunlightcs@gmail.com + */ +public class SecurityUser { + + public static Subject getSubject() { + try { + return SecurityUtils.getSubject(); + }catch (Exception e){ + return null; + } + } + + /** + * 获取用户信息 + */ + public static UserDetail getUser() { + Subject subject = getSubject(); + if(subject == null){ + return new UserDetail(); + } + + UserDetail user = (UserDetail)subject.getPrincipal(); + if(user == null){ + return new UserDetail(); + } + + return user; + } + + /** + * 获取用户ID + */ + public static Long getUserId() { + return getUser().getId(); + } + + /** + * 获取部门ID + */ + public static Long getDeptId() { + return getUser().getDeptId(); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/security/user/UserDetail.java b/renren-admin/src/main/java/io/renren/modules/security/user/UserDetail.java new file mode 100644 index 0000000..aee9cf5 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/security/user/UserDetail.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.security.user; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 登录用户信息 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +public class UserDetail implements Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + private String username; + private String realName; + private String headUrl; + private Integer gender; + private String email; + private String mobile; + private Long deptId; + private String password; + private Integer status; + private Integer superAdmin; + /** + * 部门数据权限 + */ + private List deptIdList; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/IndexController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/IndexController.java new file mode 100644 index 0000000..18fb248 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/IndexController.java @@ -0,0 +1,20 @@ +package io.renren.modules.sys.controller; + +import io.renren.common.utils.Result; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 首页提示 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +public class IndexController { + + @GetMapping("/") + public Result index(){ + String tips = "你好,renren-admin已启动,请启动renren-ui,才能访问页面!"; + return new Result().ok(tips); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDeptController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDeptController.java new file mode 100644 index 0000000..d232079 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDeptController.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.sys.dto.SysDeptDTO; +import io.renren.modules.sys.service.SysDeptService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; + +/** + * 部门管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/sys/dept") +@Tag(name = "部门管理") +@AllArgsConstructor +public class SysDeptController { + private final SysDeptService sysDeptService; + + @GetMapping("list") + @Operation(summary = "列表") + @RequiresPermissions("sys:dept:list") + public Result> list() { + List list = sysDeptService.list(new HashMap<>(1)); + + return new Result>().ok(list); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:dept:info") + public Result get(@PathVariable("id") Long id) { + SysDeptDTO data = sysDeptService.get(id); + + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:dept:save") + public Result save(@RequestBody SysDeptDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); + + sysDeptService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:dept:update") + public Result update(@RequestBody SysDeptDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + sysDeptService.update(dto); + + return new Result(); + } + + @DeleteMapping("{id}") + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:dept:delete") + public Result delete(@PathVariable("id") Long id) { + //效验数据 + AssertUtils.isNull(id, "id"); + + sysDeptService.delete(id); + + return new Result(); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDictDataController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDictDataController.java new file mode 100644 index 0000000..40fd04c --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDictDataController.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.sys.dto.SysDictDataDTO; +import io.renren.modules.sys.service.SysDictDataService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 字典数据 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("sys/dict/data") +@Tag(name = "字典数据") +@AllArgsConstructor +public class SysDictDataController { + private final SysDictDataService sysDictDataService; + + @GetMapping("page") + @Operation(summary = "字典数据") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "dictLabel", description = "字典标签", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "dictValue", description = "字典值", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:dict:page") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + //字典类型 + PageData page = sysDictDataService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:dict:info") + public Result get(@PathVariable("id") Long id) { + SysDictDataDTO data = sysDictDataService.get(id); + + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:dict:save") + public Result save(@RequestBody SysDictDataDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, DefaultGroup.class); + + sysDictDataService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:dict:update") + public Result update(@RequestBody SysDictDataDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + sysDictDataService.update(dto); + + return new Result(); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:dict:delete") + public Result delete(@RequestBody Long[] ids) { + //效验数据 + AssertUtils.isArrayEmpty(ids, "id"); + + sysDictDataService.delete(ids); + + return new Result(); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDictTypeController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDictTypeController.java new file mode 100644 index 0000000..beed4ff --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysDictTypeController.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.sys.dto.SysDictTypeDTO; +import io.renren.modules.sys.entity.DictType; +import io.renren.modules.sys.service.SysDictTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("sys/dict/type") +@Tag(name = "字典类型") +@AllArgsConstructor +public class SysDictTypeController { + private final SysDictTypeService sysDictTypeService; + + @GetMapping("page") + @Operation(summary = "字典类型") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "dictType", description = "字典类型", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "dictName", description = "字典名称", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:dict:page") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + //字典类型 + PageData page = sysDictTypeService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:dict:info") + public Result get(@PathVariable("id") Long id) { + SysDictTypeDTO data = sysDictTypeService.get(id); + + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:dict:save") + public Result save(@RequestBody SysDictTypeDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, DefaultGroup.class); + + sysDictTypeService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:dict:update") + public Result update(@RequestBody SysDictTypeDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + sysDictTypeService.update(dto); + + return new Result(); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:dict:delete") + public Result delete(@RequestBody Long[] ids) { + //效验数据 + AssertUtils.isArrayEmpty(ids, "id"); + + sysDictTypeService.delete(ids); + + return new Result(); + } + + @GetMapping("all") + @Operation(summary = "所有字典数据") + public Result> all() { + List list = sysDictTypeService.getAllList(); + + return new Result>().ok(list); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysMenuController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysMenuController.java new file mode 100644 index 0000000..3bb8ff0 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysMenuController.java @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.exception.ErrorCode; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.modules.security.service.ShiroService; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dto.SysMenuDTO; +import io.renren.modules.sys.enums.MenuTypeEnum; +import io.renren.modules.sys.service.SysMenuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Set; + +/** + * 菜单管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/sys/menu") +@Tag(name = "菜单管理") +@AllArgsConstructor +public class SysMenuController { + private final SysMenuService sysMenuService; + private final ShiroService shiroService; + + @GetMapping("nav") + @Operation(summary = "导航") + public Result> nav() { + UserDetail user = SecurityUser.getUser(); + List list = sysMenuService.getUserMenuList(user, MenuTypeEnum.MENU.value()); + + return new Result>().ok(list); + } + + @GetMapping("permissions") + @Operation(summary = "权限标识") + public Result> permissions() { + UserDetail user = SecurityUser.getUser(); + Set set = shiroService.getUserPermissions(user); + + return new Result>().ok(set); + } + + @GetMapping("list") + @Operation(summary = "列表") + @Parameter(name = "type", description = "菜单类型 0:菜单 1:按钮 null:全部", in = ParameterIn.QUERY, ref = "int") + @RequiresPermissions("sys:menu:list") + public Result> list(Integer type) { + List list = sysMenuService.getAllMenuList(type); + + return new Result>().ok(list); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:menu:info") + public Result get(@PathVariable("id") Long id) { + SysMenuDTO data = sysMenuService.get(id); + + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:menu:save") + public Result save(@RequestBody SysMenuDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, DefaultGroup.class); + + sysMenuService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:menu:update") + public Result update(@RequestBody SysMenuDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, DefaultGroup.class); + + sysMenuService.update(dto); + + return new Result(); + } + + @DeleteMapping("{id}") + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:menu:delete") + public Result delete(@PathVariable("id") Long id) { + //效验数据 + AssertUtils.isNull(id, "id"); + + //判断是否有子菜单或按钮 + List list = sysMenuService.getListPid(id); + if (list.size() > 0) { + return new Result().error(ErrorCode.SUB_MENU_EXIST); + } + + sysMenuService.delete(id); + + return new Result(); + } + + @GetMapping("select") + @Operation(summary = "角色菜单权限") + @RequiresPermissions("sys:menu:select") + public Result> select() { + UserDetail user = SecurityUser.getUser(); + List list = sysMenuService.getUserMenuList(user, null); + + return new Result>().ok(list); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysParamsController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysParamsController.java new file mode 100644 index 0000000..eb13ece --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysParamsController.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.ExcelUtils; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.sys.dto.SysParamsDTO; +import io.renren.modules.sys.excel.SysParamsExcel; +import io.renren.modules.sys.service.SysParamsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@RestController +@RequestMapping("sys/params") +@Tag(name = "参数管理") +@AllArgsConstructor +public class SysParamsController { + private final SysParamsService sysParamsService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "paramCode", description = "参数编码", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:params:page") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysParamsService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:params:info") + public Result get(@PathVariable("id") Long id) { + SysParamsDTO data = sysParamsService.get(id); + + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:params:save") + public Result save(@RequestBody SysParamsDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); + + sysParamsService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:params:update") + public Result update(@RequestBody SysParamsDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + sysParamsService.update(dto); + + return new Result(); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:params:delete") + public Result delete(@RequestBody Long[] ids) { + //效验数据 + AssertUtils.isArrayEmpty(ids, "id"); + + sysParamsService.delete(ids); + + return new Result(); + } + + @GetMapping("export") + @Operation(summary = "导出") + @LogOperation("导出") + @RequiresPermissions("sys:params:export") + @Parameter(name = "paramCode", description = "参数编码", in = ParameterIn.QUERY, ref = "String") + public void export(@Parameter(hidden = true) @RequestParam Map params, HttpServletResponse response) throws Exception { + List list = sysParamsService.list(params); + + ExcelUtils.exportExcelToTarget(response, null, "参数管理", list, SysParamsExcel.class); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysRoleController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysRoleController.java new file mode 100644 index 0000000..a9d5776 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysRoleController.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.sys.dto.SysRoleDTO; +import io.renren.modules.sys.service.SysRoleDataScopeService; +import io.renren.modules.sys.service.SysRoleMenuService; +import io.renren.modules.sys.service.SysRoleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 角色管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/sys/role") +@Tag(name = "角色管理") +@AllArgsConstructor +public class SysRoleController { + private final SysRoleService sysRoleService; + private final SysRoleMenuService sysRoleMenuService; + private final SysRoleDataScopeService sysRoleDataScopeService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "name", description = "角色名", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:role:page") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysRoleService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("list") + @Operation(summary = "列表") + @RequiresPermissions("sys:role:list") + public Result> list() { + List data = sysRoleService.list(new HashMap<>(1)); + + return new Result>().ok(data); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:role:info") + public Result get(@PathVariable("id") Long id) { + SysRoleDTO data = sysRoleService.get(id); + + //查询角色对应的菜单 + List menuIdList = sysRoleMenuService.getMenuIdList(id); + data.setMenuIdList(menuIdList); + + //查询角色对应的数据权限 + List deptIdList = sysRoleDataScopeService.getDeptIdList(id); + data.setDeptIdList(deptIdList); + + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:role:save") + public Result save(@RequestBody SysRoleDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); + + sysRoleService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:role:update") + public Result update(@RequestBody SysRoleDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + sysRoleService.update(dto); + + return new Result(); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:role:delete") + public Result delete(@RequestBody Long[] ids) { + //效验数据 + AssertUtils.isArrayEmpty(ids, "id"); + + sysRoleService.delete(ids); + + return new Result(); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysUserController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysUserController.java new file mode 100644 index 0000000..25c20eb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysUserController.java @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.controller; + +import io.renren.common.annotation.LogOperation; +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.page.PageData; +import io.renren.common.utils.ConvertUtils; +import io.renren.common.utils.ExcelUtils; +import io.renren.common.utils.Result; +import io.renren.common.validator.AssertUtils; +import io.renren.common.validator.ValidatorUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.renren.modules.security.password.PasswordUtils; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dto.PasswordDTO; +import io.renren.modules.sys.dto.SysUserDTO; +import io.renren.modules.sys.excel.SysUserExcel; +import io.renren.modules.sys.service.SysRoleUserService; +import io.renren.modules.sys.service.SysUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 用户管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/sys/user") +@Tag(name = "用户管理") +@AllArgsConstructor +public class SysUserController { + private final SysUserService sysUserService; + private final SysRoleUserService sysRoleUserService; + + @GetMapping("page") + @Operation(summary = "分页") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"), + @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "username", description = "用户名", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "gender", description = "性别", in = ParameterIn.QUERY, ref = "String"), + @Parameter(name = "deptId", description = "部门ID", in = ParameterIn.QUERY, ref = "String") + }) + @RequiresPermissions("sys:user:page") + public Result> page(@Parameter(hidden = true) @RequestParam Map params) { + PageData page = sysUserService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "信息") + @RequiresPermissions("sys:user:info") + public Result get(@PathVariable("id") Long id) { + SysUserDTO data = sysUserService.get(id); + + //用户角色列表 + List roleIdList = sysRoleUserService.getRoleIdList(id); + data.setRoleIdList(roleIdList); + + return new Result().ok(data); + } + + @GetMapping("info") + @Operation(summary = "登录用户信息") + public Result info() { + SysUserDTO data = ConvertUtils.sourceToTarget(SecurityUser.getUser(), SysUserDTO.class); + return new Result().ok(data); + } + + @PutMapping("password") + @Operation(summary = "修改密码") + @LogOperation("修改密码") + public Result password(@RequestBody PasswordDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto); + + UserDetail user = SecurityUser.getUser(); + + //原密码不正确 + if (!PasswordUtils.matches(dto.getPassword(), user.getPassword())) { + return new Result().error(ErrorCode.PASSWORD_ERROR); + } + + sysUserService.updatePassword(user.getId(), dto.getNewPassword()); + + return new Result(); + } + + @PostMapping + @Operation(summary = "保存") + @LogOperation("保存") + @RequiresPermissions("sys:user:save") + public Result save(@RequestBody SysUserDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); + + sysUserService.save(dto); + + return new Result(); + } + + @PutMapping + @Operation(summary = "修改") + @LogOperation("修改") + @RequiresPermissions("sys:user:update") + public Result update(@RequestBody SysUserDTO dto) { + //效验数据 + ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); + + sysUserService.update(dto); + + return new Result(); + } + + @DeleteMapping + @Operation(summary = "删除") + @LogOperation("删除") + @RequiresPermissions("sys:user:delete") + public Result delete(@RequestBody Long[] ids) { + //效验数据 + AssertUtils.isArrayEmpty(ids, "id"); + + sysUserService.deleteBatchIds(Arrays.asList(ids)); + + return new Result(); + } + + @GetMapping("export") + @Operation(summary = "导出") + @LogOperation("导出") + @RequiresPermissions("sys:user:export") + @Parameter(name = "username", description = "用户名", in = ParameterIn.QUERY, ref = "String") + public void export(@Parameter(hidden = true) @RequestParam Map params, HttpServletResponse response) throws Exception { + List list = sysUserService.list(params); + + ExcelUtils.exportExcelToTarget(response, null, "用户管理", list, SysUserExcel.class); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDeptDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDeptDao.java new file mode 100644 index 0000000..d098933 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDeptDao.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysDeptEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * 部门管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysDeptDao extends BaseDao { + + List getList(Map params); + + SysDeptEntity getById(Long id); + + /** + * 获取所有部门的id、pid列表 + */ + List getIdAndPidList(); + + /** + * 根据部门ID,获取所有子部门ID列表 + * @param id 部门ID + */ + List getSubDeptIdList(String id); + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDictDataDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDictDataDao.java new file mode 100644 index 0000000..61ec809 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDictDataDao.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.DictData; +import io.renren.modules.sys.entity.SysDictDataEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 字典数据 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysDictDataDao extends BaseDao { + + /** + * 字典数据列表 + */ + List getDictDataList(); +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDictTypeDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDictTypeDao.java new file mode 100644 index 0000000..fa6e05d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysDictTypeDao.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.DictType; +import io.renren.modules.sys.entity.SysDictTypeEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysDictTypeDao extends BaseDao { + + /** + * 字典类型列表 + */ + List getDictTypeList(); + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysMenuDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysMenuDao.java new file mode 100644 index 0000000..039c14d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysMenuDao.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysMenuEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 菜单管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysMenuDao extends BaseDao { + + SysMenuEntity getById(@Param("id") Long id); + + /** + * 查询所有菜单列表 + * + * @param menuType 菜单类型 + */ + List getMenuList(@Param("menuType") Integer menuType); + + /** + * 查询用户菜单列表 + * + * @param userId 用户ID + * @param menuType 菜单类型 + */ + List getUserMenuList(@Param("userId") Long userId, @Param("menuType") Integer menuType); + + /** + * 查询用户权限列表 + * @param userId 用户ID + */ + List getUserPermissionsList(Long userId); + + /** + * 查询所有权限列表 + */ + List getPermissionsList(); + + /** + * 根据父菜单,查询子菜单 + * @param pid 父菜单ID + */ + List getListPid(Long pid); + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysParamsDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysParamsDao.java new file mode 100644 index 0000000..1d4c0cb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysParamsDao.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysParamsEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Mapper +public interface SysParamsDao extends BaseDao { + /** + * 根据参数编码,查询value + * @param paramCode 参数编码 + * @return 参数值 + */ + String getValueByCode(String paramCode); + + /** + * 获取参数编码列表 + * @param ids ids + * @return 返回参数编码列表 + */ + List getParamCodeList(Long[] ids); + + /** + * 根据参数编码,更新value + * @param paramCode 参数编码 + * @param paramValue 参数值 + */ + int updateValueByCode(@Param("paramCode") String paramCode, @Param("paramValue") String paramValue); +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleDao.java new file mode 100644 index 0000000..68c7664 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleDao.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysRoleEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 角色管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysRoleDao extends BaseDao { + + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleDataScopeDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleDataScopeDao.java new file mode 100644 index 0000000..8ad26c8 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleDataScopeDao.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysRoleDataScopeEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 角色数据权限 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Mapper +public interface SysRoleDataScopeDao extends BaseDao { + + /** + * 根据角色ID,获取部门ID列表 + */ + List getDeptIdList(Long roleId); + + /** + * 获取用户的部门数据权限列表 + */ + List getDataScopeList(Long userId); + + /** + * 根据角色id,删除角色数据权限关系 + * @param roleIds 角色ids + */ + void deleteByRoleIds(Long[] roleIds); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleMenuDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleMenuDao.java new file mode 100644 index 0000000..ed9252b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleMenuDao.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysRoleMenuEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 角色与菜单对应关系 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysRoleMenuDao extends BaseDao { + + /** + * 根据角色ID,获取菜单ID列表 + */ + List getMenuIdList(Long roleId); + + /** + * 根据角色id,删除角色菜单关系 + * @param roleIds 角色ids + */ + void deleteByRoleIds(Long[] roleIds); + + /** + * 根据菜单id,删除角色菜单关系 + * @param menuId 菜单id + */ + void deleteByMenuId(Long menuId); +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleUserDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleUserDao.java new file mode 100644 index 0000000..0038b12 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysRoleUserDao.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysRoleUserEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 角色用户关系 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Mapper +public interface SysRoleUserDao extends BaseDao { + + /** + * 根据角色ids,删除角色用户关系 + * @param roleIds 角色ids + */ + void deleteByRoleIds(Long[] roleIds); + + /** + * 根据用户id,删除角色用户关系 + * @param userIds 用户ids + */ + void deleteByUserIds(Long[] userIds); + + /** + * 角色ID列表 + * @param userId 用户ID + * + * @return + */ + List getRoleIdList(Long userId); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dao/SysUserDao.java b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysUserDao.java new file mode 100644 index 0000000..fc3c46b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dao/SysUserDao.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.modules.sys.entity.SysUserEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 系统用户 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SysUserDao extends BaseDao { + + List getList(Map params); + + SysUserEntity getById(Long id); + + SysUserEntity getByUsername(String username); + + int updatePassword(@Param("id") Long id, @Param("newPassword") String newPassword); + + /** + * 根据部门ID,查询用户数 + */ + int getCountByDeptId(Long deptId); + + /** + * 根据部门ID,查询用户ID列表 + */ + List getUserIdListByDeptId(List deptIdList); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/PasswordDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/PasswordDTO.java new file mode 100644 index 0000000..f0cd075 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/PasswordDTO.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 修改密码 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "修改密码") +public class PasswordDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "原密码") + @NotBlank(message="{sysuser.password.require}") + private String password; + + @Schema(title = "新密码") + @NotBlank(message="{sysuser.password.require}") + private String newPassword; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDeptDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDeptDTO.java new file mode 100644 index 0000000..e95901f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDeptDTO.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.utils.TreeNode; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +/** + * 部门管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(title = "部门管理") +public class SysDeptDTO extends TreeNode implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "上级ID") + @NotNull(message="{sysdept.pid.require}", groups = DefaultGroup.class) + private Long pid; + + @Schema(title = "部门名称") + @NotBlank(message="{sysdept.name.require}", groups = DefaultGroup.class) + private String name; + + @Schema(title = "排序") + @Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class) + private Integer sort; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date createDate; + + @Schema(title = "上级部门名称") + private String parentName; + + @Override + public Long getId() { + return id; + } + + @Override + public void setId(Long id) { + this.id = id; + } + + @Override + public Long getPid() { + return pid; + } + + @Override + public void setPid(Long pid) { + this.pid = pid; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDictDataDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDictDataDTO.java new file mode 100644 index 0000000..1fada6b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDictDataDTO.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 字典数据 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "字典数据") +public class SysDictDataDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "字典类型ID") + @NotNull(message="{sysdict.type.require}", groups = DefaultGroup.class) + private Long dictTypeId; + + @Schema(title = "字典标签") + @NotBlank(message="{sysdict.label.require}", groups = DefaultGroup.class) + private String dictLabel; + + @Schema(title = "字典值") + private String dictValue; + + @Schema(title = "备注") + private String remark; + + @Schema(title = "排序") + @Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class) + private Integer sort; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date createDate; + + @Schema(title = "更新时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date updateDate; +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDictTypeDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDictTypeDTO.java new file mode 100644 index 0000000..813667c --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysDictTypeDTO.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.utils.DateUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "字典类型") +public class SysDictTypeDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "字典类型") + @NotBlank(message="{sysdict.type.require}", groups = DefaultGroup.class) + private String dictType; + + @Schema(title = "字典名称") + @NotBlank(message="{sysdict.name.require}", groups = DefaultGroup.class) + private String dictName; + + @Schema(title = "备注") + private String remark; + + @Schema(title = "排序") + @Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class) + private Integer sort; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date createDate; + + @Schema(title = "更新时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date updateDate; +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysMenuDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysMenuDTO.java new file mode 100644 index 0000000..7431d47 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysMenuDTO.java @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.utils.TreeNode; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.validator.constraints.Range; + +import java.io.Serializable; +import java.util.Date; + +/** + * 菜单管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(title = "菜单管理") +public class SysMenuDTO extends TreeNode implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "上级ID") + @NotNull(message="{sysmenu.pid.require}", groups = DefaultGroup.class) + private Long pid; + + @Schema(title = "菜单名称") + @NotBlank(message="sysmenu.name.require", groups = DefaultGroup.class) + private String name; + + @Schema(title = "菜单URL") + private String url; + + @Schema(title = "类型 0:菜单 1:按钮") + @Range(min=0, max=1, message = "{sysmenu.type.range}", groups = DefaultGroup.class) + private Integer menuType; + + @Schema(title = "菜单图标") + private String icon; + + @Schema(title = "授权(多个用逗号分隔,如:sys:user:list,sys:user:save)") + private String permissions; + + @Schema(title = "排序") + @Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class) + private Integer sort; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date createDate; + + @Schema(title = "上级菜单名称") + private String parentName; + + @Override + public Long getId() { + return id; + } + + @Override + public void setId(Long id) { + this.id = id; + } + + @Override + public Long getPid() { + return pid; + } + + @Override + public void setPid(Long pid) { + this.pid = pid; + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysParamsDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysParamsDTO.java new file mode 100644 index 0000000..ee743ed --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysParamsDTO.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "参数管理") +public class SysParamsDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "参数编码") + @NotBlank(message="{sysparams.paramcode.require}", groups = DefaultGroup.class) + private String paramCode; + + @Schema(title = "参数值") + @NotBlank(message="{sysparams.paramvalue.require}", groups = DefaultGroup.class) + private String paramValue; + + @Schema(title = "备注") + private String remark; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date createDate; + + @Schema(title = "更新时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date updateDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysRoleDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysRoleDTO.java new file mode 100644 index 0000000..1664c42 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysRoleDTO.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 角色管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "角色管理") +public class SysRoleDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "角色名称") + @NotBlank(message="{sysrole.name.require}", groups = DefaultGroup.class) + private String name; + + @Schema(title = "备注") + private String remark; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Date createDate; + + @Schema(title = "菜单ID列表") + private List menuIdList; + + @Schema(title = "部门ID列表") + private List deptIdList; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SysUserDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysUserDTO.java new file mode 100644 index 0000000..e0cb5fd --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SysUserDTO.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.renren.common.utils.DateUtils; +import io.renren.common.validator.group.AddGroup; +import io.renren.common.validator.group.DefaultGroup; +import io.renren.common.validator.group.UpdateGroup; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import lombok.Data; +import org.hibernate.validator.constraints.Range; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 用户管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "用户管理") +public class SysUserDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "id") + @Null(message="{id.null}", groups = AddGroup.class) + @NotNull(message="{id.require}", groups = UpdateGroup.class) + private Long id; + + @Schema(title = "用户名", required = true) + @NotBlank(message="{sysuser.username.require}", groups = DefaultGroup.class) + private String username; + + @Schema(title = "密码") + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + @NotBlank(message="{sysuser.password.require}", groups = AddGroup.class) + private String password; + + @Schema(title = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message="{sysuser.realName.require}", groups = DefaultGroup.class) + private String realName; + + @Schema(title = "头像") + private String headUrl; + + @Schema(title = "性别 0:男 1:女 2:保密", required = true) + @Range(min=0, max=2, message = "{sysuser.gender.range}", groups = DefaultGroup.class) + private Integer gender; + + @Schema(title = "邮箱") + @Email(message="{sysuser.email.error}", groups = DefaultGroup.class) + private String email; + + @Schema(title = "手机号") + private String mobile; + + @Schema(title = "部门ID", required = true) + @NotNull(message="{sysuser.deptId.require}", groups = DefaultGroup.class) + private Long deptId; + + @Schema(title = "状态 0:停用 1:正常", required = true) + @Range(min=0, max=1, message = "{sysuser.status.range}", groups = DefaultGroup.class) + private Integer status; + + @Schema(title = "创建时间") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date createDate; + + @Schema(title = "超级管理员 0:否 1:是") + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Integer superAdmin; + + @Schema(title = "角色ID列表") + private List roleIdList; + + @Schema(title = "部门名称") + private String deptName; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/dto/SystemDTO.java b/renren-admin/src/main/java/io/renren/modules/sys/dto/SystemDTO.java new file mode 100644 index 0000000..1fdfa3a --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/dto/SystemDTO.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 系统数据 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@Schema(title = "系统数据") +public class SystemDTO implements Serializable { + private static final long serialVersionUID = 1L; + + private Long sysTime; + private String osName; + private String osArch; + private String osVersion; + private String userLanguage; + private String userDir; + private Long totalPhysical; + private Long freePhysical; + private BigDecimal memoryRate; + private Integer processors; + private String jvmName; + private String javaVersion; + private String javaHome; + private Long javaTotalMemory; + private Long javaFreeMemory; + private Long javaMaxMemory; + private String userName; + private BigDecimal systemCpuLoad; + private String userTimezone; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/DictData.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/DictData.java new file mode 100644 index 0000000..4b5d451 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/DictData.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2019 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * 字典数据 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +public class DictData { + @JsonIgnore + private Long dictTypeId; + private String dictLabel; + private String dictValue; +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/DictType.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/DictType.java new file mode 100644 index 0000000..a391710 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/DictType.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2019 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +public class DictType { + @JsonIgnore + private Long id; + private String dictType; + private List dataList = new ArrayList<>(); +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDeptEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDeptEntity.java new file mode 100644 index 0000000..ddf9d06 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDeptEntity.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 部门管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_dept") +public class SysDeptEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 上级ID + */ + private Long pid; + /** + * 所有上级ID,用逗号分开 + */ + private String pids; + /** + * 部门名称 + */ + private String name; + /** + * 排序 + */ + private Integer sort; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; + /** + * 上级部门名称 + */ + @TableField(exist = false) + private String parentName; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDictDataEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDictDataEntity.java new file mode 100644 index 0000000..b84197b --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDictDataEntity.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 数据字典 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_dict_data") +public class SysDictDataEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * 字典类型ID + */ + private Long dictTypeId; + /** + * 字典标签 + */ + private String dictLabel; + /** + * 字典值 + */ + private String dictValue; + /** + * 备注 + */ + private String remark; + /** + * 排序 + */ + private Integer sort; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDictTypeEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDictTypeEntity.java new file mode 100644 index 0000000..2a830ef --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysDictTypeEntity.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_dict_type") +public class SysDictTypeEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * 字典类型 + */ + private String dictType; + /** + * 字典名称 + */ + private String dictName; + /** + * 备注 + */ + private String remark; + /** + * 排序 + */ + private Integer sort; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysMenuEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysMenuEntity.java new file mode 100644 index 0000000..3168339 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysMenuEntity.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 菜单管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_menu") +public class SysMenuEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 父菜单ID,一级菜单为0 + */ + private Long pid; + /** + * 菜单名称 + */ + private String name; + /** + * 菜单URL + */ + private String url; + /** + * 授权(多个用逗号分隔,如:sys:user:list,sys:user:save) + */ + private String permissions; + /** + * 类型 0:菜单 1:按钮 + */ + private Integer menuType; + /** + * 菜单图标 + */ + private String icon; + /** + * 排序 + */ + private Integer sort; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; + /** + * 上级菜单名称 + */ + @TableField(exist = false) + private String parentName; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysParamsEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysParamsEntity.java new file mode 100644 index 0000000..fb7e62d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysParamsEntity.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_params") +public class SysParamsEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 参数编码 + */ + private String paramCode; + /** + * 参数值 + */ + private String paramValue; + /** + * 类型 0:系统参数 1:非系统参数 + */ + private Integer paramType; + /** + * 备注 + */ + private String remark; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleDataScopeEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleDataScopeEntity.java new file mode 100644 index 0000000..38188f8 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleDataScopeEntity.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 角色数据权限 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_role_data_scope") +public class SysRoleDataScopeEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 角色ID + */ + private Long roleId; + /** + * 部门ID + */ + private Long deptId; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleEntity.java new file mode 100644 index 0000000..ed02e52 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleEntity.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 角色 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_role") +public class SysRoleEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 角色名称 + */ + private String name; + /** + * 备注 + */ + private String remark; + /** + * 部门ID + */ + @TableField(fill = FieldFill.INSERT) + private Long deptId; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleMenuEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleMenuEntity.java new file mode 100644 index 0000000..a654e6d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleMenuEntity.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 角色菜单关系 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_role_menu") +public class SysRoleMenuEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * 角色ID + */ + private Long roleId; + /** + * 菜单ID + */ + private Long menuId; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleUserEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleUserEntity.java new file mode 100644 index 0000000..d793da5 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysRoleUserEntity.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 角色用户关系 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_role_user") +public class SysRoleUserEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 角色ID + */ + private Long roleId; + /** + * 用户ID + */ + private Long userId; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/entity/SysUserEntity.java b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysUserEntity.java new file mode 100644 index 0000000..864c7eb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/entity/SysUserEntity.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.renren.common.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 系统用户 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("sys_user") +public class SysUserEntity extends BaseEntity { + private static final long serialVersionUID = 1L; + /** + * 用户名 + */ + private String username; + /** + * 密码 + */ + private String password; + /** + * 姓名 + */ + private String realName; + /** + * 头像 + */ + private String headUrl; + /** + * 性别 0:男 1:女 2:保密 + */ + private Integer gender; + /** + * 邮箱 + */ + private String email; + /** + * 手机号 + */ + private String mobile; + /** + * 部门ID + */ + private Long deptId; + /** + * 超级管理员 0:否 1:是 + */ + private Integer superAdmin; + /** + * 状态 0:停用 1:正常 + */ + private Integer status; + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updater; + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateDate; + /** + * 部门名称 + */ + @TableField(exist=false) + private String deptName; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/enums/MenuTypeEnum.java b/renren-admin/src/main/java/io/renren/modules/sys/enums/MenuTypeEnum.java new file mode 100644 index 0000000..3cf2ba9 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/enums/MenuTypeEnum.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.enums; + +/** + * 菜单类型枚举 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public enum MenuTypeEnum { + /** + * 菜单 + */ + MENU(0), + /** + * 按钮 + */ + BUTTON(1); + + private int value; + + MenuTypeEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/enums/SuperAdminEnum.java b/renren-admin/src/main/java/io/renren/modules/sys/enums/SuperAdminEnum.java new file mode 100644 index 0000000..1c32493 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/enums/SuperAdminEnum.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.enums; + +/** + * 超级管理员枚举 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public enum SuperAdminEnum { + YES(1), + NO(0); + + private int value; + + SuperAdminEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/enums/UserStatusEnum.java b/renren-admin/src/main/java/io/renren/modules/sys/enums/UserStatusEnum.java new file mode 100644 index 0000000..ae114b4 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/enums/UserStatusEnum.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.enums; + +/** + * 用户状态 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public enum UserStatusEnum { + DISABLE(0), + ENABLED(1); + + private int value; + + UserStatusEnum(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/excel/SysParamsExcel.java b/renren-admin/src/main/java/io/renren/modules/sys/excel/SysParamsExcel.java new file mode 100644 index 0000000..1cdaffd --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/excel/SysParamsExcel.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +public class SysParamsExcel { + @ExcelProperty("参数编码") + private String paramCode; + @ExcelProperty("参数值") + private String paramValue; + @ExcelProperty("备注") + private String remark; + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/excel/SysUserExcel.java b/renren-admin/src/main/java/io/renren/modules/sys/excel/SysUserExcel.java new file mode 100644 index 0000000..53a35da --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/excel/SysUserExcel.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import io.renren.modules.sys.excel.converter.GenderConverter; +import io.renren.modules.sys.excel.converter.StatusConverter; +import lombok.Data; + +import java.util.Date; + +/** + * 用户管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Data +public class SysUserExcel { + @ExcelProperty("用户名") + private String username; + @ExcelProperty("姓名") + private String realName; + @ExcelProperty(value = "性别", converter = GenderConverter.class) + private Integer gender; + @ExcelProperty("邮箱") + private String email; + @ExcelProperty("手机号") + private String mobile; + @ExcelProperty("部门名称") + private String deptName; + @ExcelProperty(value = "状态", converter = StatusConverter.class) + private Integer status; + @ExcelProperty("备注") + private String remark; + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty("创建时间") + private Date createDate; + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/excel/converter/GenderConverter.java b/renren-admin/src/main/java/io/renren/modules/sys/excel/converter/GenderConverter.java new file mode 100644 index 0000000..6342de7 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/excel/converter/GenderConverter.java @@ -0,0 +1,45 @@ +package io.renren.modules.sys.excel.converter; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + + +public class GenderConverter implements Converter { + + + @Override + public Class supportJavaTypeKey() { + return Integer.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if(cellData.getStringValue().equals("男")){ + return 0; + }else if(cellData.getStringValue().equals("女")){ + return 1; + }else { + return 2; + } + } + + @Override + public WriteCellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if(value == 0){ + return new WriteCellData<>("男"); + }else if(value == 1){ + return new WriteCellData<>("女"); + }else { + return new WriteCellData<>("保密"); + } + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/excel/converter/StatusConverter.java b/renren-admin/src/main/java/io/renren/modules/sys/excel/converter/StatusConverter.java new file mode 100644 index 0000000..3fdb458 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/excel/converter/StatusConverter.java @@ -0,0 +1,30 @@ +package io.renren.modules.sys.excel.converter; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +public class StatusConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return Integer.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return cellData.getStringValue().equals("正常") ? 1 : 0; + } + + @Override + public WriteCellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return new WriteCellData<>(value == 1 ? "正常" : "停用"); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/redis/SysParamsRedis.java b/renren-admin/src/main/java/io/renren/modules/sys/redis/SysParamsRedis.java new file mode 100644 index 0000000..83c44a5 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/redis/SysParamsRedis.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.redis; + +import io.renren.common.redis.RedisKeys; +import io.renren.common.redis.RedisUtils; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Component +@AllArgsConstructor +public class SysParamsRedis { + private final RedisUtils redisUtils; + + public void delete(Object[] paramCodes) { + String key = RedisKeys.getSysParamsKey(); + redisUtils.hDel(key, paramCodes); + } + + public void set(String paramCode, String paramValue) { + if (paramValue == null) { + return; + } + String key = RedisKeys.getSysParamsKey(); + redisUtils.hSet(key, paramCode, paramValue); + } + + public String get(String paramCode) { + String key = RedisKeys.getSysParamsKey(); + return (String) redisUtils.hGet(key, paramCode); + } + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysDeptService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysDeptService.java new file mode 100644 index 0000000..5f1047f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysDeptService.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.service.BaseService; +import io.renren.modules.sys.dto.SysDeptDTO; +import io.renren.modules.sys.entity.SysDeptEntity; + +import java.util.List; +import java.util.Map; + +/** + * 部门管理 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysDeptService extends BaseService { + + List list(Map params); + + SysDeptDTO get(Long id); + + void save(SysDeptDTO dto); + + void update(SysDeptDTO dto); + + void delete(Long id); + + /** + * 根据部门ID,获取本部门及子部门ID列表 + * @param id 部门ID + */ + List getSubDeptIdList(Long id); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysDictDataService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysDictDataService.java new file mode 100644 index 0000000..8f67ccb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysDictDataService.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.sys.dto.SysDictDataDTO; +import io.renren.modules.sys.entity.SysDictDataEntity; + +import java.util.Map; + +/** + * 数据字典 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysDictDataService extends BaseService { + + PageData page(Map params); + + SysDictDataDTO get(Long id); + + void save(SysDictDataDTO dto); + + void update(SysDictDataDTO dto); + + void delete(Long[] ids); + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysDictTypeService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysDictTypeService.java new file mode 100644 index 0000000..6c051ae --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysDictTypeService.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.sys.dto.SysDictTypeDTO; +import io.renren.modules.sys.entity.DictType; +import io.renren.modules.sys.entity.SysDictTypeEntity; + +import java.util.List; +import java.util.Map; + +/** + * 数据字典 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysDictTypeService extends BaseService { + + PageData page(Map params); + + SysDictTypeDTO get(Long id); + + void save(SysDictTypeDTO dto); + + void update(SysDictTypeDTO dto); + + void delete(Long[] ids); + + /** + * 获取所有字典 + */ + List getAllList(); + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysMenuService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysMenuService.java new file mode 100644 index 0000000..8243978 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysMenuService.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.service.BaseService; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dto.SysMenuDTO; +import io.renren.modules.sys.entity.SysMenuEntity; + +import java.util.List; + + +/** + * 菜单管理 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysMenuService extends BaseService { + + SysMenuDTO get(Long id); + + void save(SysMenuDTO dto); + + void update(SysMenuDTO dto); + + void delete(Long id); + + /** + * 菜单列表 + * + * @param menuType 菜单类型 + */ + List getAllMenuList(Integer menuType); + + /** + * 用户菜单列表 + * + * @param user 用户 + * @param menuType 菜单类型 + */ + List getUserMenuList(UserDetail user, Integer menuType); + + /** + * 根据父菜单,查询子菜单 + * @param pid 父菜单ID + */ + List getListPid(Long pid); +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysParamsService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysParamsService.java new file mode 100644 index 0000000..0629aec --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysParamsService.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.sys.dto.SysParamsDTO; +import io.renren.modules.sys.entity.SysParamsEntity; + +import java.util.List; +import java.util.Map; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface SysParamsService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + SysParamsDTO get(Long id); + + void save(SysParamsDTO dto); + + void update(SysParamsDTO dto); + + void delete(Long[] ids); + + /** + * 根据参数编码,获取参数的value值 + * + * @param paramCode 参数编码 + */ + String getValue(String paramCode); + + /** + * 根据参数编码,获取value的Object对象 + * @param paramCode 参数编码 + * @param clazz Object对象 + */ + T getValueObject(String paramCode, Class clazz); + + /** + * 根据参数编码,更新value + * @param paramCode 参数编码 + * @param paramValue 参数值 + */ + int updateValueByCode(String paramCode, String paramValue); +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleDataScopeService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleDataScopeService.java new file mode 100644 index 0000000..59f8668 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleDataScopeService.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.service.BaseService; +import io.renren.modules.sys.entity.SysRoleDataScopeEntity; + +import java.util.List; + +/** + * 角色数据权限 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface SysRoleDataScopeService extends BaseService { + + /** + * 根据角色ID,获取部门ID列表 + */ + List getDeptIdList(Long roleId); + + /** + * 保存或修改 + * @param roleId 角色ID + * @param deptIdList 部门ID列表 + */ + void saveOrUpdate(Long roleId, List deptIdList); + + /** + * 根据角色id,删除角色数据权限关系 + * @param roleId 角色ids + */ + void deleteByRoleIds(Long[] roleId); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleMenuService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleMenuService.java new file mode 100644 index 0000000..e7d54a1 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleMenuService.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.service.BaseService; +import io.renren.modules.sys.entity.SysRoleMenuEntity; + +import java.util.List; + + +/** + * 角色与菜单对应关系 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysRoleMenuService extends BaseService { + + /** + * 根据角色ID,获取菜单ID列表 + */ + List getMenuIdList(Long roleId); + + /** + * 保存或修改 + * @param roleId 角色ID + * @param menuIdList 菜单ID列表 + */ + void saveOrUpdate(Long roleId, List menuIdList); + + /** + * 根据角色id,删除角色菜单关系 + * @param roleIds 角色ids + */ + void deleteByRoleIds(Long[] roleIds); + + /** + * 根据菜单id,删除角色菜单关系 + * @param menuId 菜单id + */ + void deleteByMenuId(Long menuId); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleService.java new file mode 100644 index 0000000..b0fd212 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleService.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.sys.dto.SysRoleDTO; +import io.renren.modules.sys.entity.SysRoleEntity; + +import java.util.List; +import java.util.Map; + + +/** + * 角色 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysRoleService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + SysRoleDTO get(Long id); + + void save(SysRoleDTO dto); + + void update(SysRoleDTO dto); + + void delete(Long[] ids); + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleUserService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleUserService.java new file mode 100644 index 0000000..de33bda --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysRoleUserService.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.service.BaseService; +import io.renren.modules.sys.entity.SysRoleUserEntity; + +import java.util.List; + +/** + * 角色用户关系 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface SysRoleUserService extends BaseService { + + /** + * 保存或修改 + * @param userId 用户ID + * @param roleIdList 角色ID列表 + */ + void saveOrUpdate(Long userId, List roleIdList); + + /** + * 根据角色ids,删除角色用户关系 + * @param roleIds 角色ids + */ + void deleteByRoleIds(Long[] roleIds); + + /** + * 根据用户id,删除角色用户关系 + * @param userIds 用户ids + */ + void deleteByUserIds(Long[] userIds); + + /** + * 角色ID列表 + * @param userId 用户ID + */ + List getRoleIdList(Long userId); +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/SysUserService.java b/renren-admin/src/main/java/io/renren/modules/sys/service/SysUserService.java new file mode 100644 index 0000000..78f68f3 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/SysUserService.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service; + +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.modules.sys.dto.SysUserDTO; +import io.renren.modules.sys.entity.SysUserEntity; + +import java.util.List; +import java.util.Map; + + +/** + * 系统用户 + * + * @author Mark sunlightcs@gmail.com + */ +public interface SysUserService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + SysUserDTO get(Long id); + + SysUserDTO getByUsername(String username); + + void save(SysUserDTO dto); + + void update(SysUserDTO dto); + + void delete(Long[] ids); + + /** + * 修改密码 + * @param id 用户ID + * @param newPassword 新密码 + */ + void updatePassword(Long id, String newPassword); + + /** + * 根据部门ID,查询用户数 + */ + int getCountByDeptId(Long deptId); + + /** + * 根据部门ID,查询用户Id列表 + */ + List getUserIdListByDeptId(List deptIdList); + +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDeptServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..88c4eca --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import com.qiniu.util.StringUtils; +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.common.utils.TreeUtils; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dao.SysDeptDao; +import io.renren.modules.sys.dao.SysUserDao; +import io.renren.modules.sys.dto.SysDeptDTO; +import io.renren.modules.sys.entity.SysDeptEntity; +import io.renren.modules.sys.enums.SuperAdminEnum; +import io.renren.modules.sys.service.SysDeptService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@Service +@AllArgsConstructor +public class SysDeptServiceImpl extends BaseServiceImpl implements SysDeptService { + private final SysUserDao sysUserDao; + + @Override + public List list(Map params) { + //普通管理员,只能查询所属部门及子部门的数据 + UserDetail user = SecurityUser.getUser(); + if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) { + params.put("deptIdList", getSubDeptIdList(user.getDeptId())); + } + + //查询部门列表 + List entityList = baseDao.getList(params); + + List dtoList = ConvertUtils.sourceToTarget(entityList, SysDeptDTO.class); + + return TreeUtils.build(dtoList); + } + + @Override + public SysDeptDTO get(Long id) { + //超级管理员,部门ID为null + if (id == null) { + return null; + } + + SysDeptEntity entity = baseDao.getById(id); + + return ConvertUtils.sourceToTarget(entity, SysDeptDTO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysDeptDTO dto) { + SysDeptEntity entity = ConvertUtils.sourceToTarget(dto, SysDeptEntity.class); + + entity.setPids(getPidList(entity.getPid())); + insert(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysDeptDTO dto) { + SysDeptEntity entity = ConvertUtils.sourceToTarget(dto, SysDeptEntity.class); + + //上级部门不能为自身 + if (entity.getId().equals(entity.getPid())) { + throw new RenException(ErrorCode.SUPERIOR_DEPT_ERROR); + } + + //上级部门不能为下级部门 + List subDeptList = getSubDeptIdList(entity.getId()); + if (subDeptList.contains(entity.getPid())) { + throw new RenException(ErrorCode.SUPERIOR_DEPT_ERROR); + } + + entity.setPids(getPidList(entity.getPid())); + updateById(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long id) { + //判断是否有子部门 + List subList = getSubDeptIdList(id); + if (subList.size() > 1) { + throw new RenException(ErrorCode.DEPT_SUB_DELETE_ERROR); + } + + //判断部门下面是否有用户 + int count = sysUserDao.getCountByDeptId(id); + if (count > 0) { + throw new RenException(ErrorCode.DEPT_USER_DELETE_ERROR); + } + + //删除 + baseDao.deleteById(id); + } + + @Override + public List getSubDeptIdList(Long id) { + List deptIdList = baseDao.getSubDeptIdList("%" + id + "%"); + deptIdList.add(id); + + return deptIdList; + } + + /** + * 获取所有上级部门ID + * + * @param pid 上级ID + */ + private String getPidList(Long pid) { + //顶级部门,无上级部门 + if (Constant.DEPT_ROOT.equals(pid)) { + return Constant.DEPT_ROOT + ""; + } + + //所有部门的id、pid列表 + List deptList = baseDao.getIdAndPidList(); + + //list转map + Map map = new HashMap<>(deptList.size()); + for (SysDeptEntity entity : deptList) { + map.put(entity.getId(), entity); + } + + //递归查询所有上级部门ID列表 + List pidList = new ArrayList<>(); + getPidTree(pid, map, pidList); + + return StringUtils.join(pidList, ","); + } + + private void getPidTree(Long pid, Map map, List pidList) { + //顶级部门,无上级部门 + if (Constant.DEPT_ROOT.equals(pid)) { + return; + } + + //上级部门存在 + SysDeptEntity parent = map.get(pid); + if (parent != null) { + getPidTree(parent.getPid(), map, pidList); + } + + pidList.add(pid); + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDictDataServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..3802bdb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.sys.dao.SysDictDataDao; +import io.renren.modules.sys.dto.SysDictDataDTO; +import io.renren.modules.sys.entity.SysDictDataEntity; +import io.renren.modules.sys.service.SysDictDataService; +import cn.hutool.core.util.StrUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Map; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class SysDictDataServiceImpl extends BaseServiceImpl implements SysDictDataService { + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, "sort", true), + getWrapper(params) + ); + + return getPageData(page, SysDictDataDTO.class); + } + + private QueryWrapper getWrapper(Map params){ + Long dictTypeId = Long.parseLong((String) params.get("dictTypeId")); + String dictLabel = (String) params.get("dictLabel"); + String dictValue = (String) params.get("dictValue"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dict_type_id", dictTypeId); + wrapper.like(StrUtil.isNotBlank(dictLabel), "dict_label", dictLabel); + wrapper.like(StrUtil.isNotBlank(dictValue), "dict_value", dictValue); + + return wrapper; + } + + @Override + public SysDictDataDTO get(Long id) { + SysDictDataEntity entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, SysDictDataDTO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysDictDataDTO dto) { + SysDictDataEntity entity = ConvertUtils.sourceToTarget(dto, SysDictDataEntity.class); + + insert(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysDictDataDTO dto) { + SysDictDataEntity entity = ConvertUtils.sourceToTarget(dto, SysDictDataEntity.class); + + updateById(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long[] ids) { + //删除 + deleteBatchIds(Arrays.asList(ids)); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDictTypeServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..0865070 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.sys.dao.SysDictDataDao; +import io.renren.modules.sys.dao.SysDictTypeDao; +import io.renren.modules.sys.dto.SysDictTypeDTO; +import io.renren.modules.sys.entity.DictData; +import io.renren.modules.sys.entity.DictType; +import io.renren.modules.sys.entity.SysDictTypeEntity; +import io.renren.modules.sys.service.SysDictTypeService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 字典类型 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +@AllArgsConstructor +public class SysDictTypeServiceImpl extends BaseServiceImpl implements SysDictTypeService { + private final SysDictDataDao sysDictDataDao; + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, "sort", true), + getWrapper(params) + ); + + return getPageData(page, SysDictTypeDTO.class); + } + + private QueryWrapper getWrapper(Map params) { + String dictType = (String) params.get("dictType"); + String dictName = (String) params.get("dictName"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.like(StrUtil.isNotBlank(dictType), "dict_type", dictType); + wrapper.like(StrUtil.isNotBlank(dictName), "dict_name", dictName); + + return wrapper; + } + + @Override + public SysDictTypeDTO get(Long id) { + SysDictTypeEntity entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, SysDictTypeDTO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysDictTypeDTO dto) { + SysDictTypeEntity entity = ConvertUtils.sourceToTarget(dto, SysDictTypeEntity.class); + + insert(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysDictTypeDTO dto) { + SysDictTypeEntity entity = ConvertUtils.sourceToTarget(dto, SysDictTypeEntity.class); + + updateById(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long[] ids) { + //删除 + deleteBatchIds(Arrays.asList(ids)); + } + + @Override + public List getAllList() { + List typeList = baseDao.getDictTypeList(); + List dataList = sysDictDataDao.getDictDataList(); + for (DictType type : typeList) { + for (DictData data : dataList) { + if (type.getId().equals(data.getDictTypeId())) { + type.getDataList().add(data); + } + } + } + return typeList; + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysMenuServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..e78abea --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.common.utils.TreeUtils; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dao.SysMenuDao; +import io.renren.modules.sys.dto.SysMenuDTO; +import io.renren.modules.sys.entity.SysMenuEntity; +import io.renren.modules.sys.enums.SuperAdminEnum; +import io.renren.modules.sys.service.SysMenuService; +import io.renren.modules.sys.service.SysRoleMenuService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@AllArgsConstructor +public class SysMenuServiceImpl extends BaseServiceImpl implements SysMenuService { + private final SysRoleMenuService sysRoleMenuService; + + @Override + public SysMenuDTO get(Long id) { + SysMenuEntity entity = baseDao.getById(id); + + SysMenuDTO dto = ConvertUtils.sourceToTarget(entity, SysMenuDTO.class); + + return dto; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysMenuDTO dto) { + SysMenuEntity entity = ConvertUtils.sourceToTarget(dto, SysMenuEntity.class); + + //保存菜单 + insert(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysMenuDTO dto) { + SysMenuEntity entity = ConvertUtils.sourceToTarget(dto, SysMenuEntity.class); + + //上级菜单不能为自身 + if (entity.getId().equals(entity.getPid())) { + throw new RenException(ErrorCode.SUPERIOR_MENU_ERROR); + } + + //更新菜单 + updateById(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long id) { + //删除菜单 + deleteById(id); + + //删除角色菜单关系 + sysRoleMenuService.deleteByMenuId(id); + } + + @Override + public List getAllMenuList(Integer menuType) { + List menuList = baseDao.getMenuList(menuType); + + List dtoList = ConvertUtils.sourceToTarget(menuList, SysMenuDTO.class); + + return TreeUtils.build(dtoList, Constant.MENU_ROOT); + } + + @Override + public List getUserMenuList(UserDetail user, Integer menuType) { + List menuList; + + //系统管理员,拥有最高权限 + if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) { + menuList = baseDao.getMenuList(menuType); + } else { + menuList = baseDao.getUserMenuList(user.getId(), menuType); + } + + List dtoList = ConvertUtils.sourceToTarget(menuList, SysMenuDTO.class); + + return TreeUtils.build(dtoList); + } + + @Override + public List getListPid(Long pid) { + List menuList = baseDao.getListPid(pid); + + return ConvertUtils.sourceToTarget(menuList, SysMenuDTO.class); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysParamsServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysParamsServiceImpl.java new file mode 100644 index 0000000..45a7a23 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysParamsServiceImpl.java @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.common.utils.JsonUtils; +import io.renren.modules.sys.dao.SysParamsDao; +import io.renren.modules.sys.dto.SysParamsDTO; +import io.renren.modules.sys.entity.SysParamsEntity; +import io.renren.modules.sys.redis.SysParamsRedis; +import io.renren.modules.sys.service.SysParamsService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 参数管理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Service +@AllArgsConstructor +public class SysParamsServiceImpl extends BaseServiceImpl implements SysParamsService { + private final SysParamsRedis sysParamsRedis; + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + + return getPageData(page, SysParamsDTO.class); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, SysParamsDTO.class); + } + + private QueryWrapper getWrapper(Map params) { + String paramCode = (String) params.get("paramCode"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("param_type", 1); + wrapper.like(StrUtil.isNotBlank(paramCode), "param_code", paramCode); + + return wrapper; + } + + @Override + public SysParamsDTO get(Long id) { + SysParamsEntity entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, SysParamsDTO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysParamsDTO dto) { + SysParamsEntity entity = ConvertUtils.sourceToTarget(dto, SysParamsEntity.class); + insert(entity); + + sysParamsRedis.set(entity.getParamCode(), entity.getParamValue()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysParamsDTO dto) { + SysParamsEntity entity = ConvertUtils.sourceToTarget(dto, SysParamsEntity.class); + updateById(entity); + + sysParamsRedis.set(entity.getParamCode(), entity.getParamValue()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long[] ids) { + //删除Redis数据 + List paramCodeList = baseDao.getParamCodeList(ids); + String[] paramCodes = paramCodeList.toArray(new String[paramCodeList.size()]); + sysParamsRedis.delete(paramCodes); + + //删除 + deleteBatchIds(Arrays.asList(ids)); + } + + @Override + public String getValue(String paramCode) { + String paramValue = sysParamsRedis.get(paramCode); + if (paramValue == null) { + paramValue = baseDao.getValueByCode(paramCode); + + sysParamsRedis.set(paramCode, paramValue); + } + return paramValue; + } + + @Override + public T getValueObject(String paramCode, Class clazz) { + String paramValue = getValue(paramCode); + if (StrUtil.isNotBlank(paramValue)) { + return JsonUtils.parseObject(paramValue, clazz); + } + + try { + return clazz.newInstance(); + } catch (Exception e) { + throw new RenException(ErrorCode.PARAMS_GET_ERROR); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int updateValueByCode(String paramCode, String paramValue) { + int count = baseDao.updateValueByCode(paramCode, paramValue); + sysParamsRedis.set(paramCode, paramValue); + return count; + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleDataScopeServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleDataScopeServiceImpl.java new file mode 100644 index 0000000..1dcd2d9 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleDataScopeServiceImpl.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.collection.CollUtil; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.modules.sys.dao.SysRoleDataScopeDao; +import io.renren.modules.sys.entity.SysRoleDataScopeEntity; +import io.renren.modules.sys.service.SysRoleDataScopeService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 角色数据权限 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Service +public class SysRoleDataScopeServiceImpl extends BaseServiceImpl + implements SysRoleDataScopeService { + + @Override + public List getDeptIdList(Long roleId) { + return baseDao.getDeptIdList(roleId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveOrUpdate(Long roleId, List deptIdList) { + //先删除角色数据权限关系 + deleteByRoleIds(new Long[]{roleId}); + + //角色没有一个数据权限的情况 + if(CollUtil.isEmpty(deptIdList)){ + return ; + } + + //保存角色数据权限关系 + for(Long deptId : deptIdList){ + SysRoleDataScopeEntity sysRoleDataScopeEntity = new SysRoleDataScopeEntity(); + sysRoleDataScopeEntity.setDeptId(deptId); + sysRoleDataScopeEntity.setRoleId(roleId); + + //保存 + insert(sysRoleDataScopeEntity); + } + } + + @Override + public void deleteByRoleIds(Long[] roleIds) { + baseDao.deleteByRoleIds(roleIds); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleMenuServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleMenuServiceImpl.java new file mode 100644 index 0000000..6f66b4f --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleMenuServiceImpl.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.collection.CollUtil; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.modules.sys.dao.SysRoleMenuDao; +import io.renren.modules.sys.entity.SysRoleMenuEntity; +import io.renren.modules.sys.service.SysRoleMenuService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + + +/** + * 角色与菜单对应关系 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class SysRoleMenuServiceImpl extends BaseServiceImpl implements SysRoleMenuService { + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveOrUpdate(Long roleId, List menuIdList) { + //先删除角色菜单关系 + deleteByRoleIds(new Long[]{roleId}); + + //角色没有一个菜单权限的情况 + if(CollUtil.isEmpty(menuIdList)){ + return ; + } + + //保存角色菜单关系 + for(Long menuId : menuIdList){ + SysRoleMenuEntity sysRoleMenuEntity = new SysRoleMenuEntity(); + sysRoleMenuEntity.setMenuId(menuId); + sysRoleMenuEntity.setRoleId(roleId); + + //保存 + insert(sysRoleMenuEntity); + } + } + + @Override + public List getMenuIdList(Long roleId){ + return baseDao.getMenuIdList(roleId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteByRoleIds(Long[] roleIds) { + baseDao.deleteByRoleIds(roleIds); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteByMenuId(Long menuId) { + baseDao.deleteByMenuId(menuId); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..ca03844 --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dao.SysRoleDao; +import io.renren.modules.sys.dto.SysRoleDTO; +import io.renren.modules.sys.entity.SysRoleEntity; +import io.renren.modules.sys.enums.SuperAdminEnum; +import io.renren.modules.sys.service.*; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 角色 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +@AllArgsConstructor +public class SysRoleServiceImpl extends BaseServiceImpl implements SysRoleService { + private final SysRoleMenuService sysRoleMenuService; + private final SysRoleDataScopeService sysRoleDataScopeService; + private final SysRoleUserService sysRoleUserService; + private final SysDeptService sysDeptService; + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, Constant.CREATE_DATE, false), + getWrapper(params) + ); + + return getPageData(page, SysRoleDTO.class); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, SysRoleDTO.class); + } + + private QueryWrapper getWrapper(Map params) { + String name = (String) params.get("name"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.like(StrUtil.isNotBlank(name), "name", name); + + //普通管理员,只能查询所属部门及子部门的数据 + UserDetail user = SecurityUser.getUser(); + if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) { + List deptIdList = sysDeptService.getSubDeptIdList(user.getDeptId()); + wrapper.in(deptIdList != null, "dept_id", deptIdList); + } + + return wrapper; + } + + @Override + public SysRoleDTO get(Long id) { + SysRoleEntity entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, SysRoleDTO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysRoleDTO dto) { + SysRoleEntity entity = ConvertUtils.sourceToTarget(dto, SysRoleEntity.class); + + //保存角色 + insert(entity); + + //保存角色菜单关系 + sysRoleMenuService.saveOrUpdate(entity.getId(), dto.getMenuIdList()); + + //保存角色数据权限关系 + sysRoleDataScopeService.saveOrUpdate(entity.getId(), dto.getDeptIdList()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysRoleDTO dto) { + SysRoleEntity entity = ConvertUtils.sourceToTarget(dto, SysRoleEntity.class); + + //更新角色 + updateById(entity); + + //更新角色菜单关系 + sysRoleMenuService.saveOrUpdate(entity.getId(), dto.getMenuIdList()); + + //更新角色数据权限关系 + sysRoleDataScopeService.saveOrUpdate(entity.getId(), dto.getDeptIdList()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long[] ids) { + //删除角色 + baseDao.deleteBatchIds(Arrays.asList(ids)); + + //删除角色用户关系 + sysRoleUserService.deleteByRoleIds(ids); + + //删除角色菜单关系 + sysRoleMenuService.deleteByRoleIds(ids); + + //删除角色数据权限关系 + sysRoleDataScopeService.deleteByRoleIds(ids); + } + +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleUserServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleUserServiceImpl.java new file mode 100644 index 0000000..691886d --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysRoleUserServiceImpl.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.collection.CollUtil; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.modules.sys.dao.SysRoleUserDao; +import io.renren.modules.sys.entity.SysRoleUserEntity; +import io.renren.modules.sys.service.SysRoleUserService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 角色用户关系 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Service +public class SysRoleUserServiceImpl extends BaseServiceImpl implements SysRoleUserService { + + @Override + public void saveOrUpdate(Long userId, List roleIdList) { + //先删除角色用户关系 + deleteByUserIds(new Long[]{userId}); + + //用户没有一个角色权限的情况 + if(CollUtil.isEmpty(roleIdList)){ + return ; + } + + //保存角色用户关系 + for(Long roleId : roleIdList){ + SysRoleUserEntity sysRoleUserEntity = new SysRoleUserEntity(); + sysRoleUserEntity.setUserId(userId); + sysRoleUserEntity.setRoleId(roleId); + + //保存 + insert(sysRoleUserEntity); + } + } + + @Override + public void deleteByRoleIds(Long[] roleIds) { + baseDao.deleteByRoleIds(roleIds); + } + + @Override + public void deleteByUserIds(Long[] userIds) { + baseDao.deleteByUserIds(userIds); + } + + @Override + public List getRoleIdList(Long userId) { + + return baseDao.getRoleIdList(userId); + } +} \ No newline at end of file diff --git a/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysUserServiceImpl.java b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..88633bb --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/sys/service/impl/SysUserServiceImpl.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.modules.sys.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.utils.ConvertUtils; +import io.renren.modules.security.password.PasswordUtils; +import io.renren.modules.security.user.SecurityUser; +import io.renren.modules.security.user.UserDetail; +import io.renren.modules.sys.dao.SysUserDao; +import io.renren.modules.sys.dto.SysUserDTO; +import io.renren.modules.sys.entity.SysUserEntity; +import io.renren.modules.sys.enums.SuperAdminEnum; +import io.renren.modules.sys.service.SysDeptService; +import io.renren.modules.sys.service.SysRoleUserService; +import io.renren.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + + +/** + * 系统用户 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +@AllArgsConstructor +public class SysUserServiceImpl extends BaseServiceImpl implements SysUserService { + private final SysRoleUserService sysRoleUserService; + private final SysDeptService sysDeptService; + + @Override + public PageData page(Map params) { + //转换成like + paramsToLike(params, "username"); + + //分页 + IPage page = getPage(params, Constant.CREATE_DATE, false); + + //普通管理员,只能查询所属部门及子部门的数据 + UserDetail user = SecurityUser.getUser(); + if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) { + params.put("deptIdList", sysDeptService.getSubDeptIdList(user.getDeptId())); + } + + //查询 + List list = baseDao.getList(params); + + return getPageData(list, page.getTotal(), SysUserDTO.class); + } + + @Override + public List list(Map params) { + //普通管理员,只能查询所属部门及子部门的数据 + UserDetail user = SecurityUser.getUser(); + if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) { + params.put("deptIdList", sysDeptService.getSubDeptIdList(user.getDeptId())); + } + + List entityList = baseDao.getList(params); + + return ConvertUtils.sourceToTarget(entityList, SysUserDTO.class); + } + + @Override + public SysUserDTO get(Long id) { + SysUserEntity entity = baseDao.getById(id); + + return ConvertUtils.sourceToTarget(entity, SysUserDTO.class); + } + + @Override + public SysUserDTO getByUsername(String username) { + SysUserEntity entity = baseDao.getByUsername(username); + return ConvertUtils.sourceToTarget(entity, SysUserDTO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysUserDTO dto) { + SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class); + + //密码加密 + String password = PasswordUtils.encode(entity.getPassword()); + entity.setPassword(password); + + //保存用户 + entity.setSuperAdmin(SuperAdminEnum.NO.value()); + insert(entity); + + //保存角色用户关系 + sysRoleUserService.saveOrUpdate(entity.getId(), dto.getRoleIdList()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysUserDTO dto) { + SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class); + + //密码加密 + if (StrUtil.isBlank(dto.getPassword())) { + entity.setPassword(null); + } else { + String password = PasswordUtils.encode(entity.getPassword()); + entity.setPassword(password); + } + + //更新用户 + updateById(entity); + + //更新角色用户关系 + sysRoleUserService.saveOrUpdate(entity.getId(), dto.getRoleIdList()); + } + + @Override + public void delete(Long[] ids) { + //删除用户 + baseDao.deleteBatchIds(Arrays.asList(ids)); + + //删除角色用户关系 + sysRoleUserService.deleteByUserIds(ids); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePassword(Long id, String newPassword) { + newPassword = PasswordUtils.encode(newPassword); + + baseDao.updatePassword(id, newPassword); + } + + @Override + public int getCountByDeptId(Long deptId) { + return baseDao.getCountByDeptId(deptId); + } + + @Override + public List getUserIdListByDeptId(List deptIdList) { + return baseDao.getUserIdListByDeptId(deptIdList); + } + +} diff --git a/renren-admin/src/main/resources/application-dev.yml b/renren-admin/src/main/resources/application-dev.yml new file mode 100644 index 0000000..ebf9fda --- /dev/null +++ b/renren-admin/src/main/resources/application-dev.yml @@ -0,0 +1,48 @@ +spring: + datasource: + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/renren4?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true + username: root + password: r2356510 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 6000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + # validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + #达梦数据库,需要注释掉,其他数据库可以打开 +# filter: +# stat: +# log-slow-sql: true +# slow-sql-millis: 1000 +# merge-sql: false +# wall: +# config: +# multi-statement-allow: true + +##多数据源的配置,需要引用renren-dynamic-datasource +#dynamic: +# datasource: +# slave1: +# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver +# url: jdbc:sqlserver://123456:1433;DatabaseName=renren_security +# username: sa +# password: 123456 +# slave2: +# driver-class-name: org.postgresql.Driver +# url: jdbc:postgresql://123456:5432/renren_security +# username: postgres +# password: 123456 diff --git a/renren-admin/src/main/resources/application-prod.yml b/renren-admin/src/main/resources/application-prod.yml new file mode 100644 index 0000000..80d85af --- /dev/null +++ b/renren-admin/src/main/resources/application-prod.yml @@ -0,0 +1,34 @@ +spring: + datasource: + druid: + #MySQL + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true + username: renren + password: 123456 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 60000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + #validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + filter: + stat: + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: false + wall: + config: + multi-statement-allow: true \ No newline at end of file diff --git a/renren-admin/src/main/resources/application-test.yml b/renren-admin/src/main/resources/application-test.yml new file mode 100644 index 0000000..80d85af --- /dev/null +++ b/renren-admin/src/main/resources/application-test.yml @@ -0,0 +1,34 @@ +spring: + datasource: + druid: + #MySQL + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true + username: renren + password: 123456 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 60000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + #validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + filter: + stat: + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: false + wall: + config: + multi-statement-allow: true \ No newline at end of file diff --git a/renren-admin/src/main/resources/application.yml b/renren-admin/src/main/resources/application.yml new file mode 100644 index 0000000..e45d050 --- /dev/null +++ b/renren-admin/src/main/resources/application.yml @@ -0,0 +1,79 @@ +# Tomcat +server: + tomcat: + uri-encoding: UTF-8 + threads: + max: 1000 + min-spare: 30 + port: 8080 + servlet: + context-path: / + session: + cookie: + http-only: true + +knife4j: + enable: false + basic: + enable: false + username: admin + password: admin + setting: + enableFooter: false + +spring: + # 环境 dev|test|prod + profiles: + active: dev + messages: + encoding: UTF-8 + basename: i18n/messages + mvc: + pathmatch: + matching-strategy: ANT_PATH_MATCHER + servlet: + multipart: + max-file-size: 100MB + max-request-size: 100MB + enabled: true + + data: + redis: + database: 0 + host: 192.168.10.10 + port: 6379 + password: # 密码(默认为空) + timeout: 6000ms # 连接超时时长(毫秒) + lettuce: + pool: + max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) + max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-idle: 10 # 连接池中的最大空闲连接 + min-idle: 5 # 连接池中的最小空闲连接 + +# 是否开启redis缓存 true开启 false关闭 +renren: + redis: + open: false + +#mybatis +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + #实体扫描,多个package用逗号或者分号分隔 + typeAliasesPackage: io.renren.modules.*.entity + global-config: + #数据库相关配置 + db-config: + #主键类型 + id-type: ASSIGN_ID + banner: false + #原生配置 + configuration: + map-underscore-to-camel-case: true + cache-enabled: false + call-setters-on-nulls: true + jdbc-type-for-null: 'null' + configuration-properties: + prefix: + blobType: BLOB + boolValue: TRUE diff --git a/renren-admin/src/main/resources/banner.txt b/renren-admin/src/main/resources/banner.txt new file mode 100644 index 0000000..d9219dd --- /dev/null +++ b/renren-admin/src/main/resources/banner.txt @@ -0,0 +1,5 @@ +==================================================================================================================== + + 欢迎使用 renren-security - Powered By https://www.renren.io + +==================================================================================================================== \ No newline at end of file diff --git a/renren-admin/src/main/resources/logback-spring.xml b/renren-admin/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..5deef21 --- /dev/null +++ b/renren-admin/src/main/resources/logback-spring.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/job/ScheduleJobDao.xml b/renren-admin/src/main/resources/mapper/job/ScheduleJobDao.xml new file mode 100644 index 0000000..d53d9e2 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/job/ScheduleJobDao.xml @@ -0,0 +1,14 @@ + + + + + + + + update schedule_job set status = #{status} where id in + + #{id} + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/job/ScheduleJobLogDao.xml b/renren-admin/src/main/resources/mapper/job/ScheduleJobLogDao.xml new file mode 100644 index 0000000..6999238 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/job/ScheduleJobLogDao.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/log/SysLogErrorDao.xml b/renren-admin/src/main/resources/mapper/log/SysLogErrorDao.xml new file mode 100644 index 0000000..27268c5 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/log/SysLogErrorDao.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/log/SysLogLoginDao.xml b/renren-admin/src/main/resources/mapper/log/SysLogLoginDao.xml new file mode 100644 index 0000000..ab6ec35 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/log/SysLogLoginDao.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/log/SysLogOperationDao.xml b/renren-admin/src/main/resources/mapper/log/SysLogOperationDao.xml new file mode 100644 index 0000000..079abc0 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/log/SysLogOperationDao.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/oss/SysOssDao.xml b/renren-admin/src/main/resources/mapper/oss/SysOssDao.xml new file mode 100644 index 0000000..bbb3af4 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/oss/SysOssDao.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysDeptDao.xml b/renren-admin/src/main/resources/mapper/sys/SysDeptDao.xml new file mode 100644 index 0000000..0941157 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysDeptDao.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysDictDataDao.xml b/renren-admin/src/main/resources/mapper/sys/SysDictDataDao.xml new file mode 100644 index 0000000..5e8e2f6 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysDictDataDao.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysDictTypeDao.xml b/renren-admin/src/main/resources/mapper/sys/SysDictTypeDao.xml new file mode 100644 index 0000000..6b92d31 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysDictTypeDao.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysMenuDao.xml b/renren-admin/src/main/resources/mapper/sys/SysMenuDao.xml new file mode 100644 index 0000000..3faeb69 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysMenuDao.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysParamsDao.xml b/renren-admin/src/main/resources/mapper/sys/SysParamsDao.xml new file mode 100644 index 0000000..964fc35 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysParamsDao.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + update sys_params set param_value = #{paramValue} where param_code = #{paramCode} + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysRoleDao.xml b/renren-admin/src/main/resources/mapper/sys/SysRoleDao.xml new file mode 100644 index 0000000..9c39f26 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysRoleDao.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysRoleDataScopeDao.xml b/renren-admin/src/main/resources/mapper/sys/SysRoleDataScopeDao.xml new file mode 100644 index 0000000..5192393 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysRoleDataScopeDao.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + delete from sys_role_data_scope where role_id in + + #{roleId} + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysRoleMenuDao.xml b/renren-admin/src/main/resources/mapper/sys/SysRoleMenuDao.xml new file mode 100644 index 0000000..912c2f2 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysRoleMenuDao.xml @@ -0,0 +1,20 @@ + + + + + + + + + delete from sys_role_menu where role_id in + + #{roleId} + + + + + delete from sys_role_menu where menu_id = #{value} + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysRoleUserDao.xml b/renren-admin/src/main/resources/mapper/sys/SysRoleUserDao.xml new file mode 100644 index 0000000..d31e2c4 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysRoleUserDao.xml @@ -0,0 +1,24 @@ + + + + + + + delete from sys_role_user where role_id in + + #{roleId} + + + + + delete from sys_role_user where user_id in + + #{userId} + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysUserDao.xml b/renren-admin/src/main/resources/mapper/sys/SysUserDao.xml new file mode 100644 index 0000000..cd2f771 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysUserDao.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + update sys_user set password = #{newPassword} where id = #{id} + + + + + + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/mapper/sys/SysUserTokenDao.xml b/renren-admin/src/main/resources/mapper/sys/SysUserTokenDao.xml new file mode 100644 index 0000000..fe77347 --- /dev/null +++ b/renren-admin/src/main/resources/mapper/sys/SysUserTokenDao.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + update sys_user_token set token = #{token} where user_id = #{userId} + + \ No newline at end of file diff --git a/renren-admin/src/main/resources/public/1.png b/renren-admin/src/main/resources/public/1.png new file mode 100644 index 0000000..4c65c74 Binary files /dev/null and b/renren-admin/src/main/resources/public/1.png differ diff --git a/renren-admin/src/main/resources/public/2.png b/renren-admin/src/main/resources/public/2.png new file mode 100644 index 0000000..06a48ec Binary files /dev/null and b/renren-admin/src/main/resources/public/2.png differ diff --git a/renren-admin/src/main/resources/public/favicon.ico b/renren-admin/src/main/resources/public/favicon.ico new file mode 100644 index 0000000..2bd581c Binary files /dev/null and b/renren-admin/src/main/resources/public/favicon.ico differ diff --git a/renren-admin/src/main/resources/public/wechat.jpg b/renren-admin/src/main/resources/public/wechat.jpg new file mode 100644 index 0000000..b3181ca Binary files /dev/null and b/renren-admin/src/main/resources/public/wechat.jpg differ diff --git a/renren-admin/src/test/java/io/renren/DynamicDataSourceTest.java b/renren-admin/src/test/java/io/renren/DynamicDataSourceTest.java new file mode 100644 index 0000000..a410df6 --- /dev/null +++ b/renren-admin/src/test/java/io/renren/DynamicDataSourceTest.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren; + +import io.renren.service.DynamicDataSourceTestService; +import jakarta.annotation.Resource; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + + +/** + * 多数据源测试 + * + * @author Mark sunlightcs@gmail.com + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class DynamicDataSourceTest { + @Resource + private DynamicDataSourceTestService dynamicDataSourceTestService; + + @Test + public void test() { + Long id = 1067246875800000001L; + + dynamicDataSourceTestService.updateUser(id); + dynamicDataSourceTestService.updateUserBySlave1(id); + //dynamicDataSourceTestService.updateUserBySlave2(id); + } + + +} diff --git a/renren-admin/src/test/java/io/renren/RedisTest.java b/renren-admin/src/test/java/io/renren/RedisTest.java new file mode 100644 index 0000000..9070892 --- /dev/null +++ b/renren-admin/src/test/java/io/renren/RedisTest.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren; + +import cn.hutool.core.util.StrUtil; +import io.renren.common.redis.RedisUtils; +import io.renren.modules.sys.entity.SysUserEntity; +import jakarta.annotation.Resource; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RedisTest { + @Resource + private RedisUtils redisUtils; + + @Test + public void contextLoads() { + SysUserEntity user = new SysUserEntity(); + user.setEmail("123456@qq.com"); + redisUtils.set("user", user); + + System.out.println(StrUtil.toString(redisUtils.get("user"))); + } + +} diff --git a/renren-admin/src/test/java/io/renren/service/DynamicDataSourceTestService.java b/renren-admin/src/test/java/io/renren/service/DynamicDataSourceTestService.java new file mode 100644 index 0000000..cb30782 --- /dev/null +++ b/renren-admin/src/test/java/io/renren/service/DynamicDataSourceTestService.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.service; + +import io.renren.commons.dynamic.datasource.annotation.DataSource; +import io.renren.modules.sys.dao.SysUserDao; +import io.renren.modules.sys.entity.SysUserEntity; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +/** + * 测试多数据源 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +//@DataSource("slave1") +public class DynamicDataSourceTestService { + @Resource + private SysUserDao sysUserDao; + + //@Transactional + public void updateUser(Long id) { + SysUserEntity user = new SysUserEntity(); + user.setId(id); + user.setMobile("13500000000"); + //sysUserDao.updateById(user); + System.out.println(sysUserDao.selectById(id)); + } + + @DataSource("slave1") + @Transactional + public void updateUserBySlave1(Long id) { + SysUserEntity user = new SysUserEntity(); + user.setId(id); + user.setMobile("13500000001"); + //sysUserDao.updateById(user); + System.out.println(sysUserDao.selectById(id)); + } + +// @DataSource("slave2") +// @Transactional +// public void updateUserBySlave2(Long id){ +// SysUserEntity user = new SysUserEntity(); +// user.setId(id); +// user.setMobile("13500000002"); +// sysUserDao.updateById(user); +// +// //测试事物 +// int i = 1/0; +// } +} diff --git a/renren-api/Dockerfile b/renren-api/Dockerfile new file mode 100644 index 0000000..251b7fc --- /dev/null +++ b/renren-api/Dockerfile @@ -0,0 +1,7 @@ +FROM java:8 +EXPOSE 8081 + +VOLUME /tmp +ADD renren-api.jar /app.jar +RUN bash -c 'touch /app.jar' +ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/renren-api/db/dm8.sql b/renren-api/db/dm8.sql new file mode 100644 index 0000000..7f1bfd0 --- /dev/null +++ b/renren-api/db/dm8.sql @@ -0,0 +1,27 @@ +CREATE TABLE tb_user ( + id bigint NOT NULL, + username varchar(50) NOT NULL, + mobile varchar(20) NOT NULL, + password varchar(64), + create_date datetime, + PRIMARY KEY (id) +); +CREATE UNIQUE INDEX idx_user_username on tb_user(username); + +CREATE TABLE tb_token ( + id bigint NOT NULL, + user_id bigint NOT NULL, + token varchar(100) NOT NULL, + expire_date datetime, + update_date datetime, + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX idx_token_user_id on tb_token(user_id); +CREATE UNIQUE INDEX idx_token on tb_token(token); + + +-- 账号:13612345678 密码:admin +INSERT INTO tb_user (id, username, mobile, password, create_date) VALUES (1067246875800000168, 'mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', now()); + +commit; diff --git a/renren-api/db/mysql.sql b/renren-api/db/mysql.sql new file mode 100644 index 0000000..ba6f058 --- /dev/null +++ b/renren-api/db/mysql.sql @@ -0,0 +1,25 @@ +-- 用户表 +CREATE TABLE tb_user ( + id bigint NOT NULL COMMENT 'id', + username varchar(50) NOT NULL COMMENT '用户名', + mobile varchar(20) NOT NULL COMMENT '手机号', + password varchar(64) COMMENT '密码', + create_date datetime COMMENT '创建时间', + PRIMARY KEY (id), + UNIQUE INDEX (username) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户'; + +-- 用户Token表 +CREATE TABLE tb_token ( + id bigint NOT NULL COMMENT 'id', + user_id bigint NOT NULL COMMENT '用户ID', + token varchar(100) NOT NULL COMMENT 'token', + expire_date datetime COMMENT '过期时间', + update_date datetime COMMENT '更新时间', + PRIMARY KEY (id), + UNIQUE INDEX (user_id), + UNIQUE INDEX (token) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户Token'; + +-- 账号:13612345678 密码:admin +INSERT INTO tb_user (id, username, mobile, password, create_date) VALUES (1067246875900000001, 'mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', now()); diff --git a/renren-api/db/oracle.sql b/renren-api/db/oracle.sql new file mode 100644 index 0000000..69b44cb --- /dev/null +++ b/renren-api/db/oracle.sql @@ -0,0 +1,24 @@ +CREATE TABLE tb_user ( + id NUMBER(20, 0) NOT NULL, + username varchar(50) NOT NULL, + mobile varchar(20) NOT NULL, + password varchar(64), + create_date date, + PRIMARY KEY (id) +); +CREATE UNIQUE INDEX idx_user_username on tb_user(username); + +CREATE TABLE tb_token ( + id NUMBER(20, 0) NOT NULL, + user_id NUMBER(20, 0) NOT NULL, + token varchar(100) NOT NULL, + expire_date date, + update_date date, + PRIMARY KEY (id) +); +CREATE UNIQUE INDEX idx_token_user_id on tb_token(user_id); +CREATE UNIQUE INDEX idx_token on tb_token(token); + + +-- 账号:13612345678 密码:admin +INSERT INTO tb_user (id, username, mobile, password, create_date) VALUES (1067246875900000001, 'mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', CURRENT_DATE); diff --git a/renren-api/db/postgresql.sql b/renren-api/db/postgresql.sql new file mode 100644 index 0000000..408b32c --- /dev/null +++ b/renren-api/db/postgresql.sql @@ -0,0 +1,24 @@ +CREATE TABLE tb_user ( + id int8 NOT NULL, + username varchar(50) NOT NULL, + mobile varchar(20) NOT NULL, + password varchar(64), + create_date timestamp, + PRIMARY KEY (id), + UNIQUE (username) +); + +CREATE TABLE tb_token ( + id int8 NOT NULL, + user_id int8 NOT NULL, + token varchar(100) NOT NULL, + expire_date timestamp, + update_date timestamp, + PRIMARY KEY (id), + UNIQUE (user_id), + UNIQUE (token) +); + + +-- 账号:13612345678 密码:admin +INSERT INTO tb_user (id, username, mobile, password, create_date) VALUES (1067246875900000001, 'mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', now()); diff --git a/renren-api/db/sqlserver.sql b/renren-api/db/sqlserver.sql new file mode 100644 index 0000000..3a600a4 --- /dev/null +++ b/renren-api/db/sqlserver.sql @@ -0,0 +1,24 @@ +CREATE TABLE tb_user ( + id bigint NOT NULL, + username varchar(50) NOT NULL, + mobile varchar(20) NOT NULL, + password varchar(64), + create_date datetime, + PRIMARY KEY (id), + UNIQUE (username) +); + +CREATE TABLE tb_token ( + id bigint NOT NULL, + user_id bigint NOT NULL, + token varchar(100) NOT NULL, + expire_date datetime, + update_date datetime, + PRIMARY KEY (id), + UNIQUE (user_id), + UNIQUE (token) +); + + +-- 账号:13612345678 密码:admin +INSERT INTO tb_user (id, username, mobile, password, create_date) VALUES (1067246875900000001, 'mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', getdate()); diff --git a/renren-api/pom.xml b/renren-api/pom.xml new file mode 100644 index 0000000..ddb5ac8 --- /dev/null +++ b/renren-api/pom.xml @@ -0,0 +1,41 @@ + + + io.renren + renren-security + 5.5.0 + + 4.0.0 + renren-api + jar + renren-api + + + + io.renren + renren-common + 5.5.0 + + + io.renren + renren-dynamic-datasource + 5.5.0 + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + diff --git a/renren-api/src/main/java/io/renren/ApiApplication.java b/renren-api/src/main/java/io/renren/ApiApplication.java new file mode 100644 index 0000000..28ec16a --- /dev/null +++ b/renren-api/src/main/java/io/renren/ApiApplication.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +/** + * renren-api + * + * @author Mark sunlightcs@gmail.com + */ +@SpringBootApplication +public class ApiApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(ApiApplication.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(ApiApplication.class); + } +} diff --git a/renren-api/src/main/java/io/renren/annotation/Login.java b/renren-api/src/main/java/io/renren/annotation/Login.java new file mode 100644 index 0000000..3b9436c --- /dev/null +++ b/renren-api/src/main/java/io/renren/annotation/Login.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.annotation; + +import java.lang.annotation.*; + +/** + * 登录效验 + * @author Mark sunlightcs@gmail.com + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Login { +} diff --git a/renren-api/src/main/java/io/renren/annotation/LoginUser.java b/renren-api/src/main/java/io/renren/annotation/LoginUser.java new file mode 100644 index 0000000..7bf522a --- /dev/null +++ b/renren-api/src/main/java/io/renren/annotation/LoginUser.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 登录用户信息 + * + * @author Mark sunlightcs@gmail.com + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginUser { + +} diff --git a/renren-api/src/main/java/io/renren/config/FilterConfig.java b/renren-api/src/main/java/io/renren/config/FilterConfig.java new file mode 100644 index 0000000..217e61f --- /dev/null +++ b/renren-api/src/main/java/io/renren/config/FilterConfig.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.config; + +import io.renren.common.xss.XssFilter; +import jakarta.servlet.DispatcherType; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +/** + * Filter配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class FilterConfig { + + @Bean + public FilterRegistrationBean xssFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns("/*"); + registration.setName("xssFilter"); + return registration; + } +} diff --git a/renren-api/src/main/java/io/renren/config/MybatisPlusConfig.java b/renren-api/src/main/java/io/renren/config/MybatisPlusConfig.java new file mode 100644 index 0000000..3885f0f --- /dev/null +++ b/renren-api/src/main/java/io/renren/config/MybatisPlusConfig.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * mybatis-plus配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 配置分页等 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); + // 分页插件 + mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + // 乐观锁 + mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + // 防止全表更新与删除 + mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + + return mybatisPlusInterceptor; + } + +} \ No newline at end of file diff --git a/renren-api/src/main/java/io/renren/config/SwaggerConfig.java b/renren-api/src/main/java/io/renren/config/SwaggerConfig.java new file mode 100644 index 0000000..8128ef8 --- /dev/null +++ b/renren-api/src/main/java/io/renren/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.config; + +import io.renren.common.constant.Constant; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + + +@Configuration +public class SwaggerConfig { + @Bean + public OpenAPI createRestApi() { + return new OpenAPI() + .info(apiInfo()) + .security(security()); + } + + private Info apiInfo() { + return new Info() + .title("人人开源") + .description("renren-api文档") + .version("5.x"); + } + + private List security() { + SecurityRequirement key = new SecurityRequirement(); + key.addList(Constant.TOKEN_HEADER, Constant.TOKEN_HEADER); + + List list = new ArrayList<>(); + list.add(key); + return list; + } + +} diff --git a/renren-api/src/main/java/io/renren/config/WebMvcConfig.java b/renren-api/src/main/java/io/renren/config/WebMvcConfig.java new file mode 100644 index 0000000..ece4daf --- /dev/null +++ b/renren-api/src/main/java/io/renren/config/WebMvcConfig.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.config; + +import io.renren.interceptor.AuthorizationInterceptor; +import io.renren.resolver.LoginUserHandlerMethodArgumentResolver; +import jakarta.annotation.Resource; +import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import tools.jackson.databind.DeserializationFeature; +import tools.jackson.databind.cfg.DateTimeFeature; +import tools.jackson.databind.module.SimpleModule; +import tools.jackson.databind.ser.std.ToStringSerializer; + +import java.util.List; + +/** + * MVC配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + @Resource + private AuthorizationInterceptor authorizationInterceptor; + @Resource + private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authorizationInterceptor).addPathPatterns("/api/**"); + } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + argumentResolvers.add(loginUserHandlerMethodArgumentResolver); + } + + @Bean + public SimpleModule apiObjectMapper() { + SimpleModule module = new SimpleModule("ApiSerializerModule"); + + // Long 类型序列化为 String,解决前端 js 精度丢失问题 + module.addSerializer(Long.class, ToStringSerializer.instance); + module.addSerializer(Long.TYPE, ToStringSerializer.instance); + + return module; + } + + /** + * 自定义 JsonMapper 构建器配置 + */ + @Bean + public JsonMapperBuilderCustomizer jsonMapperBuilderCustomizer() { + return builder -> builder + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS); + } +} \ No newline at end of file diff --git a/renren-api/src/main/java/io/renren/controller/ApiLoginController.java b/renren-api/src/main/java/io/renren/controller/ApiLoginController.java new file mode 100644 index 0000000..14df755 --- /dev/null +++ b/renren-api/src/main/java/io/renren/controller/ApiLoginController.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.controller; + + +import io.renren.annotation.Login; +import io.renren.common.utils.Result; +import io.renren.common.validator.ValidatorUtils; +import io.renren.dto.LoginDTO; +import io.renren.service.TokenService; +import io.renren.service.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 登录接口 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/api") +@Tag(name = "登录接口") +@AllArgsConstructor +public class ApiLoginController { + private final UserService userService; + private final TokenService tokenService; + + + @PostMapping("login") + @Operation(summary = "登录") + public Result> login(@RequestBody LoginDTO dto) { + //表单校验 + ValidatorUtils.validateEntity(dto); + + //用户登录 + Map map = userService.login(dto); + + return new Result().ok(map); + } + + @Login + @PostMapping("logout") + @Operation(summary = "退出") + public Result logout(@Parameter(hidden = true) @RequestAttribute("userId") Long userId) { + tokenService.expireToken(userId); + return new Result(); + } + +} diff --git a/renren-api/src/main/java/io/renren/controller/ApiRegisterController.java b/renren-api/src/main/java/io/renren/controller/ApiRegisterController.java new file mode 100644 index 0000000..d2dd544 --- /dev/null +++ b/renren-api/src/main/java/io/renren/controller/ApiRegisterController.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.controller; + +import cn.hutool.crypto.digest.DigestUtil; +import io.renren.common.utils.Result; +import io.renren.common.validator.ValidatorUtils; +import io.renren.dto.RegisterDTO; +import io.renren.entity.UserEntity; +import io.renren.service.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Date; + +/** + * 注册接口 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/api") +@Tag(name = "注册接口") +@AllArgsConstructor +public class ApiRegisterController { + private final UserService userService; + + @PostMapping("register") + @Operation(summary = "注册") + public Result register(@RequestBody RegisterDTO dto) { + //表单校验 + ValidatorUtils.validateEntity(dto); + + UserEntity user = new UserEntity(); + user.setMobile(dto.getMobile()); + user.setUsername(dto.getMobile()); + user.setPassword(DigestUtil.sha256Hex(dto.getPassword())); + user.setCreateDate(new Date()); + userService.insert(user); + + return new Result(); + } +} diff --git a/renren-api/src/main/java/io/renren/controller/ApiTestController.java b/renren-api/src/main/java/io/renren/controller/ApiTestController.java new file mode 100644 index 0000000..0d600a8 --- /dev/null +++ b/renren-api/src/main/java/io/renren/controller/ApiTestController.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.controller; + +import io.renren.annotation.Login; +import io.renren.annotation.LoginUser; +import io.renren.common.utils.Result; +import io.renren.entity.UserEntity; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 测试接口 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("/api") +@Tag(name = "测试接口") +public class ApiTestController { + + @Login + @GetMapping("userInfo") + @Operation(summary = "获取用户信息") + public Result userInfo(@Parameter(hidden = true) @LoginUser UserEntity user) { + return new Result().ok(user); + } + + @Login + @GetMapping("userId") + @Operation(summary = "获取用户ID") + public Result userInfo(@Parameter(hidden = true) @RequestAttribute("userId") Long userId) { + return new Result().ok(userId); + } + + @GetMapping("notToken") + @Operation(summary = "忽略Token验证测试") + public Result notToken() { + return new Result().ok("无需token也能访问。。。"); + } + +} diff --git a/renren-api/src/main/java/io/renren/dao/TokenDao.java b/renren-api/src/main/java/io/renren/dao/TokenDao.java new file mode 100644 index 0000000..65e4c66 --- /dev/null +++ b/renren-api/src/main/java/io/renren/dao/TokenDao.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.entity.TokenEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户Token + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface TokenDao extends BaseDao { + TokenEntity getByToken(String token); + + TokenEntity getByUserId(Long userId); +} diff --git a/renren-api/src/main/java/io/renren/dao/UserDao.java b/renren-api/src/main/java/io/renren/dao/UserDao.java new file mode 100644 index 0000000..babcfff --- /dev/null +++ b/renren-api/src/main/java/io/renren/dao/UserDao.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import io.renren.common.dao.BaseDao; +import io.renren.entity.UserEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface UserDao extends BaseDao { + UserEntity getUserByMobile(String mobile); + + UserEntity getUserByUserId(Long userId); +} diff --git a/renren-api/src/main/java/io/renren/dto/LoginDTO.java b/renren-api/src/main/java/io/renren/dto/LoginDTO.java new file mode 100644 index 0000000..7f0cb54 --- /dev/null +++ b/renren-api/src/main/java/io/renren/dto/LoginDTO.java @@ -0,0 +1,33 @@ +/** + /** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + + +/** + * 登录表单 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "登录表单") +public class LoginDTO { + @Schema(title = "手机号") + @NotBlank(message="手机号不能为空") + private String mobile; + + @Schema(title = "密码") + @NotBlank(message="密码不能为空") + private String password; + +} diff --git a/renren-api/src/main/java/io/renren/dto/RegisterDTO.java b/renren-api/src/main/java/io/renren/dto/RegisterDTO.java new file mode 100644 index 0000000..4fadc84 --- /dev/null +++ b/renren-api/src/main/java/io/renren/dto/RegisterDTO.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + + +/** + * 注册表单 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "注册表单") +public class RegisterDTO { + @Schema(title = "手机号") + @NotBlank(message="手机号不能为空") + private String mobile; + + @Schema(title = "密码") + @NotBlank(message="密码不能为空") + private String password; + +} diff --git a/renren-api/src/main/java/io/renren/entity/TokenEntity.java b/renren-api/src/main/java/io/renren/entity/TokenEntity.java new file mode 100644 index 0000000..4a5bd75 --- /dev/null +++ b/renren-api/src/main/java/io/renren/entity/TokenEntity.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 用户Token + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@TableName("tb_token") +public class TokenEntity implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId + private Long id; + /** + * 用户ID + */ + private Long userId; + /** + * 用户token + */ + private String token; + /** + * 过期时间 + */ + private Date expireDate; + /** + * 更新时间 + */ + private Date updateDate; + +} \ No newline at end of file diff --git a/renren-api/src/main/java/io/renren/entity/UserEntity.java b/renren-api/src/main/java/io/renren/entity/UserEntity.java new file mode 100644 index 0000000..1934da4 --- /dev/null +++ b/renren-api/src/main/java/io/renren/entity/UserEntity.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 用户 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@TableName("tb_user") +public class UserEntity implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @TableId + private Long id; + /** + * 用户名 + */ + private String username; + /** + * 手机号 + */ + private String mobile; + /** + * 密码 + */ + @JsonIgnore + private String password; + /** + * 创建时间 + */ + private Date createDate; + +} \ No newline at end of file diff --git a/renren-api/src/main/java/io/renren/exception/RenExceptionHandler.java b/renren-api/src/main/java/io/renren/exception/RenExceptionHandler.java new file mode 100644 index 0000000..9c4a968 --- /dev/null +++ b/renren-api/src/main/java/io/renren/exception/RenExceptionHandler.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.exception; + +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.utils.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 异常处理器 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@RestControllerAdvice +public class RenExceptionHandler { + private static final Logger logger = LoggerFactory.getLogger(RenExceptionHandler.class); + + /** + * 处理自定义异常 + */ + @ExceptionHandler(RenException.class) + public Result handleRenException(RenException ex){ + Result result = new Result(); + result.error(ex.getCode(), ex.getMsg()); + + return result; + } + + @ExceptionHandler(DuplicateKeyException.class) + public Result handleDuplicateKeyException(DuplicateKeyException ex){ + Result result = new Result(); + result.error(ErrorCode.DB_RECORD_EXISTS); + + return result; + } + + @ExceptionHandler(Exception.class) + public Result handleException(Exception ex){ + logger.error(ex.getMessage(), ex); + + return new Result().error(); + } +} \ No newline at end of file diff --git a/renren-api/src/main/java/io/renren/interceptor/AuthorizationInterceptor.java b/renren-api/src/main/java/io/renren/interceptor/AuthorizationInterceptor.java new file mode 100644 index 0000000..2a7b9be --- /dev/null +++ b/renren-api/src/main/java/io/renren/interceptor/AuthorizationInterceptor.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.interceptor; + +import cn.hutool.core.util.StrUtil; +import io.renren.annotation.Login; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.entity.TokenEntity; +import io.renren.service.TokenService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * 权限(Token)验证 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +public class AuthorizationInterceptor implements HandlerInterceptor { + @Resource + private TokenService tokenService; + + public static final String USER_KEY = "userId"; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Login annotation; + if (handler instanceof HandlerMethod) { + annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class); + } else { + return true; + } + + if (annotation == null) { + return true; + } + + //从header中获取token + String token = request.getHeader("token"); + //如果header中不存在token,则从参数中获取token + if (StrUtil.isBlank(token)) { + token = request.getParameter("token"); + } + + //token为空 + if (StrUtil.isBlank(token)) { + throw new RenException(ErrorCode.TOKEN_NOT_EMPTY); + } + + //查询token信息 + TokenEntity tokenEntity = tokenService.getByToken(token); + if (tokenEntity == null || tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()) { + throw new RenException(ErrorCode.TOKEN_INVALID); + } + + //设置userId到request里,后续根据userId,获取用户信息 + request.setAttribute(USER_KEY, tokenEntity.getUserId()); + + return true; + } +} diff --git a/renren-api/src/main/java/io/renren/resolver/LoginUserHandlerMethodArgumentResolver.java b/renren-api/src/main/java/io/renren/resolver/LoginUserHandlerMethodArgumentResolver.java new file mode 100644 index 0000000..91836c1 --- /dev/null +++ b/renren-api/src/main/java/io/renren/resolver/LoginUserHandlerMethodArgumentResolver.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.resolver; + +import io.renren.annotation.LoginUser; +import io.renren.entity.UserEntity; +import io.renren.interceptor.AuthorizationInterceptor; +import io.renren.service.UserService; +import lombok.AllArgsConstructor; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +/** + * 有@LoginUser注解的方法参数,注入当前登录用户 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +@AllArgsConstructor +public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { + private final UserService userService; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container, + NativeWebRequest request, WebDataBinderFactory factory) throws Exception { + //获取用户ID + Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST); + if (object == null) { + return null; + } + + //获取用户信息 + UserEntity user = userService.getUserByUserId((Long) object); + + return user; + } +} diff --git a/renren-api/src/main/java/io/renren/service/TokenService.java b/renren-api/src/main/java/io/renren/service/TokenService.java new file mode 100644 index 0000000..2394400 --- /dev/null +++ b/renren-api/src/main/java/io/renren/service/TokenService.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.service; + +import io.renren.common.service.BaseService; +import io.renren.entity.TokenEntity; + +/** + * 用户Token + * + * @author Mark sunlightcs@gmail.com + */ +public interface TokenService extends BaseService { + + TokenEntity getByToken(String token); + + /** + * 生成token + * @param userId 用户ID + * @return 返回token信息 + */ + TokenEntity createToken(Long userId); + + /** + * 设置token过期 + * @param userId 用户ID + */ + void expireToken(Long userId); + +} diff --git a/renren-api/src/main/java/io/renren/service/UserService.java b/renren-api/src/main/java/io/renren/service/UserService.java new file mode 100644 index 0000000..d796b5d --- /dev/null +++ b/renren-api/src/main/java/io/renren/service/UserService.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.service; + +import io.renren.common.service.BaseService; +import io.renren.entity.UserEntity; +import io.renren.dto.LoginDTO; + +import java.util.Map; + +/** + * 用户 + * + * @author Mark sunlightcs@gmail.com + */ +public interface UserService extends BaseService { + + UserEntity getByMobile(String mobile); + + UserEntity getUserByUserId(Long userId); + + /** + * 用户登录 + * @param dto 登录表单 + * @return 返回登录信息 + */ + Map login(LoginDTO dto); +} diff --git a/renren-api/src/main/java/io/renren/service/impl/TokenServiceImpl.java b/renren-api/src/main/java/io/renren/service/impl/TokenServiceImpl.java new file mode 100644 index 0000000..ba55f6c --- /dev/null +++ b/renren-api/src/main/java/io/renren/service/impl/TokenServiceImpl.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.service.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.dao.TokenDao; +import io.renren.entity.TokenEntity; +import io.renren.service.TokenService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.UUID; + + +@Service +public class TokenServiceImpl extends BaseServiceImpl implements TokenService { + + @Resource + private TokenDao tokenDao; + + /** + * 12小时后过期 + */ + private final static int EXPIRE = 3600 * 12; + + @Override + public TokenEntity getByToken(String token) { + return baseDao.getByToken(token); + } + + @Override + public TokenEntity createToken(Long userId) { + //当前时间 + Date now = new Date(); + //过期时间 + Date expireTime = new Date(now.getTime() + EXPIRE * 1000); + + //用户token + String token; + + //判断是否生成过token + TokenEntity tokenEntity = baseDao.getByUserId(userId); + if(tokenEntity == null){ + //生成一个token + token = generateToken(); + + tokenEntity = new TokenEntity(); + tokenEntity.setUserId(userId); + tokenEntity.setToken(token); + tokenEntity.setUpdateDate(now); + tokenEntity.setExpireDate(expireTime); + + //保存token + this.insert(tokenEntity); + }else{ + //判断token是否过期 + if(tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()){ + //token过期,重新生成token + token = generateToken(); + }else { + token = tokenEntity.getToken(); + } + + tokenEntity.setToken(token); + tokenEntity.setUpdateDate(now); + tokenEntity.setExpireDate(expireTime); + + //更新token + this.updateById(tokenEntity); + } + + return tokenEntity; + } + + @Override + public void expireToken(Long userId){ + Date now = new Date(); + + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(TokenEntity::getUserId, userId); + updateWrapper.set(TokenEntity::getExpireDate, now); + updateWrapper.set(TokenEntity::getUpdateDate, now); + + tokenDao.update(updateWrapper); + } + + private String generateToken(){ + return UUID.randomUUID().toString().replace("-", ""); + } +} diff --git a/renren-api/src/main/java/io/renren/service/impl/UserServiceImpl.java b/renren-api/src/main/java/io/renren/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..c32704c --- /dev/null +++ b/renren-api/src/main/java/io/renren/service/impl/UserServiceImpl.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.service.impl; + +import cn.hutool.crypto.digest.DigestUtil; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import io.renren.common.service.impl.BaseServiceImpl; +import io.renren.common.validator.AssertUtils; +import io.renren.dao.UserDao; +import io.renren.dto.LoginDTO; +import io.renren.entity.TokenEntity; +import io.renren.entity.UserEntity; +import io.renren.service.TokenService; +import io.renren.service.UserService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +@Service +@AllArgsConstructor +public class UserServiceImpl extends BaseServiceImpl implements UserService { + private final TokenService tokenService; + + @Override + public UserEntity getByMobile(String mobile) { + return baseDao.getUserByMobile(mobile); + } + + @Override + public UserEntity getUserByUserId(Long userId) { + return baseDao.getUserByUserId(userId); + } + + @Override + public Map login(LoginDTO dto) { + UserEntity user = getByMobile(dto.getMobile()); + AssertUtils.isNull(user, ErrorCode.ACCOUNT_PASSWORD_ERROR); + + //密码错误 + if (!user.getPassword().equals(DigestUtil.sha256Hex(dto.getPassword()))) { + throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); + } + + //获取登录token + TokenEntity tokenEntity = tokenService.createToken(user.getId()); + + Map map = new HashMap<>(2); + map.put("token", tokenEntity.getToken()); + map.put("expire", tokenEntity.getExpireDate().getTime() - System.currentTimeMillis()); + + return map; + } + +} \ No newline at end of file diff --git a/renren-api/src/main/resources/application-dev.yml b/renren-api/src/main/resources/application-dev.yml new file mode 100644 index 0000000..fa43e6c --- /dev/null +++ b/renren-api/src/main/resources/application-dev.yml @@ -0,0 +1,33 @@ +spring: + datasource: + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true + username: renren + password: 123456 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 60000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + #validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + filter: + stat: + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: false + wall: + config: + multi-statement-allow: true diff --git a/renren-api/src/main/resources/application-prod.yml b/renren-api/src/main/resources/application-prod.yml new file mode 100644 index 0000000..fa43e6c --- /dev/null +++ b/renren-api/src/main/resources/application-prod.yml @@ -0,0 +1,33 @@ +spring: + datasource: + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true + username: renren + password: 123456 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 60000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + #validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + filter: + stat: + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: false + wall: + config: + multi-statement-allow: true diff --git a/renren-api/src/main/resources/application-test.yml b/renren-api/src/main/resources/application-test.yml new file mode 100644 index 0000000..fa43e6c --- /dev/null +++ b/renren-api/src/main/resources/application-test.yml @@ -0,0 +1,33 @@ +spring: + datasource: + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true + username: renren + password: 123456 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 60000 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + #Oracle需要打开注释 + #validation-query: SELECT 1 FROM DUAL + test-while-idle: true + test-on-borrow: false + test-on-return: false + stat-view-servlet: + enabled: true + url-pattern: /druid/* + #login-username: admin + #login-password: admin + filter: + stat: + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: false + wall: + config: + multi-statement-allow: true diff --git a/renren-api/src/main/resources/application.yml b/renren-api/src/main/resources/application.yml new file mode 100644 index 0000000..64ec478 --- /dev/null +++ b/renren-api/src/main/resources/application.yml @@ -0,0 +1,83 @@ +# Tomcat +server: + tomcat: + uri-encoding: UTF-8 + threads: + max: 1000 + min-spare: 30 + port: 8081 + servlet: + context-path: /renren-api + session: + cookie: + http-only: true + +knife4j: + enable: false + basic: + enable: false + username: admin + password: admin + setting: + enableFooter: false + +spring: + # 环境 dev|test|prod + profiles: + active: dev + messages: + encoding: UTF-8 + basename: i18n/messages + # jackson时间格式化 + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + mvc: + pathmatch: + matching-strategy: ANT_PATH_MATCHER + servlet: + multipart: + max-file-size: 100MB + max-request-size: 100MB + enabled: true + + data: + redis: + database: 0 + host: 192.168.10.10 + port: 6379 + password: # 密码(默认为空) + timeout: 6000ms # 连接超时时长(毫秒) + lettuce: + pool: + max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) + max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-idle: 10 # 连接池中的最大空闲连接 + min-idle: 5 # 连接池中的最小空闲连接 + +renren: + redis: + open: false # 是否开启redis缓存 true开启 false关闭 + + +#mybatis +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + #实体扫描,多个package用逗号或者分号分隔 + typeAliasesPackage: io.renren.entity + global-config: + #数据库相关配置 + db-config: + #主键类型 + id-type: ASSIGN_ID + banner: false + #原生配置 + configuration: + map-underscore-to-camel-case: true + cache-enabled: false + call-setters-on-nulls: true + jdbc-type-for-null: 'null' + configuration-properties: + prefix: + blobType: BLOB + boolValue: TRUE diff --git a/renren-api/src/main/resources/banner.txt b/renren-api/src/main/resources/banner.txt new file mode 100644 index 0000000..a4028b9 --- /dev/null +++ b/renren-api/src/main/resources/banner.txt @@ -0,0 +1,5 @@ +==================================================================================================================== + + 欢迎使用 renren-api - Powered By https://www.renren.io + +==================================================================================================================== \ No newline at end of file diff --git a/renren-api/src/main/resources/logback-spring.xml b/renren-api/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..5deef21 --- /dev/null +++ b/renren-api/src/main/resources/logback-spring.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/renren-api/src/main/resources/mapper/TokenDao.xml b/renren-api/src/main/resources/mapper/TokenDao.xml new file mode 100644 index 0000000..44665e8 --- /dev/null +++ b/renren-api/src/main/resources/mapper/TokenDao.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/renren-api/src/main/resources/mapper/UserDao.xml b/renren-api/src/main/resources/mapper/UserDao.xml new file mode 100644 index 0000000..8a1e4e9 --- /dev/null +++ b/renren-api/src/main/resources/mapper/UserDao.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/renren-common/pom.xml b/renren-common/pom.xml new file mode 100644 index 0000000..5545198 --- /dev/null +++ b/renren-common/pom.xml @@ -0,0 +1,16 @@ + + + io.renren + renren-security + 5.5.0 + + 4.0.0 + renren-common + jar + renren-common + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/aspect/RedisAspect.java b/renren-common/src/main/java/io/renren/common/aspect/RedisAspect.java new file mode 100644 index 0000000..b681e40 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/aspect/RedisAspect.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.aspect; + +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * Redis切面处理类 + * + * @author Mark sunlightcs@gmail.com + */ +@Aspect +@Component +public class RedisAspect { + private final Logger logger = LoggerFactory.getLogger(getClass()); + /** + * 是否开启redis缓存 true开启 false关闭 + */ + @Value("${renren.redis.open: false}") + private boolean open; + + @Around("execution(* io.renren.common.redis.RedisUtils.*(..))") + public Object around(ProceedingJoinPoint point) throws Throwable { + Object result = null; + if (open) { + try { + result = point.proceed(); + } catch (Exception e) { + logger.error("redis error", e); + throw new RenException(ErrorCode.REDIS_ERROR); + } + } + return result; + } +} diff --git a/renren-common/src/main/java/io/renren/common/constant/Constant.java b/renren-common/src/main/java/io/renren/common/constant/Constant.java new file mode 100644 index 0000000..15a2a94 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/constant/Constant.java @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.constant; + +/** + * 常量 + * + * @author Mark sunlightcs@gmail.com + */ +public interface Constant { + /** + * 成功 + */ + int SUCCESS = 1; + /** + * 失败 + */ + int FAIL = 0; + /** + * 菜单根节点标识 + */ + Long MENU_ROOT = 0L; + /** + * 部门根节点标识 + */ + Long DEPT_ROOT = 0L; + /** + * 升序 + */ + String ASC = "asc"; + /** + * 降序 + */ + String DESC = "desc"; + /** + * 创建时间字段名 + */ + String CREATE_DATE = "create_date"; + + /** + * 数据权限过滤 + */ + String SQL_FILTER = "sqlFilter"; + /** + * 当前页码 + */ + String PAGE = "page"; + /** + * 每页显示记录数 + */ + String LIMIT = "limit"; + /** + * 排序字段 + */ + String ORDER_FIELD = "orderField"; + /** + * 排序方式 + */ + String ORDER = "order"; + /** + * token header + */ + String TOKEN_HEADER = "token"; + + /** + * 云存储配置KEY + */ + String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY"; + + /** + * 定时任务状态 + */ + enum ScheduleStatus { + /** + * 暂停 + */ + PAUSE(0), + /** + * 正常 + */ + NORMAL(1); + + private int value; + + ScheduleStatus(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + /** + * 云服务商 + */ + enum CloudService { + /** + * 七牛云 + */ + QINIU(1), + /** + * 阿里云 + */ + ALIYUN(2), + /** + * 腾讯云 + */ + QCLOUD(3); + + private int value; + + CloudService(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/convert/DateConverter.java b/renren-common/src/main/java/io/renren/common/convert/DateConverter.java new file mode 100644 index 0000000..451d7a1 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/convert/DateConverter.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.convert; + +import cn.hutool.core.util.StrUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 日期转换 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +public class DateConverter implements Converter { + private static final Logger logger = LoggerFactory.getLogger(DateConverter.class); + private static final List formatList = new ArrayList<>(5); + + static { + formatList.add("yyyy-MM"); + formatList.add("yyyy-MM-dd"); + formatList.add("yyyy-MM-dd HH:mm"); + formatList.add("yyyy-MM-dd HH:mm:ss"); + formatList.add("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + } + + @Override + public Date convert(String source) { + String value = source.trim(); + if (StrUtil.isEmpty(value)) { + return null; + } + + if (source.matches("^\\d{4}-\\d{1,2}$")) { + return parseDate(source, formatList.get(0)); + } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) { + return parseDate(source, formatList.get(1)); + } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) { + return parseDate(source, formatList.get(2)); + } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) { + return parseDate(source, formatList.get(3)); + } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}.*T.*\\d{1,2}:\\d{1,2}:\\d{1,2}.*..*$")) { + return parseDate(source, formatList.get(4)); + } else { + throw new IllegalArgumentException("Invalid boolean value '" + source + "'"); + } + } + + /** + * 格式化日期 + * @param dateStr String 字符型日期 + * @param format String 格式 + * @return Date 日期 + */ + public Date parseDate(String dateStr, String format) { + Date date = null; + try { + DateFormat dateFormat = new SimpleDateFormat(format); + date = dateFormat.parse(dateStr); + } catch (Exception e) { + logger.error("Formatted date with date: {} and format : {} ", dateStr, format); + } + return date; + } + +} diff --git a/renren-common/src/main/java/io/renren/common/dao/BaseDao.java b/renren-common/src/main/java/io/renren/common/dao/BaseDao.java new file mode 100644 index 0000000..1c06a14 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/dao/BaseDao.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 基础Dao + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface BaseDao extends BaseMapper { + +} diff --git a/renren-common/src/main/java/io/renren/common/entity/BaseEntity.java b/renren-common/src/main/java/io/renren/common/entity/BaseEntity.java new file mode 100644 index 0000000..18d1ec8 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/entity/BaseEntity.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 基础实体类,所有实体都需要继承 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +public abstract class BaseEntity implements Serializable { + /** + * id + */ + @TableId + private Long id; + /** + * 创建者 + */ + @TableField(fill = FieldFill.INSERT) + private Long creator; + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createDate; +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/exception/ErrorCode.java b/renren-common/src/main/java/io/renren/common/exception/ErrorCode.java new file mode 100644 index 0000000..e4cf514 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/exception/ErrorCode.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.exception; + +/** + * 错误编码,由5位数字组成,前2位为模块编码,后3位为业务编码 + *

+ * 如:10001(10代表系统模块,001代表业务代码) + *

+ * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface ErrorCode { + int INTERNAL_SERVER_ERROR = 500; + int UNAUTHORIZED = 401; + + int NOT_NULL = 10001; + int DB_RECORD_EXISTS = 10002; + int PARAMS_GET_ERROR = 10003; + int ACCOUNT_PASSWORD_ERROR = 10004; + int ACCOUNT_DISABLE = 10005; + int IDENTIFIER_NOT_NULL = 10006; + int CAPTCHA_ERROR = 10007; + int SUB_MENU_EXIST = 10008; + int PASSWORD_ERROR = 10009; + int SUPERIOR_DEPT_ERROR = 10011; + int SUPERIOR_MENU_ERROR = 10012; + int DATA_SCOPE_PARAMS_ERROR = 10013; + int DEPT_SUB_DELETE_ERROR = 10014; + int DEPT_USER_DELETE_ERROR = 10015; + int UPLOAD_FILE_EMPTY = 10019; + int TOKEN_NOT_EMPTY = 10020; + int TOKEN_INVALID = 10021; + int ACCOUNT_LOCK = 10022; + int OSS_UPLOAD_FILE_ERROR = 10024; + int REDIS_ERROR = 10027; + int JOB_ERROR = 10028; + int INVALID_SYMBOL = 10029; +} diff --git a/renren-common/src/main/java/io/renren/common/exception/ExceptionUtils.java b/renren-common/src/main/java/io/renren/common/exception/ExceptionUtils.java new file mode 100644 index 0000000..ce79649 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/exception/ExceptionUtils.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.exception; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Exception工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class ExceptionUtils { + + /** + * 获取异常信息 + * @param ex 异常 + * @return 返回异常信息 + */ + public static String getErrorStackTrace(Exception ex){ + StringWriter sw = null; + PrintWriter pw = null; + try { + sw = new StringWriter(); + pw = new PrintWriter(sw, true); + ex.printStackTrace(pw); + }finally { + try { + if(pw != null) { + pw.close(); + } + } catch (Exception e) { + + } + try { + if(sw != null) { + sw.close(); + } + } catch (IOException e) { + + } + } + + return sw.toString(); + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/exception/RenException.java b/renren-common/src/main/java/io/renren/common/exception/RenException.java new file mode 100644 index 0000000..baf0825 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/exception/RenException.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.exception; + + +import io.renren.common.utils.MessageUtils; + +/** + * 自定义异常 + * + * @author Mark sunlightcs@gmail.com + */ +public class RenException extends RuntimeException { + private static final long serialVersionUID = 1L; + + private int code; + private String msg; + + public RenException(int code) { + this.code = code; + this.msg = MessageUtils.getMessage(code); + } + + public RenException(int code, String... params) { + this.code = code; + this.msg = MessageUtils.getMessage(code, params); + } + + public RenException(int code, Throwable e) { + super(e); + this.code = code; + this.msg = MessageUtils.getMessage(code); + } + + public RenException(int code, Throwable e, String... params) { + super(e); + this.code = code; + this.msg = MessageUtils.getMessage(code, params); + } + + public RenException(String msg) { + super(msg); + this.code = ErrorCode.INTERNAL_SERVER_ERROR; + this.msg = msg; + } + + public RenException(String msg, Throwable e) { + super(msg, e); + this.code = ErrorCode.INTERNAL_SERVER_ERROR; + this.msg = msg; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/page/PageData.java b/renren-common/src/main/java/io/renren/common/page/PageData.java new file mode 100644 index 0000000..abe523e --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/page/PageData.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.page; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 分页工具类 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Schema(title = "分页数据") +public class PageData implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(title = "总记录数") + private int total; + + @Schema(title = "列表数据") + private List list; + + /** + * 分页 + * @param list 列表数据 + * @param total 总记录数 + */ + public PageData(List list, long total) { + this.list = list; + this.total = (int)total; + } +} diff --git a/renren-common/src/main/java/io/renren/common/redis/RedisConfig.java b/renren-common/src/main/java/io/renren/common/redis/RedisConfig.java new file mode 100644 index 0000000..d7ba88b --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/redis/RedisConfig.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.redis; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * Redis配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class RedisConfig { + @Resource + private RedisConnectionFactory factory; + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(RedisSerializer.json()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(RedisSerializer.json()); + redisTemplate.setConnectionFactory(factory); + + return redisTemplate; + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/redis/RedisKeys.java b/renren-common/src/main/java/io/renren/common/redis/RedisKeys.java new file mode 100644 index 0000000..dbcdb6c --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/redis/RedisKeys.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.redis; + +/** + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class RedisKeys { + /** + * 系统参数Key + */ + public static String getSysParamsKey(){ + return "sys:params"; + } + + /** + * 验证码Key + */ + public static String getCaptchaKey(String uuid){ + return "sys:captcha:" + uuid; + } + + /** + * 登录用户Key + */ + public static String getSecurityUserKey(Long id){ + return "sys:security:user:" + id; + } + + /** + * 系统日志Key + */ + public static String getSysLogKey(){ + return "sys:log"; + } + + /** + * 系统资源Key + */ + public static String getSysResourceKey(){ + return "sys:resource"; + } + + /** + * 用户菜单导航Key + */ + public static String getUserMenuNavKey(Long userId){ + return "sys:user:nav:" + userId; + } + + /** + * 用户权限标识Key + */ + public static String getUserPermissionsKey(Long userId){ + return "sys:user:permissions:" + userId; + } +} diff --git a/renren-common/src/main/java/io/renren/common/redis/RedisUtils.java b/renren-common/src/main/java/io/renren/common/redis/RedisUtils.java new file mode 100644 index 0000000..dea505b --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/redis/RedisUtils.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.redis; + +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Redis工具类 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +public class RedisUtils { + @Resource + private RedisTemplate redisTemplate; + + /** 默认过期时长为24小时,单位:秒 */ + public final static long DEFAULT_EXPIRE = 60 * 60 * 24L; + /** 过期时长为1小时,单位:秒 */ + public final static long HOUR_ONE_EXPIRE = 60 * 60 * 1L; + /** 过期时长为6小时,单位:秒 */ + public final static long HOUR_SIX_EXPIRE = 60 * 60 * 6L; + /** 不设置过期时长 */ + public final static long NOT_EXPIRE = -1L; + + public void set(String key, Object value, long expire) { + redisTemplate.opsForValue().set(key, value); + if (expire != NOT_EXPIRE) { + expire(key, expire); + } + } + + public void set(String key, Object value) { + set(key, value, DEFAULT_EXPIRE); + } + + public Object get(String key, long expire) { + Object value = redisTemplate.opsForValue().get(key); + if (expire != NOT_EXPIRE) { + expire(key, expire); + } + return value; + } + + public Object get(String key) { + return get(key, NOT_EXPIRE); + } + + public void delete(String key) { + redisTemplate.delete(key); + } + + public void delete(Collection keys) { + redisTemplate.delete(keys); + } + + public Object hGet(String key, String field) { + return redisTemplate.opsForHash().get(key, field); + } + + public Map hGetAll(String key) { + HashOperations hashOperations = redisTemplate.opsForHash(); + return hashOperations.entries(key); + } + + public void hMSet(String key, Map map) { + hMSet(key, map, DEFAULT_EXPIRE); + } + + public void hMSet(String key, Map map, long expire) { + redisTemplate.opsForHash().putAll(key, map); + + if (expire != NOT_EXPIRE) { + expire(key, expire); + } + } + + public void hSet(String key, String field, Object value) { + hSet(key, field, value, DEFAULT_EXPIRE); + } + + public void hSet(String key, String field, Object value, long expire) { + redisTemplate.opsForHash().put(key, field, value); + + if (expire != NOT_EXPIRE) { + expire(key, expire); + } + } + + public void expire(String key, long expire) { + redisTemplate.expire(key, expire, TimeUnit.SECONDS); + } + + public void hDel(String key, Object... fields) { + redisTemplate.opsForHash().delete(key, fields); + } + + public void leftPush(String key, Object value) { + leftPush(key, value, DEFAULT_EXPIRE); + } + + public void leftPush(String key, Object value, long expire) { + redisTemplate.opsForList().leftPush(key, value); + + if (expire != NOT_EXPIRE) { + expire(key, expire); + } + } + + public Object rightPop(String key) { + return redisTemplate.opsForList().rightPop(key); + } +} diff --git a/renren-common/src/main/java/io/renren/common/service/BaseService.java b/renren-common/src/main/java/io/renren/common/service/BaseService.java new file mode 100644 index 0000000..6de9f9c --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/service/BaseService.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.service; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; + +import java.io.Serializable; +import java.util.Collection; + +/** + * 基础服务接口,所有Service接口都要继承 + * + * @author Mark sunlightcs@gmail.com + */ +public interface BaseService { + Class currentModelClass(); + + /** + *

+ * 插入一条记录(选择字段,策略插入) + *

+ * + * @param entity 实体对象 + */ + boolean insert(T entity); + + /** + *

+ * 插入(批量),该方法不支持 Oracle、SQL Server + *

+ * + * @param entityList 实体对象集合 + */ + boolean insertBatch(Collection entityList); + + /** + *

+ * 插入(批量),该方法不支持 Oracle、SQL Server + *

+ * + * @param entityList 实体对象集合 + * @param batchSize 插入批次数量 + */ + boolean insertBatch(Collection entityList, int batchSize); + + /** + *

+ * 根据 ID 选择修改 + *

+ * + * @param entity 实体对象 + */ + boolean updateById(T entity); + + /** + *

+ * 根据 whereEntity 条件,更新记录 + *

+ * + * @param entity 实体对象 + * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper} + */ + boolean update(T entity, Wrapper updateWrapper); + + /** + *

+ * 根据ID 批量更新 + *

+ * + * @param entityList 实体对象集合 + */ + boolean updateBatchById(Collection entityList); + + /** + *

+ * 根据ID 批量更新 + *

+ * + * @param entityList 实体对象集合 + * @param batchSize 更新批次数量 + */ + boolean updateBatchById(Collection entityList, int batchSize); + + /** + *

+ * 根据 ID 查询 + *

+ * + * @param id 主键ID + */ + T selectById(Serializable id); + + /** + *

+ * 根据 ID 删除 + *

+ * + * @param id 主键ID + */ + boolean deleteById(Serializable id); + + /** + *

+ * 删除(根据ID 批量删除) + *

+ * + * @param idList 主键ID列表 + */ + boolean deleteBatchIds(Collection idList); +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/service/CrudService.java b/renren-common/src/main/java/io/renren/common/service/CrudService.java new file mode 100644 index 0000000..78e636c --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/service/CrudService.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.service; + +import io.renren.common.page.PageData; + +import java.util.List; +import java.util.Map; + +/** + * CRUD基础服务接口 + * + * @author Mark sunlightcs@gmail.com + */ +public interface CrudService extends BaseService { + + PageData page(Map params); + + List list(Map params); + + D get(Long id); + + void save(D dto); + + void update(D dto); + + void delete(Long[] ids); + +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/service/impl/BaseServiceImpl.java b/renren-common/src/main/java/io/renren/common/service/impl/BaseServiceImpl.java new file mode 100644 index 0000000..fcf22cb --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/service/impl/BaseServiceImpl.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.enums.SqlMethod; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import io.renren.common.constant.Constant; +import io.renren.common.page.PageData; +import io.renren.common.service.BaseService; +import io.renren.common.utils.ConvertUtils; +import org.apache.ibatis.binding.MapperMethod; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.logging.LogFactory; +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + +/** + * 基础服务类,所有Service都要继承 + * + * @author Mark sunlightcs@gmail.com + */ +public abstract class BaseServiceImpl, T> implements BaseService { + @Autowired + protected M baseDao; + protected Log log = LogFactory.getLog(getClass()); + + /** + * 获取分页对象 + * @param params 分页查询参数 + * @param defaultOrderField 默认排序字段 + * @param isAsc 排序方式 + */ + protected IPage getPage(Map params, String defaultOrderField, boolean isAsc) { + //分页参数 + long curPage = 1; + long limit = 10; + + if (params.get(Constant.PAGE) != null) { + curPage = Long.parseLong((String) params.get(Constant.PAGE)); + } + if (params.get(Constant.LIMIT) != null) { + limit = Long.parseLong((String) params.get(Constant.LIMIT)); + } + + //分页对象 + Page page = new Page<>(curPage, limit); + + //分页参数 + params.put(Constant.PAGE, page); + + //排序字段 + String orderField = (String) params.get(Constant.ORDER_FIELD); + String order = (String) params.get(Constant.ORDER); + + //前端字段排序 + if (StrUtil.isNotBlank(orderField) && StrUtil.isNotBlank(order)) { + if (Constant.ASC.equalsIgnoreCase(order)) { + return page.addOrder(OrderItem.asc(orderField)); + } else { + return page.addOrder(OrderItem.desc(orderField)); + } + } + + //没有排序字段,则不排序 + if (StrUtil.isBlank(defaultOrderField)) { + return page; + } + + //默认排序 + if (isAsc) { + page.addOrder(OrderItem.asc(defaultOrderField)); + } else { + page.addOrder(OrderItem.desc(defaultOrderField)); + } + + return page; + } + + protected PageData getPageData(List list, long total, Class target) { + List targetList = ConvertUtils.sourceToTarget(list, target); + + return new PageData<>(targetList, total); + } + + protected PageData getPageData(IPage page, Class target) { + return getPageData(page.getRecords(), page.getTotal(), target); + } + + protected void paramsToLike(Map params, String... likes) { + for (String like : likes) { + String val = (String) params.get(like); + if (StrUtil.isNotBlank(val)) { + params.put(like, "%" + val + "%"); + } else { + params.put(like, null); + } + } + } + + /** + *

+ * 判断数据库操作是否成功 + *

+ *

+ * 注意!! 该方法为 Integer 判断,不可传入 int 基本类型 + *

+ * + * @param result 数据库操作返回影响条数 + * @return boolean + */ + protected static boolean retBool(Integer result) { + return SqlHelper.retBool(result); + } + + protected Class currentMapperClass() { + return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 0); + } + + @Override + public Class currentModelClass() { + return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 1); + } + + protected String getSqlStatement(SqlMethod sqlMethod) { + return SqlHelper.getSqlStatement(this.currentMapperClass(), sqlMethod); + } + + @Override + public boolean insert(T entity) { + return BaseServiceImpl.retBool(baseDao.insert(entity)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean insertBatch(Collection entityList) { + return insertBatch(entityList, 100); + } + + /** + * 批量插入 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean insertBatch(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity)); + } + + /** + * 执行批量操作 + */ + protected boolean executeBatch(Collection list, int batchSize, BiConsumer consumer) { + return SqlHelper.executeBatch(this.currentModelClass(), this.log, list, batchSize, consumer); + } + + + @Override + public boolean updateById(T entity) { + return BaseServiceImpl.retBool(baseDao.updateById(entity)); + } + + @Override + public boolean update(T entity, Wrapper updateWrapper) { + return BaseServiceImpl.retBool(baseDao.update(entity, updateWrapper)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateBatchById(Collection entityList) { + return updateBatchById(entityList, 30); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateBatchById(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(sqlStatement, param); + }); + } + + @Override + public T selectById(Serializable id) { + return baseDao.selectById(id); + } + + @Override + public boolean deleteById(Serializable id) { + return SqlHelper.retBool(baseDao.deleteById(id)); + } + + @Override + public boolean deleteBatchIds(Collection idList) { + return SqlHelper.retBool(baseDao.deleteBatchIds(idList)); + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/service/impl/CrudServiceImpl.java b/renren-common/src/main/java/io/renren/common/service/impl/CrudServiceImpl.java new file mode 100644 index 0000000..dc12fca --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/service/impl/CrudServiceImpl.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; +import io.renren.common.page.PageData; +import io.renren.common.service.CrudService; +import io.renren.common.utils.ConvertUtils; +import org.springframework.beans.BeanUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * CRUD基础服务类 + * + * @author Mark sunlightcs@gmail.com + */ +public abstract class CrudServiceImpl, T, D> extends BaseServiceImpl implements CrudService { + + protected Class currentDtoClass() { + return (Class)ReflectionKit.getSuperClassGenericType(getClass(), CrudServiceImpl.class, 2); + } + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, null, false), + getWrapper(params) + ); + + return getPageData(page, currentDtoClass()); + } + + @Override + public List list(Map params) { + List entityList = baseDao.selectList(getWrapper(params)); + + return ConvertUtils.sourceToTarget(entityList, currentDtoClass()); + } + + public abstract QueryWrapper getWrapper(Map params); + + @Override + public D get(Long id) { + T entity = baseDao.selectById(id); + + return ConvertUtils.sourceToTarget(entity, currentDtoClass()); + } + + @Override + public void save(D dto) { + T entity = ConvertUtils.sourceToTarget(dto, currentModelClass()); + insert(entity); + + //copy主键值到dto + BeanUtils.copyProperties(entity, dto); + } + + @Override + public void update(D dto) { + T entity = ConvertUtils.sourceToTarget(dto, currentModelClass()); + updateById(entity); + } + + @Override + public void delete(Long[] ids) { + baseDao.deleteBatchIds(Arrays.asList(ids)); + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/utils/ConvertUtils.java b/renren-common/src/main/java/io/renren/common/utils/ConvertUtils.java new file mode 100644 index 0000000..f5c7680 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/ConvertUtils.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * 转换工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class ConvertUtils { + private static Logger logger = LoggerFactory.getLogger(ConvertUtils.class); + + public static T sourceToTarget(Object source, Class target){ + if(source == null){ + return null; + } + T targetObject = null; + try { + targetObject = target.newInstance(); + BeanUtils.copyProperties(source, targetObject); + } catch (Exception e) { + logger.error("convert error ", e); + } + + return targetObject; + } + + public static List sourceToTarget(Collection sourceList, Class target){ + if(sourceList == null){ + return null; + } + + List targetList = new ArrayList<>(sourceList.size()); + try { + for(Object source : sourceList){ + T targetObject = target.newInstance(); + BeanUtils.copyProperties(source, targetObject); + targetList.add(targetObject); + } + }catch (Exception e){ + logger.error("convert error ", e); + } + + return targetList; + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/utils/DateUtils.java b/renren-common/src/main/java/io/renren/common/utils/DateUtils.java new file mode 100644 index 0000000..a321302 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/DateUtils.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 日期处理 + * + * @author Mark sunlightcs@gmail.com + */ +public class DateUtils { + /** 时间格式(yyyy-MM-dd) */ + public final static String DATE_PATTERN = "yyyy-MM-dd"; + /** 时间格式(yyyy-MM-dd HH:mm:ss) */ + public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + + /** + * 日期格式化 日期格式为:yyyy-MM-dd + * @param date 日期 + * @return 返回yyyy-MM-dd格式日期 + */ + public static String format(Date date) { + return format(date, DATE_PATTERN); + } + + /** + * 日期格式化 日期格式为:yyyy-MM-dd + * @param date 日期 + * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN + * @return 返回yyyy-MM-dd格式日期 + */ + public static String format(Date date, String pattern) { + if (date != null) { + SimpleDateFormat df = new SimpleDateFormat(pattern); + return df.format(date); + } + return null; + } + + /** + * 日期解析 + * @param date 日期 + * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN + * @return 返回Date + */ + public static Date parse(String date, String pattern) { + try { + return new SimpleDateFormat(pattern).parse(date); + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/renren-common/src/main/java/io/renren/common/utils/HttpContextUtils.java b/renren-common/src/main/java/io/renren/common/utils/HttpContextUtils.java new file mode 100644 index 0000000..ed45763 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/HttpContextUtils.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import cn.hutool.core.util.StrUtil; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.http.HttpHeaders; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * Http + * + * @author Mark sunlightcs@gmail.com + */ +public class HttpContextUtils { + + public static HttpServletRequest getHttpServletRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + if(requestAttributes == null){ + return null; + } + + return ((ServletRequestAttributes) requestAttributes).getRequest(); + } + + public static Map getParameterMap(HttpServletRequest request) { + Enumeration parameters = request.getParameterNames(); + + Map params = new HashMap<>(); + while (parameters.hasMoreElements()) { + String parameter = parameters.nextElement(); + String value = request.getParameter(parameter); + if (StrUtil.isNotBlank(value)) { + params.put(parameter, value); + } + } + + return params; + } + + public static String getDomain(){ + HttpServletRequest request = getHttpServletRequest(); + StringBuffer url = request.getRequestURL(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString(); + } + + public static String getOrigin(){ + HttpServletRequest request = getHttpServletRequest(); + return request.getHeader(HttpHeaders.ORIGIN); + } +} diff --git a/renren-common/src/main/java/io/renren/common/utils/IpUtils.java b/renren-common/src/main/java/io/renren/common/utils/IpUtils.java new file mode 100644 index 0000000..013f4b4 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/IpUtils.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import cn.hutool.core.util.StrUtil; +import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * IP地址 + * + * @author Mark sunlightcs@gmail.com + */ +public class IpUtils { + private static Logger logger = LoggerFactory.getLogger(IpUtils.class); + + /** + * 获取IP地址 + * + * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 + * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 + */ + public static String getIpAddr(HttpServletRequest request) { + String unknown = "unknown"; + String ip = null; + try { + ip = request.getHeader("x-forwarded-for"); + if (StrUtil.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (StrUtil.isEmpty(ip) || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (StrUtil.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (StrUtil.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (StrUtil.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } catch (Exception e) { + logger.error("IPUtils ERROR ", e); + } + + return ip; + } + +} diff --git a/renren-common/src/main/java/io/renren/common/utils/JsonUtils.java b/renren-common/src/main/java/io/renren/common/utils/JsonUtils.java new file mode 100644 index 0000000..984b033 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/JsonUtils.java @@ -0,0 +1,68 @@ +package io.renren.common.utils; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ArrayList; +import java.util.List; + +/** + * JSON 工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class JsonUtils { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static String toJsonString(Object object) { + try { + return objectMapper.writeValueAsString(object); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, Class clazz) { + if (StrUtil.isEmpty(text)) { + return null; + } + try { + return objectMapper.readValue(text, clazz); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(byte[] bytes, Class clazz) { + if (ArrayUtil.isEmpty(bytes)) { + return null; + } + try { + return objectMapper.readValue(bytes, clazz); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, TypeReference typeReference) { + try { + return objectMapper.readValue(text, typeReference); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static List parseArray(String text, Class clazz) { + if (StrUtil.isEmpty(text)) { + return new ArrayList<>(); + } + try { + return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/renren-common/src/main/java/io/renren/common/utils/MessageUtils.java b/renren-common/src/main/java/io/renren/common/utils/MessageUtils.java new file mode 100644 index 0000000..ae28366 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/MessageUtils.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; + +/** + * 国际化 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class MessageUtils { + private static MessageSource messageSource; + static { + messageSource = (MessageSource)SpringContextUtils.getBean("messageSource"); + } + + public static String getMessage(int code){ + return getMessage(code, new String[0]); + } + + public static String getMessage(int code, String... params){ + return messageSource.getMessage(code+"", params, LocaleContextHolder.getLocale()); + } +} diff --git a/renren-common/src/main/java/io/renren/common/utils/Result.java b/renren-common/src/main/java/io/renren/common/utils/Result.java new file mode 100644 index 0000000..b6a1a2d --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/Result.java @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import io.renren.common.exception.ErrorCode; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; + +/** + * 响应数据 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Schema(title = "响应") +public class Result implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 编码:0表示成功,其他值表示失败 + */ + @Schema(title = "编码:0表示成功,其他值表示失败") + private int code = 0; + /** + * 消息内容 + */ + @Schema(title = "消息内容") + private String msg = "success"; + /** + * 响应数据 + */ + @Schema(title = "响应数据") + private T data; + + public Result ok(T data) { + this.setData(data); + return this; + } + + public boolean success(){ + return code == 0; + } + + public Result error() { + this.code = ErrorCode.INTERNAL_SERVER_ERROR; + this.msg = MessageUtils.getMessage(this.code); + return this; + } + + public Result error(int code) { + this.code = code; + this.msg = MessageUtils.getMessage(this.code); + return this; + } + + public Result error(int code, String msg) { + this.code = code; + this.msg = msg; + return this; + } + + public Result error(String msg) { + this.code = ErrorCode.INTERNAL_SERVER_ERROR; + this.msg = msg; + return this; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/renren-common/src/main/java/io/renren/common/utils/SpringContextUtils.java b/renren-common/src/main/java/io/renren/common/utils/SpringContextUtils.java new file mode 100644 index 0000000..4e3c1f4 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/SpringContextUtils.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring Context 工具类 + * + * @author Mark sunlightcs@gmail.com + */ +@Component +public class SpringContextUtils implements ApplicationContextAware { + public static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static T getBean(Class requiredType) { + return applicationContext.getBean(requiredType); + } + + public static T getBean(String name, Class requiredType) { + return applicationContext.getBean(name, requiredType); + } + + public static boolean containsBean(String name) { + return applicationContext.containsBean(name); + } + + public static boolean isSingleton(String name) { + return applicationContext.isSingleton(name); + } + + public static Class getType(String name) { + return applicationContext.getType(name); + } + +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/utils/TreeNode.java b/renren-common/src/main/java/io/renren/common/utils/TreeNode.java new file mode 100644 index 0000000..1168b9b --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/TreeNode.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import lombok.Data; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 树节点,所有需要实现树节点的,都需要继承该类 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ + @Data +public class TreeNode implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 主键 + */ + private Long id; + /** + * 上级ID + */ + private Long pid; + /** + * 子节点列表 + */ + private List children = new ArrayList<>(); +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/utils/TreeUtils.java b/renren-common/src/main/java/io/renren/common/utils/TreeUtils.java new file mode 100644 index 0000000..e986e66 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/utils/TreeUtils.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.utils; + +import io.renren.common.validator.AssertUtils; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * 树形结构工具类,如:菜单、部门等 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class TreeUtils { + + /** + * 根据pid,构建树节点 + */ + public static List build(List treeNodes, Long pid) { + //pid不能为空 + AssertUtils.isNull(pid, "pid"); + + List treeList = new ArrayList<>(); + for(T treeNode : treeNodes) { + if (pid.equals(treeNode.getPid())) { + treeList.add(findChildren(treeNodes, treeNode)); + } + } + + return treeList; + } + + /** + * 查找子节点 + */ + private static T findChildren(List treeNodes, T rootNode) { + for(T treeNode : treeNodes) { + if(rootNode.getId().equals(treeNode.getPid())) { + rootNode.getChildren().add(findChildren(treeNodes, treeNode)); + } + } + return rootNode; + } + + /** + * 构建树节点 + */ + public static List build(List treeNodes) { + List result = new ArrayList<>(); + + //list转map + Map nodeMap = new LinkedHashMap<>(treeNodes.size()); + for(T treeNode : treeNodes){ + nodeMap.put(treeNode.getId(), treeNode); + } + + for(T node : nodeMap.values()) { + T parent = nodeMap.get(node.getPid()); + if(parent != null && !(node.getId().equals(parent.getId()))){ + parent.getChildren().add(node); + continue; + } + + result.add(node); + } + + return result; + } + +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/validator/AssertUtils.java b/renren-common/src/main/java/io/renren/common/validator/AssertUtils.java new file mode 100644 index 0000000..b12fe64 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/validator/AssertUtils.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; +import cn.hutool.core.util.StrUtil; + +import java.util.List; +import java.util.Map; + +/** + * 校验工具类 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class AssertUtils { + + public static void isBlank(String str, String... params) { + isBlank(str, ErrorCode.NOT_NULL, params); + } + + public static void isBlank(String str, Integer code, String... params) { + if(code == null){ + throw new RenException(ErrorCode.NOT_NULL, "code"); + } + + if (StrUtil.isBlank(str)) { + throw new RenException(code, params); + } + } + + public static void isNull(Object object, String... params) { + isNull(object, ErrorCode.NOT_NULL, params); + } + + public static void isNull(Object object, Integer code, String... params) { + if(code == null){ + throw new RenException(ErrorCode.NOT_NULL, "code"); + } + + if (object == null) { + throw new RenException(code, params); + } + } + + public static void isArrayEmpty(Object[] array, String... params) { + isArrayEmpty(array, ErrorCode.NOT_NULL, params); + } + + public static void isArrayEmpty(Object[] array, Integer code, String... params) { + if(code == null){ + throw new RenException(ErrorCode.NOT_NULL, "code"); + } + + if(ArrayUtil.isEmpty(array)){ + throw new RenException(code, params); + } + } + + public static void isListEmpty(List list, String... params) { + isListEmpty(list, ErrorCode.NOT_NULL, params); + } + + public static void isListEmpty(List list, Integer code, String... params) { + if(code == null){ + throw new RenException(ErrorCode.NOT_NULL, "code"); + } + + if(CollUtil.isEmpty(list)){ + throw new RenException(code, params); + } + } + + public static void isMapEmpty(Map map, String... params) { + isMapEmpty(map, ErrorCode.NOT_NULL, params); + } + + public static void isMapEmpty(Map map, Integer code, String... params) { + if(code == null){ + throw new RenException(ErrorCode.NOT_NULL, "code"); + } + + if(MapUtil.isEmpty(map)){ + throw new RenException(code, params); + } + } +} \ No newline at end of file diff --git a/renren-common/src/main/java/io/renren/common/validator/ValidatorUtils.java b/renren-common/src/main/java/io/renren/common/validator/ValidatorUtils.java new file mode 100644 index 0000000..263d8cc --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/validator/ValidatorUtils.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator; + +import io.renren.common.exception.RenException; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator; + +import java.util.Locale; +import java.util.Set; + +/** + * hibernate-validator校验工具类 + * 参考文档:http://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/ + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class ValidatorUtils { + + private static ResourceBundleMessageSource getMessageSource() { + ResourceBundleMessageSource bundleMessageSource = new ResourceBundleMessageSource(); + bundleMessageSource.setDefaultEncoding("UTF-8"); + bundleMessageSource.setBasenames("i18n/validation"); + return bundleMessageSource; + } + + /** + * 校验对象 + * @param object 待校验对象 + * @param groups 待校验的组 + */ + public static void validateEntity(Object object, Class... groups) + throws RenException { + Locale.setDefault(LocaleContextHolder.getLocale()); + Validator validator = Validation.byDefaultProvider().configure().messageInterpolator( + new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(getMessageSource()))) + .buildValidatorFactory().getValidator(); + + Set> constraintViolations = validator.validate(object, groups); + if (!constraintViolations.isEmpty()) { + ConstraintViolation constraint = constraintViolations.iterator().next(); + throw new RenException(constraint.getMessage()); + } + } +} diff --git a/renren-common/src/main/java/io/renren/common/validator/group/AddGroup.java b/renren-common/src/main/java/io/renren/common/validator/group/AddGroup.java new file mode 100644 index 0000000..9a8cfb9 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/validator/group/AddGroup.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + +/** + * 新增 Group + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface AddGroup { + +} diff --git a/renren-common/src/main/java/io/renren/common/validator/group/DefaultGroup.java b/renren-common/src/main/java/io/renren/common/validator/group/DefaultGroup.java new file mode 100644 index 0000000..2e69248 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/validator/group/DefaultGroup.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + +/** + * 默认 Group + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface DefaultGroup { + +} diff --git a/renren-common/src/main/java/io/renren/common/validator/group/Group.java b/renren-common/src/main/java/io/renren/common/validator/group/Group.java new file mode 100644 index 0000000..05c4775 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/validator/group/Group.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + + +import jakarta.validation.GroupSequence; + +/** + * 定义校验顺序,如果AddGroup组失败,则UpdateGroup组不会再校验 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@GroupSequence({AddGroup.class, UpdateGroup.class}) +public interface Group { + +} diff --git a/renren-common/src/main/java/io/renren/common/validator/group/UpdateGroup.java b/renren-common/src/main/java/io/renren/common/validator/group/UpdateGroup.java new file mode 100644 index 0000000..83ed02c --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/validator/group/UpdateGroup.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.validator.group; + +/** + * 修改 Group + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public interface UpdateGroup { + +} diff --git a/renren-common/src/main/java/io/renren/common/xss/SqlFilter.java b/renren-common/src/main/java/io/renren/common/xss/SqlFilter.java new file mode 100644 index 0000000..6997ff8 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/xss/SqlFilter.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + *

+ * https://www.renren.io + *

+ * 版权所有,侵权必究! + */ + +package io.renren.common.xss; + +import cn.hutool.core.util.StrUtil; +import io.renren.common.exception.ErrorCode; +import io.renren.common.exception.RenException; + +/** + * SQL过滤 + * + * @author Mark sunlightcs@gmail.com + */ +public class SqlFilter { + + /** + * SQL注入过滤 + * + * @param str 待验证的字符串 + */ + public static String sqlInject(String str) { + if (StrUtil.isBlank(str)) { + return null; + } + //去掉'|"|;|\字符 + str = StrUtil.replace(str, "'", ""); + str = StrUtil.replace(str, "\"", ""); + str = StrUtil.replace(str, ";", ""); + str = StrUtil.replace(str, "\\", ""); + + //转换成小写 + str = str.toLowerCase(); + + //非法字符 + String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"}; + + //判断是否包含非法字符 + for (String keyword : keywords) { + if (str.contains(keyword)) { + throw new RenException(ErrorCode.INVALID_SYMBOL); + } + } + + return str; + } +} diff --git a/renren-common/src/main/java/io/renren/common/xss/XssFilter.java b/renren-common/src/main/java/io/renren/common/xss/XssFilter.java new file mode 100644 index 0000000..f518df0 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/xss/XssFilter.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.xss; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; + +import java.io.IOException; + +/** + * XSS过滤 + * @author Mark sunlightcs@gmail.com + */ +public class XssFilter implements Filter { + + @Override + public void init(FilterConfig config) { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper( + (HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + @Override + public void destroy() { + } + +} diff --git a/renren-common/src/main/java/io/renren/common/xss/XssHttpServletRequestWrapper.java b/renren-common/src/main/java/io/renren/common/xss/XssHttpServletRequestWrapper.java new file mode 100644 index 0000000..6bf4f33 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/xss/XssHttpServletRequestWrapper.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.xss; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * XSS过滤处理 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + HttpServletRequest orgRequest; + + public XssHttpServletRequestWrapper(HttpServletRequest request) { + super(request); + orgRequest = request; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + //非json类型,直接返回 + if(!checkContentTypeIsJson()){ + return super.getInputStream(); + } + + //为空,直接返回 + String json = IoUtil.readUtf8(super.getInputStream()); + if (StrUtil.isBlank(json)) { + return super.getInputStream(); + } + + //xss过滤 + json = xssEncode(json); + final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() { + return bis.read(); + } + }; + } + + @Override + public String getParameter(String name) { + String value = super.getParameter(xssEncode(name)); + if (StrUtil.isNotBlank(value)) { + value = xssEncode(value); + } + return value; + } + + @Override + public String[] getParameterValues(String name) { + String[] parameters = super.getParameterValues(name); + if (parameters == null || parameters.length == 0) { + return null; + } + + for (int i = 0; i < parameters.length; i++) { + parameters[i] = xssEncode(parameters[i]); + } + return parameters; + } + + @Override + public Map getParameterMap() { + Map map = new LinkedHashMap<>(); + Map parameters = super.getParameterMap(); + for (String key : parameters.keySet()) { + String[] values = parameters.get(key); + for (int i = 0; i < values.length; i++) { + values[i] = xssEncode(values[i]); + } + map.put(key, values); + } + return map; + } + + @Override + public String getHeader(String name) { + String value = super.getHeader(xssEncode(name)); + if (StrUtil.isNotBlank(value)) { + value = xssEncode(value); + } + return value; + } + + private String xssEncode(String input) { + return XssUtils.filter(input); + } + + /** + * 获取最原始的request + */ + public HttpServletRequest getOrgRequest() { + return orgRequest; + } + + /** + * 获取最原始的request + */ + public static HttpServletRequest getOrgRequest(HttpServletRequest request) { + if (request instanceof XssHttpServletRequestWrapper) { + return ((XssHttpServletRequestWrapper) request).getOrgRequest(); + } + + return request; + } + /** + * 判断是否是json请求,以前缀的方式 + */ + private boolean checkContentTypeIsJson() + { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return StrUtil.startWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } +} diff --git a/renren-common/src/main/java/io/renren/common/xss/XssUtils.java b/renren-common/src/main/java/io/renren/common/xss/XssUtils.java new file mode 100644 index 0000000..8a01255 --- /dev/null +++ b/renren-common/src/main/java/io/renren/common/xss/XssUtils.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.common.xss; + +import org.jsoup.Jsoup; +import org.jsoup.safety.Safelist; + +/** + * XSS过滤工具类 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class XssUtils extends Safelist { + + /** + * XSS过滤 + */ + public static String filter(String html){ + return Jsoup.clean(html, xssWhitelist()); + } + + /** + * XSS过滤白名单 + */ + private static Safelist xssWhitelist(){ + return new Safelist() + //支持的标签 + .addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "dl", + "dt", "em", "h1", "h2", "h3", "h4", "h5", "h6", "i", "img", "li", "ol", "p", "pre", "q", "small", + "strike", "strong","sub", "sup", "table", "tbody", "td","tfoot", "th", "thead", "tr", "u","ul", + "embed","object","param","span") + + //支持的标签属性 + .addAttributes("a", "href", "class", "style", "target", "rel", "nofollow") + .addAttributes("blockquote", "cite") + .addAttributes("code", "class", "style") + .addAttributes("col", "span", "width") + .addAttributes("colgroup", "span", "width") + .addAttributes("img", "align", "alt", "height", "src", "title", "width", "class", "style") + .addAttributes("ol", "start", "type") + .addAttributes("q", "cite") + .addAttributes("table", "summary", "width", "class", "style") + .addAttributes("tr", "abbr", "axis", "colspan", "rowspan", "width", "style") + .addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width", "style") + .addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope","width", "style") + .addAttributes("ul", "type", "style") + .addAttributes("pre", "class", "style") + .addAttributes("div", "class", "id", "style") + .addAttributes("embed", "src", "wmode", "flashvars", "pluginspage", "allowFullScreen", "allowfullscreen", + "quality", "width", "height", "align", "allowScriptAccess", "allowscriptaccess", "allownetworking", "type") + .addAttributes("object", "type", "id", "name", "data", "width", "height", "style", "classid", "codebase") + .addAttributes("param", "name", "value") + .addAttributes("span", "class", "style") + + //标签属性对应的协议 + .addProtocols("a", "href", "ftp", "http", "https", "mailto") + .addProtocols("img", "src", "http", "https") + .addProtocols("blockquote", "cite", "http", "https") + .addProtocols("cite", "cite", "http", "https") + .addProtocols("q", "cite", "http", "https") + .addProtocols("embed", "src", "http", "https"); + } + + public static void main(String[] args) { + StringBuilder html = new StringBuilder(); + html.append("人人开源"); + + System.out.println(filter(html.toString())); + } + +} \ No newline at end of file diff --git a/renren-common/src/main/resources/i18n/messages.properties b/renren-common/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000..e4c723f --- /dev/null +++ b/renren-common/src/main/resources/i18n/messages.properties @@ -0,0 +1,26 @@ +#Default +500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38 +401=\u672A\u6388\u6743 +10001={0}\u4E0D\u80FD\u4E3A\u7A7A +10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55 +10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25 +10004=\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF +10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528 +10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A +10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E +10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE +10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E +10010=\u8D26\u53F7\u4E0D\u5B58\u5728 +10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF +10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB +10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570 +10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8 +10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237 +10019=\u8BF7\u4E0A\u4F20\u6587\u4EF6 +10020=token\u4E0D\u80FD\u4E3A\u7A7A +10021=token\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55 +10022=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A +10024=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25{0} +10027=Redis\u670D\u52A1\u5F02\u5E38 +10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25 +10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26 \ No newline at end of file diff --git a/renren-common/src/main/resources/i18n/validation.properties b/renren-common/src/main/resources/i18n/validation.properties new file mode 100644 index 0000000..e2c400d --- /dev/null +++ b/renren-common/src/main/resources/i18n/validation.properties @@ -0,0 +1,67 @@ +#\u7B80\u4F53\u4E2D\u6587 +id.require=ID\u4E0D\u80FD\u4E3A\u7A7A +id.null=ID\u5FC5\u987B\u4E3A\u7A7A +pid.require=\u4E0A\u7EA7ID\uFF0C\u4E0D\u80FD\u4E3A\u7A7A +sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0 + +sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A +sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A + +sysuser.username.require=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A +sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A +sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A +sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2 +sysuser.email.require=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A +sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E +sysuser.mobile.require=\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A +sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A +sysuser.superadmin.range=\u8D85\u7EA7\u7BA1\u7406\u5458\u53D6\u503C\u8303\u56F40~1 +sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 +sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A +sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A + +sysmenu.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u83DC\u5355 +sysmenu.name.require=\u83DC\u5355\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A +sysmenu.type.range=\u83DC\u5355\u7C7B\u578B\u53D6\u503C\u8303\u56F40~1 + +sysdept.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u90E8\u95E8 +sysdept.name.require=\u90E8\u95E8\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A + +sysrole.name.require=\u89D2\u8272\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A + +sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A +sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A +sysdict.label.require=\u5B57\u5178\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A + +schedule.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 +schedule.cron.require=cron\u8868\u8FBE\u5F0F\u4E0D\u80FD\u4E3A\u7A7A +schedule.bean.require=bean\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A + +oss.type.range=\u7C7B\u578B\u53D6\u503C\u8303\u56F41~3 + +aliyun.accesskeyid.require=\u963F\u91CC\u4E91AccessKeyId\u4E0D\u80FD\u4E3A\u7A7A +aliyun.accesskeysecret.require=\u963F\u91CC\u4E91AccessKeySecret\u4E0D\u80FD\u4E3A\u7A7A +aliyun.signname.require=\u963F\u91CC\u4E91\u77ED\u4FE1\u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A +aliyun.templatecode.require=\u963F\u91CC\u4E91\u77ED\u4FE1\u6A21\u677F\u4E0D\u80FD\u4E3A\u7A7A +aliyun.domain.require=\u963F\u91CC\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A +aliyun.domain.url=\u963F\u91CC\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E +aliyun.endPoint.require=\u963F\u91CC\u4E91EndPoint\u4E0D\u80FD\u4E3A\u7A7A +aliyun.bucketname.require=\u963F\u91CC\u4E91BucketName\u4E0D\u80FD\u4E3A\u7A7A + +qcloud.appid.require=\u817E\u8BAF\u4E91AppId\u4E0D\u80FD\u4E3A\u7A7A +qcloud.appkey.require=\u817E\u8BAF\u4E91AppKey\u4E0D\u80FD\u4E3A\u7A7A +qcloud.secretId.require=\u817E\u8BAF\u4E91SecretId\u4E0D\u80FD\u4E3A\u7A7A +qcloud.secretkey.require=\u817E\u8BAF\u4E91SecretKey\u4E0D\u80FD\u4E3A\u7A7A +qcloud.signname.require=\u817E\u8BAF\u4E91\u77ED\u4FE1\u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A +qcloud.templateid.require=\u817E\u8BAF\u4E91\u77ED\u4FE1\u6A21\u677FID\u4E0D\u80FD\u4E3A\u7A7A +qcloud.domain.require=\u817E\u8BAF\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A +qcloud.domain.url=\u817E\u8BAF\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E +qcloud.bucketname.require=\u817E\u8BAF\u4E91BucketName\u4E0D\u80FD\u4E3A\u7A7A +qcloud.region.require=\u6240\u5C5E\u5730\u533A\u4E0D\u80FD\u4E3A\u7A7A + +qiniu.domain.require=\u4E03\u725B\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A +qiniu.domain.url=\u4E03\u725B\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E +qiniu.accesskey.require=\u4E03\u725BAccessKey\u4E0D\u80FD\u4E3A\u7A7A +qiniu.secretkey.require=\u4E03\u725BSecretKey\u4E0D\u80FD\u4E3A\u7A7A +qiniu.bucketname.require=\u4E03\u725B\u7A7A\u95F4\u540D\u4E0D\u80FD\u4E3A\u7A7A +qiniu.templateId.require=\u4E03\u725B\u6A21\u677FID\u4E0D\u80FD\u4E3A\u7A7A