mirror of
https://github.com/mfish-qf/mfish-nocode.git
synced 2026-09-21 05:42:57 +08:00
feat: 审批功能完善、个人信息增加git绑定解绑功能
This commit is contained in:
@@ -199,13 +199,14 @@
|
||||
| `mf_system.sql` | 系统管理数据库 |
|
||||
| `mf_scheduler.sql` | 调度中心数据库 |
|
||||
| `mf_nocode.sql` | 低代码中心数据库 |
|
||||
| `mf_workflow.sql` | 工作流数据库 |
|
||||
| `mf_demo.sql` | 样例中心数据库(非必须) |
|
||||
| `mfish-nocode.sql` | 单实例数据库<br />`单实例启动只需要执行这个脚本` |
|
||||
|
||||
```
|
||||
如果单实例使用只需要导入mfish_nocode.sql库即可
|
||||
如果使用微服务需要导入mf_config.sql、mf_oauth.sql
|
||||
、mf_system.sql、mf_scheduler.sql、mf_nocode.sql、mf_demo.sql等数据库
|
||||
、mf_system.sql、mf_scheduler.sql、mf_nocode.sql、mf_workflow.sql、mf_demo.sql等数据库
|
||||
```
|
||||
#### 单实例启动
|
||||
* 初始化SQL脚本 mfish-nocode.sql
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ CREATE TABLE `config_info` (
|
||||
-- Records of config_info
|
||||
-- ----------------------------
|
||||
INSERT INTO `config_info` VALUES (1, 'application-dev.yml', 'DEFAULT_GROUP', 'spring:\n data:\n redis:\n host: localhost\n port: 6379\n password: \"1qaz@WSX\"\n database: 5\n timeout: 10s\n lettuce:\n pool:\n # 连接池中的最小空闲连接\n min-idle: 0\n # 连接池中的最大空闲连接\n max-idle: 8\n # 连接池的最大数据库连接数\n max-active: 8\n # #连接池最大阻塞等待时间(使用负值表示没有限制)\n max-wait: -1ms\n servlet:\n multipart:\n # 单个文件大小\n max-file-size: 1200MB\n # 设置总上传的文件大小\n max-request-size: 1200MB\n ai:\n openai:\n api-key: sk-or-v1-b4**************************************a99b135dae3b\n base-url: https://openrouter.ai/api\n chat:\n options:\n model: meta-llama/llama-3.3-70b-instruct:free\n max-tokens: 1000\n temperature: 0.7\n ollama:\n base-url: http://localhost:11434\n chat:\n model: qwen3:8b\n# feign 配置\nfeign:\n sentinel:\n enabled: true\n okhttp: \n enabled: true\n httpclient:\n enabled: false\n client:\n config:\n default:\n connectTimeout: 10000\n readTimeout: 10000\n compression:\n request:\n enabled: false\n response:\n enabled: false\n\n# 暴露监控端点\nmanagement:\n health:\n sentinel:\n # 关闭健康检查,避免日志刷屏\n enabled: false\n endpoints:\n web:\n exposure:\n include: \'*\'\n endpoint:\n health:\n show-details: always\nlogging:\n config: classpath:logback-logstash.xml\nlog:\n level: info\n maxSize: 30MB\n# 临时缓存存储时间(单位:天)\ncache:\n temp:\n time: 7\nDBConnect:\n password:\n privateKey: 54f0e36b98cf63c3bc6185b61c6e4f2a6e1df3bdeb293a50d7b0bc66881c2419\nswagger:\n title: \'摸鱼低代码平台\'\n enabled: true\n description: 摸鱼框架接口文档\n license: Powered By mfish\n licenseUrl: http://www.mfish.com.cn\n version: 版本号:V2.1.1\n termsOfServiceUrl: http://www.mfish.com.cn\n ignoreServers: mf-gateway,mf-monitor\n contact:\n name: mfish\n email: qiufeng9862@qq.com\n url: http://www.mfish.com.cn\nspringdoc:\n swagger-ui:\n enabled: true\n path: /swagger-ui.html\n tags-sorter: alpha\n operations-sorter: alpha\n default-models-expand-depth: -1\n docExpansion: none\n api-docs:\n enabled: true\n path: /v3/api-docs\n use-management-port: false\n default-flat-param-object: true', '7e1f6a2d2b02f7b666445e626043d9f5', '2023-01-11 12:10:11', '2025-09-05 15:25:07', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
INSERT INTO `config_info` VALUES (2, 'mf-gateway-dev.yml', 'DEFAULT_GROUP', 'spring:\n cloud:\n gateway:\n server:\n webflux:\n globalcors:\n cors-configurations:\n \'[/**]\':\n max-age: 3600\n allowed-origin-patterns: \"*\"\n allowed-headers: \"*\"\n allow-credentials: true\n allowed-methods:\n - GET\n - POST\n - DELETE\n - PUT\n - OPTION \n discovery:\n locator:\n lowerCaseServiceId: true\n enabled: true\n routes:\n # 认证中心\n - id: oauth2\n uri: lb://mf-oauth\n predicates:\n - Path=/oauth2/**\n filters:\n - CacheFilter\n # 验证码处理\n - CheckCodeFilter\n - StripPrefix=1\n # 测试中心\n - id: test\n uri: lb://mf-test\n predicates:\n - Path=/test/**\n filters:\n - StripPrefix=1\n - id: sys\n uri: lb://mf-sys\n predicates:\n - Path=/sys/**\n filters:\n - StripPrefix=1\n - id: demo\n uri: lb://mf-demo\n predicates:\n - Path=/demo/**\n filters:\n - StripPrefix=1\n - id: storage\n uri: lb://mf-storage\n predicates:\n - Path=/storage/**\n filters:\n - StripPrefix=1\n - id: scheduler\n uri: lb://mf-scheduler\n predicates:\n - Path=/scheduler/**\n filters:\n - StripPrefix=1\n - id: nocode\n uri: lb://mf-nocode\n predicates:\n - Path=/nocode/**\n filters:\n - StripPrefix=1\n - id: workflow\n uri: lb://mf-workflow\n predicates:\n - Path=/workflow/**\n filters:\n - StripPrefix=1\n - id: ai\n uri: lb://mf-ai\n predicates:\n - Path=/ai/**\n filters:\n - StripPrefix=1\n# 安全配置\nsecurity:\n # 验证码\n captcha:\n enabled: true\n type: math\n # 网关校验直接返回\n gatewayCheckCaptcha:\n # - /oauth2/authorize\n # 网关校验,自己服务返回\n selfCheckCaptcha:\n - /oauth2/authorize?loginType=user_password\n # 防止XSS攻击\n xss:\n enabled: true\n excludeUrls:\n # 不校验白名单\n ignore:\n whites:\n - /oauth2/user/revoke\n - /oauth2/accessToken\n - /oauth2/authorize\n - /oauth2/sendMsg\n - /oauth2/qrCodeLogin/*\n - /oauth2/wx/bind/**\n - /oauth2/static/**\n - /oauth2/gitee/**\n - /oauth2/github/**\n - /storage/file/*.*\n - /code/**\n - /test/**\n - /*/v3/api-docs\n# swagger configuration\nspringdoc: \n webjars: \n # 设置为空,不要前缀,不配置这个就需要多加一层路径`/webjars`->`http:host:网关ip/webjars/swagger-ui/index.html`\n prefix:', '038e03dabf17cbb6a5e170d24b10ce04', '2023-01-11 12:10:11', '2025-09-28 22:48:56', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
INSERT INTO `config_info` VALUES (3, 'mf-oauth-dev.yml', 'DEFAULT_GROUP', 'swagger:\n title: \'摸鱼认证中心\'\n prefix: /oauth2\n# mybatis配置\nmybatis-plus:\n # 搜索指定包别名\n type-aliases-package: cn.com.mfish.oauth.mapper\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapper-locations: classpath*:cn/com/mfish/**/mapper/**/*Mapper.xml\n global-config:\n # 关闭MP3.0自带的banner\n banner: false\n db-config:\n #主键类型 0:\"数据库ID自增\",1:\"该类型为未设置主键类型\", 2:\"用户输入ID\",3:\"全局唯一ID (数字类型唯一ID)\", 4:\"全局唯一ID UUID\",5:\"字符串全局唯一ID (idWorker 的字符串表示)\";\n #id-type: 0\n # 默认数据库表下划线命名\n table-underline: true\n #逻辑删除 删除前\n logic-not-delete-value: 0\n #逻辑删除 删除后\n logic-delete-value: 1\n configuration:\n # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用\n #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n # 返回类型为Map,显示null对应的字段\n call-setters-on-nulls: true\n map-underscore-to-camel-case: true\n auto-mapping-behavior: full\n jdbc-type-for-null:\nspring: \n thymeleaf:\n cache: false\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n dynamic:\n druid:\n initial-size: 5\n min-idle: 5\n maxActive: 20\n maxWait: 60000\n timeBetweenEvictionRunsMillis: 60000\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n filters: stat,slf4j\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n datasource:\n # 主库数据源\n master:\n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://localhost:3306/mf_oauth?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\nredisCache:\n expire: 50400\n keyPrefix: sso_cache\nredisSession:\n expire: 50400\n keyPrefix: sso_session\noauth2:\n expire:\n code: 180\n token: 21600\n refreshToken: 604800\n login:\n mutex: false\n user:\n autoCreate: false\n token:\n sm4key: 143be1ae6ee10b048f7e441cec2a9803\nwechat:\n miniapp:\n appId: wx*************e34a3\n secret: a65e*************fa222\ngitee:\n clientId: a83ea66522fef5f382c6aaffa875c7e87b21d3933277c44a326cd3407fc0b651\n clientSecret: 3ebdce2afcb4a7df9b16355f60d898d452f4d9cf8ad1ab8279bb3bb465e614db\n redirectUri: http://localhost:5186/giteeOauth2\ngithub:\n clientId: Ov23li7oH0Djw3ZEJCoJ\n clientSecret: ada9a510b3bde542e7510142f07d32a5f6bed131\n redirectUri: http://localhost:5186/githubOauth2', '67911ca64ac75db33987b9490f2bd989', '2023-01-11 12:10:11', '2025-08-15 18:42:36', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
INSERT INTO `config_info` VALUES (2, 'mf-gateway-dev.yml', 'DEFAULT_GROUP', 'spring:\n cloud:\n gateway:\n server:\n webflux:\n globalcors:\n cors-configurations:\n \'[/**]\':\n max-age: 3600\n allowed-origin-patterns: \"*\"\n allowed-headers: \"*\"\n allow-credentials: true\n allowed-methods:\n - GET\n - POST\n - DELETE\n - PUT\n - OPTION \n discovery:\n locator:\n lowerCaseServiceId: true\n enabled: true\n routes:\n # 认证中心\n - id: oauth2\n uri: lb://mf-oauth\n predicates:\n - Path=/oauth2/**\n filters:\n - CacheFilter\n # 验证码处理\n - CheckCodeFilter\n - StripPrefix=1\n # 测试中心\n - id: test\n uri: lb://mf-test\n predicates:\n - Path=/test/**\n filters:\n - StripPrefix=1\n - id: sys\n uri: lb://mf-sys\n predicates:\n - Path=/sys/**\n filters:\n - StripPrefix=1\n - id: demo\n uri: lb://mf-demo\n predicates:\n - Path=/demo/**\n filters:\n - StripPrefix=1\n - id: storage\n uri: lb://mf-storage\n predicates:\n - Path=/storage/**\n filters:\n - StripPrefix=1\n - id: scheduler\n uri: lb://mf-scheduler\n predicates:\n - Path=/scheduler/**\n filters:\n - StripPrefix=1\n - id: nocode\n uri: lb://mf-nocode\n predicates:\n - Path=/nocode/**\n filters:\n - StripPrefix=1\n - id: workflow\n uri: lb://mf-workflow\n predicates:\n - Path=/workflow/**\n filters:\n - StripPrefix=1\n - id: ai\n uri: lb://mf-ai\n predicates:\n - Path=/ai/**\n filters:\n - StripPrefix=1\n# 安全配置\nsecurity:\n # 验证码\n captcha:\n enabled: true\n type: math\n # 网关校验直接返回\n gatewayCheckCaptcha:\n # - /oauth2/authorize\n # 网关校验,自己服务返回\n selfCheckCaptcha:\n - /oauth2/authorize?loginType=user_password\n # 防止XSS攻击\n xss:\n enabled: true\n excludeUrls:\n # 不校验白名单\n ignore:\n whites:\n - /oauth2/user/revoke\n - /oauth2/accessToken\n - /oauth2/authorize\n - /oauth2/sendMsg\n - /oauth2/qrCodeLogin/*\n - /oauth2/wx/bind/**\n - /oauth2/static/**\n - /oauth2/gitee/token/**\n - /oauth2/gitee/url\n - /oauth2/github/token/**\n - /oauth2/github/url\n - /storage/file/*.*\n - /code/**\n - /test/**\n - /*/v3/api-docs\n# swagger configuration\nspringdoc: \n webjars: \n # 设置为空,不要前缀,不配置这个就需要多加一层路径`/webjars`->`http:host:网关ip/webjars/swagger-ui/index.html`\n prefix:', '16d5ac795ab719bf5027706cc64dcae8', '2023-01-11 12:10:11', '2025-10-23 00:07:13', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
INSERT INTO `config_info` VALUES (3, 'mf-oauth-dev.yml', 'DEFAULT_GROUP', 'swagger:\n title: \'摸鱼认证中心\'\n prefix: /oauth2\n# mybatis配置\nmybatis-plus:\n # 搜索指定包别名\n type-aliases-package: cn.com.mfish.oauth.mapper\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapper-locations: classpath*:cn/com/mfish/**/mapper/**/*Mapper.xml\n global-config:\n # 关闭MP3.0自带的banner\n banner: false\n db-config:\n #主键类型 0:\"数据库ID自增\",1:\"该类型为未设置主键类型\", 2:\"用户输入ID\",3:\"全局唯一ID (数字类型唯一ID)\", 4:\"全局唯一ID UUID\",5:\"字符串全局唯一ID (idWorker 的字符串表示)\";\n #id-type: 0\n # 默认数据库表下划线命名\n table-underline: true\n #逻辑删除 删除前\n logic-not-delete-value: 0\n #逻辑删除 删除后\n logic-delete-value: 1\n configuration:\n # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用\n #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n # 返回类型为Map,显示null对应的字段\n call-setters-on-nulls: true\n map-underscore-to-camel-case: true\n auto-mapping-behavior: full\n jdbc-type-for-null:\nspring: \n thymeleaf:\n cache: false\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n dynamic:\n druid:\n initial-size: 5\n min-idle: 5\n maxActive: 20\n maxWait: 60000\n timeBetweenEvictionRunsMillis: 60000\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n filters: stat,slf4j\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n datasource:\n # 主库数据源\n master:\n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://localhost:3306/mf_oauth?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\nredisCache:\n expire: 50400\n keyPrefix: sso_cache\nredisSession:\n expire: 50400\n keyPrefix: sso_session\noauth2:\n expire:\n code: 180\n token: 21600\n refreshToken: 604800\n login:\n mutex: false\n user:\n autoCreate: false\n token:\n sm4key: 143be1ae6ee10b048f7e441cec2a9803\nwechat:\n miniapp:\n appId: wx*************e34a3\n secret: a65e*************fa222\ngitee:\n clientId: a83ea66522fef5f382c6aaffa875c7e87b21d3933277c44a326cd3407fc0b651\n clientSecret: 3ebdce2afcb4a7df9b16355f60d898d452f4d9cf8ad1ab8279bb3bb465e614db\n redirectUri: http://localhost:5186/giteeOauth2\n bindUri: http://localhost:5186/tenant/info/1?callback=gitee\ngithub:\n clientId: Ov23li7oH0Djw3ZEJCoJ\n clientSecret: ada9a510b3bde542e7510142f07d32a5f6bed131\n redirectUri: http://localhost:5186/githubOauth2\n bindUri: http://localhost:5186/tenant/info/1?callback=github', 'b8bae3fbb48e0e5ccb625f6d47ed99be', '2023-01-11 12:10:11', '2025-10-23 00:09:57', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
INSERT INTO `config_info` VALUES (4, 'sentinel-mf-gateway', 'DEFAULT_GROUP', '[\n {\n \"resource\": \"mf-oauth\",\n \"count\": 500,\n \"grade\": 1,\n \"limitApp\": \"default\",\n \"strategy\": 0,\n \"controlBehavior\": 0\n },\n {\n \"resource\": \"mf-sys\",\n \"count\": 500,\n \"grade\": 1,\n \"limitApp\": \"default\",\n \"strategy\": 0,\n \"controlBehavior\": 0\n },\n {\n \"resource\": \"mf-storage\",\n \"count\": 100,\n \"grade\": 1,\n \"limitApp\": \"default\",\n \"strategy\": 0,\n \"controlBehavior\": 0\n },\n {\n \"resource\": \"mf-scheduler\",\n \"count\": 100,\n \"grade\": 1,\n \"limitApp\": \"default\",\n \"strategy\": 0,\n \"controlBehavior\": 0\n }\n]', '07a23c3f1d6580115132bd0ba7897504', '2023-01-11 12:10:11', '2024-01-31 23:07:56', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'text', '', '');
|
||||
INSERT INTO `config_info` VALUES (6, 'mf-sys-dev.yml', 'DEFAULT_GROUP', 'swagger:\n title: \'摸鱼系统业务中心\'\n prefix: /sys\n# mybatis配置\nmybatis-plus:\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapper-locations: classpath*:cn/com/mfish/sys/mapper/**/*Mapper.xml\n global-config:\n # 关闭MP3.0自带的banner\n banner: false\n db-config:\n #主键类型 0:\"数据库ID自增\",1:\"该类型为未设置主键类型\", 2:\"用户输入ID\",3:\"全局唯一ID (数字类型唯一ID)\", 4:\"全局唯一ID UUID\",5:\"字符串全局唯一ID (idWorker 的字符串表示)\";\n #id-type: 0\n # 默认数据库表下划线命名\n table-underline: true\n #逻辑删除 删除前\n logic-not-delete-value: 0\n #逻辑删除 删除后\n logic-delete-value: 1\n configuration:\n # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用\n #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n # 返回类型为Map,显示null对应的字段\n call-setters-on-nulls: true\n map-underscore-to-camel-case: true\n auto-mapping-behavior: full\n jdbc-type-for-null:\nspring: \n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n dynamic:\n druid:\n initial-size: 5\n min-idle: 5\n maxActive: 20\n maxWait: 60000\n timeBetweenEvictionRunsMillis: 60000\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n filters: stat,slf4j\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n datasource:\n # 主库数据源\n master:\n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://localhost:3306/mf_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\ncode:\n template:\n keys:\n - src/main/java/${packageName}/controller/${entityName}Controller.java.ftl\n - src/main/java/${packageName}/entity/${entityName}.java.ftl\n - src/main/java/${packageName}/mapper/${entityName}Mapper.java.ftl\n - src/main/java/${packageName}/mapper/xml/${entityName}Mapper.xml.ftl\n - src/main/java/${packageName}/req/Req${entityName}.java.ftl\n - src/main/java/${packageName}/service/${entityName}Service.java.ftl\n - src/main/java/${packageName}/service/impl/${entityName}ServiceImpl.java.ftl\n - mfish-nocode-view/src/views/${apiPrefix}/${entityName#kebab-case}/${entityName#uncap_first}.data.ts.ftl\n - mfish-nocode-view/src/views/${apiPrefix}/${entityName#kebab-case}/${entityName}Modal.vue.ftl\n - mfish-nocode-view/src/views/${apiPrefix}/${entityName#kebab-case}/${entityName}ViewModal.vue.ftl\n - mfish-nocode-view/src/views/${apiPrefix}/${entityName#kebab-case}/index.vue.ftl\n - mfish-nocode-view/src/api/${apiPrefix}/model/${entityName}Model.ts.ftl\n - mfish-nocode-view/src/api/${apiPrefix}/${entityName}.ts.ftl\n path: template\n savePath:\n #前端地址\n front: E:/webcode\n #后端地址(需要指定到具体模块路径)\n back: E:/javacode/mfish-nocode-pro/mf-business/mf-sys', 'f2b7082dc14fdc4d10c54cc556d23dba', '2023-01-11 12:10:11', '2025-08-15 18:42:23', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
INSERT INTO `config_info` VALUES (7, 'mf-storage-dev.yml', 'DEFAULT_GROUP', 'swagger:\n title: \'摸鱼文件管理\'\n prefix: /storage\n# mybatis配置\nmybatis-plus:\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\n mapper-locations: classpath*:cn/com/mfish/storage/mapper/**/*Mapper.xml\n global-config:\n # 关闭MP3.0自带的banner\n banner: false\n db-config:\n #主键类型 0:\"数据库ID自增\",1:\"该类型为未设置主键类型\", 2:\"用户输入ID\",3:\"全局唯一ID (数字类型唯一ID)\", 4:\"全局唯一ID UUID\",5:\"字符串全局唯一ID (idWorker 的字符串表示)\";\n #id-type: 0\n # 默认数据库表下划线命名\n table-underline: true\n #逻辑删除 删除前\n logic-not-delete-value: 0\n #逻辑删除 删除后\n logic-delete-value: 1\n configuration:\n # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用\n #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n # 返回类型为Map,显示null对应的字段\n call-setters-on-nulls: true\n map-underscore-to-camel-case: true\n auto-mapping-behavior: full\n jdbc-type-for-null:\nspring: \n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n dynamic:\n druid:\n initial-size: 5\n min-idle: 5\n maxActive: 20\n maxWait: 60000\n timeBetweenEvictionRunsMillis: 60000\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n filters: stat,slf4j\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n datasource:\n # 主库数据源\n master:\n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://localhost:3306/mf_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n username: root\n password: 123456\n # 从库数据源\n # slave:\n # username: \n # password: \n # url: \n # driver-class-name: \n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\nstorage:\n active: local\n address: http://localhost:8888/storage/file/\n local:\n storagePath: E:/storage\n aliyun:\n endpoint: oss-cn-hangzhou.aliyuncs.com\n accessKeyId: LTAI5***********FsgT\n accessKeySecret: ZtZGF***************JADjS2f\n bucketName: landwise\n qiniu:\n domain: http://cdn.mfish.com.cn\n accessKey: cHlX4*******************cdsexgvP\n secretKey: QPACH*******************1vEa1t4S\n bucket: mfish-nocode', 'a7db423b2fa6fc36f58379d97fc7a0e5', '2023-01-11 12:10:11', '2025-08-15 18:42:08', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
|
||||
|
||||
+1
-1
@@ -168,6 +168,7 @@ INSERT INTO `sso_menu` VALUES ('442f89857faa6bc929ef4f422b8c4b99', '74ce27a1e940
|
||||
INSERT INTO `sso_menu` VALUES ('520873645d565776988d81481d8b0d26', '74ce27a1e94091da2efa714e32680e7a', '000120000100003', 3, '修改', '#', 3, 2, '', NULL, 'sys:ssoTenant:query,sys:ssoTenant:update', 0, 1, NULL, NULL, '', 'mfish', '2023-06-28 13:02:59', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('d9832cd3aefbb5f99267edb995ff8c75', '74ce27a1e94091da2efa714e32680e7a', '000120000100004', 3, '删除', '#', 4, 2, '', NULL, 'sys:ssoTenant:query,sys:ssoTenant:delete', 0, 1, NULL, NULL, '', 'mfish', '2023-06-28 13:03:15', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('eb5f513d5430597d3ea312e1bf760b23', '40bf4846599bf8dbd307f77bf51a7dad', '0001200002', 2, '租户信息', 'ant-design:info-circle-outlined', 2, 1, '/info/3', '/sys/account/setting/index.vue', NULL, 0, 1, NULL, 1, '', 'admin', '2023-06-25 20:21:51', 'admin', '2023-06-25 21:15:54');
|
||||
INSERT INTO `sso_menu` VALUES ('8f6ed381a02535791c17521ff0475808', 'eb5f513d5430597d3ea312e1bf760b23', '000120000200001', 3, '查询', '#', 1, 2, '', NULL, 'sys:tenant:query', 0, 1, NULL, 1, '', 'admin', '2025-06-03 13:53:51', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('7e690410346c4d3a1610d85e8c9f906b', '40bf4846599bf8dbd307f77bf51a7dad', '0001200003', 2, '个人信息', 'ion:person', 1, 1, '/info/1', '/sys/account/setting/index.vue', NULL, 0, 1, '0000200002', 1, '', 'admin', '2023-06-29 10:54:29', 'admin', '2024-04-09 17:08:26');
|
||||
INSERT INTO `sso_menu` VALUES ('6d71e92a5a3712acbcfcc58f65b93f4f', '7e690410346c4d3a1610d85e8c9f906b', '000120000300001', 3, '上传图像', '#', 1, 2, '', NULL, 'sys:file:upload', 0, 1, NULL, NULL, '', 'admin', '2023-06-29 10:54:29', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('604277501ebb1c92d70912c49188eaa5', '7e690410346c4d3a1610d85e8c9f906b', '000120000300002', 3, '密码修改', '#', 2, 2, '', NULL, 'sys:password:update', 0, 1, NULL, 1, '', 'admin', '2024-10-31 22:06:28', '', NULL);
|
||||
@@ -219,7 +220,6 @@ INSERT INTO `sso_menu` VALUES ('29db2a54d3226d1ec2f90c6498033c99', '70943d8248fd
|
||||
INSERT INTO `sso_menu` VALUES ('312d2bc9ac4f1a7d2f2b5a61fa59ff64', '29db2a54d3226d1ec2f90c6498033c99', '000110000600003', 3, '修改', '#', 3, 2, '', NULL, 'nocode:screenCharts:query,nocode:screenCharts:update', 0, 1, NULL, NULL, '', 'admin', '2024-11-19 09:27:16', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('77c042434b5bebf53cd89afbd04ca28a', '29db2a54d3226d1ec2f90c6498033c99', '000110000600001', 3, '查询', '#', 1, 2, '', NULL, 'nocode:screenCharts:query', 0, 1, NULL, NULL, '', 'admin', '2024-11-19 09:27:16', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('d4257d0d8d32697a82718a312e51fcda', '29db2a54d3226d1ec2f90c6498033c99', '000110000600002', 3, '新增', '#', 2, 2, '', NULL, 'nocode:screenCharts:query,nocode:screenCharts:insert', 0, 1, NULL, NULL, '', 'admin', '2024-11-19 09:27:16', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('8f6ed381a02535791c17521ff0475808', 'eb5f513d5430597d3ea312e1bf760b23', '000120000200001', 3, '查询', '#', 1, 2, '', NULL, 'sys:tenant:query', 0, 1, NULL, 1, '', 'admin', '2025-06-03 13:53:51', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('3a9999ccbdcdc36d69cd0266a6513a05', '', '00014', 1, '审批管理', 'ant-design:audit-outlined', 9, 0, '/audit', NULL, NULL, 0, 1, NULL, 1, '', 'admin', '2025-10-15 15:47:38', 'admin', '2025-10-16 10:36:51');
|
||||
INSERT INTO `sso_menu` VALUES ('e7a2fcb9e2eb633d4008c7f295fffc65', '3a9999ccbdcdc36d69cd0266a6513a05', '0001400001', 2, '审批列表', 'ant-design:file-search-outlined', 1, 1, '/list', '/workflow/audit/index.vue', NULL, 0, 1, NULL, 0, '', 'admin', '2025-10-15 15:47:59', 'admin', '2025-10-17 11:16:41');
|
||||
INSERT INTO `sso_menu` VALUES ('8a47a373c5b79c7fa495f1abe06efa5d', '3a9999ccbdcdc36d69cd0266a6513a05', '0001400002', 2, '我的申请', 'ant-design:solution-outlined', 2, 1, '/apply', '/workflow/apply/index.vue', NULL, 0, 1, NULL, 1, '', 'admin', '2025-10-17 11:12:30', 'admin', '2025-10-17 11:14:15');
|
||||
|
||||
+1
-1
@@ -502,6 +502,7 @@ INSERT INTO `sso_menu` VALUES ('442f89857faa6bc929ef4f422b8c4b99', '74ce27a1e940
|
||||
INSERT INTO `sso_menu` VALUES ('520873645d565776988d81481d8b0d26', '74ce27a1e94091da2efa714e32680e7a', '000120000100003', 3, '修改', '#', 3, 2, '', NULL, 'sys:ssoTenant:query,sys:ssoTenant:update', 0, 1, NULL, NULL, '', 'mfish', '2023-06-28 13:02:59', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('d9832cd3aefbb5f99267edb995ff8c75', '74ce27a1e94091da2efa714e32680e7a', '000120000100004', 3, '删除', '#', 4, 2, '', NULL, 'sys:ssoTenant:query,sys:ssoTenant:delete', 0, 1, NULL, NULL, '', 'mfish', '2023-06-28 13:03:15', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('eb5f513d5430597d3ea312e1bf760b23', '40bf4846599bf8dbd307f77bf51a7dad', '0001200002', 2, '租户信息', 'ant-design:info-circle-outlined', 2, 1, '/info/3', '/sys/account/setting/index.vue', NULL, 0, 1, NULL, 1, '', 'admin', '2023-06-25 20:21:51', 'admin', '2023-06-25 21:15:54');
|
||||
INSERT INTO `sso_menu` VALUES ('8f6ed381a02535791c17521ff0475808', 'eb5f513d5430597d3ea312e1bf760b23', '000120000200001', 3, '查询', '#', 1, 2, '', NULL, 'sys:tenant:query', 0, 1, NULL, 1, '', 'admin', '2025-06-03 13:53:51', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('7e690410346c4d3a1610d85e8c9f906b', '40bf4846599bf8dbd307f77bf51a7dad', '0001200003', 2, '个人信息', 'ion:person', 1, 1, '/info/1', '/sys/account/setting/index.vue', NULL, 0, 1, '0000200002', 1, '', 'admin', '2023-06-29 10:54:29', 'admin', '2024-04-09 17:08:26');
|
||||
INSERT INTO `sso_menu` VALUES ('6d71e92a5a3712acbcfcc58f65b93f4f', '7e690410346c4d3a1610d85e8c9f906b', '000120000300001', 3, '上传图像', '#', 1, 2, '', NULL, 'sys:file:upload', 0, 1, NULL, NULL, '', 'admin', '2023-06-29 10:54:29', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('604277501ebb1c92d70912c49188eaa5', '7e690410346c4d3a1610d85e8c9f906b', '000120000300002', 3, '密码修改', '#', 2, 2, '', NULL, 'sys:password:update', 0, 1, NULL, 1, '', 'admin', '2024-10-31 22:06:28', '', NULL);
|
||||
@@ -553,7 +554,6 @@ INSERT INTO `sso_menu` VALUES ('29db2a54d3226d1ec2f90c6498033c99', '70943d8248fd
|
||||
INSERT INTO `sso_menu` VALUES ('312d2bc9ac4f1a7d2f2b5a61fa59ff64', '29db2a54d3226d1ec2f90c6498033c99', '000110000600003', 3, '修改', '#', 3, 2, '', NULL, 'nocode:screenCharts:query,nocode:screenCharts:update', 0, 1, NULL, NULL, '', 'admin', '2024-11-19 09:27:16', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('77c042434b5bebf53cd89afbd04ca28a', '29db2a54d3226d1ec2f90c6498033c99', '000110000600001', 3, '查询', '#', 1, 2, '', NULL, 'nocode:screenCharts:query', 0, 1, NULL, NULL, '', 'admin', '2024-11-19 09:27:16', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('d4257d0d8d32697a82718a312e51fcda', '29db2a54d3226d1ec2f90c6498033c99', '000110000600002', 3, '新增', '#', 2, 2, '', NULL, 'nocode:screenCharts:query,nocode:screenCharts:insert', 0, 1, NULL, NULL, '', 'admin', '2024-11-19 09:27:16', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('8f6ed381a02535791c17521ff0475808', 'eb5f513d5430597d3ea312e1bf760b23', '000120000200001', 3, '查询', '#', 1, 2, '', NULL, 'sys:tenant:query', 0, 1, NULL, 1, '', 'admin', '2025-06-03 13:53:51', '', NULL);
|
||||
INSERT INTO `sso_menu` VALUES ('3a9999ccbdcdc36d69cd0266a6513a05', '', '00014', 1, '审批管理', 'ant-design:audit-outlined', 9, 0, '/audit', NULL, NULL, 0, 1, NULL, 1, '', 'admin', '2025-10-15 15:47:38', 'admin', '2025-10-16 10:36:51');
|
||||
INSERT INTO `sso_menu` VALUES ('e7a2fcb9e2eb633d4008c7f295fffc65', '3a9999ccbdcdc36d69cd0266a6513a05', '0001400001', 2, '审批列表', 'ant-design:file-search-outlined', 1, 1, '/list', '/workflow/audit/index.vue', NULL, 0, 1, NULL, 0, '', 'admin', '2025-10-15 15:47:59', 'admin', '2025-10-17 11:16:41');
|
||||
INSERT INTO `sso_menu` VALUES ('8a47a373c5b79c7fa495f1abe06efa5d', '3a9999ccbdcdc36d69cd0266a6513a05', '0001400002', 2, '我的申请', 'ant-design:solution-outlined', 2, 1, '/apply', '/workflow/apply/index.vue', NULL, 0, 1, NULL, 1, '', 'admin', '2025-10-17 11:12:30', 'admin', '2025-10-17 11:14:15');
|
||||
|
||||
+5
@@ -1,6 +1,7 @@
|
||||
package cn.com.mfish.common.core.utils.http;
|
||||
|
||||
import cn.com.mfish.common.core.enums.HttpType;
|
||||
import cn.com.mfish.common.core.exception.MyRuntimeException;
|
||||
import cn.com.mfish.common.core.web.Result;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.Data;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import javax.net.ssl.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
@@ -344,6 +346,9 @@ public class OkHttpUtils {
|
||||
return Result.buildResult(data, code, msg);
|
||||
}
|
||||
return Result.buildResult(null, code, msg);
|
||||
} catch (SocketTimeoutException se) {
|
||||
log.error("错误:OkHttp请求超时", se);
|
||||
throw new MyRuntimeException("Http请求超时");
|
||||
} catch (IOException e) {
|
||||
log.error("错误:OkHttp请求异常", e);
|
||||
throw e;
|
||||
|
||||
+50
-3
@@ -55,7 +55,7 @@ public interface SsoUserService extends IService<SsoUser> {
|
||||
/**
|
||||
* 通过用户ID获取按钮权限
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param userId 用户id
|
||||
* @param tenantId 租户id
|
||||
* @return 返回权限集合
|
||||
*/
|
||||
@@ -80,7 +80,7 @@ public interface SsoUserService extends IService<SsoUser> {
|
||||
* 插入用户角色关系
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param roles 角色id集合
|
||||
* @param roles 角色id集合
|
||||
* @return 插入数量
|
||||
*/
|
||||
int insertUserRole(String userId, List<String> roles);
|
||||
@@ -88,7 +88,7 @@ public interface SsoUserService extends IService<SsoUser> {
|
||||
/**
|
||||
* 插入用户组织关系
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param userId 用户id
|
||||
* @param orgList 组织id集合
|
||||
* @return 返回插入数量
|
||||
*/
|
||||
@@ -123,5 +123,52 @@ public interface SsoUserService extends IService<SsoUser> {
|
||||
|
||||
boolean allowChangeAccount(String userId);
|
||||
|
||||
/**
|
||||
* 修改账号
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param account 账号
|
||||
* @return 返回修改后的用户
|
||||
*/
|
||||
Result<SsoUser> changeAccount(String userId, String account);
|
||||
|
||||
/**
|
||||
* 获取用户安全设置
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 返回用户安全设置
|
||||
*/
|
||||
SsoUser getSecureSetting(String userId);
|
||||
|
||||
/**
|
||||
* 解绑gitee账号
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 返回解绑结果
|
||||
*/
|
||||
Result<Boolean> unbindGitee(String userId);
|
||||
|
||||
/**
|
||||
* 绑定gitee账号
|
||||
*
|
||||
* @param giteeAccount gitee账号
|
||||
* @return 返回绑定结果
|
||||
*/
|
||||
Result<Boolean> bindGitee(String giteeAccount);
|
||||
|
||||
/**
|
||||
* 解绑github账号
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 返回解绑结果
|
||||
*/
|
||||
Result<Boolean> unbindGithub(String userId);
|
||||
|
||||
/**
|
||||
* 绑定github账号
|
||||
*
|
||||
* @param githubAccount github账号
|
||||
* @return 返回绑定结果
|
||||
*/
|
||||
Result<Boolean> bindGithub(String githubAccount);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.com.mfish.oauth.common;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @description: Git登录信息
|
||||
* @author: mfish
|
||||
* @date: 2025/10/22
|
||||
*/
|
||||
@Getter
|
||||
public class GitLoginInfo {
|
||||
private final String token;
|
||||
private final String gitInfo;
|
||||
private final String account;
|
||||
public GitLoginInfo(String token, String account, String gitInfo) {
|
||||
this.token = token;
|
||||
this.account = account;
|
||||
this.gitInfo = gitInfo;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import cn.com.mfish.common.core.web.Result;
|
||||
import cn.com.mfish.common.oauth.common.SerConstant;
|
||||
import cn.com.mfish.common.oauth.entity.SsoUser;
|
||||
import cn.com.mfish.common.oauth.service.SsoUserService;
|
||||
import cn.com.mfish.oauth.common.GitLoginInfo;
|
||||
import cn.com.mfish.oauth.service.LoginService;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
@@ -15,10 +16,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
@@ -44,6 +42,8 @@ public class GiteeController {
|
||||
private String clientSecret;
|
||||
@Value("${gitee.redirectUri}")
|
||||
private String redirectUri;
|
||||
@Value("${gitee.bindUri:http://localhost:5186/tenant/info/1?callback=gitee}")
|
||||
private String bindUri;
|
||||
@Resource
|
||||
SsoUserService ssoUserService;
|
||||
|
||||
@@ -53,6 +53,51 @@ public class GiteeController {
|
||||
@Parameter(name = SerConstant.QR_CODE, description = "gitee认证Code", required = true)
|
||||
})
|
||||
public Result<Integer> getToken(@PathVariable String code) throws IOException {
|
||||
Result<GitLoginInfo> result = getGiteeAccount(code, redirectUri);
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
}
|
||||
String account = result.getData().getAccount();
|
||||
String token = result.getData().getToken();
|
||||
SsoUser user = ssoUserService.getUserByGitee(account);
|
||||
// 新用户判断是否关注仓库
|
||||
if ((user == null || user.getCreateTime().getTime() > System.currentTimeMillis() - 24 * 3600 * 1000) && !isStarred(token, account)) {
|
||||
return Result.ok(1, "警告:未关注码云仓库");
|
||||
}
|
||||
Result<String> res = loginService.login(result.getData().getGitInfo(), token, SerConstant.LoginType.Gitee, "system", "false");
|
||||
if (!res.isSuccess()) {
|
||||
return Result.fail(res.getMsg());
|
||||
}
|
||||
return Result.ok(0, "登录成功");
|
||||
}
|
||||
|
||||
@GetMapping("/url")
|
||||
@Operation(summary = "获取gitee url")
|
||||
public Result<String> getUrl() {
|
||||
return Result.ok("https://gitee.com/oauth/authorize?client_id=" + clientId
|
||||
+ "&redirect_uri=" + redirectUri + "&response_type=code", "获取地址成功");
|
||||
}
|
||||
|
||||
@PutMapping("/bind/{code}")
|
||||
@Operation(summary = "绑定gitee账号")
|
||||
public Result<Boolean> bindGitee(@Parameter(name = "code", description = "gitee认证Code", required = true) @PathVariable String code) throws IOException {
|
||||
Result<GitLoginInfo> result = getGiteeAccount(code, bindUri);
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
}
|
||||
String account = result.getData().getAccount();
|
||||
return ssoUserService.bindGitee(account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取码云账号信息
|
||||
*
|
||||
* @param code 认证码
|
||||
* @param redirectUri 重定向地址
|
||||
* @return 码云账号信息
|
||||
* @throws IOException 网络异常
|
||||
*/
|
||||
private Result<GitLoginInfo> getGiteeAccount(String code, String redirectUri) throws IOException {
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("client_secret", clientSecret);
|
||||
Result<String> result = OkHttpUtils.postJson("https://gitee.com/oauth/token?grant_type=authorization_code" +
|
||||
@@ -69,24 +114,7 @@ public class GiteeController {
|
||||
return Result.fail("错误:请求码云用户信息失败");
|
||||
}
|
||||
JSONObject giteeUser = JSON.parseObject(result.getData());
|
||||
String login = giteeUser.getString("login");
|
||||
SsoUser user = ssoUserService.getUserByGitee(giteeUser.getString("login"));
|
||||
// 新用户判断是否关注仓库
|
||||
if ((user == null || user.getCreateTime().getTime() > System.currentTimeMillis() - 24 * 3600 * 1000) && !isStarred(token, login)) {
|
||||
return Result.ok(1, "警告:未关注码云仓库");
|
||||
}
|
||||
result = loginService.login(result.getData(), token, SerConstant.LoginType.Gitee, "system", "false");
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
}
|
||||
return Result.ok(0, "登录成功");
|
||||
}
|
||||
|
||||
@GetMapping("/url")
|
||||
@Operation(summary = "获取gitee url")
|
||||
public Result<String> getUrl() {
|
||||
return Result.ok("https://gitee.com/oauth/authorize?client_id=" + clientId
|
||||
+ "&redirect_uri=" + redirectUri + "&response_type=code", "获取地址成功");
|
||||
return Result.ok(new GitLoginInfo(token, giteeUser.getString("login"), result.getData()), "获取码云账号成功");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +139,7 @@ public class GiteeController {
|
||||
Result<String> result = OkHttpUtils.get("https://gitee.com/api/v5/repos/qiufeng9862/mfish-nocode/events?limit=500&access_token=" + token);
|
||||
if (result.isSuccess()) {
|
||||
Pattern pattern = Pattern.compile("\"StarEvent\".*?\"login\"\\s*:\\s*\"(?<login>.*?)\"");
|
||||
String data = result.getData().replace(" ","");
|
||||
String data = result.getData().replace(" ", "");
|
||||
Matcher matcher = pattern.matcher(data);
|
||||
while (matcher.find()) {
|
||||
String value = matcher.group("login");
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package cn.com.mfish.oauth.controller;
|
||||
|
||||
import cn.com.mfish.common.core.utils.StringUtils;
|
||||
import cn.com.mfish.common.core.utils.http.OkHttpUtils;
|
||||
import cn.com.mfish.common.core.web.Result;
|
||||
import cn.com.mfish.common.oauth.common.SerConstant;
|
||||
import cn.com.mfish.common.oauth.service.SsoUserService;
|
||||
import cn.com.mfish.oauth.common.GitLoginInfo;
|
||||
import cn.com.mfish.oauth.service.LoginService;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
@@ -12,10 +15,7 @@ import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
@@ -38,6 +38,10 @@ public class GithubController {
|
||||
private String clientSecret;
|
||||
@Value("${github.redirectUri}")
|
||||
private String redirectUri;
|
||||
@Value("${github.bindUri:http://localhost:5186/tenant/info/1?callback=github}")
|
||||
private String bindUri;
|
||||
@Resource
|
||||
SsoUserService ssoUserService;
|
||||
|
||||
@GetMapping("/token/{code}")
|
||||
@Operation(summary = "获取github token")
|
||||
@@ -45,6 +49,47 @@ public class GithubController {
|
||||
@Parameter(name = SerConstant.QR_CODE, description = "github认证Code", required = true)
|
||||
})
|
||||
public Result<Integer> getToken(@PathVariable String code) throws IOException {
|
||||
Result<GitLoginInfo> result = getGithubAccount(code, redirectUri);
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
}
|
||||
String token = result.getData().getToken();
|
||||
if (!isStarred(token)) {
|
||||
return Result.ok(1, "警告:未关注github仓库");
|
||||
}
|
||||
Result<String> res = loginService.login(result.getData().getGitInfo(), token, SerConstant.LoginType.Github, "system", "false");
|
||||
if (!res.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
}
|
||||
return Result.ok(0, "登录成功");
|
||||
}
|
||||
|
||||
@GetMapping("/url")
|
||||
@Operation(summary = "获取github url")
|
||||
public Result<String> getUrl() {
|
||||
return Result.ok("https://github.com/login/oauth/authorize?client_id=" + clientId
|
||||
+ "&redirect_uri=" + redirectUri + "&response_type=code", "获取地址成功");
|
||||
}
|
||||
|
||||
@PutMapping("/bind/{code}")
|
||||
@Operation(summary = "绑定github账号")
|
||||
public Result<Boolean> bindGithub(@Parameter(name = "code", description = "github认证Code", required = true) @PathVariable String code) throws IOException {
|
||||
Result<GitLoginInfo> result = getGithubAccount(code, bindUri);
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
}
|
||||
String account = result.getData().getAccount();
|
||||
return ssoUserService.bindGithub(account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取github账号信息
|
||||
*
|
||||
* @param code 认证code
|
||||
* @param redirectUri 回调地址
|
||||
* @return 账号信息
|
||||
*/
|
||||
private Result<GitLoginInfo> getGithubAccount(String code, String redirectUri) throws IOException {
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("client_id", clientId);
|
||||
param.put("client_secret", clientSecret);
|
||||
@@ -59,28 +104,18 @@ public class GithubController {
|
||||
}
|
||||
jsonObject = JSON.parseObject(result.getData());
|
||||
String token = jsonObject.getString("access_token");
|
||||
if (!isStarred(token)) {
|
||||
return Result.ok(1, "警告:未关注github仓库");
|
||||
}
|
||||
header.clear();
|
||||
header.put("Authorization", "Bearer " + token);
|
||||
result = OkHttpUtils.get("https://api.github.com/user", header);
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail("错误:请求github用户信息失败");
|
||||
}
|
||||
result = loginService.login(result.getData(), token, SerConstant.LoginType.Github, "system", "false");
|
||||
if (!result.isSuccess()) {
|
||||
return Result.fail(result.getMsg());
|
||||
jsonObject = JSON.parseObject(result.getData());
|
||||
String account = jsonObject.getString("login");
|
||||
if (StringUtils.isEmpty(account)) {
|
||||
return Result.fail("错误:未获取到账号");
|
||||
}
|
||||
return Result.ok(0, "登录成功");
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/url")
|
||||
@Operation(summary = "获取github url")
|
||||
public Result<String> getUrl() {
|
||||
return Result.ok("https://github.com/login/oauth/authorize?client_id=" + clientId
|
||||
+ "&redirect_uri=" + redirectUri + "&response_type=code", "获取地址成功");
|
||||
return Result.ok(new GitLoginInfo(token, account, result.getData()), "获取github账号成功");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -329,4 +329,26 @@ public class SsoUserController {
|
||||
public Result<SsoUser> changeAccount(@RequestBody SsoUser ssoUser) {
|
||||
return ssoUserService.changeAccount(ssoUser.getId(), ssoUser.getAccount());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "获取用户安全设置")
|
||||
@GetMapping("/secureSetting/{userId}")
|
||||
public Result<SsoUser> getSecureSetting(@PathVariable("userId") String userId) {
|
||||
return Result.ok(ssoUserService.getSecureSetting(userId));
|
||||
}
|
||||
|
||||
@Operation(summary = "解绑gitee账号")
|
||||
@PutMapping("/unbind/gitee/{userId}")
|
||||
@Log(title = "解绑gitee账号", operateType = OperateType.UPDATE)
|
||||
public Result<Boolean> unbindGitee(@PathVariable("userId") String userId) {
|
||||
return ssoUserService.unbindGitee(userId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Operation(summary = "解绑github账号")
|
||||
@PutMapping("/unbind/github/{userId}")
|
||||
@Log(title = "解绑github账号", operateType = OperateType.UPDATE)
|
||||
public Result<Boolean> unbindGithub(@PathVariable("userId") String userId) {
|
||||
return ssoUserService.unbindGithub(userId);
|
||||
}
|
||||
}
|
||||
@@ -503,7 +503,6 @@ public class SsoUserServiceImpl extends ServiceImpl<SsoUserMapper, SsoUser> impl
|
||||
if (isAccountExist(account, userId)) {
|
||||
return Result.fail(user, "错误:账号已存在");
|
||||
}
|
||||
|
||||
if (baseMapper.updateById(user) > 0) {
|
||||
userTempCache.removeOneCache(userId);
|
||||
return Result.ok(user, "修改账号成功");
|
||||
@@ -511,6 +510,123 @@ public class SsoUserServiceImpl extends ServiceImpl<SsoUserMapper, SsoUser> impl
|
||||
return Result.fail(user, "修改账号失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SsoUser getSecureSetting(String userId) {
|
||||
SsoUser ssoUser = userTempCache.getFromCacheAndDB(userId);
|
||||
//脱敏
|
||||
ssoUser.setPassword(null);
|
||||
ssoUser.setOldPassword(null);
|
||||
if(ssoUser.getPhone() != null){
|
||||
ssoUser.setPhone(ssoUser.getPhone().replaceAll("(\\d{3})(\\d*)(\\d{2})", "$1****$3"));
|
||||
}
|
||||
if(ssoUser.getEmail() != null){
|
||||
ssoUser.setEmail(ssoUser.getEmail().replaceAll("(\\w)\\w*(@\\w+\\.\\w+)", "$1****$2"));
|
||||
}
|
||||
if(ssoUser.getGitee() != null){
|
||||
ssoUser.setGitee(ssoUser.getGitee().replaceAll("(\\w{1})(\\w*)(\\w{1})", "$1****$3"));
|
||||
}
|
||||
if(ssoUser.getGithub() != null){
|
||||
ssoUser.setGithub(ssoUser.getGithub().replaceAll("(\\w{1})(\\w*)(\\w{1})", "$1****$3"));
|
||||
}
|
||||
if(ssoUser.getOpenid() != null){
|
||||
ssoUser.setOpenid(ssoUser.getOpenid().replaceAll("(\\w{1})(\\w*)(\\w{2})", "$1****$3"));
|
||||
}
|
||||
return ssoUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> unbindGitee(String userId) {
|
||||
Result<SsoUser> result = unbindVerify(userId);
|
||||
if(!result.isSuccess()){
|
||||
return Result.fail(false, result.getMsg());
|
||||
}
|
||||
SsoUser ssoUser = result.getData();
|
||||
if(StringUtils.isEmpty(ssoUser.getGitee())){
|
||||
return Result.fail(false, "错误:未绑定gitee账号");
|
||||
}
|
||||
ssoUser.setGitee("");
|
||||
if(baseMapper.updateById(ssoUser) > 0){
|
||||
userTempCache.removeOneCache(userId);
|
||||
return Result.ok(true, "解绑gitee账号成功");
|
||||
}
|
||||
return Result.fail(false, "解绑gitee账号失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> bindGitee(String giteeAccount) {
|
||||
SsoUser user = getUserByGitee(giteeAccount);
|
||||
// 新用户判断是否关注仓库
|
||||
if (user != null) {
|
||||
return Result.fail(false, "警告:Gitee账号已被其他用户绑定");
|
||||
}
|
||||
String userId = AuthInfoUtils.getCurrentUserId();
|
||||
if(StringUtils.isEmpty(userId)){
|
||||
return Result.fail(false, "错误:未获取到当前用户ID");
|
||||
}
|
||||
SsoUser ssoUser = userTempCache.getFromCacheAndDB(userId);
|
||||
if(StringUtils.isNotEmpty(ssoUser.getGitee())){
|
||||
return Result.fail(false, "错误:已绑定gitee账号");
|
||||
}
|
||||
ssoUser.setGitee(giteeAccount);
|
||||
if(baseMapper.updateById(ssoUser) > 0){
|
||||
userTempCache.removeOneCache(AuthInfoUtils.getCurrentUserId());
|
||||
return Result.ok(true, "绑定gitee账号成功");
|
||||
}
|
||||
return Result.fail(false, "错误:绑定gitee账号失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> unbindGithub(String userId) {
|
||||
Result<SsoUser> result = unbindVerify(userId);
|
||||
if(!result.isSuccess()){
|
||||
return Result.fail(false, result.getMsg());
|
||||
}
|
||||
SsoUser ssoUser = result.getData();
|
||||
if(StringUtils.isEmpty(ssoUser.getGithub())){
|
||||
return Result.fail(false, "错误:未绑定github账号");
|
||||
}
|
||||
ssoUser.setGithub("");
|
||||
if(baseMapper.updateById(ssoUser) > 0){
|
||||
userTempCache.removeOneCache(userId);
|
||||
return Result.ok(true, "解绑github账号成功");
|
||||
}
|
||||
return Result.fail(false, "解绑github账号失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> bindGithub(String githubAccount) {
|
||||
SsoUser user = getUserByGithub(githubAccount);
|
||||
// 新用户判断是否关注仓库
|
||||
if (user != null) {
|
||||
return Result.fail(false, "警告:Github账号已被其他用户绑定");
|
||||
}
|
||||
String userId = AuthInfoUtils.getCurrentUserId();
|
||||
if(StringUtils.isEmpty(userId)){
|
||||
return Result.fail(false, "错误:未获取到当前用户ID");
|
||||
}
|
||||
SsoUser ssoUser = userTempCache.getFromCacheAndDB(userId);
|
||||
if(StringUtils.isNotEmpty(ssoUser.getGithub())){
|
||||
return Result.fail(false, "错误:已绑定github账号");
|
||||
}
|
||||
ssoUser.setGithub(githubAccount);
|
||||
if(baseMapper.updateById(ssoUser) > 0){
|
||||
userTempCache.removeOneCache(AuthInfoUtils.getCurrentUserId());
|
||||
return Result.ok(true, "绑定github账号成功");
|
||||
}
|
||||
return Result.fail(false, "错误:绑定github账号失败");
|
||||
}
|
||||
|
||||
private Result<SsoUser> unbindVerify(String userId) {
|
||||
SsoUser ssoUser = userTempCache.getFromCacheAndDB(userId);
|
||||
if(StringUtils.isEmpty(ssoUser.getPassword())){
|
||||
return Result.fail(ssoUser, "错误:未设置密码,请设置密码后再解绑");
|
||||
}
|
||||
if(StringUtils.isMatch("^G[0-9]*$", ssoUser.getAccount())){
|
||||
return Result.fail(ssoUser, "错误:自动生成账号,请在个人信息中修改账号名称后再解绑");
|
||||
}
|
||||
return Result.ok(ssoUser, "验证通过");
|
||||
}
|
||||
|
||||
private OnlineUser buildOnlineUser(RedisAccessToken redisAccessToken, String sessionId) {
|
||||
return new OnlineUser().setAccount(redisAccessToken.getAccount())
|
||||
.setSid(SM4Utils.encryptEcb(sm4key, sessionId))
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -36,7 +36,9 @@ gitee:
|
||||
clientId: a83ea66522fef5f382c6aaffa875c7e87b21d3933277c44a326cd3407fc0b651
|
||||
clientSecret: 3ebdce2afcb4a7df9b16355f60d898d452f4d9cf8ad1ab8279bb3bb465e614db
|
||||
redirectUri: http://localhost:5186/giteeOauth2
|
||||
bindUri: http://localhost:5186/tenant/info/1?callback=gitee
|
||||
github:
|
||||
clientId: Ov23li7oH0Djw3ZEJCoJ
|
||||
clientSecret: ada9a510b3bde542e7510142f07d32a5f6bed131
|
||||
redirectUri: http://localhost:5186/githubOauth2
|
||||
redirectUri: http://localhost:5186/githubOauth2
|
||||
bindUri: http://localhost:5186/tenant/info/1?callback=github
|
||||
@@ -9,8 +9,10 @@ security:
|
||||
- "/oauth2/qrCodeLogin/**"
|
||||
- "/oauth2/wx/bind/**"
|
||||
- "/oauth2/static/**"
|
||||
- "/oauth2/gitee/**"
|
||||
- "/oauth2/github/**"
|
||||
- "/oauth2/gitee/token/**"
|
||||
- "/oauth2/gitee/url"
|
||||
- "/oauth2/github/token/**"
|
||||
- "/oauth2/github/url"
|
||||
- "/captcha"
|
||||
- "/storage/file/*.*"
|
||||
- "/css/**"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user