76 Commits

Author SHA1 Message Date
e3ac63f9f9 程序包com.agileboot.domain.system.dict.type不存在 2025-08-08 09:07:24 +08:00
cuijiawang
0bb060b273 refactor(admin): 重构开发环境配置并添加 Docker 支持
- 修改应用端口为 18080
- 更新数据库配置,使用加密凭据
- 调整 Redis 配置
- 添加 Jasypt 加密器配置
- 新增 Dockerfile 用于构建 Docker 镜像
- 更新 Maven 依赖,添加 Jasypt 支持
2025-07-31 16:06:55 +08:00
valarchie
4e9ab30d68 Merge pull request #81 from BruceBlink/dev
更新junit单元测试的相关依赖
2025-06-04 20:26:41 +08:00
valarchie
454bdd44bc Merge pull request #80 from BruceBlink/main
增加Github Actions的CI/CD配置
2025-06-04 20:24:11 +08:00
likanug
2fa20aaaf3 更新junit的相关依赖及版本,修复admin模块中maven test批量跑单元测试时报错的问题 2025-06-04 20:09:26 +08:00
likanug
d017e2bb64 更新AgileBootConfigTest单元测试 2025-06-04 19:08:03 +08:00
likanug
e2f398b794 Revert "添加发布release的GitHub Actions配置"
This reverts commit 9fbc14c171.
2025-06-04 18:30:50 +08:00
likanug
664d845ea4 Revert "增加GitHub打包配置"
This reverts commit 5b3809abd9.
2025-06-04 18:30:18 +08:00
likanug
5b3809abd9 增加GitHub打包配置 2025-06-04 17:55:54 +08:00
likanug
9fbc14c171 添加发布release的GitHub Actions配置 2025-06-04 17:45:56 +08:00
likanug
bc1b97f720 删除更新依赖图的配置 2025-06-04 17:31:27 +08:00
likanug
f5c6125d74 修复Java 17更新依赖图时报错的问题 2025-06-04 17:18:47 +08:00
likanug
4ed71fdf5d 删除构建完成后的slack通知配置 2025-06-04 17:08:28 +08:00
likanug
ab3bcda857 修复发送构建通知失败的问题 2025-06-04 17:03:24 +08:00
likanug
68575d141c 修复Missing download info for actions/cache@v2的问题 2025-06-04 16:56:46 +08:00
likanug
dd535bfa50 增加Java 8的构建配置 2025-06-04 16:53:25 +08:00
likanug
47394d92ae 修复更新“依赖图”错误的问题 2025-06-04 16:52:18 +08:00
likanug
2644ed4368 更新actions/upload-artifact为v4 2025-06-04 16:41:30 +08:00
likanug
c09c7e4ca8 增加GitHub Actions的CI/CD配置 2025-06-04 16:38:06 +08:00
valarchie
ce83324c44 Merge pull request #79 from BruceBlink/main
更新Lombok版本,修复在JDK21下,代码编译报错的问题
更新h2的sql脚本以及增加h2的MySQL语法兼容设置,修复test模式下项目启动报错的问题
2025-05-07 16:15:16 +08:00
likanug
9ad9895510 Revert "删除无用的pom依赖"
This reverts commit f489ef45fd.
2025-05-07 15:49:06 +08:00
likanug
f489ef45fd 删除无用的pom依赖 2025-05-07 12:10:18 +08:00
likanug
f1b3ca650d 更新h2的sql脚本以及增加h2的MySQL语法兼容设置,修复test模式下项目启动报错的问题 2025-05-07 12:07:33 +08:00
likanug
42bf932d86 更新Lombok版本,修复在JDK21下,代码编译报错的问题 2025-05-07 11:13:04 +08:00
valarchie
1ccbfa2881 Merge pull request #77 from gongxuanzhang/main
Util classes should have private constructors
2024-12-31 14:26:28 +08:00
Xuan-Zhang Gong
6e4155a146 Util classes should have private constructors 2024-11-18 14:11:20 +08:00
valarchie
0bc4148a34 Merge pull request #75 from 1065700104/develop
fix(DeptModel): 修复父级部门为null时NPE的bug
2024-09-12 16:06:49 +08:00
李嘉伟
6a4245f541 feat(DeptModel): 修复父级部门为null时NPE的bug 2024-09-04 17:05:42 +08:00
valarchie
660dfa6a1e Update README.md 2024-05-29 08:29:38 +08:00
valarchie
62f81adc74 Merge pull request #71 from deepbreath/main
update:更新 pgsql 表
2024-04-09 17:14:24 +08:00
Yuchen
21ed5ef781 update:更新 pgsql 表 2024-04-09 17:09:06 +08:00
valarchie
073cda31e8 Merge pull request #70 from habyss/main
fix: xxxQuery放到对应目录
2024-04-03 17:06:20 +08:00
hankun
a845cf66ce fix: xxxQuery放到对应目录 2024-04-03 13:35:17 +08:00
valarchie
d2eb733ab3 Merge pull request #61 from aniyayee/main
fix: 删除角色时将操作类型更正为DELETE
2023-11-13 16:07:28 +08:00
yayee
f09c1fa47f fix: 删除角色时将操作类型更正为DELETE 2023-11-13 15:57:41 +08:00
valarchie
4716b3c977 Merge pull request #60 from burningimlam/main
fix: 分页查询时可能出现的NPE
2023-11-08 19:32:42 +08:00
imlam
aa2de6a6f2 fix: 分页查询时可能出现的NPE 2023-11-08 19:02:57 +08:00
valarchie
e9df8f01a1 Merge remote-tracking branch 'origin/main' 2023-10-12 16:09:24 +08:00
valarchie
9793f97613 fix: 修复缓存问题 2023-10-12 16:09:10 +08:00
valarchie
ea6117cf4e Merge pull request #56 from qcxy/main
修改引入包注释
2023-10-12 09:49:49 +08:00
gzy
a8afdce2fa 修改引入包注释 2023-10-12 09:36:21 +08:00
valarchie
7b78527e6d Merge pull request #55 from qcxy/main
去掉多余的两个引入的包
2023-10-12 09:35:37 +08:00
gzy
5a20edaff8 去掉多余的两个引入的包
结构变为common->infrastructure->domain->admin
2023-10-12 09:30:40 +08:00
valarchie
c054f3e3e8 Merge pull request #54 from gyzhang/fix_by_kevin_20231004
fix: 修改“岗位管理”-查询功能中的1-默认排序为数据库中的post_sort,2-设置漏掉的前端查询条件“创建时间”对应的字段cre…
2023-10-06 22:11:58 +08:00
Kevin Zhang
1ba6a55e93 fix: 代码异动位置:“岗位管理”-查询功能中的1-默认排序为数据库中的post_sort,2-设置漏掉的前端查询条件“创建时间”对应的字段 2023-10-06 15:30:29 +08:00
Kevin Zhang
72cde4c5cf fix: 修改“岗位管理”-查询功能中的1-默认排序为数据库中的post_sort,2-设置漏掉的前端查询条件“创建时间”对应的字段create_time 2023-10-04 23:40:14 +08:00
valarchie
050905fbc0 Merge pull request #53 from gyzhang/fix_by_kevin_20231003
fix: 修改“岗位管理”-删除-按钮功能错误:前端传递参数和后端不匹配,参照操作日志的删除功能做了修改。
2023-10-03 18:14:28 +08:00
Kevin Zhang
135a135d0f fix: 修改“岗位管理”-删除-按钮功能错误:前端传递参数和后端不匹配,参照操作日志的删除功能做了修改。 2023-10-03 16:39:30 +08:00
valarchie
0c4f58fd23 Merge pull request #52 from gyzhang/fix_by_kevin_20231002
fix: 修改“岗位管理”-全部导出-按钮功能错误:请求类型修改为get,请求路径修改为/excel,重新提供方法返回不分页的查询结果。
2023-10-02 18:38:22 +08:00
Kevin Zhang
a6344a2662 fix: 修改“岗位管理”-全部导出-按钮功能错误:请求类型修改为get,请求路径修改为/excel,重新提供方法返回不分页的查询结果。 2023-10-02 16:53:18 +08:00
Kevin Zhang
9527c95734 fix: 修改“岗位管理”-全部导出-按钮功能错误:请求类型修改为get,请求路径修改为/excel,重新提供方法返回不分页的查询结果。 2023-10-02 16:44:54 +08:00
valarchie
fcf41c68da Merge pull request #51 from penbox/main
fix: AddRoleCommand 中的 roleSort 约束为 @NotBlank,导致新增角色报错
2023-09-22 16:50:18 +08:00
penbox
c7436ec289 Merge branch 'main' into main 2023-09-22 16:45:36 +08:00
penbox86@126.com
90f80a7d27 fix: AddRoleCommand 中的 roleSort 约束为 @NotBlank,导致新增角色报错 2023-09-22 16:39:16 +08:00
valarchie
4aeafb8ab1 Merge pull request #47 from wunaidouzi/fixed-20230914
fixed: roleSort使用NotBlank导致无法update
2023-09-14 19:20:13 +08:00
LiuZhiYun
d8093fffe9 fixed: roleSort使用NotBlank导致无法update 2023-09-14 18:35:18 +08:00
valarchie
33ce250371 Merge pull request #45 from penbox/main
fix:移除 selectMenuListByUserId 中无效的排序字段
2023-09-07 10:36:19 +08:00
penbox86@126.com
88841b7ed0 fix:移除 selectMenuListByUserId 中无效的排序字段 2023-09-07 10:13:08 +08:00
valarchie
1a93fe4d95 refactor: 更新readMe 2023-08-16 18:52:54 +08:00
valarchie
251db3a146 refactor: 更新readMe 2023-08-15 11:01:19 +08:00
valarchie
18cba6b975 refactor: 更新gitignore 2023-08-15 09:53:44 +08:00
valarchie
a6792705ba refactor: 去除NonNull注解 2023-08-15 09:42:58 +08:00
valarchie
02fb771994 refactor: 修改Readme 2023-08-15 08:50:53 +08:00
valarchie
6ebea15fb3 refactor: 添加初始化sql文件 2023-08-15 08:40:08 +08:00
valarchie
76f1ddc9fe refactor: 修改ReadMe 2023-08-15 08:38:54 +08:00
valarchie
198b0856af refactor: 修改ReadMe 2023-08-15 08:32:07 +08:00
valarchie
0ab467dc6c Merge branch 'For-Pure'
# Conflicts:
#	agileboot-common/src/main/java/com/agileboot/common/enums/BasicEnumUtil.java
#	agileboot-common/src/test/java/com/agileboot/common/enums/BasicEnumUtilTest.java
2023-08-15 08:22:36 +08:00
valarchie
3b091cbd4a Merge pull request #43 from daniyyer/exportExcel
Update CustomExcelUtil.java
2023-07-20 16:34:36 +08:00
daniyyer
df4996096c Update CustomExcelUtil.java
ExcelUtil.getWriter()默认创建xls格式的Excel,因此写出到客户端也需要自定义文件名为XXX.xls,现在配套的前端代码中设置的文件扩展名为xlsx,导出后打开会出现文件损坏的提示。改为ExcelUtil.getWriter(true)后,可生成xlsx格式的文件。
2023-07-20 16:06:38 +08:00
valarchie
fb40f307b9 Update README.md 2023-07-14 16:03:29 +08:00
valarchie
2e435497b9 Update README.md 2023-07-14 16:02:46 +08:00
valarchie
bcc9d7c757 Merge pull request #39 from TheLastSunset/mvnw
feat: add maven wrapper
2023-07-13 16:07:08 +08:00
valarchie
8d214bc4d1 Merge pull request #40 from TheLastSunset/optimize
refactor: optimize BasicEnumUtil
2023-07-13 15:41:29 +08:00
TheLastSunset
7bb6d625e4 refactor: optimize BasicEnumUtil 2023-07-13 14:11:40 +08:00
TheLastSunset
88e22c270d feat: add mvnw execute permission 2023-07-12 08:40:48 +00:00
TheLastSunset
37e297626b feat: add maven wrapper 2023-07-12 10:58:12 +08:00
182 changed files with 2260 additions and 2568 deletions

116
.github/workflows/ci-cd.yml vendored Normal file
View File

@@ -0,0 +1,116 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
# 权限声明,确保 workflow 有权限写 checks 和 security-events
permissions:
contents: read
checks: write
security-events: write
name: Java CI with Maven
on:
push:
branches: [ "main" ]
paths-ignore:
- 'README.md'
- 'LICENSE'
- '.gitignore'
- '.gitattributes'
- 'picture'
pull_request:
branches: [ "main" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
java-version: ['8', '17', '21']
fail-fast: false
name: Build with Java ${{ matrix.java-version }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java-version }}
distribution: 'temurin'
cache: 'maven'
# 优化Maven本地仓库缓存策略
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}-${{ matrix.java-version }}
restore-keys: |
${{ runner.os }}-m2-
# 编译和测试去掉failOnWarning避免因为警告导致失败
- name: Build and Test with Maven
run: |
mvn -B verify --file pom.xml -Dmaven.test.failure.ignore=false -Dgpg.skip -Dmaven.javadoc.skip=false
env:
MAVEN_OPTS: -Xmx4g -XX:MaxMetaspaceSize=1g
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
- name: Publish Test Report
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
report_paths: '**/target/surefire-reports/TEST-*.xml'
detailed_summary: true
include_passed: true
fail_on_failure: true
- name: Run SonarQube Analysis
if: matrix.java-version == '17' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
continue-on-error: true
run: |
if [[ ! -z "${{ secrets.SONAR_TOKEN }}" ]]; then
mvn sonar:sonar \
-Dsonar.projectKey=agileboot \
-Dsonar.organization=${{ secrets.SONAR_ORGANIZATION || 'default' }} \
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL || 'https://sonarcloud.io' }} \
-Dsonar.login=${{ secrets.SONAR_TOKEN }} \
-Dsonar.java.source=${{ matrix.java-version }}
else
echo "Skipping SonarQube analysis - SONAR_TOKEN not configured"
fi
# 上传构建产物if-no-files-found 改为 warn
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: agileboot-artifacts-java-${{ matrix.java-version }}
path: |
**/target/*.jar
!**/target/original-*.jar
retention-days: 5
if-no-files-found: warn
# # 只在 Java 17 版本上更新依赖图权限和token已修复
# - name: Update dependency graph
# uses: advanced-security/maven-dependency-submission-action@v4
# if: matrix.java-version == '17' && success()
# with:
# token: ${{ secrets.GITHUB_TOKEN }}
# # 发送构建状态通知
# - name: Notify Build Status
# if: always()
# uses: rtCamp/action-slack-notify@v2.2.1
# env:
# SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK || '' }}
# SLACK_CHANNEL: build-notifications
# SLACK_COLOR: ${{ job.status }}
# SLACK_TITLE: Build Status for Java ${{ matrix.java-version }}
# SLACK_MESSAGE: 'Build ${{ job.status }} on Java ${{ matrix.java-version }}'

6
.gitignore vendored
View File

@@ -45,6 +45,6 @@ nbdist/
!*/build/*.java
!*/build/*.html
!*/build/*.xml
/agileboot-admin/src/main/resources/application-dev.yml
/agileboot-infrastructure/src/main/resources/application-prod.yml
/agileboot-infrastructure/src/main/resources/logback-prod.xml
/agileboot-admin/src/main/resources/application-prod.yml

BIN
.mvn/wrapper/maven-wrapper.jar vendored Normal file

Binary file not shown.

18
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM amazoncorretto:17
ADD agileboot-admin/target/agileboot-admin-1.0.0.jar /agileboot-admin.jar
EXPOSE 18080
#ENV CONTEXT_PATH /
# ENV NACOS_ENABLED true
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT ["java", "-jar", "/agileboot-admin.jar"]

View File

@@ -15,8 +15,7 @@
<img alt="logo" height="200" src="https://oscimg.oschina.net/oscnet/up-eda2a402cc061f1f5f40d9ac4c084f4c98c.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">AgileBoot v1.8.0</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">AgileBoot v2.0.0 </h1>
<h4 align="center">基于SpringBoot+Vue3前后端分离的Java快速开发脚手架</h4>
<p align="center">
</p>
@@ -27,7 +26,8 @@ AgileBoot是一套开源的全栈精简快速开发平台毫无保留给个
适合个人开发者的小型项目或者公司内部项目使用。也可作为供初学者学习使用的案例。
* 前端采用Vue3、Element Plus。对应前端仓库 [AgileBoot-Front-End](https://github.com/valarchie/AgileBoot-Front-End) ,保持同步更新
* 前端是基于优秀的开源项目[Pure-Admin](https://github.com/pure-admin/vue-pure-admin)开发而成。在此感谢Pure-Admin作者
* 前端采用Vue3、Element Plus、TypeScript、Pinia。对应前端仓库 [AgileBoot-Front-End](https://github.com/valarchie/AgileBoot-Front-End) ,保持同步更新。
* 后端采用Spring Boot、Spring Security & Jwt、Redis & MySql、Mybatis Plus、Hutool工具包。
* 权限认证使用Jwt支持多终端认证系统。
* 支持注解式主从数据库切换,注解式请求限流,注解式重复请求拦截。
@@ -35,6 +35,9 @@ AgileBoot是一套开源的全栈精简快速开发平台毫无保留给个
* 支持加载动态权限菜单,实时权限控制。
* ***有大量的单元测试,集成测试覆盖确保业务逻辑正确***。
***V1.0.0版本使用JS开发V2.0.0版本使用TS开发***。
***V1.0.0地址:[后端(AgileBoot-Back-End-Basic)](https://github.com/valarchie/AgileBoot-Back-End-Basic) - [前端(AgileBoot-Front-End-Basic)](https://github.com/valarchie/AgileBoot-Front-End-Basic)***
> 有任何问题或者建议,可以在 _Issues_ 中提给作者。
>
> 您的Issue比Star更重要
@@ -148,9 +151,9 @@ git clone https://github.com/valarchie/AgileBoot-Front-End
#### 后端启动
```
1. 生成所需的数据库表
找到后端项目根目录下的sql目录中的agileboot_xxxxx.sql脚本文件。 导入到你新建的数据库中。
找到后端项目根目录下的sql目录中的agileboot_xxxxx.sql脚本文件(取最新的sql文件)。 导入到你新建的数据库中。
2. 在infrastructure模块底下找到resource目录下的application-dev.yml文件
2. 在admin模块底下找到resource目录下的application-dev.yml文件
配置数据库以及Redis的 地址、端口、账号密码
3. 在根目录执行mvn install
@@ -168,16 +171,18 @@ git clone https://github.com/valarchie/AgileBoot-Front-End
```
#### 前端启动
```
1. npm install
详细步骤请查看对应前端部分
2. npm run dev
```
1. pnpm install
2. pnpm run dev
3. 当出现以下字样时即为启动成功
vite v2.6.14 dev server running at:
> Local: http://127.0.0.1:3000/
> Local: http://127.0.0.1:80/
ready in 4376ms.
@@ -232,8 +237,6 @@ agileboot.embedded.redis: true
| | 连接池监视 | 监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈 |
目前版本是V1.8.0将在2.0版本后陆续新增新功能。
## 🐯 工程结构 🐯
```
@@ -244,25 +247,20 @@ agileboot
├── agileboot-common -- 精简基础工具模块
├── agileboot-infrastructure -- 基础设施模块(主要是配置和集成)
├── agileboot-infrastructure -- 基础设施模块(主要是配置和集成,不包含业务逻辑
├── agileboot-domain -- 业务模块
├ ├── user -- 用户模块(举例)
├ ├── command -- 命令参数接收模型(命令)
├ ├── dto -- 返回数据类
├ ├── db -- DB操作类
├ ├── entity -- 实体类
├ ├── service -- DB Service
├ ├── mapper -- DB Dao
├ ├── model -- 领域模型类
├ ├── query -- 查询参数模型(查询)
│ ├────── UserApplicationService -- 应用服务(事务层,操作领域模型类完成业务逻辑)
├── agileboot-integration-test -- 集成测试模块
├── agileboot-orm -- 数据映射模块(仅包含数据相关逻辑)
├ ├── entiy -- 实体类
├ ├── enums -- 数据相关枚举
├ ├── mapper -- DAO
├ ├── query -- 封装查询对象
├ ├── result -- 封装多表查询对象
└── └── service -- 服务层
```
### 代码流转
@@ -286,11 +284,16 @@ agileboot
│ ├── member -- 会员模块
├── agileboot-domain --
├ ├── member -- 会员模块
── agileboot-orm --
├── member -- 会员模块
├ ├── member -- 会员模块(举例)
├ ├── command -- 命令参数接收模型(命令)
├── dto -- 返回数据类
├── db -- DB操作类
├ ├── entity -- 实体类
├ ├── service -- DB Service
├ ├── mapper -- DB Dao
├ ├── model -- 领域模型类
├ ├── query -- 查询参数模型(查询)
│ ├────── MemberApplicationService -- 应用服务(事务层,操作领域模型类完成业务逻辑)
└─
```
@@ -315,11 +318,12 @@ agileboot
- 请导入统一的代码格式化模板Google: Settings > Editor > Code Style > Java > 设置按钮 > import schema > 选择项目根目录下的GoogleStyle.xml文件
- 如需要生成新的表请使用CodeGenerator类进行生成。
- 填入数据库地址,账号密码,库名。然后填入所需的表名执行代码即可。(大概看一下代码就知道怎么填啦)
- 生成的类在orm模块下的target/classes目录下
- 生成的类在infrastructure模块下的target/classes目录下
- 不同的数据库keywordsHandler方法请填入对应不同数据库handler。搜索keywordsHandler关键字
- 项目基础环境搭建请参考docker目录下的指南搭建。保姆级启动说明
- [AgileBoot - 手把手一步一步带你Run起全栈项目(SpringBoot+Vue3)](https://juejin.cn/post/7153812187834744845)
- 注意管理后台的后端启动类是AgileBoot**Admin**Application
- Swagger的API地址为 http://localhost:8080/v3/api-docs
## 🎬 AgileBoot全栈交流群 🎬

View File

@@ -18,12 +18,6 @@
<dependencies>
<!-- 核心模块-->
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>agileboot-infrastructure</artifactId>
</dependency>
<!-- 业务领域 -->
<dependency>
<groupId>com.agileboot</groupId>
@@ -61,6 +55,15 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
<!-- 想跑test的话 设置成false -->
<configuration>
<skipTests>false</skipTests>
</configuration>
</plugin>
</plugins>
</build>

View File

@@ -12,6 +12,7 @@ import org.springframework.context.annotation.ComponentScan;
* http://www.network-science.de/ascii/
* http://www.degraeve.com/img2txt.php
* http://life.chacuo.net/convertfont2char
*
* @author valarchie
*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@@ -21,11 +22,11 @@ public class AgileBootAdminApplication {
public static void main(String[] args) {
SpringApplication.run(AgileBootAdminApplication.class, args);
String successMsg = " ____ _ _ __ _ _ \n"
+ " / ___| | |_ __ _ _ __ | |_ _ _ _ __ ___ _ _ ___ ___ ___ ___ ___ / _| _ _ | || |\n"
+ " \\___ \\ | __|/ _` || '__|| __| | | | || '_ \\ / __|| | | | / __|/ __|/ _ \\/ __|/ __|| |_ | | | || || |\n"
+ " ___) || |_| (_| || | | |_ | |_| || |_) | \\__ \\| |_| || (__| (__| __/\\__ \\\\__ \\| _|| |_| || ||_|\n"
+ " |____/ \\__|\\__,_||_| \\__| \\__,_|| .__/ |___/ \\__,_| \\___|\\___|\\___||___/|___/|_| \\__,_||_|(_)\n"
+ " |_| ";
+ " / ___| | |_ __ _ _ __ | |_ _ _ _ __ ___ _ _ ___ ___ ___ ___ ___ / _| _ _ | || |\n"
+ " \\___ \\ | __|/ _` || '__|| __| | | | || '_ \\ / __|| | | | / __|/ __|/ _ \\/ __|/ __|| |_ | | | || || |\n"
+ " ___) || |_| (_| || | | |_ | |_| || |_) | \\__ \\| |_| || (__| (__| __/\\__ \\\\__ \\| _|| |_| || ||_|\n"
+ " |____/ \\__|\\__,_||_| \\__| \\__,_|| .__/ |___/ \\__,_| \\___|\\___|\\___||___/|___/|_| \\__,_||_|(_)\n"
+ " |_| ";
System.out.println(successMsg);
}

View File

@@ -14,9 +14,6 @@ import com.agileboot.common.utils.jackson.JacksonUtil;
import com.agileboot.domain.common.dto.UploadDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -28,9 +25,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* 通用请求处理
* TODO 需要重构
*
* @author valarchie
*/
@Tag(name = "上传API", description = "上传相关接口")
@@ -43,6 +45,7 @@ public class FileController {
/**
* 通用下载请求
* download接口 其实不是很有必要
*
* @param fileName 文件名称
*/
@Operation(summary = "下载文件")
@@ -52,7 +55,7 @@ public class FileController {
if (!FileUploadUtils.isAllowDownload(fileName)) {
// 返回类型是ResponseEntity 不能捕获异常, 需要手动将错误填到 ResponseEntity
ResponseDTO<Object> fail = ResponseDTO.fail(
new ApiException(Business.COMMON_FILE_NOT_ALLOWED_TO_DOWNLOAD, fileName));
new ApiException(Business.COMMON_FILE_NOT_ALLOWED_TO_DOWNLOAD, fileName));
return new ResponseEntity<>(JacksonUtil.to(fail).getBytes(), null, HttpStatus.OK);
}
@@ -84,14 +87,14 @@ public class FileController {
String url = ServletHolderUtil.getContextUrl() + fileName;
UploadDTO uploadDTO = UploadDTO.builder()
// 全路径
.url(url)
// 相对路径
.fileName(fileName)
// 新生成的文件名
.newFileName(FileNameUtil.getName(fileName))
// 原始的文件名
.originalFilename(file.getOriginalFilename()).build();
// 全路径
.url(url)
// 相对路径
.fileName(fileName)
// 新生成的文件名
.newFileName(FileNameUtil.getName(fileName))
// 原始的文件名
.originalFilename(file.getOriginalFilename()).build();
return ResponseDTO.ok(uploadDTO);
}
@@ -114,10 +117,10 @@ public class FileController {
String fileName = FileUploadUtils.upload(UploadSubDir.UPLOAD_PATH, file);
String url = ServletHolderUtil.getContextUrl() + fileName;
UploadDTO uploadDTO = UploadDTO.builder()
.url(url)
.fileName(fileName)
.newFileName(FileNameUtil.getName(fileName))
.originalFilename(file.getOriginalFilename()).build();
.url(url)
.fileName(fileName)
.newFileName(FileNameUtil.getName(fileName))
.originalFilename(file.getOriginalFilename()).build();
uploads.add(uploadDTO);

View File

@@ -1,6 +1,10 @@
package com.agileboot.admin.controller.common;
import cn.hutool.core.util.StrUtil;
import com.agileboot.admin.customize.service.login.LoginService;
import com.agileboot.admin.customize.service.login.command.LoginCommand;
import com.agileboot.admin.customize.service.login.dto.CaptchaDTO;
import com.agileboot.admin.customize.service.login.dto.ConfigDTO;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.exception.ApiException;
@@ -14,23 +18,19 @@ import com.agileboot.domain.system.user.command.AddUserCommand;
import com.agileboot.infrastructure.annotations.ratelimit.RateLimit;
import com.agileboot.infrastructure.annotations.ratelimit.RateLimit.CacheType;
import com.agileboot.infrastructure.annotations.ratelimit.RateLimit.LimitType;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.admin.customize.service.login.dto.CaptchaDTO;
import com.agileboot.admin.customize.service.login.dto.ConfigDTO;
import com.agileboot.admin.customize.service.login.command.LoginCommand;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.annotations.ratelimit.RateLimitKey;
import com.agileboot.admin.customize.service.login.LoginService;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
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.util.List;
/**
* 首页
*
@@ -55,10 +55,10 @@ public class LoginController {
@Operation(summary = "首页")
@GetMapping("/")
@RateLimit(key = RateLimitKey.TEST_KEY, time = 10, maxCount = 5, cacheType = CacheType.Map,
limitType = LimitType.GLOBAL)
limitType = LimitType.GLOBAL)
public String index() {
return StrUtil.format("欢迎使用{}后台管理框架当前版本v{},请通过前端地址访问。",
agileBootConfig.getName(), agileBootConfig.getVersion());
agileBootConfig.getName(), agileBootConfig.getVersion());
}
@@ -78,7 +78,7 @@ public class LoginController {
*/
@Operation(summary = "验证码")
@RateLimit(key = RateLimitKey.LOGIN_CAPTCHA_KEY, time = 10, maxCount = 10, cacheType = CacheType.REDIS,
limitType = LimitType.IP)
limitType = LimitType.IP)
@GetMapping("/captchaImage")
public ResponseDTO<CaptchaDTO> getCaptchaImg() {
CaptchaDTO captchaImg = loginService.generateCaptchaImg();
@@ -120,6 +120,7 @@ public class LoginController {
/**
* 获取路由信息
* TODO 如果要在前端开启路由缓存的话 需要在ServerConfig.json 中 设置CachingAsyncRoutes=true 避免一直重复请求路由接口
*
* @return 路由信息
*/
@Operation(summary = "获取用户对应的菜单路由", description = "用于动态生成路由")

View File

@@ -1,26 +1,22 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.system.monitor.MonitorApplicationService;
import com.agileboot.domain.system.monitor.dto.OnlineUserDTO;
import com.agileboot.domain.system.monitor.dto.RedisCacheInfoDTO;
import com.agileboot.domain.system.monitor.dto.ServerInfo;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
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.util.List;
/**
* 缓存监控
@@ -56,7 +52,7 @@ public class MonitorController extends BaseController {
* 获取在线用户列表
*
* @param ipAddress ip地址
* @param username 用户名
* @param username 用户名
* @return 分页处理后的在线用户信息
*/
@Operation(summary = "在线用户列表")

View File

@@ -1,33 +1,28 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.system.config.ConfigApplicationService;
import com.agileboot.domain.system.config.command.ConfigUpdateCommand;
import com.agileboot.domain.system.config.dto.ConfigDTO;
import com.agileboot.domain.system.config.query.ConfigQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
/**
* 参数配置 信息操作处理
*
* @author valarchie
*/
@RestController
@@ -66,7 +61,7 @@ public class SysConfigController extends BaseController {
* 修改参数配置
*/
@PreAuthorize("@permission.has('system:config:edit')")
@AccessLog(title = "参数管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "参数管理", businessType = BusinessTypeEnum.UPDATE)
@Operation(summary = "配置修改", description = "配置修改")
@PutMapping(value = "/config/{configId}")
public ResponseDTO<Void> edit(@NotNull @Positive @PathVariable Long configId, @RequestBody ConfigUpdateCommand config) {

View File

@@ -1,31 +1,24 @@
package com.agileboot.admin.controller.system;
import cn.hutool.core.lang.tree.Tree;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.system.dept.DeptApplicationService;
import com.agileboot.domain.system.dept.command.AddDeptCommand;
import com.agileboot.domain.system.dept.command.UpdateDeptCommand;
import com.agileboot.domain.system.dept.dto.DeptDTO;
import com.agileboot.domain.system.dept.query.DeptQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 部门信息
@@ -78,7 +71,7 @@ public class SysDeptController extends BaseController {
*/
@Operation(summary = "新增部门")
@PreAuthorize("@permission.has('system:dept:add')")
@AccessLog(title = "部门管理", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "部门管理", businessType = BusinessTypeEnum.INSERT)
@PostMapping("/dept")
public ResponseDTO<Void> add(@RequestBody AddDeptCommand addCommand) {
deptApplicationService.addDept(addCommand);
@@ -90,9 +83,9 @@ public class SysDeptController extends BaseController {
*/
@Operation(summary = "修改部门")
@PreAuthorize("@permission.has('system:dept:edit') AND @dataScope.checkDeptId(#updateCommand.deptId)")
@AccessLog(title = "部门管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "部门管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/dept/{deptId}")
public ResponseDTO<Void> edit(@PathVariable("deptId")Long deptId, @RequestBody UpdateDeptCommand updateCommand) {
public ResponseDTO<Void> edit(@PathVariable("deptId") Long deptId, @RequestBody UpdateDeptCommand updateCommand) {
updateCommand.setDeptId(deptId);
deptApplicationService.updateDept(updateCommand);
return ResponseDTO.ok();

View File

@@ -1,32 +1,29 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.utils.poi.CustomExcelUtil;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.system.log.LogApplicationService;
import com.agileboot.domain.system.log.dto.LoginLogDTO;
import com.agileboot.domain.system.log.query.LoginLogQuery;
import com.agileboot.domain.system.log.dto.OperationLogDTO;
import com.agileboot.domain.system.log.dto.OperationLogQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.system.log.query.LoginLogQuery;
import com.agileboot.domain.system.log.query.OperationLogQuery;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
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 org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 系统访问记录
@@ -93,8 +90,10 @@ public class SysLogsController extends BaseController {
// .contentLength(file.length())
// .body(resource);
// }
/**
* 可否改成以上的形式 TODO
*
* @param response
* @param query
*/

View File

@@ -1,35 +1,28 @@
package com.agileboot.admin.controller.system;
import cn.hutool.core.lang.tree.Tree;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.system.menu.MenuApplicationService;
import com.agileboot.domain.system.menu.command.AddMenuCommand;
import com.agileboot.domain.system.menu.command.UpdateMenuCommand;
import com.agileboot.domain.system.menu.dto.MenuDTO;
import com.agileboot.domain.system.menu.dto.MenuDetailDTO;
import com.agileboot.domain.system.menu.query.MenuQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import java.util.List;
/**
* 菜单信息
@@ -86,7 +79,7 @@ public class SysMenuController extends BaseController {
*/
@Operation(summary = "添加菜单")
@PreAuthorize("@permission.has('system:menu:add')")
@AccessLog(title = "菜单管理", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "菜单管理", businessType = BusinessTypeEnum.INSERT)
@PostMapping
public ResponseDTO<Void> add(@RequestBody AddMenuCommand addCommand) {
menuApplicationService.addMenu(addCommand);
@@ -98,7 +91,7 @@ public class SysMenuController extends BaseController {
*/
@Operation(summary = "编辑菜单")
@PreAuthorize("@permission.has('system:menu:edit')")
@AccessLog(title = "菜单管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "菜单管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{menuId}")
public ResponseDTO<Void> edit(@PathVariable("menuId") Long menuId, @RequestBody UpdateMenuCommand updateCommand) {
updateCommand.setMenuId(menuId);

View File

@@ -1,37 +1,29 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.system.notice.NoticeApplicationService;
import com.agileboot.domain.system.notice.command.NoticeAddCommand;
import com.agileboot.domain.system.notice.command.NoticeUpdateCommand;
import com.agileboot.domain.system.notice.dto.NoticeDTO;
import com.agileboot.domain.system.notice.query.NoticeQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.infrastructure.annotations.unrepeatable.Unrepeatable;
import com.agileboot.infrastructure.annotations.unrepeatable.Unrepeatable.CheckType;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.baomidou.dynamic.datasource.annotation.DS;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import java.util.List;
/**
* 公告 信息操作处理
@@ -87,7 +79,7 @@ public class SysNoticeController extends BaseController {
@Operation(summary = "添加公告")
@Unrepeatable(interval = 60, checkType = CheckType.SYSTEM_USER)
@PreAuthorize("@permission.has('system:notice:add')")
@AccessLog(title = "通知公告", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "通知公告", businessType = BusinessTypeEnum.INSERT)
@PostMapping
public ResponseDTO<Void> add(@RequestBody NoticeAddCommand addCommand) {
noticeApplicationService.addNotice(addCommand);
@@ -99,7 +91,7 @@ public class SysNoticeController extends BaseController {
*/
@Operation(summary = "修改公告")
@PreAuthorize("@permission.has('system:notice:edit')")
@AccessLog(title = "通知公告", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "通知公告", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{noticeId}")
public ResponseDTO<Void> edit(@PathVariable Long noticeId, @RequestBody NoticeUpdateCommand updateCommand) {
updateCommand.setNoticeId(noticeId);

View File

@@ -1,8 +1,10 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.utils.poi.CustomExcelUtil;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.system.post.PostApplicationService;
@@ -10,24 +12,17 @@ import com.agileboot.domain.system.post.command.AddPostCommand;
import com.agileboot.domain.system.post.command.UpdatePostCommand;
import com.agileboot.domain.system.post.dto.PostDTO;
import com.agileboot.domain.system.post.query.PostQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 岗位信息操作处理
@@ -54,13 +49,21 @@ public class SysPostController extends BaseController {
return ResponseDTO.ok(pageDTO);
}
/**
* 导出查询到的所有岗位信息到excel文件
*
* @param response http响应
* @param query 查询参数
* @author Kevin Zhang
* @date 2023-10-02
*/
@Operation(summary = "职位列表导出")
@AccessLog(title = "岗位管理", businessType = BusinessTypeEnum.EXPORT)
@PreAuthorize("@permission.has('system:post:export')")
@PostMapping("/export")
@GetMapping("/excel")
public void export(HttpServletResponse response, PostQuery query) {
PageDTO<PostDTO> pageDTO = postApplicationService.getPostList(query);
CustomExcelUtil.writeToResponse(pageDTO.getRows(), PostDTO.class, response);
List<PostDTO> all = postApplicationService.getPostListAll(query);
CustomExcelUtil.writeToResponse(all, PostDTO.class, response);
}
/**
@@ -79,7 +82,7 @@ public class SysPostController extends BaseController {
*/
@Operation(summary = "添加职位")
@PreAuthorize("@permission.has('system:post:add')")
@AccessLog(title = "岗位管理", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "岗位管理", businessType = BusinessTypeEnum.INSERT)
@PostMapping
public ResponseDTO<Void> add(@RequestBody AddPostCommand addCommand) {
postApplicationService.addPost(addCommand);
@@ -91,7 +94,7 @@ public class SysPostController extends BaseController {
*/
@Operation(summary = "修改职位")
@PreAuthorize("@permission.has('system:post:edit')")
@AccessLog(title = "岗位管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "岗位管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping
public ResponseDTO<Void> edit(@RequestBody UpdatePostCommand updateCommand) {
postApplicationService.updatePost(updateCommand);
@@ -104,9 +107,9 @@ public class SysPostController extends BaseController {
@Operation(summary = "删除职位")
@PreAuthorize("@permission.has('system:post:remove')")
@AccessLog(title = "岗位管理", businessType = BusinessTypeEnum.DELETE)
@DeleteMapping("/{postIds}")
public ResponseDTO<Void> remove(@PathVariable List<Long> postIds) {
postApplicationService.deletePost(new BulkOperationCommand<>(postIds));
@DeleteMapping
public ResponseDTO<Void> remove(@RequestParam @NotNull @NotEmpty List<Long> ids) {
postApplicationService.deletePost(new BulkOperationCommand<>(ids));
return ResponseDTO.ok();
}

View File

@@ -1,8 +1,10 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.constant.Constants.UploadSubDir;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.utils.file.FileUploadUtils;
@@ -12,21 +14,12 @@ import com.agileboot.domain.system.user.command.UpdateProfileCommand;
import com.agileboot.domain.system.user.command.UpdateUserAvatarCommand;
import com.agileboot.domain.system.user.command.UpdateUserPasswordCommand;
import com.agileboot.domain.system.user.dto.UserProfileDTO;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
@@ -57,7 +50,7 @@ public class SysProfileController extends BaseController {
* 修改用户
*/
@Operation(summary = "修改个人信息")
@AccessLog(title = "个人信息", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "个人信息", businessType = BusinessTypeEnum.UPDATE)
@PutMapping
public ResponseDTO<Void> updateProfile(@RequestBody UpdateProfileCommand command) {
SystemLoginUser loginUser = AuthenticationUtils.getSystemLoginUser();
@@ -70,7 +63,7 @@ public class SysProfileController extends BaseController {
* 重置密码
*/
@Operation(summary = "重置个人密码")
@AccessLog(title = "个人信息", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "个人信息", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/password")
public ResponseDTO<Void> updatePassword(@RequestBody UpdateUserPasswordCommand command) {
SystemLoginUser loginUser = AuthenticationUtils.getSystemLoginUser();
@@ -83,7 +76,7 @@ public class SysProfileController extends BaseController {
* 头像上传
*/
@Operation(summary = "修改个人头像")
@AccessLog(title = "用户头像", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "用户头像", businessType = BusinessTypeEnum.UPDATE)
@PostMapping("/avatar")
public ResponseDTO<UploadFileDTO> avatar(@RequestParam("avatarfile") MultipartFile file) {
if (file.isEmpty()) {

View File

@@ -1,8 +1,10 @@
package com.agileboot.admin.controller.system;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.utils.poi.CustomExcelUtil;
import com.agileboot.domain.system.role.RoleApplicationService;
import com.agileboot.domain.system.role.command.AddRoleCommand;
@@ -14,25 +16,16 @@ import com.agileboot.domain.system.role.query.AllocatedRoleQuery;
import com.agileboot.domain.system.role.query.RoleQuery;
import com.agileboot.domain.system.role.query.UnallocatedRoleQuery;
import com.agileboot.domain.system.user.dto.UserDTO;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 角色信息
@@ -81,7 +74,7 @@ public class SysRoleController extends BaseController {
*/
@Operation(summary = "添加角色")
@PreAuthorize("@permission.has('system:role:add')")
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.INSERT)
@PostMapping
public ResponseDTO<Void> add(@RequestBody AddRoleCommand addCommand) {
roleApplicationService.addRole(addCommand);
@@ -93,7 +86,7 @@ public class SysRoleController extends BaseController {
*/
@Operation(summary = "删除角色")
@PreAuthorize("@permission.has('system:role:remove')")
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.DELETE)
@DeleteMapping(value = "/{roleId}")
public ResponseDTO<Void> remove(@PathVariable("roleId") List<Long> roleIds) {
roleApplicationService.deleteRoleByBulk(roleIds);
@@ -105,7 +98,7 @@ public class SysRoleController extends BaseController {
*/
@Operation(summary = "修改角色")
@PreAuthorize("@permission.has('system:role:edit')")
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping
public ResponseDTO<Void> edit(@Validated @RequestBody UpdateRoleCommand updateCommand) {
roleApplicationService.updateRole(updateCommand);
@@ -117,10 +110,10 @@ public class SysRoleController extends BaseController {
*/
@Operation(summary = "修改角色数据权限")
@PreAuthorize("@permission.has('system:role:edit')")
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{roleId}/dataScope")
public ResponseDTO<Void> dataScope(@PathVariable("roleId") Long roleId,
@RequestBody UpdateDataScopeCommand command) {
@RequestBody UpdateDataScopeCommand command) {
command.setRoleId(roleId);
roleApplicationService.updateDataScope(command);
@@ -132,10 +125,10 @@ public class SysRoleController extends BaseController {
*/
@Operation(summary = "修改角色状态")
@PreAuthorize("@permission.has('system:role:edit')")
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{roleId}/status")
public ResponseDTO<Void> changeStatus(@PathVariable("roleId") Long roleId,
@RequestBody UpdateStatusCommand command) {
@RequestBody UpdateStatusCommand command) {
command.setRoleId(roleId);
roleApplicationService.updateStatus(command);
@@ -150,7 +143,7 @@ public class SysRoleController extends BaseController {
@PreAuthorize("@permission.has('system:role:list')")
@GetMapping("/{roleId}/allocated/list")
public ResponseDTO<PageDTO<UserDTO>> allocatedUserList(@PathVariable("roleId") Long roleId,
AllocatedRoleQuery query) {
AllocatedRoleQuery query) {
query.setRoleId(roleId);
PageDTO<UserDTO> page = roleApplicationService.getAllocatedUserList(query);
return ResponseDTO.ok(page);
@@ -163,7 +156,7 @@ public class SysRoleController extends BaseController {
@PreAuthorize("@permission.has('system:role:list')")
@GetMapping("/{roleId}/unallocated/list")
public ResponseDTO<PageDTO<UserDTO>> unallocatedUserList(@PathVariable("roleId") Long roleId,
UnallocatedRoleQuery query) {
UnallocatedRoleQuery query) {
query.setRoleId(roleId);
PageDTO<UserDTO> page = roleApplicationService.getUnallocatedUserList(query);
return ResponseDTO.ok(page);
@@ -190,7 +183,7 @@ public class SysRoleController extends BaseController {
@AccessLog(title = "角色管理", businessType = BusinessTypeEnum.GRANT)
@PostMapping("/{roleId}/users/{userIds}/grant/bulk")
public ResponseDTO<Void> addRoleForUserByBulk(@PathVariable("roleId") Long roleId,
@PathVariable("userIds") List<Long> userIds) {
@PathVariable("userIds") List<Long> userIds) {
roleApplicationService.addRoleOfUserByBulk(roleId, userIds);
return ResponseDTO.ok();
}

View File

@@ -1,9 +1,11 @@
package com.agileboot.admin.controller.system;
import cn.hutool.core.collection.ListUtil;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.utils.poi.CustomExcelUtil;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.system.user.UserApplicationService;
@@ -11,34 +13,26 @@ import com.agileboot.domain.system.user.command.AddUserCommand;
import com.agileboot.domain.system.user.command.ChangeStatusCommand;
import com.agileboot.domain.system.user.command.ResetPasswordCommand;
import com.agileboot.domain.system.user.command.UpdateUserCommand;
import com.agileboot.domain.system.user.db.SearchUserDO;
import com.agileboot.domain.system.user.dto.UserDTO;
import com.agileboot.domain.system.user.dto.UserDetailDTO;
import com.agileboot.domain.system.user.query.SearchUserQuery;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.system.user.db.SearchUserDO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 用户信息
*
* @author valarchie
*/
@Tag(name = "用户API", description = "用户相关的增删查改")
@@ -107,7 +101,7 @@ public class SysUserController extends BaseController {
*/
@Operation(summary = "新增用户")
@PreAuthorize("@permission.has('system:user:add') AND @dataScope.checkDeptId(#command.deptId)")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.INSERT)
@PostMapping
public ResponseDTO<Void> add(@Validated @RequestBody AddUserCommand command) {
userApplicationService.addUser(command);
@@ -119,7 +113,7 @@ public class SysUserController extends BaseController {
*/
@Operation(summary = "修改用户")
@PreAuthorize("@permission.has('system:user:edit') AND @dataScope.checkUserId(#command.userId)")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{userId}")
public ResponseDTO<Void> edit(@Validated @RequestBody UpdateUserCommand command) {
userApplicationService.updateUser(command);
@@ -145,7 +139,7 @@ public class SysUserController extends BaseController {
*/
@Operation(summary = "重置用户密码")
@PreAuthorize("@permission.has('system:user:resetPwd') AND @dataScope.checkUserId(#userId)")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{userId}/password")
public ResponseDTO<Void> resetPassword(@PathVariable Long userId, @RequestBody ResetPasswordCommand command) {
command.setUserId(userId);
@@ -158,7 +152,7 @@ public class SysUserController extends BaseController {
*/
@Operation(summary = "修改用户状态")
@PreAuthorize("@permission.has('system:user:edit') AND @dataScope.checkUserId(#command.userId)")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.UPDATE)
@PutMapping("/{userId}/status")
public ResponseDTO<Void> changeStatus(@PathVariable Long userId, @RequestBody ChangeStatusCommand command) {
command.setUserId(userId);

View File

@@ -2,11 +2,8 @@ package com.agileboot.admin.customize.aop.accessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.enums.common.OperatorTypeEnum;
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;
import java.lang.annotation.*;
/**
* 自定义操作日志记录注解

View File

@@ -33,7 +33,7 @@ public class AccessLogAspect {
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
* @param e 异常
*/
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, AccessLog controllerLog, Exception e) {

View File

@@ -5,13 +5,13 @@ import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.OperationStatusEnum;
import com.agileboot.common.enums.common.RequestMethodEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.domain.system.log.db.SysOperationLogEntity;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.springframework.validation.BindingResult;
@@ -98,7 +98,7 @@ public class OperationLogModel extends SysOperationLogEntity {
*/
private void recordRequestData(JoinPoint joinPoint) {
RequestMethodEnum requestMethodEnum = BasicEnumUtil.fromValue(RequestMethodEnum.class,
this.getRequestMethod());
this.getRequestMethod());
if (requestMethodEnum == RequestMethodEnum.GET || requestMethodEnum == RequestMethodEnum.POST) {
String params = argsArrayToString(joinPoint.getArgs());
@@ -154,7 +154,7 @@ public class OperationLogModel extends SysOperationLogEntity {
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|| o instanceof BindingResult;
|| o instanceof BindingResult;
}
}

View File

@@ -3,12 +3,12 @@ package com.agileboot.admin.customize.async;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.common.utils.ip.IpRegionUtil;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.domain.system.log.db.SysLoginInfoEntity;
import com.agileboot.domain.system.log.db.SysOperationLogEntity;
import com.agileboot.domain.system.log.db.SysLoginInfoService;
import com.agileboot.domain.system.log.db.SysOperationLogEntity;
import com.agileboot.domain.system.log.db.SysOperationLogService;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
@@ -35,7 +35,7 @@ public class AsyncTaskFactory {
public static Runnable loginInfoTask(final String username, final LoginStatusEnum loginStatusEnum, final String message) {
// 优化一下这个类
final UserAgent userAgent = UserAgent.parseUserAgentString(
ServletHolderUtil.getRequest().getHeader("User-Agent"));
ServletHolderUtil.getRequest().getHeader("User-Agent"));
// 获取客户端浏览器
final String browser = userAgent.getBrowser() != null ? userAgent.getBrowser().getName() : "";
final String ip = ServletUtil.getClientIP(ServletHolderUtil.getRequest());
@@ -44,7 +44,7 @@ public class AsyncTaskFactory {
final String os = userAgent.getOperatingSystem() != null ? userAgent.getOperatingSystem().getName() : "";
log.info("ip: {}, address: {}, username: {}, loginStatusEnum: {}, message: {}", ip, address, username,
loginStatusEnum, message);
loginStatusEnum, message);
return () -> {
// 封装对象
SysLoginInfoEntity loginInfo = new SysLoginInfoEntity();

View File

@@ -1,14 +1,8 @@
package com.agileboot.admin.customize.config;
import com.agileboot.admin.customize.service.login.TokenService;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.login.TokenService;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -17,9 +11,16 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* token过滤器 验证token有效性
* 继承OncePerRequestFilter类的话 可以确保只执行filter一次 避免执行多次
*
* @author valarchie
*/
@Component
@@ -31,7 +32,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
throws ServletException, IOException {
SystemLoginUser loginUser = tokenService.getLoginUser(request);
if (loginUser != null && AuthenticationUtils.getAuthentication() == null) {
tokenService.refreshToken(loginUser);
@@ -46,7 +47,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private void putCurrentLoginUserIntoContext(HttpServletRequest request, SystemLoginUser loginUser) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(loginUser,
null, loginUser.getAuthorities());
null, loginUser.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}

View File

@@ -1,18 +1,18 @@
package com.agileboot.admin.customize.config;
import cn.hutool.json.JSONUtil;
import com.agileboot.admin.customize.async.AsyncTaskFactory;
import com.agileboot.admin.customize.service.login.LoginService;
import com.agileboot.admin.customize.service.login.TokenService;
import com.agileboot.admin.customize.service.login.UserDetailsServiceImpl;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode.Client;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.domain.common.cache.RedisCacheService;
import com.agileboot.admin.customize.async.AsyncTaskFactory;
import com.agileboot.infrastructure.thread.ThreadPoolManager;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.login.TokenService;
import com.agileboot.common.enums.common.LoginStatusEnum;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,12 +34,13 @@ import org.springframework.web.filter.CorsFilter;
/**
* 主要配置登录流程逻辑涉及以下几个类
*
* @author valarchie
* @see UserDetailsServiceImpl#loadUserByUsername 用于登录流程通过用户名加载用户
* @see this#unauthorizedHandler() 用于用户未授权或登录失败处理
* @see this#logOutSuccessHandler 用于退出登录成功后的逻辑
* @see JwtAuthenticationTokenFilter#doFilter token的校验和刷新
* @see LoginService#login 登录逻辑
* @author valarchie
*/
@Configuration
@EnableWebSecurity
@@ -72,7 +73,7 @@ public class SecurityConfig {
public AuthenticationEntryPoint unauthorizedHandler() {
return (request, response, exception) -> {
ResponseDTO<Object> responseDTO = ResponseDTO.fail(
new ApiException(Client.COMMON_NO_AUTHORIZATION, request.getRequestURI())
new ApiException(Client.COMMON_NO_AUTHORIZATION, request.getRequestURI())
);
ServletHolderUtil.renderString(response, JSONUtil.toJsonStr(responseDTO));
};
@@ -80,8 +81,8 @@ public class SecurityConfig {
/**
* 退出成功处理类 返回成功
* 在SecurityConfig类当中 定义了/logout 路径对应处理逻辑
* 退出成功处理类 返回成功
* 在SecurityConfig类当中 定义了/logout 路径对应处理逻辑
*/
@Bean
public LogoutSuccessHandler logOutSuccessHandler() {
@@ -93,7 +94,7 @@ public class SecurityConfig {
redisCache.loginUserCache.delete(loginUser.getCachedKey());
// 记录用户退出日志
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(
userName, LoginStatusEnum.LOGOUT, LoginStatusEnum.LOGOUT.description()));
userName, LoginStatusEnum.LOGOUT, LoginStatusEnum.LOGOUT.description()));
}
ServletHolderUtil.renderString(response, JSONUtil.toJsonStr(ResponseDTO.ok()));
};
@@ -110,47 +111,48 @@ public class SecurityConfig {
/**
* 鉴权管理类
*
* @see UserDetailsServiceImpl#loadUserByUsername
*/
@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder())
.and()
.build();
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder())
.and()
.build();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// CSRF禁用因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler()).and()
// 基于token所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 以及公共Api的请求允许匿名访问
// 注意: 当携带token请求以下这几个接口时 会返回403的错误
.antMatchers("/login", "/register", "/getConfig", "/captchaImage", "/api/**").anonymous()
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js",
"/profile/**").permitAll()
// TODO this is danger.
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs","/*/api-docs/swagger-config").anonymous()
.antMatchers("/**/api-docs.yaml" ).anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
// 禁用 X-Frame-Options 响应头。下面是具体解释:
// X-Frame-Options 是一个 HTTP 响应头,用于防止网页被嵌入到其他网页的 <frame>、<iframe> 或 <object> 标签中,从而可以减少点击劫持攻击的风险
.headers().frameOptions().disable();
// CSRF禁用因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler()).and()
// 基于token所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 以及公共Api的请求允许匿名访问
// 注意: 当携带token请求以下这几个接口时 会返回403的错误
.antMatchers("/login", "/register", "/getConfig", "/captchaImage", "/api/**").anonymous()
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js",
"/profile/**").permitAll()
// TODO this is danger.
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs", "/*/api-docs/swagger-config").anonymous()
.antMatchers("/**/api-docs.yaml").anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
// 禁用 X-Frame-Options 响应头。下面是具体解释:
// X-Frame-Options 是一个 HTTP 响应头,用于防止网页被嵌入到其他网页的 <frame>、<iframe> 或 <object> 标签中,从而可以减少点击劫持攻击的风险
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logOutSuccessHandler());
// 添加JWT filter 需要一开始就通过token识别出登录用户 并放到上下文中 所以jwtFilter需要放前面
httpSecurity.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);

View File

@@ -10,8 +10,14 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.extra.servlet.ServletUtil;
import com.agileboot.admin.customize.async.AsyncTaskFactory;
import com.agileboot.admin.customize.service.login.command.LoginCommand;
import com.agileboot.admin.customize.service.login.dto.CaptchaDTO;
import com.agileboot.admin.customize.service.login.dto.ConfigDTO;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants.Captcha;
import com.agileboot.common.enums.common.ConfigKeyEnum;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.exception.error.ErrorCode.Business;
@@ -20,19 +26,10 @@ import com.agileboot.common.utils.i18n.MessageUtils;
import com.agileboot.domain.common.cache.GuavaCacheService;
import com.agileboot.domain.common.cache.MapCache;
import com.agileboot.domain.common.cache.RedisCacheService;
import com.agileboot.admin.customize.async.AsyncTaskFactory;
import com.agileboot.infrastructure.thread.ThreadPoolManager;
import com.agileboot.admin.customize.service.login.dto.CaptchaDTO;
import com.agileboot.admin.customize.service.login.dto.ConfigDTO;
import com.agileboot.admin.customize.service.login.command.LoginCommand;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.common.enums.common.ConfigKeyEnum;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.infrastructure.thread.ThreadPoolManager;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.google.code.kaptcha.Producer;
import java.awt.image.BufferedImage;
import javax.annotation.Resource;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
@@ -44,6 +41,9 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import javax.annotation.Resource;
import java.awt.image.BufferedImage;
/**
* 登录校验方法
*
@@ -85,10 +85,10 @@ public class LoginService {
try {
// 该方法会去调用UserDetailsServiceImpl#loadUserByUsername 校验用户名和密码 认证鉴权
authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
loginCommand.getUsername(), decryptPassword));
loginCommand.getUsername(), decryptPassword));
} catch (BadCredentialsException e) {
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(loginCommand.getUsername(), LoginStatusEnum.LOGIN_FAIL,
MessageUtils.message("Business.LOGIN_WRONG_USER_PASSWORD")));
MessageUtils.message("Business.LOGIN_WRONG_USER_PASSWORD")));
throw new ApiException(e, ErrorCode.Business.LOGIN_WRONG_USER_PASSWORD);
} catch (AuthenticationException e) {
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(loginCommand.getUsername(), LoginStatusEnum.LOGIN_FAIL, e.getMessage()));
@@ -175,8 +175,8 @@ public class LoginService {
/**
* 校验验证码
*
* @param username 用户名
* @param captchaCode 验证码
* @param username 用户名
* @param captchaCode 验证码
* @param captchaCodeKey 验证码对应的缓存key
*/
public void validateCaptcha(String username, String captchaCode, String captchaCodeKey) {
@@ -184,23 +184,24 @@ public class LoginService {
redisCache.captchaCache.delete(captchaCodeKey);
if (captcha == null) {
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(username, LoginStatusEnum.LOGIN_FAIL,
ErrorCode.Business.LOGIN_CAPTCHA_CODE_EXPIRE.message()));
ErrorCode.Business.LOGIN_CAPTCHA_CODE_EXPIRE.message()));
throw new ApiException(ErrorCode.Business.LOGIN_CAPTCHA_CODE_EXPIRE);
}
if (!captchaCode.equalsIgnoreCase(captcha)) {
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(username, LoginStatusEnum.LOGIN_FAIL,
ErrorCode.Business.LOGIN_CAPTCHA_CODE_WRONG.message()));
ErrorCode.Business.LOGIN_CAPTCHA_CODE_WRONG.message()));
throw new ApiException(ErrorCode.Business.LOGIN_CAPTCHA_CODE_WRONG);
}
}
/**
* 记录登录信息
*
* @param loginUser 登录用户
*/
public void recordLoginInfo(SystemLoginUser loginUser) {
ThreadPoolManager.execute(AsyncTaskFactory.loginInfoTask(loginUser.getUsername(), LoginStatusEnum.LOGIN_SUCCESS,
LoginStatusEnum.LOGIN_SUCCESS.description()));
LoginStatusEnum.LOGIN_SUCCESS.description()));
SysUserEntity entity = redisCache.userCache.getObjectById(loginUser.getUserId());
@@ -211,7 +212,7 @@ public class LoginService {
public String decryptPassword(String originalPassword) {
byte[] decryptBytes = SecureUtil.rsa(AgileBootConfig.getRsaPrivateKey(), null)
.decrypt(Base64.decode(originalPassword), KeyType.PrivateKey);
.decrypt(Base64.decode(originalPassword), KeyType.PrivateKey);
return StrUtil.str(decryptBytes, CharsetUtil.CHARSET_UTF_8);
}

View File

@@ -8,22 +8,17 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.common.cache.RedisCacheService;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import io.jsonwebtoken.*;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* token验证处理
*
@@ -72,7 +67,8 @@ public class TokenService {
String uuid = (String) claims.get(Token.LOGIN_USER_KEY);
return redisCache.loginUserCache.getObjectOnlyInCacheById(uuid);
} catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException jwtException) {
} catch (SignatureException | MalformedJwtException | UnsupportedJwtException |
IllegalArgumentException jwtException) {
log.error("parse token failed.", jwtException);
throw new ApiException(jwtException, ErrorCode.Client.INVALID_TOKEN);
} catch (Exception e) {
@@ -100,6 +96,7 @@ public class TokenService {
/**
* 当超过20分钟自动刷新token
*
* @param loginUser 登录用户
*/
public void refreshToken(SystemLoginUser loginUser) {
@@ -120,8 +117,8 @@ public class TokenService {
*/
private String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact();
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
/**
@@ -132,9 +129,9 @@ public class TokenService {
*/
private Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
/**

View File

@@ -2,27 +2,21 @@ package com.agileboot.admin.customize.service.login;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.UserStatusEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.infrastructure.user.web.DataScopeEnum;
import com.agileboot.common.enums.common.UserStatusEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.domain.system.menu.db.SysMenuEntity;
import com.agileboot.domain.system.role.db.SysRoleEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.menu.db.SysMenuService;
import com.agileboot.domain.system.role.db.SysRoleEntity;
import com.agileboot.domain.system.role.db.SysRoleService;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.user.db.SysUserService;
import com.agileboot.infrastructure.user.web.DataScopeEnum;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.SetUtils;
@@ -32,12 +26,19 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 自定义加载用户信息通过用户名
* 用于SpringSecurity 登录流程
* 没有办法把这个类 放进loginService中 会在SecurityConfig中造成循环依赖
* @see com.agileboot.infrastructure.config.SecurityConfig#filterChain(HttpSecurity)
*
* @author valarchie
* @see com.agileboot.infrastructure.config.SecurityConfig#filterChain(HttpSecurity)
*/
@Service
@Slf4j
@@ -68,10 +69,10 @@ public class UserDetailsServiceImpl implements UserDetailsService {
RoleInfo roleInfo = getRoleInfo(userEntity.getRoleId(), userEntity.getIsAdmin());
SystemLoginUser loginUser = new SystemLoginUser(userEntity.getUserId(), userEntity.getIsAdmin(), userEntity.getUsername(),
userEntity.getPassword(), roleInfo, userEntity.getDeptId());
userEntity.getPassword(), roleInfo, userEntity.getDeptId());
loginUser.fillLoginInfo();
loginUser.setAutoRefreshCacheTime(loginUser.getLoginInfo().getLoginTime()
+ TimeUnit.MINUTES.toMillis(tokenService.getAutoRefreshTime()));
+ TimeUnit.MINUTES.toMillis(tokenService.getAutoRefreshTime()));
return loginUser;
}
@@ -88,7 +89,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
Set<Long> allMenuIds = allMenus.stream().map(SysMenuEntity::getMenuId).collect(Collectors.toSet());
return new RoleInfo(RoleInfo.ADMIN_ROLE_ID, RoleInfo.ADMIN_ROLE_KEY, DataScopeEnum.ALL, SetUtils.emptySet(),
RoleInfo.ADMIN_PERMISSIONS, allMenuIds);
RoleInfo.ADMIN_PERMISSIONS, allMenuIds);
}
@@ -108,7 +109,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
Set<Long> deptIdSet = SetUtils.emptySet();
if (StrUtil.isNotEmpty(roleEntity.getDeptIdSet())) {
deptIdSet = StrUtil.split(roleEntity.getDeptIdSet(), ",").stream()
.map(Convert::toLong).collect(Collectors.toSet());
.map(Convert::toLong).collect(Collectors.toSet());
}
return new RoleInfo(roleId, roleEntity.getRoleKey(), dataScopeEnum, deptIdSet, permissions, menuIds);

View File

@@ -1,9 +1,10 @@
package com.agileboot.admin.customize.service.login.dto;
import com.agileboot.common.enums.dictionary.DictionaryData;
import lombok.Data;
import java.util.List;
import java.util.Map;
import lombok.Data;
/**
* @author valarchie

View File

@@ -2,20 +2,17 @@ package com.agileboot.admin.customize.service.permission;
import cn.hutool.extra.spring.SpringUtil;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.checker.AllDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.checker.CustomDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.checker.DefaultDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.checker.DeptTreeDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.checker.OnlySelfDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.checker.SingleDeptDataPermissionChecker;
import com.agileboot.infrastructure.user.web.DataScopeEnum;
import com.agileboot.admin.customize.service.permission.model.checker.*;
import com.agileboot.domain.system.dept.db.SysDeptService;
import javax.annotation.PostConstruct;
import com.agileboot.infrastructure.user.web.DataScopeEnum;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* 数据权限检测器工厂
*
* @author valarchie
*/
@Component

View File

@@ -3,17 +3,18 @@ package com.agileboot.admin.customize.service.permission;
import cn.hutool.core.collection.CollUtil;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.user.db.SysUserService;
import java.util.List;
import lombok.NonNull;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 数据权限校验服务
*
* @author valarchie
*/
@Service("dataScope")
@@ -39,6 +40,7 @@ public class DataPermissionService {
/**
* 通过userId 校验当前用户 对 目标用户是否有操作权限
*
* @param userIds 用户id列表
* @return 校验结果
*/
@@ -67,5 +69,4 @@ public class DataPermissionService {
}
}

View File

@@ -3,13 +3,13 @@ package com.agileboot.admin.customize.service.permission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import java.util.Set;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
*
* @author valarchie
*/
@Service("permission")
@@ -38,7 +38,7 @@ public class MenuPermissionService {
* 判断是否包含权限
*
* @param permissions 权限列表
* @param permission 权限字符串
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
private boolean has(Set<String> permissions, String permission) {

View File

@@ -1,11 +1,12 @@
package com.agileboot.admin.customize.service.permission.model;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.Data;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@Data

View File

@@ -1,14 +1,15 @@
package com.agileboot.admin.customize.service.permission.model.checker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,18 +1,20 @@
package com.agileboot.admin.customize.service.permission.model.checker;
import cn.hutool.core.collection.CollUtil;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import java.util.Set;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,14 +1,15 @@
package com.agileboot.admin.customize.service.permission.model.checker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,17 +1,19 @@
package com.agileboot.admin.customize.service.permission.model.checker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import java.util.Objects;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,17 +1,19 @@
package com.agileboot.admin.customize.service.permission.model.checker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import java.util.Objects;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,17 +1,19 @@
package com.agileboot.admin.customize.service.permission.model.checker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.AbstractDataPermissionChecker;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import java.util.Objects;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* 数据权限测试接口
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)

View File

@@ -1,105 +1,105 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: agileboot
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic:
primary: master
strict: false
druid:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
datasource:
# 主库数据源
master:
url: jdbc:mysql://localhost:33067/agileboot-pure?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 12345
# 从库数据源
# slave:
# url: jdbc:mysql://localhost:33067/agileboot2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: root
# password: 12345
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: agileboot
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic:
primary: master
strict: false
druid:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
datasource:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/agileboot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
# 从库数据源
# slave:
# url: jdbc:mysql://localhost:33067/agileboot2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: root
# password: 12345
# redis 配置
redis:
# 地址
host: localhost
# 端口默认为6379
port: 36379
# 数据库索引
database: 0
# 密码
password: 12345
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# redis 配置
redis:
# 地址
host: localhost
# 端口默认为6379
port: 63795
# 数据库索引
database: 0
# 密码
password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
logging:
file:
path: D:/logs/agileboot-dev
file:
path: F:/logs/agileboot-dev
springdoc:
swagger-ui:
# ***注意*** 开启Swagger UI界面 **安全考虑的话生产环境需要关掉**
# 因为knife4j的一些配置不灵活 所以重新改回springdoc+swagger的组合 真实开发的时候 使用apifox这种工具效率更高
enabled: true
url: ${agileboot.api-prefix}/v3/api-docs
config-url: ${agileboot.api-prefix}/v3/api-docs/swagger-config
swagger-ui:
# ***注意*** 开启Swagger UI界面 **安全考虑的话生产环境需要关掉**
# 因为knife4j的一些配置不灵活 所以重新改回springdoc+swagger的组合 真实开发的时候 使用apifox这种工具效率更高
enabled: true
url: ${agileboot.api-prefix}/v3/api-docs
config-url: ${agileboot.api-prefix}/v3/api-docs/swagger-config
# 项目相关配置
agileboot:
# 文件基路径 示例( Windows配置D:\agilebootLinux配置 /home/agileboot
file-base-dir: D:\agileboot
# 前端url请求转发前缀
api-prefix: /dev-api
demo-enabled: false
# 文件基路径 示例( Windows配置D:\agilebootLinux配置 /home/agileboot
file-base-dir: D:\agileboot
# 前端url请求转发前缀
api-prefix: /dev-api
demo-enabled: false

View File

@@ -1,53 +1,52 @@
# 数据源配置
spring:
datasource:
# 驱动
driver-class-name: org.h2.Driver
dynamic:
primary: master
strict: false
datasource:
master:
# h2 内存数据库 内存模式连接配置 库名: agileboot
url: jdbc:h2:mem:agileboot;DB_CLOSE_DELAY=-1
h2:
# 开启console 访问 默认false
console:
enabled: true
settings:
# 开启h2 console 跟踪 方便调试 默认 false
trace: true
# 允许console 远程访问 默认false
web-allow-others: true
# h2 访问路径上下文
path: /h2-console
datasource:
# 驱动
driver-class-name: org.h2.Driver
dynamic:
primary: master
strict: false
datasource:
master:
# h2 内存数据库 内存模式连接配置 库名: agileboot
url: jdbc:h2:mem:agileboot;DB_CLOSE_DELAY=-1;MODE=MySQL
h2:
# 开启console 访问 默认false
console:
enabled: true
settings:
# 开启h2 console 跟踪 方便调试 默认 false
trace: true
# 允许console 远程访问 默认false
web-allow-others: true
# h2 访问路径上下文
path: /h2-console
sql:
init:
platform: mysql
# 初始化数据
schema-locations: classpath:h2sql/agileboot_schema.sql
data-locations: classpath:h2sql/agileboot_data.sql
sql:
init:
platform: mysql
# 初始化数据
schema-locations: classpath:h2sql/agileboot_schema.sql
data-locations: classpath:h2sql/agileboot_data.sql
# redis 配置
redis:
# 地址
host: localhost
# 端口默认为6379
port: 36379
# 数据库索引
database: 0
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# redis 配置
redis:
# 地址
host: localhost
# 端口默认为6379
port: 36379
# 数据库索引
database: 0
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms

View File

@@ -4,14 +4,15 @@ package com.agileboot.admin.config;
import com.agileboot.admin.AgileBootAdminApplication;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants.UploadSubDir;
import java.io.File;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.io.File;
@SpringBootTest(classes = AgileBootAdminApplication.class)
@RunWith(SpringRunner.class)
public class AgileBootConfigTest {
@@ -24,21 +25,21 @@ public class AgileBootConfigTest {
String fileBaseDir = "D:\\agileboot\\profile";
Assertions.assertEquals("AgileBoot", config.getName());
Assertions.assertEquals("1.0.0", config.getVersion());
Assertions.assertEquals("1.8.0", config.getVersion());
Assertions.assertEquals("2022", config.getCopyrightYear());
Assertions.assertTrue(config.isDemoEnabled());
Assertions.assertFalse(config.isDemoEnabled());
Assertions.assertEquals(fileBaseDir, AgileBootConfig.getFileBaseDir());
Assertions.assertFalse(AgileBootConfig.isAddressEnabled());
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
Assertions.assertEquals(fileBaseDir + "\\import",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.IMPORT_PATH);
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.IMPORT_PATH);
Assertions.assertEquals(fileBaseDir + "\\avatar",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.AVATAR_PATH);
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.AVATAR_PATH);
Assertions.assertEquals(fileBaseDir + "\\download",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.DOWNLOAD_PATH);
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.DOWNLOAD_PATH);
Assertions.assertEquals(fileBaseDir + "\\upload",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.UPLOAD_PATH);
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.UPLOAD_PATH);
}
}

View File

@@ -1,19 +1,19 @@
package com.agileboot.admin.customize.service.permission;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.admin.customize.service.permission.model.checker.CustomDataPermissionChecker;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import org.apache.commons.collections4.SetUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.agileboot.admin.customize.service.permission.model.checker.CustomDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.apache.commons.collections4.SetUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CustomDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
@@ -26,15 +26,15 @@ class CustomDataPermissionCheckerTest {
@Test
void testCheckWhenParameterNull() {
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
boolean check1 = customChecker.check(null, null);
boolean check2 = customChecker.check(loginUser, null);
boolean check3 = customChecker.check(null, new DataCondition());
boolean check1 = customChecker.check(null, null);
boolean check2 = customChecker.check(loginUser, null);
boolean check3 = customChecker.check(null, new DataCondition());
assertFalse(check1);
assertFalse(check2);
assertFalse(check3);
assertFalse(check1);
assertFalse(check2);
assertFalse(check3);
}
@Test

View File

@@ -1,19 +1,19 @@
package com.agileboot.admin.customize.service.permission;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.admin.customize.service.permission.model.checker.DeptTreeDataPermissionChecker;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.agileboot.admin.customize.service.permission.model.checker.DeptTreeDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class DeptTreeDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
@@ -87,6 +87,4 @@ class DeptTreeDataPermissionCheckerTest {
}
}

View File

@@ -1,18 +1,18 @@
package com.agileboot.admin.customize.service.permission;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.admin.customize.service.permission.model.checker.SingleDeptDataPermissionChecker;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.agileboot.admin.customize.service.permission.model.checker.SingleDeptDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class SingleDeptDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
@@ -66,7 +66,4 @@ class SingleDeptDataPermissionCheckerTest {
}
}

View File

@@ -5,7 +5,6 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode.Client;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.common.utils.jackson.JacksonUtil;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@@ -15,7 +15,6 @@ import io.jsonwebtoken.UnsupportedJwtException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

View File

@@ -141,11 +141,6 @@
<artifactId>ip2region</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
</dependency>
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>embedded-redis</artifactId>
@@ -182,6 +177,13 @@
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<!--ENC加密-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- swagger注解 -->
<dependency>
<groupId>io.swagger</groupId>

View File

@@ -1,11 +1,11 @@
package com.agileboot.common.core.page;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import javax.validation.constraints.Max;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.Max;
/**
* @author valarchie
*/
@@ -13,15 +13,31 @@ import javax.validation.constraints.Max;
@Data
public abstract class AbstractPageQuery<T> extends AbstractQuery<T> {
/**
* 最大分页页数
*/
public static final int MAX_PAGE_NUM = 200;
/**
* 单页最大大小
*/
public static final int MAX_PAGE_SIZE = 500;
/**
* 默认分页页数
*/
public static final int DEFAULT_PAGE_NUM = 1;
/**
* 默认分页大小
*/
public static final int DEFAULT_PAGE_SIZE = 10;
@Max(MAX_PAGE_NUM)
protected Integer pageNum = 1;
protected Integer pageNum;
@Max(MAX_PAGE_SIZE)
protected Integer pageSize = 10;
protected Integer pageSize;
public Page<T> toPage() {
pageNum = ObjectUtil.defaultIfNull(pageNum, DEFAULT_PAGE_NUM);
pageSize = ObjectUtil.defaultIfNull(pageSize, DEFAULT_PAGE_SIZE);
return new Page<>(pageNum, pageSize);
}

View File

@@ -82,6 +82,10 @@ public class JacksonUtil {
}
}
private JacksonUtil() {
throw new IllegalStateException("Utility class JacksonUtil can not be instantiated");
}
public static ObjectMapper initMapper() {
JsonMapper.Builder builder = JsonMapper.builder()
.enable(JSON_READ_FEATURES_ENABLED.toArray(new JsonReadFeature[0]));

View File

@@ -48,7 +48,7 @@ public class CustomExcelUtil {
public static <T> void writeToOutputStream(List<T> list, Class<T> clazz, OutputStream outputStream) {
// 通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter();
ExcelWriter writer = ExcelUtil.getWriter(true);
ExcelSheet sheetAnno = clazz.getAnnotation(ExcelSheet.class);

View File

@@ -18,12 +18,6 @@
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>agileboot-common</artifactId>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>agileboot-infrastructure</artifactId>

View File

@@ -1,20 +1,22 @@
package com.agileboot.domain.common.cache;
import cn.hutool.extra.spring.SpringUtil;
import com.agileboot.infrastructure.cache.guava.AbstractGuavaCacheTemplate;
import com.agileboot.infrastructure.cache.redis.RedisCacheTemplate;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import com.agileboot.domain.system.post.db.SysPostEntity;
import com.agileboot.domain.system.role.db.SysRoleEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import javax.annotation.PostConstruct;
import com.agileboot.infrastructure.cache.guava.AbstractGuavaCacheTemplate;
import com.agileboot.infrastructure.cache.redis.RedisCacheTemplate;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* 缓存中心 提供全局访问点
* 如果是领域类的缓存 可以自己新建一个直接放在CacheCenter 不用放在infrastructure包里的GuavaCacheService
* 或者RedisCacheService
*
* @author valarchie
*/
@Component

View File

@@ -5,7 +5,6 @@ import com.agileboot.infrastructure.cache.guava.AbstractGuavaCacheTemplate;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import com.agileboot.domain.system.config.db.SysConfigService;
import com.agileboot.domain.system.dept.db.SysDeptService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

View File

@@ -3,18 +3,9 @@ package com.agileboot.domain.common.cache;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.enums.common.GenderEnum;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.common.enums.common.NoticeStatusEnum;
import com.agileboot.common.enums.common.NoticeTypeEnum;
import com.agileboot.common.enums.common.OperationStatusEnum;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.common.enums.common.UserStatusEnum;
import com.agileboot.common.enums.common.VisibleStatusEnum;
import com.agileboot.common.enums.common.YesOrNoEnum;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.enums.common.*;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.dictionary.DictionaryData;
import java.util.Arrays;
@@ -73,7 +64,7 @@ public class MapCache {
@SuppressWarnings("rawtypes")
private static List<DictionaryData> arrayToList(DictionaryEnum[] dictionaryEnums) {
if(ArrayUtil.isEmpty(dictionaryEnums)) {
if (ArrayUtil.isEmpty(dictionaryEnums)) {
return ListUtil.empty();
}
return Arrays.stream(dictionaryEnums).map(DictionaryData::new).collect(Collectors.toList());

View File

@@ -1,22 +1,22 @@
package com.agileboot.domain.common.cache;
import cn.hutool.extra.spring.SpringUtil;
import com.agileboot.domain.system.post.db.SysPostEntity;
import com.agileboot.domain.system.post.db.SysPostService;
import com.agileboot.domain.system.role.db.SysRoleEntity;
import com.agileboot.domain.system.role.db.SysRoleService;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.user.db.SysUserService;
import com.agileboot.infrastructure.cache.RedisUtil;
import com.agileboot.infrastructure.cache.redis.CacheKeyEnum;
import com.agileboot.infrastructure.cache.redis.RedisCacheTemplate;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.domain.system.post.db.SysPostEntity;
import com.agileboot.domain.system.role.db.SysRoleEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.post.db.SysPostService;
import com.agileboot.domain.system.role.db.SysRoleService;
import com.agileboot.domain.system.user.db.SysUserService;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.Serializable;
/**
* @author valarchie
*/

View File

@@ -3,12 +3,12 @@ package com.agileboot.domain.common.command;
import cn.hutool.core.collection.CollUtil;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import lombok.Data;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.Data;
/**
* @author valarchie
*/

View File

@@ -1,9 +1,10 @@
package com.agileboot.domain.common.dto;
import com.agileboot.domain.system.user.dto.UserDTO;
import java.util.Set;
import lombok.Data;
import java.util.Set;
/**
* @author valarchie
*/

View File

@@ -1,10 +1,11 @@
package com.agileboot.domain.common.dto;
import cn.hutool.core.lang.tree.Tree;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author valarchie
*/

View File

@@ -3,19 +3,19 @@ package com.agileboot.domain.system.config;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.system.config.command.ConfigUpdateCommand;
import com.agileboot.domain.system.config.db.SysConfigEntity;
import com.agileboot.domain.system.config.db.SysConfigService;
import com.agileboot.domain.system.config.dto.ConfigDTO;
import com.agileboot.domain.system.config.model.ConfigModel;
import com.agileboot.domain.system.config.model.ConfigModelFactory;
import com.agileboot.domain.system.config.query.ConfigQuery;
import com.agileboot.domain.system.config.db.SysConfigEntity;
import com.agileboot.domain.system.config.db.SysConfigService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author valarchie
*/

View File

@@ -1,10 +1,11 @@
package com.agileboot.domain.system.config.command;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import lombok.Data;
/**
* @author valarchie

View File

@@ -7,10 +7,11 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* <p>
* 参数配置表

View File

@@ -15,7 +15,7 @@ import org.springframework.stereotype.Service;
*/
@Service
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfigEntity> implements
SysConfigService {
SysConfigService {
@Override
public String getConfigValueByKey(String key) {

View File

@@ -3,13 +3,14 @@ package com.agileboot.domain.system.config.dto;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.enums.common.YesOrNoEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.YesOrNoEnum;
import com.agileboot.domain.system.config.db.SysConfigEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
import java.util.List;
import lombok.Data;
/**
* @author valarchie
@@ -25,8 +26,8 @@ public class ConfigDTO {
configKey = entity.getConfigKey();
configValue = entity.getConfigValue();
configOptions =
JSONUtil.isTypeJSONArray(entity.getConfigOptions()) ? JSONUtil.toList(entity.getConfigOptions(),
String.class) : ListUtil.empty();
JSONUtil.isTypeJSONArray(entity.getConfigOptions()) ? JSONUtil.toList(entity.getConfigOptions(),
String.class) : ListUtil.empty();
isAllowChange = Convert.toInt(entity.getIsAllowChange());
isAllowChangeStr = BasicEnumUtil.getDescriptionByBool(YesOrNoEnum.class, entity.getIsAllowChange());
remark = entity.getRemark();

View File

@@ -9,11 +9,12 @@ import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.system.config.command.ConfigUpdateCommand;
import com.agileboot.domain.system.config.db.SysConfigEntity;
import com.agileboot.domain.system.config.db.SysConfigService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author valarchie
@@ -34,8 +35,8 @@ public class ConfigModel extends SysConfigEntity {
BeanUtil.copyProperties(entity, this);
List<String> options =
JSONUtil.isTypeJSONArray(entity.getConfigOptions()) ? JSONUtil.toList(entity.getConfigOptions(),
String.class) : ListUtil.empty();
JSONUtil.isTypeJSONArray(entity.getConfigOptions()) ? JSONUtil.toList(entity.getConfigOptions(),
String.class) : ListUtil.empty();
this.configOptionSet = new HashSet<>(options);

View File

@@ -4,12 +4,12 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.system.config.db.SysConfigEntity;
import com.agileboot.domain.system.config.db.SysConfigService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 配置模型工厂
*
* @author valarchie
*/
@Component

View File

@@ -31,9 +31,9 @@ public class ConfigQuery extends AbstractPageQuery<SysConfigEntity> {
@Override
public QueryWrapper<SysConfigEntity> addQueryCondition() {
QueryWrapper<SysConfigEntity> queryWrapper = new QueryWrapper<SysConfigEntity>()
.like(StrUtil.isNotEmpty(configName), "config_name", configName)
.eq(StrUtil.isNotEmpty(configKey), "config_key", configKey)
.eq(isAllowChange != null, "is_allow_change", isAllowChange);
.like(StrUtil.isNotEmpty(configName), "config_name", configName)
.eq(StrUtil.isNotEmpty(configKey), "config_key", configKey)
.eq(isAllowChange != null, "is_allow_change", isAllowChange);
this.timeRangeColumn = "create_time";

View File

@@ -4,21 +4,22 @@ import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import com.agileboot.domain.system.dept.command.AddDeptCommand;
import com.agileboot.domain.system.dept.command.UpdateDeptCommand;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.domain.system.dept.dto.DeptDTO;
import com.agileboot.domain.system.dept.model.DeptModel;
import com.agileboot.domain.system.dept.model.DeptModelFactory;
import com.agileboot.domain.system.dept.query.DeptQuery;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import com.agileboot.domain.system.dept.db.SysDeptService;
import com.agileboot.domain.system.role.db.SysRoleService;
import java.util.List;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* 部门服务
*
* @author valarchie
*/
@Service
@@ -85,5 +86,4 @@ public class DeptApplicationService {
}
}

View File

@@ -1,12 +1,9 @@
package com.agileboot.domain.system.dept.command;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import javax.validation.constraints.Size;
import lombok.Data;
import javax.validation.constraints.*;
/**
* @author valarchie
*/

View File

@@ -1,9 +1,10 @@
package com.agileboot.domain.system.dept.command;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author valarchie

View File

@@ -7,10 +7,11 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* <p>
* 部门表

View File

@@ -25,7 +25,8 @@ public interface SysDeptService extends IService<SysDeptEntity> {
/**
* 检测部门底下是否还有正在使用中的子部门
* @param deptId 部门id
*
* @param deptId 部门id
* @param enabled 部门是否开启
* @return 结果
*/
@@ -33,14 +34,16 @@ public interface SysDeptService extends IService<SysDeptEntity> {
/**
* 是否是目标部门的子部门
*
* @param parentId 目标部门id
* @param childId 子部门id
* @param childId 子部门id
* @return 校验结果
*/
boolean isChildOfTheDept(Long parentId, Long childId);
/**
* 检测该部门是否已有用户使用
*
* @param deptId 部门id
* @return 校验结果
*/

View File

@@ -4,7 +4,6 @@ import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.user.db.SysUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -27,8 +26,8 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDeptEntity
public boolean isDeptNameDuplicated(String deptName, Long deptId, Long parentId) {
QueryWrapper<SysDeptEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dept_name", deptName)
.ne(deptId != null, "dept_id", deptId)
.eq(parentId != null, "parent_id", parentId);
.ne(deptId != null, "dept_id", deptId)
.eq(parentId != null, "parent_id", parentId);
return this.baseMapper.exists(queryWrapper);
}
@@ -38,9 +37,9 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDeptEntity
public boolean hasChildrenDept(Long deptId, Boolean enabled) {
QueryWrapper<SysDeptEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(enabled != null, "status", 1)
.and(o -> o.eq("parent_id", deptId).or()
.apply("FIND_IN_SET (" + deptId + " , ancestors)")
);
.and(o -> o.eq("parent_id", deptId).or()
.apply("FIND_IN_SET (" + deptId + " , ancestors)")
);
return this.baseMapper.exists(queryWrapper);
}

View File

@@ -1,11 +1,12 @@
package com.agileboot.domain.system.dept.dto;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import java.util.Date;
import lombok.Data;
import java.util.Date;
/**
* @author valarchie
*/

View File

@@ -2,14 +2,15 @@ package com.agileboot.domain.system.dept.model;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.system.dept.command.AddDeptCommand;
import com.agileboot.domain.system.dept.command.UpdateDeptCommand;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import com.agileboot.domain.system.dept.db.SysDeptService;
import java.util.Objects;
/**
@@ -71,19 +72,24 @@ public class DeptModel extends SysDeptEntity {
}
public void generateAncestors() {
if (getParentId() == 0) {
setAncestors(getParentId().toString());
// 处理 getParentId 可能为 null 的情况
if (getParentId() == null || getParentId() == 0) {
setAncestors(String.valueOf(getParentId() == null ? 0 : getParentId()));
return;
}
SysDeptEntity parentDept = deptService.getById(getParentId());
// 检查 parentDept 是否为 null 或者状态为禁用
if (parentDept == null || StatusEnum.DISABLE.equals(
BasicEnumUtil.fromValue(StatusEnum.class, parentDept.getStatus()))) {
BasicEnumUtil.fromValue(StatusEnum.class, parentDept.getStatus()))) {
throw new ApiException(ErrorCode.Business.DEPT_PARENT_DEPT_NO_EXIST_OR_DISABLED);
}
setAncestors(parentDept.getAncestors() + "," + getParentId());
// 处理 parentDept.getAncestors() 可能为 null 的情况
String ancestors = parentDept.getAncestors() == null ? "" : parentDept.getAncestors();
setAncestors(ancestors + "," + getParentId());
}
@@ -92,7 +98,7 @@ public class DeptModel extends SysDeptEntity {
*/
public void checkStatusAllowChange() {
if (StatusEnum.DISABLE.getValue().equals(getStatus()) &&
deptService.hasChildrenDept(getDeptId(), true)) {
deptService.hasChildrenDept(getDeptId(), true)) {
throw new ApiException(ErrorCode.Business.DEPT_STATUS_ID_IS_NOT_ALLOWED_CHANGE);
}

View File

@@ -5,12 +5,12 @@ import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.system.dept.command.AddDeptCommand;
import com.agileboot.domain.system.dept.db.SysDeptEntity;
import com.agileboot.domain.system.dept.db.SysDeptService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 部门模型工厂
*
* @author valarchie
*/
@Component
@@ -42,5 +42,4 @@ public class DeptModelFactory {
}
}

View File

@@ -25,7 +25,7 @@ public class DeptQuery extends AbstractQuery<SysDeptEntity> {
// TODO parentId 这个似乎没使用
return new QueryWrapper<SysDeptEntity>()
// .eq(status != null, "status", status)
.eq(parentId != null, "parent_id", parentId);
.eq(parentId != null, "parent_id", parentId);
// .like(StrUtil.isNotEmpty(deptName), "dept_name", deptName);
// .and(deptId != null && isExcludeCurrentDept, o ->
// o.ne("dept_id", deptId)

View File

@@ -2,22 +2,22 @@ package com.agileboot.domain.system.log;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.system.log.dto.LoginLogDTO;
import com.agileboot.domain.system.log.query.LoginLogQuery;
import com.agileboot.domain.system.log.dto.OperationLogDTO;
import com.agileboot.domain.system.log.dto.OperationLogQuery;
import com.agileboot.domain.system.log.db.SysLoginInfoEntity;
import com.agileboot.domain.system.log.db.SysOperationLogEntity;
import com.agileboot.domain.system.log.db.SysLoginInfoService;
import com.agileboot.domain.system.log.db.SysOperationLogEntity;
import com.agileboot.domain.system.log.db.SysOperationLogService;
import com.agileboot.domain.system.log.dto.LoginLogDTO;
import com.agileboot.domain.system.log.dto.OperationLogDTO;
import com.agileboot.domain.system.log.query.LoginLogQuery;
import com.agileboot.domain.system.log.query.OperationLogQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author valarchie
*/

View File

@@ -1,18 +1,15 @@
package com.agileboot.domain.system.log.db;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 系统访问记录

View File

@@ -13,6 +13,6 @@ import org.springframework.stereotype.Service;
*/
@Service
public class SysLoginInfoServiceImpl extends ServiceImpl<SysLoginInfoMapper, SysLoginInfoEntity> implements
SysLoginInfoService {
SysLoginInfoService {
}

View File

@@ -1,18 +1,15 @@
package com.agileboot.domain.system.log.db;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 操作日志记录

View File

@@ -13,6 +13,6 @@ import org.springframework.stereotype.Service;
*/
@Service
public class SysOperationLogServiceImpl extends ServiceImpl<SysOperationLogMapper, SysOperationLogEntity> implements
SysOperationLogService {
SysOperationLogService {
}

View File

@@ -2,12 +2,13 @@ package com.agileboot.domain.system.log.dto;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.domain.system.log.db.SysLoginInfoEntity;
import java.util.Date;
import lombok.Data;
import java.util.Date;
/**
* @author valarchie
*/

View File

@@ -3,15 +3,16 @@ package com.agileboot.domain.system.log.dto;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.enums.common.OperationStatusEnum;
import com.agileboot.common.enums.common.OperatorTypeEnum;
import com.agileboot.common.enums.common.RequestMethodEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.domain.system.log.db.SysOperationLogEntity;
import java.util.Date;
import lombok.Data;
import java.util.Date;
/**
* @author valarchie
*/
@@ -23,7 +24,7 @@ public class OperationLogDTO {
if (entity != null) {
BeanUtil.copyProperties(entity, this);
this.requestMethod = BasicEnumUtil.getDescriptionByValue(RequestMethodEnum.class,
entity.getRequestMethod());
entity.getRequestMethod());
this.statusStr = BasicEnumUtil.getDescriptionByValue(OperationStatusEnum.class, entity.getStatus());
businessTypeStr = BasicEnumUtil.getDescriptionByValue(BusinessTypeEnum.class, entity.getBusinessType());
operatorTypeStr = BasicEnumUtil.getDescriptionByValue(OperatorTypeEnum.class, entity.getOperatorType());

View File

@@ -22,9 +22,9 @@ public class LoginLogQuery extends AbstractPageQuery<SysLoginInfoEntity> {
@Override
public QueryWrapper<SysLoginInfoEntity> addQueryCondition() {
QueryWrapper<SysLoginInfoEntity> queryWrapper = new QueryWrapper<SysLoginInfoEntity>()
.like(StrUtil.isNotEmpty(ipAddress), "ip_address", ipAddress)
.eq(StrUtil.isNotEmpty(status), "status", status)
.like(StrUtil.isNotEmpty(username), "username", username);
.like(StrUtil.isNotEmpty(ipAddress), "ip_address", ipAddress)
.eq(StrUtil.isNotEmpty(status), "status", status)
.like(StrUtil.isNotEmpty(username), "username", username);
addSortCondition(queryWrapper);

View File

@@ -1,4 +1,4 @@
package com.agileboot.domain.system.log.dto;
package com.agileboot.domain.system.log.query;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.core.page.AbstractPageQuery;
@@ -22,10 +22,10 @@ public class OperationLogQuery extends AbstractPageQuery<SysOperationLogEntity>
@Override
public QueryWrapper<SysOperationLogEntity> addQueryCondition() {
QueryWrapper<SysOperationLogEntity> queryWrapper = new QueryWrapper<SysOperationLogEntity>()
.like(businessType!=null, "business_type", businessType)
.eq(status != null, "status", status)
.like(StrUtil.isNotEmpty(username), "username", username)
.like(StrUtil.isNotEmpty(requestModule), "request_module", requestModule);
.like(businessType != null, "business_type", businessType)
.eq(status != null, "status", status)
.like(StrUtil.isNotEmpty(username), "username", username)
.like(StrUtil.isNotEmpty(requestModule), "request_module", requestModule);
this.timeRangeColumn = "operation_time";

View File

@@ -4,8 +4,11 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.domain.system.menu.command.AddMenuCommand;
import com.agileboot.domain.system.menu.command.UpdateMenuCommand;
import com.agileboot.domain.system.menu.db.SysMenuEntity;
import com.agileboot.domain.system.menu.db.SysMenuService;
import com.agileboot.domain.system.menu.dto.MenuDTO;
import com.agileboot.domain.system.menu.dto.MenuDetailDTO;
import com.agileboot.domain.system.menu.dto.RouterDTO;
@@ -13,19 +16,17 @@ import com.agileboot.domain.system.menu.model.MenuModel;
import com.agileboot.domain.system.menu.model.MenuModelFactory;
import com.agileboot.domain.system.menu.query.MenuQuery;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.domain.system.menu.db.SysMenuEntity;
import com.agileboot.domain.system.menu.db.SysMenuService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 菜单应用服务
*
* @author valarchie
*/
@Service
@@ -40,8 +41,8 @@ public class MenuApplicationService {
public List<MenuDTO> getMenuList(MenuQuery query) {
List<SysMenuEntity> list = menuService.list(query.toQueryWrapper());
return list.stream().map(MenuDTO::new)
.sorted(Comparator.comparing(MenuDTO::getRank, Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
.sorted(Comparator.comparing(MenuDTO::getRank, Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
}
public MenuDetailDTO getMenuInfo(Long menuId) {
@@ -51,7 +52,7 @@ public class MenuApplicationService {
public List<Tree<Long>> getDropdownList(SystemLoginUser loginUser) {
List<SysMenuEntity> menuEntityList =
loginUser.isAdmin() ? menuService.list() : menuService.getMenuListByUserId(loginUser.getUserId());
loginUser.isAdmin() ? menuService.list() : menuService.getMenuListByUserId(loginUser.getUserId());
return buildMenuTreeSelect(menuEntityList);
}
@@ -124,9 +125,9 @@ public class MenuApplicationService {
// 传给前端的路由排除掉按钮和停用的菜单
List<SysMenuEntity> noButtonMenus = allMenus.stream()
.filter(menu -> !menu.getIsButton())
.filter(menu-> StatusEnum.ENABLE.getValue().equals(menu.getStatus()))
.collect(Collectors.toList());
.filter(menu -> !menu.getIsButton())
.filter(menu -> StatusEnum.ENABLE.getValue().equals(menu.getStatus()))
.collect(Collectors.toList());
TreeNodeConfig config = new TreeNodeConfig();
// 默认为id 可以不设置

View File

@@ -1,11 +1,11 @@
package com.agileboot.domain.system.menu.command;
import com.agileboot.domain.system.menu.dto.MetaDTO;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* @author valarchie
*/

View File

@@ -1,9 +1,10 @@
package com.agileboot.domain.system.menu.command;
import javax.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
/**
* @author valarchie
*/

View File

@@ -5,12 +5,13 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* <p>
* 菜单权限表

View File

@@ -23,14 +23,14 @@ public interface SysMenuMapper extends BaseMapper<SysMenuEntity> {
* @return 菜单列表
*/
@Select("SELECT DISTINCT m.* "
+ "FROM sys_menu m "
+ " LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id "
+ " LEFT JOIN sys_user u ON rm.role_id = u.role_id "
+ "WHERE u.user_id = #{userId} "
+ " AND m.status = 1 "
+ " AND m.deleted = 0 "
+ "ORDER BY m.parent_id, m.order_num")
List<SysMenuEntity> selectMenuListByUserId(@Param("userId")Long userId);
+ "FROM sys_menu m "
+ " LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id "
+ " LEFT JOIN sys_user u ON rm.role_id = u.role_id "
+ "WHERE u.user_id = #{userId} "
+ " AND m.status = 1 "
+ " AND m.deleted = 0 "
+ "ORDER BY m.parent_id")
List<SysMenuEntity> selectMenuListByUserId(@Param("userId") Long userId);
/**
@@ -40,11 +40,11 @@ public interface SysMenuMapper extends BaseMapper<SysMenuEntity> {
* @return 选中菜单列表
*/
@Select("SELECT DISTINCT m.menu_id "
+ "FROM sys_menu m "
+ " LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id "
+ "WHERE rm.role_id = #{roleId} "
+ " AND m.deleted = 0 "
+ "GROUP BY m.menu_id ")
+ "FROM sys_menu m "
+ " LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id "
+ "WHERE rm.role_id = #{roleId} "
+ " AND m.deleted = 0 "
+ "GROUP BY m.menu_id ")
List<Long> selectMenuIdsByRoleId(@Param("roleId") Long roleId);
}

View File

@@ -42,6 +42,7 @@ public interface SysMenuService extends IService<SysMenuEntity> {
/**
* 是否存在菜单子节点
*
* @param menuId 菜单ID
* @return 结果 true 存在 false 不存在
*/
@@ -49,11 +50,11 @@ public interface SysMenuService extends IService<SysMenuEntity> {
/**
* 查询菜单是否存在角色
*
* @param menuId 菜单ID
* @return 结果 true 存在 false 不存在
*/
boolean isMenuAssignToRoles(Long menuId);
}

View File

@@ -4,11 +4,11 @@ import com.agileboot.domain.system.role.db.SysRoleMenuEntity;
import com.agileboot.domain.system.role.db.SysRoleMenuMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.List;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 菜单权限表 服务实现类
@@ -39,8 +39,8 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity
public boolean isMenuNameDuplicated(String menuName, Long menuId, Long parentId) {
QueryWrapper<SysMenuEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("menu_name", menuName)
.ne(menuId != null, "menu_id", menuId)
.eq(parentId != null, "parent_id", parentId);
.ne(menuId != null, "menu_id", menuId)
.eq(parentId != null, "parent_id", parentId);
return this.baseMapper.exists(queryWrapper);
}
@@ -66,7 +66,6 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity
}
@Override
public List<SysMenuEntity> getMenuListByUserId(Long userId) {
return baseMapper.selectMenuListByUserId(userId);

View File

@@ -1,15 +1,16 @@
package com.agileboot.domain.system.menu.dto;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.utils.jackson.JacksonUtil;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.enums.common.MenuTypeEnum;
import com.agileboot.common.enums.common.StatusEnum;
import com.agileboot.common.enums.BasicEnumUtil;
import com.agileboot.common.utils.jackson.JacksonUtil;
import com.agileboot.domain.system.menu.db.SysMenuEntity;
import java.util.Date;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author valarchie
*/
@@ -72,5 +73,4 @@ public class MenuDTO {
private String icon;
}

View File

@@ -2,13 +2,15 @@ package com.agileboot.domain.system.menu.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 路由显示信息
* 必须加上@JsonInclude(Include.NON_NULL)的注解 否则传null值给Vue动态路由渲染时会出错
*
* @author valarchie
*/
@Data
@@ -30,14 +32,14 @@ public class MetaDTO {
// 需要内嵌的iframe链接地址
private String frameSrc;
/**
* 是否是内部页面 使用frameSrc来嵌入页面时当isFrameSrcInternal=true的时候, 前端需要做特殊处理
* 比如链接是 /druid/login.html
* 前端需要处理成 http://localhost:8080/druid/login.html
*/
* 是否是内部页面 使用frameSrc来嵌入页面时当isFrameSrcInternal=true的时候, 前端需要做特殊处理
* 比如链接是 /druid/login.html
* 前端需要处理成 http://localhost:8080/druid/login.html
*/
private Boolean isFrameSrcInternal;
/**
* 菜单排序,值越高排的越后(只针对顶级路由)
* 菜单排序,值越高排的越后(只针对顶级路由)
*/
private Integer rank;

View File

@@ -5,13 +5,15 @@ import com.agileboot.domain.system.menu.db.SysMenuEntity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Lists;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 动态路由信息
* 必须加上@JsonInclude(Include.NON_NULL)的注解 否则传null值给Vue动态路由渲染时会出错
*
* @author valarchie
*/
@JsonInclude(Include.NON_NULL)

View File

@@ -1,18 +1,19 @@
package com.agileboot.domain.system.menu.model;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.common.enums.common.MenuTypeEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.exception.error.ErrorCode.Business;
import com.agileboot.common.utils.jackson.JacksonUtil;
import com.agileboot.domain.system.menu.command.AddMenuCommand;
import com.agileboot.domain.system.menu.command.UpdateMenuCommand;
import com.agileboot.common.enums.common.MenuTypeEnum;
import com.agileboot.domain.system.menu.db.SysMenuEntity;
import com.agileboot.domain.system.menu.db.SysMenuService;
import java.util.Objects;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author valarchie
*/
@@ -64,8 +65,8 @@ public class MenuModel extends SysMenuEntity {
SysMenuEntity parentMenu = menuService.getById(getParentId());
if (parentMenu != null && getIsButton() && (
Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.IFRAME.getValue())
|| Objects.equals(parentMenu.getMenuType(),MenuTypeEnum.OUTSIDE_LINK_REDIRECT.getValue())
Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.IFRAME.getValue())
|| Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.OUTSIDE_LINK_REDIRECT.getValue())
)) {
throw new ApiException(Business.MENU_NOT_ALLOWED_TO_CREATE_BUTTON_ON_IFRAME_OR_OUT_LINK);
}
@@ -78,7 +79,7 @@ public class MenuModel extends SysMenuEntity {
SysMenuEntity parentMenu = menuService.getById(getParentId());
if (parentMenu != null && !getIsButton() && (
!Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.CATALOG.getValue())
!Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.CATALOG.getValue())
)) {
throw new ApiException(Business.MENU_ONLY_ALLOWED_TO_CREATE_SUB_MENU_IN_CATALOG);
}

View File

@@ -4,12 +4,12 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.system.menu.db.SysMenuEntity;
import com.agileboot.domain.system.menu.db.SysMenuService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 菜单模型工厂
*
* @author valarchie
*/
@Component

View File

@@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class MenuQuery extends AbstractQuery<SysMenuEntity> {
// 直接交给前端筛选
// 直接交给前端筛选
// private String menuName;
// private Boolean isVisible;
// private Integer status;

Some files were not shown because too many files have changed in this diff Show More