Merge branch 'dev'
This commit is contained in:
commit
f3ea4ffdfa
|
@ -26,6 +26,7 @@ ENTRYPOINT ["java","-jar","/home/server/app.jar"]
|
||||||
|
|
||||||
#暴露 8000 端口
|
#暴露 8000 端口
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
EXPOSE 7070
|
||||||
|
|
||||||
# 生产环境
|
# 生产环境
|
||||||
# mvn clean package -Pprod -DskipTests
|
# mvn clean package -Pprod -DskipTests
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cn.bunny.services.controller.configuration;
|
||||||
import cn.bunny.services.domain.system.configuration.dto.WebConfigurationDto;
|
import cn.bunny.services.domain.system.configuration.dto.WebConfigurationDto;
|
||||||
import cn.bunny.services.domain.system.configuration.entity.WebConfiguration;
|
import cn.bunny.services.domain.system.configuration.entity.WebConfiguration;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.configuration.ConfigurationService;
|
import cn.bunny.services.service.configuration.ConfigurationService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package cn.bunny.services.controller.configuration;
|
package cn.bunny.services.controller.configuration;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto;
|
import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto;
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateDto;
|
import cn.bunny.services.domain.system.email.dto.EmailTemplateDto;
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto;
|
import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto;
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
||||||
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.service.configuration.EmailTemplateService;
|
import cn.bunny.services.service.configuration.EmailTemplateService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
@ -71,7 +71,7 @@ public class EmailTemplateController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "全部邮件类型列表", description = "获取全部邮件类型列表", tags = "emailTemplate::query")
|
@Operation(summary = "全部邮件类型列表", description = "获取全部邮件类型列表", tags = "emailTemplate::query")
|
||||||
@GetMapping("public")
|
@GetMapping("private")
|
||||||
public Result<List<Map<String, String>>> getEmailTypeList() {
|
public Result<List<Map<String, String>>> getEmailTypeList() {
|
||||||
List<Map<String, String>> list = emailTemplateService.getEmailTypeList();
|
List<Map<String, String>> list = emailTemplateService.getEmailTypeList();
|
||||||
return Result.success(list);
|
return Result.success(list);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.email.entity.EmailUsers;
|
||||||
import cn.bunny.services.domain.system.email.vo.EmailUsersVo;
|
import cn.bunny.services.domain.system.email.vo.EmailUsersVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.configuration.EmailUsersService;
|
import cn.bunny.services.service.configuration.EmailUsersService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import cn.bunny.services.domain.system.i18n.entity.I18n;
|
||||||
import cn.bunny.services.domain.system.i18n.vo.I18nVo;
|
import cn.bunny.services.domain.system.i18n.vo.I18nVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.configuration.I18nService;
|
import cn.bunny.services.service.configuration.I18nService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import cn.bunny.services.domain.system.i18n.dto.I18nTypeDto;
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nTypeUpdateDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nTypeUpdateDto;
|
||||||
import cn.bunny.services.domain.system.i18n.vo.I18nTypeVo;
|
import cn.bunny.services.domain.system.i18n.vo.I18nTypeVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.configuration.I18nTypeService;
|
import cn.bunny.services.service.configuration.I18nTypeService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.menuIcon.entity.MenuIcon;
|
||||||
import cn.bunny.services.domain.system.menuIcon.vo.MenuIconVo;
|
import cn.bunny.services.domain.system.menuIcon.vo.MenuIconVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.configuration.MenuIconService;
|
import cn.bunny.services.service.configuration.MenuIconService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import cn.bunny.services.domain.system.log.entity.ScheduleExecuteLog;
|
||||||
import cn.bunny.services.domain.system.log.vo.ScheduleExecuteLogVo;
|
import cn.bunny.services.domain.system.log.vo.ScheduleExecuteLogVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.log.ScheduleExecuteLogService;
|
import cn.bunny.services.service.log.ScheduleExecuteLogService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import cn.bunny.services.domain.system.log.vo.UserLoginLogLocalVo;
|
||||||
import cn.bunny.services.domain.system.log.vo.UserLoginLogVo;
|
import cn.bunny.services.domain.system.log.vo.UserLoginLogVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.log.UserLoginLogService;
|
import cn.bunny.services.service.log.UserLoginLogService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import cn.bunny.services.domain.system.message.vo.MessageReceivedWithUserVo;
|
||||||
import cn.bunny.services.domain.system.message.vo.MessageVo;
|
import cn.bunny.services.domain.system.message.vo.MessageVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.message.MessageService;
|
import cn.bunny.services.service.message.MessageService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import cn.bunny.services.domain.system.message.vo.MessageReceivedWithMessageVo;
|
||||||
import cn.bunny.services.domain.system.message.vo.MessageUserVo;
|
import cn.bunny.services.domain.system.message.vo.MessageUserVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.message.MessageReceivedService;
|
import cn.bunny.services.service.message.MessageReceivedService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.message.entity.MessageType;
|
||||||
import cn.bunny.services.domain.system.message.vo.MessageTypeVo;
|
import cn.bunny.services.domain.system.message.vo.MessageTypeVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.message.MessageTypeService;
|
import cn.bunny.services.service.message.MessageTypeService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cn.bunny.services.controller.schedule;
|
||||||
import cn.bunny.services.aop.scanner.QuartzSchedulersScanner;
|
import cn.bunny.services.aop.scanner.QuartzSchedulersScanner;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.quartz.dto.SchedulersAddDto;
|
import cn.bunny.services.domain.system.quartz.dto.SchedulersAddDto;
|
||||||
import cn.bunny.services.domain.system.quartz.dto.SchedulersDto;
|
import cn.bunny.services.domain.system.quartz.dto.SchedulersDto;
|
||||||
import cn.bunny.services.domain.system.quartz.dto.SchedulersUpdateDto;
|
import cn.bunny.services.domain.system.quartz.dto.SchedulersUpdateDto;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.quartz.entity.SchedulersGroup;
|
||||||
import cn.bunny.services.domain.system.quartz.vo.SchedulersGroupVo;
|
import cn.bunny.services.domain.system.quartz.vo.SchedulersGroupVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.schedule.SchedulersGroupService;
|
import cn.bunny.services.service.schedule.SchedulersGroupService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.system.entity.Dept;
|
||||||
import cn.bunny.services.domain.system.system.vo.DeptVo;
|
import cn.bunny.services.domain.system.system.vo.DeptVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.system.DeptService;
|
import cn.bunny.services.service.system.DeptService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import cn.bunny.services.domain.system.files.vo.FileInfoVo;
|
||||||
import cn.bunny.services.domain.system.files.vo.FilesVo;
|
import cn.bunny.services.domain.system.files.vo.FilesVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.system.FilesService;
|
import cn.bunny.services.service.system.FilesService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import cn.bunny.services.aop.scanner.ControllerApiPermissionScanner;
|
||||||
import cn.bunny.services.domain.common.model.dto.scanner.ScannerControllerInfoVo;
|
import cn.bunny.services.domain.common.model.dto.scanner.ScannerControllerInfoVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.system.dto.power.PermissionAddDto;
|
import cn.bunny.services.domain.system.system.dto.power.PermissionAddDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.power.PermissionDto;
|
import cn.bunny.services.domain.system.system.dto.power.PermissionDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.power.PermissionUpdateBatchByParentIdDto;
|
import cn.bunny.services.domain.system.system.dto.power.PermissionUpdateBatchByParentIdDto;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.system.entity.Role;
|
||||||
import cn.bunny.services.domain.system.system.vo.RoleVo;
|
import cn.bunny.services.domain.system.system.vo.RoleVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.system.RoleService;
|
import cn.bunny.services.service.system.RoleService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import cn.bunny.services.domain.system.system.dto.router.RouterUpdateDto;
|
||||||
import cn.bunny.services.domain.system.system.vo.router.RouterManageVo;
|
import cn.bunny.services.domain.system.system.vo.router.RouterManageVo;
|
||||||
import cn.bunny.services.domain.system.system.vo.router.WebUserRouterVo;
|
import cn.bunny.services.domain.system.system.vo.router.WebUserRouterVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.service.system.RouterService;
|
import cn.bunny.services.service.system.RouterService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package cn.bunny.services.controller.system;
|
package cn.bunny.services.controller.system;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.domain.system.system.dto.user.AdminUserAddDto;
|
import cn.bunny.services.domain.system.system.dto.user.AdminUserAddDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.AdminUserDto;
|
import cn.bunny.services.domain.system.system.dto.user.AdminUserDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateDto;
|
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateDto;
|
||||||
|
@ -91,13 +90,13 @@ public class UserController {
|
||||||
|
|
||||||
@Operation(summary = "已登录用户", description = "查询缓存中已登录用户", tags = "user::query")
|
@Operation(summary = "已登录用户", description = "查询缓存中已登录用户", tags = "user::query")
|
||||||
@GetMapping("getCacheUserPage/{page}/{limit}")
|
@GetMapping("getCacheUserPage/{page}/{limit}")
|
||||||
public Result<PageResult<LoginVo>> getCacheUserPage(
|
public Result<PageResult<UserVo>> getCacheUserPage(
|
||||||
@Parameter(name = "page", description = "当前页", required = true)
|
@Parameter(name = "page", description = "当前页", required = true)
|
||||||
@PathVariable("page") Integer page,
|
@PathVariable("page") Integer page,
|
||||||
@Parameter(name = "limit", description = "每页记录数", required = true)
|
@Parameter(name = "limit", description = "每页记录数", required = true)
|
||||||
@PathVariable("limit") Integer limit) {
|
@PathVariable("limit") Integer limit) {
|
||||||
Page<AdminUser> pageParams = new Page<>(page, limit);
|
Page<AdminUser> pageParams = new Page<>(page, limit);
|
||||||
PageResult<LoginVo> pageResult = userService.getCacheUserPage(pageParams);
|
PageResult<UserVo> pageResult = userService.getCacheUserPage(pageParams);
|
||||||
return Result.success(pageResult);
|
return Result.success(pageResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cn.bunny.services.controller.system;
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateByLocalUserDto;
|
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateByLocalUserDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.RefreshTokenDto;
|
import cn.bunny.services.domain.system.system.dto.user.RefreshTokenDto;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
server:
|
server:
|
||||||
port: 8000
|
port: 8000
|
||||||
|
tomcat:
|
||||||
|
threads:
|
||||||
|
max: 1000
|
||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: @profiles.active@
|
active: @profiles.active@
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
public abstract class AbstractPermissionCheckHandler {
|
|
||||||
|
|
||||||
private AbstractPermissionCheckHandler abstractPermissionCheckHandler;
|
|
||||||
|
|
||||||
public AbstractPermissionCheckHandler(AbstractPermissionCheckHandler abstractPermissionCheckHandler) {
|
|
||||||
this.abstractPermissionCheckHandler = abstractPermissionCheckHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract protected void checkPermission(String requestUrl);
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package cn.bunny.services.config;
|
|
||||||
|
|
||||||
import cn.bunny.services.utils.TokenUtilsTest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.test.context.TestConfiguration;
|
|
||||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
// @TestConfiguration
|
|
||||||
// public class WebConfig {
|
|
||||||
// @Value("${server.port}")
|
|
||||||
// private String port;
|
|
||||||
//
|
|
||||||
// @Autowired
|
|
||||||
// private TokenUtilsTest tokenUtils;
|
|
||||||
//
|
|
||||||
// @Bean
|
|
||||||
// public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
|
||||||
// String token = tokenUtils.getToken();
|
|
||||||
// return builder.rootUri("http://localhost:" + port)
|
|
||||||
// .defaultHeader("token", token)
|
|
||||||
// .defaultHeader("Content-Type", "application/json")
|
|
||||||
// .build();
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -1,37 +0,0 @@
|
||||||
package cn.bunny.services.controller;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.openqa.selenium.chrome.ChromeDriver;
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@AutoConfigureMockMvc
|
|
||||||
public class LoginTest {
|
|
||||||
private ChromeDriver chromeDriver;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUpMockMvc() {
|
|
||||||
chromeDriver = new ChromeDriver();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void tearDown() {
|
|
||||||
chromeDriver.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 测试登录页面
|
|
||||||
@Test
|
|
||||||
// @WithMockUser(username = "Administrator", password = "admin123", roles = "admin")
|
|
||||||
// @WithUserDetails("Administrator")
|
|
||||||
void testLogin() throws InterruptedException {
|
|
||||||
chromeDriver.get("http://localhost:7000/");
|
|
||||||
TimeUnit.MINUTES.sleep(100);
|
|
||||||
chromeDriver.manage().timeouts().implicitlyWait(Duration.of(1000L, TimeUnit.SECONDS.toChronoUnit()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
package cn.bunny.services.controller;
|
|
||||||
|
|
||||||
import cn.bunny.services.aop.scanner.ControllerApiPermissionScanner;
|
|
||||||
import cn.bunny.services.domain.common.model.dto.scanner.ScannerControllerInfoVo;
|
|
||||||
import cn.bunny.services.domain.system.system.entity.Permission;
|
|
||||||
import cn.bunny.services.service.system.PermissionService;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class TestControllerTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private PermissionService permissionService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test1() {
|
|
||||||
List<ScannerControllerInfoVo> list = ControllerApiPermissionScanner.getSystemApiInfoList();
|
|
||||||
list.forEach(parent -> {
|
|
||||||
String parentPath = parent.getPath();
|
|
||||||
String powerCode = parentPath.replace("/api/", "").replace("/**", "");
|
|
||||||
powerCode = "user::" + powerCode;
|
|
||||||
|
|
||||||
Permission permission = new Permission();
|
|
||||||
permission.setParentId(0L);
|
|
||||||
permission.setPowerCode(powerCode);
|
|
||||||
permission.setPowerName(parent.getSummary());
|
|
||||||
permission.setRequestUrl(parentPath);
|
|
||||||
permissionService.saveOrUpdate(permission);
|
|
||||||
// System.out.println(permission);
|
|
||||||
|
|
||||||
List<Permission> permissionList = parent.getChildren().stream()
|
|
||||||
.map(children -> {
|
|
||||||
Permission childrenPermission = new Permission();
|
|
||||||
childrenPermission.setParentId(permission.getId());
|
|
||||||
childrenPermission.setPowerName(children.getSummary());
|
|
||||||
if (!children.getPowerCodes().isEmpty()) {
|
|
||||||
String ChildrenPowerCode = children.getPowerCodes().get(0);
|
|
||||||
childrenPermission.setPowerCode(ChildrenPowerCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
String childrenPath = children.getPath();
|
|
||||||
childrenPermission.setRequestUrl(childrenPath);
|
|
||||||
childrenPermission.setRequestMethod(children.getHttpMethod());
|
|
||||||
|
|
||||||
return childrenPermission;
|
|
||||||
})
|
|
||||||
.toList();
|
|
||||||
// System.out.println(JSON.toJSONString(permissionList));
|
|
||||||
permissionService.saveOrUpdateBatch(permissionList);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,163 +0,0 @@
|
||||||
package cn.bunny.services.controller.configuration;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.configuration.dto.WebConfigurationDto;
|
|
||||||
import cn.bunny.services.domain.system.configuration.entity.WebConfiguration;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
|
||||||
import cn.bunny.services.utils.TokenUtilsTest;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.alibaba.fastjson2.TypeReference;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
|
||||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@WebAppConfiguration
|
|
||||||
class ConfigurationControllerTest {
|
|
||||||
private static final String prefix = "/api/config";
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WebApplicationContext webApplicationContext;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TokenUtilsTest tokenUtils;
|
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUpMockMvc() {
|
|
||||||
token = tokenUtils.getToken();
|
|
||||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
|
|
||||||
.apply(SecurityMockMvcConfigurers.springSecurity())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void webConfig() throws Exception {
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.get(prefix + "/noAuth/webConfig")
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
|
|
||||||
WebConfiguration webConfiguration = JSON.parseObject(contentAsString, WebConfiguration.class);
|
|
||||||
|
|
||||||
if (!webConfiguration.getTitle().equals("BunnyAdmin")) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(webConfiguration);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getWebConfig() throws Exception {
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.request(HttpMethod.GET, prefix + "/getWebConfig")
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
|
|
||||||
Result<WebConfiguration> webConfigurationResult = JSON.parseObject(contentAsString, new TypeReference<>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!webConfigurationResult.getCode().equals(200)) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!webConfigurationResult.getData().getShowModel().equals("smart")) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void updateWebConfiguration() throws Exception {
|
|
||||||
AtomicReference<WebConfigurationDto> webConfigurationDto = new AtomicReference<>();
|
|
||||||
String testTitle = "修改的之";
|
|
||||||
|
|
||||||
// 获取原本的配置信息
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.request(HttpMethod.GET, prefix + "/getWebConfig")
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
|
|
||||||
Result<WebConfiguration> webConfigurationResult = JSON.parseObject(contentAsString, new TypeReference<>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
WebConfigurationDto dto = new WebConfigurationDto();
|
|
||||||
BeanUtils.copyProperties(webConfigurationResult.getData(), dto);
|
|
||||||
|
|
||||||
webConfigurationDto.set(dto);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 修改原本的测试内容
|
|
||||||
webConfigurationDto.get().setTitle(testTitle);
|
|
||||||
|
|
||||||
// 测试修改方法
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.put(prefix + "/updateWebConfiguration")
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
|
||||||
.content(JSON.toJSONString(webConfigurationDto.get()))
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
String contentAsString = result.getResponse().getContentAsString();
|
|
||||||
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
|
|
||||||
Result<String> stringResult = JSON.parseObject(contentAsString, new TypeReference<>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!stringResult.getCode().equals(200)) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 验证是否修改成功
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.request(HttpMethod.GET, prefix + "/getWebConfig")
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
|
|
||||||
Result<WebConfiguration> webConfigurationResult = JSON.parseObject(contentAsString, new TypeReference<>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!webConfigurationResult.getCode().equals(200)) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!webConfigurationResult.getData().getTitle().equals(testTitle)) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
package cn.bunny.services.controller.configuration;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto;
|
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto;
|
|
||||||
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
|
||||||
import cn.bunny.services.domain.common.enums.EmailTemplateEnums;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
|
||||||
import cn.bunny.services.utils.TokenUtilsTest;
|
|
||||||
import cn.hutool.crypto.digest.MD5;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.alibaba.fastjson2.TypeReference;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
|
||||||
import org.springframework.http.HttpEntity;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@WebAppConfiguration
|
|
||||||
class EmailTemplateControllerTest {
|
|
||||||
private static final String prefix = "/api/emailTemplate";
|
|
||||||
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WebApplicationContext webApplicationContext;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TokenUtilsTest tokenUtilsTest;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RestTemplate restTemplate;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
token = tokenUtilsTest.getToken();
|
|
||||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
|
|
||||||
.apply(SecurityMockMvcConfigurers.springSecurity())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void tearDown() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getEmailTemplatePage() throws Exception {
|
|
||||||
String api = prefix + "/getEmailTemplateList/1/10";
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.get(api)
|
|
||||||
.header("token", token)
|
|
||||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
||||||
.param("type", "code"))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
String contentAsString = result.getResponse().getContentAsString();
|
|
||||||
JSONObject jsonObject = JSONObject.parseObject(contentAsString);
|
|
||||||
|
|
||||||
if (jsonObject == null) {
|
|
||||||
throw new Exception(contentAsString);
|
|
||||||
}
|
|
||||||
System.out.println(jsonObject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getEmailTypeList() throws Exception {
|
|
||||||
String api = prefix + "/getEmailTypes";
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get(api).header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
String contentAsString = result.getResponse().getContentAsString();
|
|
||||||
JSONObject jsonObject = JSONObject.parseObject(contentAsString);
|
|
||||||
|
|
||||||
if (jsonObject == null) {
|
|
||||||
throw new Exception(contentAsString);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(jsonObject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void addEmailTemplate() throws Exception {
|
|
||||||
String api = prefix + "/addEmailTemplate";
|
|
||||||
|
|
||||||
EmailTemplateAddDto dto = EmailTemplateAddDto.builder()
|
|
||||||
.emailUser(2L)
|
|
||||||
.body("哈哈哈")
|
|
||||||
.templateName("测试")
|
|
||||||
.subject("test")
|
|
||||||
.type(EmailTemplateEnums.NOTIFICATION.getType())
|
|
||||||
.isDefault(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.post(api)
|
|
||||||
.header("token", token)
|
|
||||||
.content(JSONObject.toJSONString(dto))
|
|
||||||
.contentType(MediaType.APPLICATION_JSON))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
String contentAsString = result.getResponse().getContentAsString();
|
|
||||||
JSONObject jsonObject = JSONObject.parseObject(contentAsString);
|
|
||||||
|
|
||||||
System.out.println(jsonObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
getEmailTemplatePage();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void updateEmailTemplate() throws Exception {
|
|
||||||
String api = prefix + "/updateEmailTemplate";
|
|
||||||
String restTemplateApi = prefix + "/getEmailTemplateList/1/10";
|
|
||||||
|
|
||||||
String url = UriComponentsBuilder.fromUriString(restTemplateApi)
|
|
||||||
.queryParam("subject", "test")
|
|
||||||
.build()
|
|
||||||
.toUriString();
|
|
||||||
|
|
||||||
Result<PageResult<EmailTemplateVo>> result = restTemplate.exchange(
|
|
||||||
url,
|
|
||||||
HttpMethod.GET,
|
|
||||||
new HttpEntity<>(null),
|
|
||||||
new ParameterizedTypeReference<Result<PageResult<EmailTemplateVo>>>() {
|
|
||||||
}
|
|
||||||
).getBody();
|
|
||||||
|
|
||||||
if (result == null) throw new Exception();
|
|
||||||
if (!result.getCode().equals(200)) throw new Exception(result.getMessage());
|
|
||||||
if (result.getData().getList().isEmpty()) throw new Exception("没有测试数据");
|
|
||||||
|
|
||||||
EmailTemplateVo emailTemplateVo = result.getData().getList().get(0);
|
|
||||||
EmailTemplateUpdateDto emailTemplateUpdateDto = new EmailTemplateUpdateDto();
|
|
||||||
BeanUtils.copyProperties(emailTemplateVo, emailTemplateUpdateDto);
|
|
||||||
|
|
||||||
System.out.println(emailTemplateUpdateDto);
|
|
||||||
|
|
||||||
emailTemplateUpdateDto.setBody(MD5.create().digestHex16(LocalDateTime.now().toString()));
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.put(api)
|
|
||||||
.header("token", token)
|
|
||||||
.content(JSON.toJSONString(emailTemplateUpdateDto))
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
|
||||||
)
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result1 -> {
|
|
||||||
String contentAsString = result1.getResponse().getContentAsString();
|
|
||||||
var pageResultResult = JSONObject.parseObject(contentAsString, new TypeReference<Result<PageResult<EmailTemplateVo>>>() {
|
|
||||||
});
|
|
||||||
if (pageResultResult == null) throw new Exception(contentAsString);
|
|
||||||
if (!pageResultResult.getCode().equals(200)) throw new Exception(pageResultResult.getMessage());
|
|
||||||
|
|
||||||
System.out.println(pageResultResult);
|
|
||||||
});
|
|
||||||
|
|
||||||
result = restTemplate.exchange(
|
|
||||||
url,
|
|
||||||
HttpMethod.GET,
|
|
||||||
new HttpEntity<>(null),
|
|
||||||
new ParameterizedTypeReference<Result<PageResult<EmailTemplateVo>>>() {
|
|
||||||
}
|
|
||||||
).getBody();
|
|
||||||
|
|
||||||
if (result == null) throw new Exception();
|
|
||||||
if (!result.getCode().equals(200)) throw new Exception(result.getMessage());
|
|
||||||
emailTemplateVo = result.getData().getList().get(0);
|
|
||||||
if (!emailTemplateVo.getBody().equals(emailTemplateUpdateDto.getBody())) {
|
|
||||||
throw new Exception(emailTemplateUpdateDto.getBody());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void deleteEmailTemplate() throws Exception {
|
|
||||||
String api = prefix + "/deleteEmailTemplate";
|
|
||||||
List<Long> ids = new ArrayList<>();
|
|
||||||
ids.add(1905180657917157378L);
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.delete(api)
|
|
||||||
.header("token", token)
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
|
||||||
.content(JSON.toJSONString(ids)))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
String contentAsString = result.getResponse().getContentAsString();
|
|
||||||
JSONObject jsonObject = JSONObject.parseObject(contentAsString);
|
|
||||||
System.out.println(jsonObject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,179 +0,0 @@
|
||||||
package cn.bunny.services.controller.log;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.log.dto.UserLoginLogDto;
|
|
||||||
import cn.bunny.services.domain.system.log.entity.UserLoginLog;
|
|
||||||
import cn.bunny.services.domain.system.log.vo.UserLoginLogLocalVo;
|
|
||||||
import cn.bunny.services.domain.system.log.vo.UserLoginLogVo;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
|
||||||
import cn.bunny.services.service.log.UserLoginLogService;
|
|
||||||
import cn.bunny.services.utils.TokenUtilsTest;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.alibaba.fastjson2.TypeReference;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
|
||||||
import org.springframework.http.HttpEntity;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
|
||||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@SpringBootTest
|
|
||||||
@WebAppConfiguration
|
|
||||||
class UserLoginLogControllerTest {
|
|
||||||
private static final String prefix = "/api/userLoginLog";
|
|
||||||
|
|
||||||
private WebTestClient testClient;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WebApplicationContext webApplicationContext;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserLoginLogService userLoginLogService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TokenUtilsTest tokenUtils;
|
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RestTemplate restTemplate;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
token = tokenUtils.getToken();
|
|
||||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
|
|
||||||
.apply(SecurityMockMvcConfigurers.springSecurity())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
testClient = WebTestClient.bindToController(new UserLoginLogController()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void tearDown() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getUserLoginLogPage() throws Exception {
|
|
||||||
UserLoginLogDto dto = UserLoginLogDto.builder()
|
|
||||||
.username("bunny")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get(prefix + "/getUserLoginLogList/1/10")
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
|
||||||
.content(JSON.toJSONString(dto))
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getUserLoginLogPage2() {
|
|
||||||
UserLoginLogDto dto = UserLoginLogDto.builder()
|
|
||||||
.username("bunny")
|
|
||||||
.build();
|
|
||||||
Map<String, String> params = JSON.parseObject(JSON.toJSONString(dto), new TypeReference<>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送请求
|
|
||||||
ResponseEntity<Result<PageResult<UserLoginLogVo>>> response = restTemplate.exchange(
|
|
||||||
prefix + "/getUserLoginLogList/1/10",
|
|
||||||
HttpMethod.GET,
|
|
||||||
new HttpEntity<>(params),
|
|
||||||
new ParameterizedTypeReference<>() {
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Result<PageResult<UserLoginLogVo>> body = response.getBody();
|
|
||||||
System.out.println(JSON.toJSONString(body));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getUserLoginLogPageByUser() throws Exception {
|
|
||||||
String api = prefix + "/noManage/getUserLoginLogListByLocalUser/1/10";
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get(api)
|
|
||||||
.header("token", token))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getUserLoginLogPageByUser2() {
|
|
||||||
String api = prefix + "/noManage/getUserLoginLogListByLocalUser/1/10";
|
|
||||||
|
|
||||||
testClient.get()
|
|
||||||
.uri(api)
|
|
||||||
.header("token", token)
|
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
|
||||||
.exchange()
|
|
||||||
.expectStatus().isOk()
|
|
||||||
.expectBody(new ParameterizedTypeReference<Result<PageResult<UserLoginLogLocalVo>>>() {
|
|
||||||
})
|
|
||||||
.consumeWith(result -> {
|
|
||||||
Result<PageResult<UserLoginLogLocalVo>> responseBody = result.getResponseBody();
|
|
||||||
System.out.println(JSON.toJSONString(responseBody));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void deleteUserLoginLog() throws Exception {
|
|
||||||
String api = prefix + "/deleteUserLoginLog";
|
|
||||||
|
|
||||||
Page<UserLoginLog> page = new Page<>(1, 10);
|
|
||||||
List<UserLoginLog> deleteBeforeList = userLoginLogService.list(page);
|
|
||||||
List<Long> ids = deleteBeforeList.stream().map(UserLoginLog::getId).limit(4).toList();
|
|
||||||
List<Long> deleteBeforeIds = deleteBeforeList.stream().map(UserLoginLog::getId).toList();
|
|
||||||
|
|
||||||
log.info("要删除的ids: {}", ids);
|
|
||||||
log.info("删除前ids数据:{}", deleteBeforeIds);
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
|
||||||
.delete(api)
|
|
||||||
.header("token", token)
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
|
||||||
.content(JSON.toJSONString(ids)))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(result -> {
|
|
||||||
MockHttpServletResponse response = result.getResponse();
|
|
||||||
String contentAsString = response.getContentAsString();
|
|
||||||
System.out.println(contentAsString);
|
|
||||||
});
|
|
||||||
|
|
||||||
deleteBeforeList = userLoginLogService.list(page);
|
|
||||||
deleteBeforeIds = deleteBeforeList.stream().map(UserLoginLog::getId).toList();
|
|
||||||
log.info("要删除的ids: {}", ids);
|
|
||||||
log.info("删除前ids数据:{}", deleteBeforeIds);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package cn.bunny.services.controller.system;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.data.redis.core.Cursor;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.ScanOptions;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class UserControllerTest {
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test() {
|
|
||||||
// Set<String> keys = redisTemplate.keys("admin::login_info::*");
|
|
||||||
// for (String key : keys) {
|
|
||||||
// System.out.println(key);
|
|
||||||
// }
|
|
||||||
|
|
||||||
Map<String, Object> adminLoginInfoWithScan = getAdminLoginInfoWithScan();
|
|
||||||
JSONObject adminLoginInfo = new JSONObject(adminLoginInfoWithScan);
|
|
||||||
System.out.println(adminLoginInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getAdminLoginInfoWithScan() {
|
|
||||||
String pattern = "admin::login_info::*";
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
|
|
||||||
// 使用scan命令迭代查找
|
|
||||||
ScanOptions options = ScanOptions.scanOptions().match(pattern).count(100).build();
|
|
||||||
Cursor<String> cursor = redisTemplate.scan(options);
|
|
||||||
|
|
||||||
while (cursor.hasNext()) {
|
|
||||||
String key = cursor.next();
|
|
||||||
Object value = redisTemplate.opsForValue().get(key);
|
|
||||||
result.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
cursor.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 处理异常
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package cn.bunny.services.utils;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
|
||||||
import cn.bunny.services.mapper.system.UserMapper;
|
|
||||||
import cn.bunny.services.service.system.helper.UserLoginHelper;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class TokenUtilsTest {
|
|
||||||
@Autowired
|
|
||||||
private UserLoginHelper userUtil;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserMapper userMapper;
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
AdminUser adminUser = userMapper.selectOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getUsername, "Administrator"));
|
|
||||||
adminUser.setPassword("admin123");
|
|
||||||
LoginVo loginVo = userUtil.buildLoginUserVo(adminUser, 7);
|
|
||||||
return loginVo.getToken();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
package impl;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
|
||||||
import cn.bunny.services.mapper.configuration.I18nMapper;
|
|
||||||
import com.alibaba.excel.EasyExcel;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
public class I18nServiceImplTest extends ServiceImpl<I18nMapper, I18n> {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void downloadI18nByExcel() {
|
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
||||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
|
|
||||||
// 查找默认语言内容
|
|
||||||
List<I18n> i18nList = list();
|
|
||||||
Map<String, List<I18nExcel>> hashMap = i18nList.stream()
|
|
||||||
.collect(Collectors.groupingBy(
|
|
||||||
I18n::getTypeName,
|
|
||||||
Collectors.mapping((I18n i18n) -> {
|
|
||||||
String keyName = i18n.getKeyName();
|
|
||||||
String translation = i18n.getTranslation();
|
|
||||||
return I18nExcel.builder().keyName(keyName).translation(translation).build();
|
|
||||||
}, Collectors.toList())
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
hashMap.forEach((key, value) -> {
|
|
||||||
// EasyExcel.write(key + ".xlsx", I18nExcel.class).sheet(key).doWrite(value);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ZipEntry zipEntry = new ZipEntry(key + ".xlsx");
|
|
||||||
zipOutputStream.putNextEntry(zipEntry);
|
|
||||||
|
|
||||||
// 直接写入到ZipOutputStream
|
|
||||||
EasyExcel.write(zipOutputStream, I18nExcel.class).sheet(key).doWrite(value);
|
|
||||||
zipOutputStream.closeEntry();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import cn.bunny.services.AuthServiceApplication;
|
||||||
|
import cn.bunny.services.core.template.PermissionTreeProcessor;
|
||||||
|
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.Permission;
|
||||||
|
import cn.bunny.services.mapper.system.PermissionMapper;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = AuthServiceApplication.class)
|
||||||
|
class PermissionServiceImplTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PermissionMapper permissionMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void exportPermission() {
|
||||||
|
|
||||||
|
List<Permission> permissionList = permissionMapper.selectList(null);
|
||||||
|
List<PermissionExcel> permissionExcelList = permissionList.stream().map(permission -> {
|
||||||
|
PermissionExcel permissionExcel = new PermissionExcel();
|
||||||
|
BeanUtils.copyProperties(permission, permissionExcel);
|
||||||
|
|
||||||
|
return permissionExcel;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
PermissionTreeProcessor permissionTreeProcessor = new PermissionTreeProcessor();
|
||||||
|
List<PermissionExcel> buildTree = permissionTreeProcessor.process(permissionExcelList);
|
||||||
|
|
||||||
|
System.out.println(JSON.toJSONString(buildTree));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
package system;
|
|
||||||
|
|
||||||
import cn.bunny.services.controller.system.UserController;
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
|
||||||
import cn.bunny.services.service.system.impl.UserServiceImpl;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.data.redis.core.RedisConnectionUtils;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
@SpringBootTest(classes = UserServiceImpl.class)
|
|
||||||
class UserServiceTest {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test() {
|
|
||||||
String prefix = RedisUserConstant.getAdminUserEmailCodePrefix("");
|
|
||||||
Set<String> keys = redisTemplate.keys(prefix);
|
|
||||||
for (String key : keys) {
|
|
||||||
System.out.println(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -127,5 +127,11 @@
|
||||||
<artifactId>ip2region</artifactId>
|
<artifactId>ip2region</artifactId>
|
||||||
<version>2.6.5</version>
|
<version>2.6.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -18,7 +18,6 @@ import org.springframework.data.redis.cache.RedisCacheManager;
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
|
||||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
@ -42,13 +41,14 @@ public class RedisConfiguration {
|
||||||
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
|
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
|
||||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||||
redisTemplate.setConnectionFactory(connectionFactory);
|
redisTemplate.setConnectionFactory(connectionFactory);
|
||||||
|
|
||||||
// 设置key序列化为string
|
// 设置key序列化为string
|
||||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
|
||||||
// 设置value序列化为JSON,使用GenericJackson2JsonRedisSerializer替换默认序列化
|
// 设置value序列化为JSON,使用GenericJackson2JsonRedisSerializer替换默认序列化
|
||||||
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
redisTemplate.setValueSerializer(jsonRedisSerializer());
|
||||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
redisTemplate.setHashValueSerializer(jsonRedisSerializer());
|
||||||
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
|
|
||||||
|
|
||||||
// 开启Redis事务
|
// 开启Redis事务
|
||||||
redisTemplate.setEnableTransactionSupport(true);
|
redisTemplate.setEnableTransactionSupport(true);
|
||||||
|
|
|
@ -12,15 +12,57 @@ public class RedisUserConstant {
|
||||||
public static final Integer Cookie_EXPIRATION_TIME = 5 * 60 * 60;// cookies 过期时间 5 分钟
|
public static final Integer Cookie_EXPIRATION_TIME = 5 * 60 * 60;// cookies 过期时间 5 分钟
|
||||||
public static final String WEB_CONFIG_KEY = "webConfig::platformConfig";// web配置
|
public static final String WEB_CONFIG_KEY = "webConfig::platformConfig";// web配置
|
||||||
|
|
||||||
private static final String ADMIN_LOGIN_INFO_PREFIX = "admin::login_info::";
|
/* 用户登录前缀 */
|
||||||
private static final String ADMIN_EMAIL_CODE_PREFIX = "admin::email_code::";
|
private static final String USER_LOGIN_INFO_PREFIX = "user::login_info::";
|
||||||
|
|
||||||
|
/* 用户邮箱验证码前缀 */
|
||||||
|
private static final String USER_EMAIL_CODE_PREFIX = "user::email_code::";
|
||||||
|
|
||||||
|
/* 用户角色前缀 */
|
||||||
|
private static final String USER_ROLES_CODE_PREFIX = "user::roles::";
|
||||||
|
|
||||||
|
/* 用户权限前缀 */
|
||||||
|
private static final String USER_PERMISSION_CODE_PREFIX = "user::permission::";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录前缀
|
||||||
|
*
|
||||||
|
* @param user 用户名信息
|
||||||
|
* @return 格式化后缓存前缀
|
||||||
|
*/
|
||||||
|
public static String getUserLoginInfoPrefix(String user) {
|
||||||
|
return USER_LOGIN_INFO_PREFIX + user;
|
||||||
|
|
||||||
public static String getAdminLoginInfoPrefix(String adminUser) {
|
|
||||||
return ADMIN_LOGIN_INFO_PREFIX + adminUser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAdminUserEmailCodePrefix(String adminUser) {
|
/**
|
||||||
return ADMIN_EMAIL_CODE_PREFIX + adminUser;
|
* 用户邮箱前缀
|
||||||
|
*
|
||||||
|
* @param user 用户信息
|
||||||
|
* @return 邮箱验证码前缀
|
||||||
|
*/
|
||||||
|
public static String getUserEmailCodePrefix(String user) {
|
||||||
|
return USER_EMAIL_CODE_PREFIX + user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户角色前缀
|
||||||
|
*
|
||||||
|
* @param user 用户信息
|
||||||
|
* @return 格式化后用户角色前缀
|
||||||
|
*/
|
||||||
|
public static String getUserRolesCodePrefix(String user) {
|
||||||
|
return USER_ROLES_CODE_PREFIX + user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户权限前缀
|
||||||
|
*
|
||||||
|
* @param user 用户信息
|
||||||
|
* @return 格式化后用户权限前缀
|
||||||
|
*/
|
||||||
|
public static String getUserPermissionCodePrefix(String user) {
|
||||||
|
return USER_PERMISSION_CODE_PREFIX + user;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.domain.common.model.vo.result;
|
package cn.bunny.services.domain.common.enums;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ public enum ResultCodeEnum {
|
||||||
LOGIN_AUTH(208, "请先登陆"),
|
LOGIN_AUTH(208, "请先登陆"),
|
||||||
AUTHENTICATION_EXPIRED(208, "身份验证过期"),
|
AUTHENTICATION_EXPIRED(208, "身份验证过期"),
|
||||||
SESSION_EXPIRATION(208, "会话过期"),
|
SESSION_EXPIRATION(208, "会话过期"),
|
||||||
|
FAIL_NO_ACCESS_DENIED_USER_LOCKED(208, "该账户已封禁"),
|
||||||
|
|
||||||
// 209
|
// 209
|
||||||
THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"),
|
THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"),
|
||||||
|
|
||||||
|
@ -71,7 +72,6 @@ public enum ResultCodeEnum {
|
||||||
FAIL_NO_ACCESS_DENIED(403, "无权访问"),
|
FAIL_NO_ACCESS_DENIED(403, "无权访问"),
|
||||||
FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"),
|
FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"),
|
||||||
TOKEN_PARSING_FAILED(403, "token解析失败"),
|
TOKEN_PARSING_FAILED(403, "token解析失败"),
|
||||||
FAIL_NO_ACCESS_DENIED_USER_LOCKED(403, "该账户已封禁"),
|
|
||||||
|
|
||||||
// 系统错误 500
|
// 系统错误 500
|
||||||
UNKNOWN_EXCEPTION(500, "服务异常"),
|
UNKNOWN_EXCEPTION(500, "服务异常"),
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.bunny.services.domain.common.model.vo.result;
|
package cn.bunny.services.domain.common.model.vo.result;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.exception;
|
package cn.bunny.services.exception;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package cn.bunny.services.exception;
|
||||||
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.mybatis.spring.MyBatisSystemException;
|
import org.mybatis.spring.MyBatisSystemException;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package cn.bunny.services.minio;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.constant.MinioConstant;
|
import cn.bunny.services.domain.common.constant.MinioConstant;
|
||||||
import cn.bunny.services.domain.common.model.dto.minio.MinioUploadFileInfo;
|
import cn.bunny.services.domain.common.model.dto.minio.MinioUploadFileInfo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import io.minio.*;
|
import io.minio.*;
|
||||||
import io.minio.messages.DeleteError;
|
import io.minio.messages.DeleteError;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.services.processor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/* 构建树型结构模板处理器 */
|
||||||
|
public abstract class TreeProcessor<T> {
|
||||||
|
public final List<T> process(List<T> list) {
|
||||||
|
List<T> roots = findRoots(list);
|
||||||
|
for (T root : roots) {
|
||||||
|
buildChildren(root, list);
|
||||||
|
}
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract List<T> findRoots(List<T> list);
|
||||||
|
|
||||||
|
protected abstract void buildChildren(T parent, List<T> list);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.utils;
|
package cn.bunny.services.utils;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jws;
|
import io.jsonwebtoken.Jws;
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class MinioTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test() {
|
|
||||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM-dd");
|
|
||||||
String date = formatter.format(new Date());
|
|
||||||
System.out.println(date);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,9 +21,9 @@ public interface RolePermissionMapper extends BaseMapper<RolePermission> {
|
||||||
/**
|
/**
|
||||||
* * 根据权限id列表删除角色权限相关
|
* * 根据权限id列表删除角色权限相关
|
||||||
*
|
*
|
||||||
* @param powerIds 权限id列表
|
* @param permissionIds 权限id列表
|
||||||
*/
|
*/
|
||||||
void deleteBatchPowerIds(List<Long> powerIds);
|
void deleteBatchPowerIds(List<Long> permissionIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 根据角色id删除角色权限
|
* * 根据角色id删除角色权限
|
||||||
|
@ -38,7 +38,7 @@ public interface RolePermissionMapper extends BaseMapper<RolePermission> {
|
||||||
* @param roleId 角色id
|
* @param roleId 角色id
|
||||||
* @return 已选择的权限列表
|
* @return 已选择的权限列表
|
||||||
*/
|
*/
|
||||||
List<RolePermission> selectPowerListByRoleId(Long roleId);
|
List<RolePermission> selectRolePermissionListByRoleId(Long roleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看所有角色关联的权限
|
* 查看所有角色关联的权限
|
||||||
|
@ -46,4 +46,12 @@ public interface RolePermissionMapper extends BaseMapper<RolePermission> {
|
||||||
* @return 角色权限关系视图
|
* @return 角色权限关系视图
|
||||||
*/
|
*/
|
||||||
List<ViewRolePermission> viewRolePowerWithAll();
|
List<ViewRolePermission> viewRolePowerWithAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据权限id列表查询角色和权限
|
||||||
|
*
|
||||||
|
* @param permissionIds 权限id列表
|
||||||
|
* @return List<RolePermission>
|
||||||
|
*/
|
||||||
|
List<RolePermission> selectRolePermissionListByPermissionIds(List<Long> permissionIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,4 +31,12 @@ public interface UserRoleMapper extends BaseMapper<UserRole> {
|
||||||
*/
|
*/
|
||||||
void deleteBatchIdsByRoleIds(List<Long> roleIds);
|
void deleteBatchIdsByRoleIds(List<Long> roleIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色id列表查询
|
||||||
|
*
|
||||||
|
* @param ids 角色id列表
|
||||||
|
* @return {@link List<UserRole>}
|
||||||
|
*/
|
||||||
|
List<UserRole> selectListByRoleIds(List<Long> ids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,15 +53,11 @@
|
||||||
<!-- 根据用户id查询当前用户所有权限 -->
|
<!-- 根据用户id查询当前用户所有权限 -->
|
||||||
<select id="selectListByUserId" resultType="cn.bunny.services.domain.system.system.entity.Permission">
|
<select id="selectListByUserId" resultType="cn.bunny.services.domain.system.system.entity.Permission">
|
||||||
SELECT p.*
|
SELECT p.*
|
||||||
FROM sys_user u,
|
FROM sys_permission p
|
||||||
sys_user_role ur,
|
INNER JOIN sys_role_permission rp ON p.id = rp.power_id
|
||||||
sys_role_permission rp,
|
INNER JOIN sys_user_role ur ON rp.role_id = ur.role_id
|
||||||
sys_permission p
|
INNER JOIN sys_user u ON ur.user_id = u.id AND u.is_deleted = 0
|
||||||
WHERE u.id = ur.user_id
|
WHERE u.id = #{userId}
|
||||||
AND u.is_deleted = 0
|
|
||||||
AND ur.role_id = rp.role_id
|
|
||||||
AND rp.power_id = p.id
|
|
||||||
AND u.id = #{userId}
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -43,12 +43,10 @@
|
||||||
<!-- 根据用户id查询当前用户所有角色 -->
|
<!-- 根据用户id查询当前用户所有角色 -->
|
||||||
<select id="selectListByUserId" resultType="cn.bunny.services.domain.system.system.entity.Role">
|
<select id="selectListByUserId" resultType="cn.bunny.services.domain.system.system.entity.Role">
|
||||||
SELECT r.*
|
SELECT r.*
|
||||||
FROM sys_user u,
|
FROM sys_user u
|
||||||
sys_role r,
|
INNER JOIN sys_user_role ur ON u.id = ur.user_id
|
||||||
sys_user_role ur
|
INNER JOIN sys_role r ON r.id = ur.role_id
|
||||||
WHERE u.id = ur.user_id
|
WHERE u.is_deleted = 0
|
||||||
AND u.is_deleted = 0
|
|
||||||
AND r.id = ur.role_id
|
|
||||||
AND ur.user_id = #{userId}
|
AND ur.user_id = #{userId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
delete
|
delete
|
||||||
from sys_role_permission
|
from sys_role_permission
|
||||||
where power_id in
|
where power_id in
|
||||||
<foreach collection="powerIds" item="id" open="(" close=")" separator=",">
|
<foreach collection="permissionIds" item="id" open="(" close=")" separator=",">
|
||||||
#{id}
|
#{id}
|
||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
@ -40,7 +40,8 @@
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<!-- 根据角色id获取权限内容 -->
|
<!-- 根据角色id获取权限内容 -->
|
||||||
<select id="selectPowerListByRoleId" resultType="cn.bunny.services.domain.system.system.entity.RolePermission">
|
<select id="selectRolePermissionListByRoleId"
|
||||||
|
resultType="cn.bunny.services.domain.system.system.entity.RolePermission">
|
||||||
select *
|
select *
|
||||||
from sys_role_permission
|
from sys_role_permission
|
||||||
where role_id = #{roleId}
|
where role_id = #{roleId}
|
||||||
|
@ -61,4 +62,14 @@
|
||||||
LEFT JOIN sys_permission permission ON rp.power_id = permission.id
|
LEFT JOIN sys_permission permission ON rp.power_id = permission.id
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据权限id列表查询角色和权限 -->
|
||||||
|
<select id="selectRolePermissionListByPermissionIds"
|
||||||
|
resultType="cn.bunny.services.domain.system.system.entity.RolePermission">
|
||||||
|
SELECT * FROM
|
||||||
|
sys_role_permission WHERE power_id IN
|
||||||
|
<foreach collection="permissionIds" item="id" separator="," open="(" close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -39,4 +39,12 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
<!-- 根据角色id列表查询 -->
|
||||||
|
<select id="selectListByRoleIds" resultType="cn.bunny.services.domain.system.system.entity.UserRole">
|
||||||
|
SELECT * FROM sys_user_role WHERE role_id IN
|
||||||
|
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
package cn.bunny;
|
|
||||||
|
|
||||||
|
|
||||||
import cn.bunny.core.TypeConvertCore;
|
|
||||||
import cn.bunny.dao.entity.ColumnMetaData;
|
|
||||||
import cn.bunny.dao.entity.TableMetaData;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DatabaseMetaData;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
public class JDBCTest {
|
|
||||||
|
|
||||||
DatabaseMetaData metaData;
|
|
||||||
|
|
||||||
private final DataSource dataSource;
|
|
||||||
|
|
||||||
public JDBCTest(DataSource dataSource) {
|
|
||||||
this.dataSource = dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
|
||||||
metaData = connection.getMetaData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testComment() throws SQLException {
|
|
||||||
String tableName = "sys_i18n";
|
|
||||||
TableMetaData tableMetaData;
|
|
||||||
ResultSet tables = metaData.getTables(null, null, tableName, new String[]{"TABLE"});
|
|
||||||
|
|
||||||
// 获取表的注释信息
|
|
||||||
if (tables.next()) {
|
|
||||||
String remarks = tables.getString("REMARKS");
|
|
||||||
String tableCat = tables.getString("TABLE_CAT");
|
|
||||||
|
|
||||||
tableMetaData = TableMetaData.builder()
|
|
||||||
.tableName(tableName)
|
|
||||||
.comment(remarks)
|
|
||||||
.tableCat(tableCat)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
System.out.println(tableMetaData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAllTableComment() throws SQLException {
|
|
||||||
ResultSet tables = metaData.getTables(null, null, "%", new String[]{"TABLE"});
|
|
||||||
List<TableMetaData> list = new ArrayList<>();
|
|
||||||
|
|
||||||
while (tables.next()) {
|
|
||||||
String tableName = tables.getString("TABLE_NAME");
|
|
||||||
String remarks = tables.getString("REMARKS");
|
|
||||||
String tableCat = tables.getString("TABLE_CAT");
|
|
||||||
|
|
||||||
TableMetaData tableMetaData = TableMetaData.builder()
|
|
||||||
.tableName(tableName).comment(remarks)
|
|
||||||
.tableCat(tableCat)
|
|
||||||
.build();
|
|
||||||
list.add(tableMetaData);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testColumnInfo() throws SQLException {
|
|
||||||
List<ColumnMetaData> columns = new ArrayList<>();
|
|
||||||
|
|
||||||
try (ResultSet columnsRs = metaData.getColumns(null, null, "sys_i18n", null)) {
|
|
||||||
while (columnsRs.next()) {
|
|
||||||
ColumnMetaData column = new ColumnMetaData();
|
|
||||||
column.setColumnName(columnsRs.getString("COLUMN_NAME"));
|
|
||||||
column.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
|
|
||||||
column.setJdbcType(columnsRs.getString("TYPE_NAME"));
|
|
||||||
column.setJavaType(TypeConvertCore.convertToJavaType(column.getJdbcType()));
|
|
||||||
column.setComment(columnsRs.getString("REMARKS"));
|
|
||||||
|
|
||||||
columns.add(column);
|
|
||||||
System.out.println(column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(columns);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
package cn.bunny;
|
|
||||||
|
|
||||||
import cn.bunny.core.TypeConvertCore;
|
|
||||||
import cn.bunny.dao.entity.ColumnMetaData;
|
|
||||||
import cn.bunny.dao.entity.TableMetaData;
|
|
||||||
import net.sf.jsqlparser.JSQLParserException;
|
|
||||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
|
||||||
import net.sf.jsqlparser.statement.Statement;
|
|
||||||
import net.sf.jsqlparser.statement.create.table.CreateTable;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class SqlParserTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws JSQLParserException {
|
|
||||||
String sql = """
|
|
||||||
CREATE TABLE `sys_files` (
|
|
||||||
`id` bigint NOT NULL COMMENT '文件的唯一标识符,自动递增',
|
|
||||||
`filename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文件的名称',
|
|
||||||
`filepath` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文件在服务器上的存储路径',
|
|
||||||
`file_size` int NOT NULL COMMENT '文件的大小,以字节为单位',
|
|
||||||
`file_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件的MIME类型',
|
|
||||||
`download_count` int NULL DEFAULT 0 COMMENT '下载数量',
|
|
||||||
`create_user` bigint NOT NULL COMMENT '创建用户',
|
|
||||||
`update_user` bigint NULL DEFAULT NULL COMMENT '操作用户',
|
|
||||||
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录文件最后修改的时间戳',
|
|
||||||
`is_deleted` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '文件是否被删除',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
|
||||||
INDEX `idx_filename`(`filename` ASC) USING BTREE COMMENT '索引文件名',
|
|
||||||
INDEX `idx_filepath`(`filepath` ASC) USING BTREE COMMENT '索引文件路径',
|
|
||||||
INDEX `idx_file_type`(`file_type` ASC) USING BTREE COMMENT '索引文件类型',
|
|
||||||
INDEX `idx_update_user`(`update_user` ASC) USING BTREE COMMENT '索引创更新用户',
|
|
||||||
INDEX `idx_create_user`(`create_user` ASC) USING BTREE COMMENT '索引创建用户',
|
|
||||||
INDEX `idx_user`(`update_user` ASC, `create_user` ASC) USING BTREE COMMENT '索引创建用户和更新用户',
|
|
||||||
INDEX `idx_time`(`update_time` ASC, `create_time` ASC) USING BTREE COMMENT '索引创建时间和更新时间'
|
|
||||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统文件表' ROW_FORMAT = DYNAMIC;
|
|
||||||
""";
|
|
||||||
|
|
||||||
TableMetaData tableInfo = new TableMetaData();
|
|
||||||
|
|
||||||
// 解析sql
|
|
||||||
Statement statement = CCJSqlParserUtil.parse(sql);
|
|
||||||
if (!(statement instanceof CreateTable createTable)) {
|
|
||||||
throw new IllegalArgumentException("Not a CREATE TABLE statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置表基本信息
|
|
||||||
tableInfo.setTableName(createTable.getTable().getName());
|
|
||||||
tableInfo.setTableType("TABLE");
|
|
||||||
String tableOptionsStrings = String.join(" ", createTable.getTableOptionsStrings());
|
|
||||||
|
|
||||||
// 注释信息
|
|
||||||
Pattern pattern = Pattern.compile("COMMENT\\s*=\\s*'(.*?)'", Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher matcher = pattern.matcher(tableOptionsStrings);
|
|
||||||
if (matcher.find()) {
|
|
||||||
tableInfo.setComment(matcher.group(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析列信息
|
|
||||||
List<ColumnMetaData> columnMetaData = createTable.getColumnDefinitions()
|
|
||||||
.stream().map(column -> {
|
|
||||||
// 列信息
|
|
||||||
ColumnMetaData columnInfo = new ColumnMetaData();
|
|
||||||
|
|
||||||
// 列名称
|
|
||||||
columnInfo.setColumnName(column.getColumnName());
|
|
||||||
|
|
||||||
// 设置 JDBC 类型
|
|
||||||
String dataType = column.getColDataType().getDataType();
|
|
||||||
columnInfo.setJdbcType(dataType);
|
|
||||||
|
|
||||||
// 设置 Java 类型
|
|
||||||
String javaType = TypeConvertCore.convertToJavaType(dataType.contains("varchar") ? "varchar" : dataType);
|
|
||||||
columnInfo.setJavaType(javaType);
|
|
||||||
|
|
||||||
// 设置 JavaScript 类型
|
|
||||||
columnInfo.setJavascriptType(StringUtils.uncapitalize(javaType));
|
|
||||||
|
|
||||||
// 列字段转成 下划线 -> 小驼峰
|
|
||||||
columnInfo.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
|
|
||||||
// 列字段转成 下划线 -> 大驼峰名称
|
|
||||||
columnInfo.setUppercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName(), true));
|
|
||||||
|
|
||||||
// 解析注释
|
|
||||||
List<String> columnSpecs = column.getColumnSpecs();
|
|
||||||
String columnSpecsString = String.join(" ", columnSpecs);
|
|
||||||
Matcher columnSpecsStringMatcher = Pattern.compile("COMMENT\\s*'(.*?)'", Pattern.CASE_INSENSITIVE).matcher(columnSpecsString);
|
|
||||||
if (columnSpecsStringMatcher.find()) {
|
|
||||||
columnInfo.setComment(columnSpecsStringMatcher.group(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return columnInfo;
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
System.out.println(tableInfo);
|
|
||||||
System.out.println("----------------------------------------------------------------------------------------");
|
|
||||||
System.out.println(columnMetaData);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
package cn.bunny;
|
|
||||||
|
|
||||||
import cn.bunny.core.TypeConvertCore;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.assertj.core.util.introspection.CaseFormatUtils;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
public class StringFormatTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test1() {
|
|
||||||
System.out.println(CaseFormatUtils.toCamelCase("user_login" ));
|
|
||||||
System.out.println(CaseFormatUtils.toCamelCase("userLogin" ));
|
|
||||||
System.out.println(CaseFormatUtils.toCamelCase("UserLogin" ));
|
|
||||||
|
|
||||||
System.out.println("--------------------------------" );
|
|
||||||
|
|
||||||
System.out.println(StringUtils.lowerCase("user_login" ));
|
|
||||||
System.out.println(StringUtils.lowerCase("userLogin" ));
|
|
||||||
System.out.println(StringUtils.lowerCase("UserLogin" ));
|
|
||||||
|
|
||||||
System.out.println("--------------------------------" );
|
|
||||||
|
|
||||||
System.out.println(StringUtils.upperCase("user_login" ));
|
|
||||||
System.out.println(StringUtils.upperCase("userLogin" ));
|
|
||||||
System.out.println(StringUtils.upperCase("UserLogin" ));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test2() {
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("user_login_A" ));
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("User_Login_A" ));
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("userLoginA" ));
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("UserLoginA" ));
|
|
||||||
|
|
||||||
System.out.println("--------------------------------" );
|
|
||||||
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("i18n_type_A" , true));
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("User_Login_A" , true));
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("userLoginA" , true));
|
|
||||||
System.out.println(TypeConvertCore.convertToCamelCase("UserLoginA" , true));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package cn.bunny;
|
|
||||||
|
|
||||||
import cn.hutool.crypto.digest.MD5;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
public class TimeTest {
|
|
||||||
@Test
|
|
||||||
void timeTest() {
|
|
||||||
long currentTimeMillis = System.currentTimeMillis();
|
|
||||||
String digestHex = MD5.create().digestHex(currentTimeMillis + "");
|
|
||||||
System.out.println(currentTimeMillis);
|
|
||||||
System.out.println(digestHex);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
package cn.bunny.service.impl;
|
|
||||||
|
|
||||||
import cn.bunny.core.ResourceFileCore;
|
|
||||||
import cn.bunny.dao.vo.VmsPathVo;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
class VmsServiceImplTest {
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void vmsResourcePathList() throws IOException, URISyntaxException {
|
|
||||||
List<String> vmsFiles = ResourceFileCore.getAbsoluteFiles("vms");
|
|
||||||
System.out.println(vmsFiles);
|
|
||||||
|
|
||||||
System.out.println("--------------------------------------------------------------");
|
|
||||||
|
|
||||||
List<String> vmsRelativeFiles = ResourceFileCore.getRelativeFiles("vms");
|
|
||||||
System.out.println(vmsRelativeFiles);
|
|
||||||
|
|
||||||
System.out.println("--------------------------集合对象模式------------------------------------");
|
|
||||||
|
|
||||||
Map<String, List<VmsPathVo>> map = vmsRelativeFiles.stream().map(vmFile -> {
|
|
||||||
String[] filepathList = vmFile.split("/");
|
|
||||||
String filename = filepathList[filepathList.length - 1].replace(".vm", "");
|
|
||||||
|
|
||||||
return VmsPathVo.builder().name(vmFile).label(filename).type(filepathList[0]).build();
|
|
||||||
}).collect(Collectors.groupingBy(VmsPathVo::getType));
|
|
||||||
|
|
||||||
System.out.println(JSON.toJSONString(map));
|
|
||||||
|
|
||||||
System.out.println("----------------------------二维数组格式----------------------------------");
|
|
||||||
List<List<VmsPathVo>> listMap = vmsRelativeFiles.stream().map(vmFile -> {
|
|
||||||
String[] filepathList = vmFile.split("/");
|
|
||||||
String filename = filepathList[filepathList.length - 1].replace(".vm", "");
|
|
||||||
|
|
||||||
return VmsPathVo.builder().name(vmFile).label(filename).type(filepathList[0]).build();
|
|
||||||
})
|
|
||||||
.collect(Collectors.groupingBy(VmsPathVo::getType))
|
|
||||||
.values().stream().toList();
|
|
||||||
|
|
||||||
System.out.println(JSON.toJSONString(listMap));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package cn.bunny.utils;
|
|
||||||
|
|
||||||
import cn.bunny.dao.entity.TableMetaData;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DatabaseMetaData;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class DatabaseInfoCoreTest {
|
|
||||||
|
|
||||||
String tableName = "sys_i18n";
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DataSource dataSource;
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testTableInfoMetaData() {
|
|
||||||
TableMetaData tableMetaData;
|
|
||||||
|
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
|
||||||
DatabaseMetaData metaData = connection.getMetaData();
|
|
||||||
ResultSet tables = metaData.getTables(null, null, tableName, new String[]{"TABLE"});
|
|
||||||
|
|
||||||
// 获取表的注释信息
|
|
||||||
if (tables.next()) {
|
|
||||||
String remarks = tables.getString("REMARKS");
|
|
||||||
String tableCat = tables.getString("TABLE_CAT");
|
|
||||||
String tableType = tables.getString("TABLE_TYPE");
|
|
||||||
|
|
||||||
tableMetaData = TableMetaData.builder()
|
|
||||||
.tableName(tableName)
|
|
||||||
.comment(remarks)
|
|
||||||
.tableCat(tableCat)
|
|
||||||
.tableType(tableType)
|
|
||||||
.build();
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("数据表不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(tableMetaData);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
@Test
|
|
||||||
void getDbTableList() {
|
|
||||||
String dbName = "auth_admin";
|
|
||||||
|
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
|
||||||
DatabaseMetaData metaData = connection.getMetaData();
|
|
||||||
ResultSet tables = metaData.getTables(dbName, null, "%", new String[]{"TABLE"});
|
|
||||||
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
|
|
||||||
while (tables.next()) {
|
|
||||||
dbName = tables.getString("TABLE_NAME");
|
|
||||||
list.add(dbName);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
2
pom.xml
2
pom.xml
|
@ -43,7 +43,7 @@
|
||||||
<velocity-tools.version>3.1</velocity-tools.version>
|
<velocity-tools.version>3.1</velocity-tools.version>
|
||||||
<HikariCP.version>6.2.1</HikariCP.version>
|
<HikariCP.version>6.2.1</HikariCP.version>
|
||||||
<dynamic.datasource.version>4.3.1</dynamic.datasource.version>
|
<dynamic.datasource.version>4.3.1</dynamic.datasource.version>
|
||||||
<jackson-dataType.version>2.12.3</jackson-dataType.version>
|
<jackson-dataType.version>2.19.0</jackson-dataType.version>
|
||||||
<quartz-scheduler.version>2.3.2</quartz-scheduler.version>
|
<quartz-scheduler.version>2.3.2</quartz-scheduler.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,5 @@
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.aop.scanner;
|
package cn.bunny.services.aop.scanner;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package cn.bunny.services.core.cache;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EmailCacheService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储邮箱验证码
|
||||||
|
*
|
||||||
|
* @param email 邮箱
|
||||||
|
* @param emailCode 邮箱验证码
|
||||||
|
*/
|
||||||
|
public void buildEmailCodeCache(@NotNull String email, String emailCode) {
|
||||||
|
// 在Redis中存储验证码
|
||||||
|
String emailCodePrefix = RedisUserConstant.getUserEmailCodePrefix(email);
|
||||||
|
redisTemplate.opsForValue().set(emailCodePrefix, emailCode, RedisUserConstant.REDIS_EXPIRATION_TIME, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取邮箱验证码
|
||||||
|
*
|
||||||
|
* @param email 邮箱
|
||||||
|
* @return 邮箱验证码
|
||||||
|
*/
|
||||||
|
public String getEmailCode(@NotNull String email) {
|
||||||
|
String userEmailCodePrefix = RedisUserConstant.getUserEmailCodePrefix(email);
|
||||||
|
Object emailCode = redisTemplate.opsForValue().get(userEmailCodePrefix);
|
||||||
|
|
||||||
|
if (emailCode == null) {
|
||||||
|
throw new UsernameNotFoundException(ResultCodeEnum.EMAIL_CODE_EMPTY.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除邮箱验证码
|
||||||
|
*
|
||||||
|
* @param email 邮箱
|
||||||
|
*/
|
||||||
|
public void deleteEmailCodeCache(String email) {
|
||||||
|
String emailCodePrefix = RedisUserConstant.getUserEmailCodePrefix(email);
|
||||||
|
redisTemplate.delete(emailCodePrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.redis;
|
package cn.bunny.services.core.cache;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
@ -26,7 +26,7 @@ public class RedisService {
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<String> scannerRedisKeyByPage(long pageNum, long pageSize) {
|
public List<String> scannerRedisKeyByPage(long pageNum, long pageSize) {
|
||||||
String prefix = RedisUserConstant.getAdminLoginInfoPrefix("*");
|
String prefix = RedisUserConstant.getUserLoginInfoPrefix("*");
|
||||||
|
|
||||||
List<String> keys = new ArrayList<>();
|
List<String> keys = new ArrayList<>();
|
||||||
ScanOptions scanOptions = ScanOptions.scanOptions()
|
ScanOptions scanOptions = ScanOptions.scanOptions()
|
110
service/src/main/java/cn/bunny/services/core/cache/UserAuthorizationCacheService.java
vendored
Normal file
110
service/src/main/java/cn/bunny/services/core/cache/UserAuthorizationCacheService.java
vendored
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package cn.bunny.services.core.cache;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.Permission;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.Role;
|
||||||
|
import cn.bunny.services.mapper.system.PermissionMapper;
|
||||||
|
import cn.bunny.services.mapper.system.RoleMapper;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.TypeReference;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserAuthorizationCacheService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PermissionMapper permissionMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户ID和用户名获取角色列表(缓存优先)
|
||||||
|
*
|
||||||
|
* <p><b>执行逻辑</b>:</p>
|
||||||
|
* <ol>
|
||||||
|
* <li>尝试从Redis缓存获取用户角色(使用用户名作为缓存key)</li>
|
||||||
|
* <li>若缓存未命中,则从数据库查询并写入缓存(有效期1天)</li>
|
||||||
|
* <li>若缓存命中,反序列化缓存数据返回</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param userId 用户ID(数据库查询用)
|
||||||
|
* @param username 用户名(缓存key生成用)
|
||||||
|
* @return 用户角色列表
|
||||||
|
*/
|
||||||
|
public List<Role> getRolesByUser(Long userId, String username) {
|
||||||
|
// 角色列表
|
||||||
|
List<Role> roleList;
|
||||||
|
|
||||||
|
// 尝试从缓存中获取当前用户角色
|
||||||
|
String userRolesCodePrefix = RedisUserConstant.getUserRolesCodePrefix(username);
|
||||||
|
Object object = redisTemplate.opsForValue().get(userRolesCodePrefix);
|
||||||
|
|
||||||
|
// 为空查询数据库,并将信息存入Redis
|
||||||
|
if (Objects.isNull(object)) {
|
||||||
|
roleList = roleMapper.selectListByUserId(userId);
|
||||||
|
redisTemplate.opsForValue().set(userRolesCodePrefix, roleList, 1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
// 从缓存中得到当前用户的角色列表
|
||||||
|
else {
|
||||||
|
String jsonString = JSON.toJSONString(object);
|
||||||
|
TypeReference<List<Role>> reference = new TypeReference<>() {
|
||||||
|
};
|
||||||
|
List<Role> list = JSON.parseObject(jsonString, reference);
|
||||||
|
// 防止 list 为空报错
|
||||||
|
roleList = list != null ? list : new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户ID和用户名获取权限列表(缓存优先)
|
||||||
|
*
|
||||||
|
* <p><b>执行逻辑</b>:</p>
|
||||||
|
* <ol>
|
||||||
|
* <li>尝试从Redis缓存获取用户权限(使用用户名作为缓存key)</li>
|
||||||
|
* <li>若缓存未命中,则从数据库查询并写入缓存(有效期1天)</li>
|
||||||
|
* <li>若缓存命中,反序列化缓存数据返回</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param userId 用户ID(数据库查询用)
|
||||||
|
* @param username 用户名(缓存key生成用)
|
||||||
|
* @return 用户权限列表
|
||||||
|
*/
|
||||||
|
public List<Permission> getPermissionsByUser(Long userId, String username) {
|
||||||
|
// 权限列表
|
||||||
|
List<Permission> permissionList;
|
||||||
|
|
||||||
|
// 获取缓存中的用户权限
|
||||||
|
String userPermissionCodePrefix = RedisUserConstant.getUserPermissionCodePrefix(username);
|
||||||
|
Object object = redisTemplate.opsForValue().get(userPermissionCodePrefix);
|
||||||
|
|
||||||
|
// 为空查询数据库,并将用户权限放在Redis中
|
||||||
|
if (Objects.isNull(object)) {
|
||||||
|
permissionList = permissionMapper.selectListByUserId(userId);
|
||||||
|
redisTemplate.opsForValue().set(userPermissionCodePrefix, permissionList, 1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
// 从缓存中得到当前用户权限
|
||||||
|
else {
|
||||||
|
String jsonString = JSON.toJSONString(object);
|
||||||
|
TypeReference<List<Permission>> reference = new TypeReference<>() {
|
||||||
|
};
|
||||||
|
List<Permission> list = JSON.parseObject(jsonString, reference);
|
||||||
|
// 防止 list 为空报错
|
||||||
|
permissionList = list != null ? list : new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissionList;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cn.bunny.services.core.cache;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserCacheCleaner {
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
public void cleanUserLoginCache(String username) {
|
||||||
|
String key = RedisUserConstant.getUserLoginInfoPrefix(username);
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUserRoleCache(String username) {
|
||||||
|
String key = RedisUserConstant.getUserRolesCodePrefix(username);
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUserPermissionCache(String username) {
|
||||||
|
String key = RedisUserConstant.getUserPermissionCodePrefix(username);
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanAllUserCache(String username) {
|
||||||
|
cleanUserLoginCache(username);
|
||||||
|
cleanUserRoleCache(username);
|
||||||
|
cleanUserPermissionCache(username);
|
||||||
|
}
|
||||||
|
}
|
105
service/src/main/java/cn/bunny/services/core/cache/UserLoginVoBuilderCacheService.java
vendored
Normal file
105
service/src/main/java/cn/bunny/services/core/cache/UserLoginVoBuilderCacheService.java
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
package cn.bunny.services.core.cache;
|
||||||
|
|
||||||
|
import cn.bunny.services.core.utils.RoleHelper;
|
||||||
|
import cn.bunny.services.domain.common.constant.LocalDateTimeConstant;
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.Permission;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.Role;
|
||||||
|
import cn.bunny.services.mapper.system.PermissionMapper;
|
||||||
|
import cn.bunny.services.mapper.system.RoleMapper;
|
||||||
|
import cn.bunny.services.minio.MinioHelper;
|
||||||
|
import cn.bunny.services.utils.JwtTokenUtil;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.Value;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserLoginVoBuilderCacheService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MinioHelper minioHelper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PermissionMapper permissionMapper;
|
||||||
|
|
||||||
|
public LoginVo buildLoginUserVo(AdminUser user, long readMeDay) {
|
||||||
|
String username = user.getUsername();
|
||||||
|
Long userId = user.getId();
|
||||||
|
|
||||||
|
UserAuthInfo authInfo = getAuthInfo(userId, user);
|
||||||
|
|
||||||
|
// 设置用户返回对象
|
||||||
|
LoginVo loginVo = new LoginVo();
|
||||||
|
BeanUtils.copyProperties(user, loginVo);
|
||||||
|
loginVo.setPersonDescription(user.getSummary());
|
||||||
|
loginVo.setRoles(authInfo.getRoles());
|
||||||
|
loginVo.setPermissions(authInfo.getPermissions());
|
||||||
|
|
||||||
|
// 使用用户名创建token
|
||||||
|
String token = JwtTokenUtil.createToken(userId, username, (int) readMeDay);
|
||||||
|
loginVo.setToken(token);
|
||||||
|
loginVo.setRefreshToken(token);
|
||||||
|
loginVo.setReadMeDay(readMeDay);
|
||||||
|
|
||||||
|
// 计算过期时间,并格式化返回
|
||||||
|
String expires = calculateExpires(readMeDay);
|
||||||
|
loginVo.setExpires(expires);
|
||||||
|
|
||||||
|
// 设置用户头像
|
||||||
|
String userAvatar = minioHelper.getUserAvatar(user.getAvatar());
|
||||||
|
loginVo.setAvatar(userAvatar);
|
||||||
|
|
||||||
|
String loginInfoPrefix = RedisUserConstant.getUserLoginInfoPrefix(username);
|
||||||
|
redisTemplate.opsForValue().set(loginInfoPrefix, loginVo, readMeDay, TimeUnit.DAYS);
|
||||||
|
return loginVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserAuthInfo getAuthInfo(Long userId, AdminUser user) {
|
||||||
|
// 用户角色
|
||||||
|
List<String> roles = new ArrayList<>(roleMapper.selectListByUserId(userId).stream().map(Role::getRoleCode).toList());
|
||||||
|
|
||||||
|
// 判断是否是 admin 如果是admin 赋予所有权限
|
||||||
|
List<String> permissions = new ArrayList<>();
|
||||||
|
boolean isAdmin = RoleHelper.checkAdmin(roles, permissions, user);
|
||||||
|
if (!isAdmin) {
|
||||||
|
permissions = permissionMapper.selectListByUserId(userId).stream()
|
||||||
|
.map(Permission::getPowerCode)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为这两个去重,在判断 checkAdmin 会重新赋值
|
||||||
|
permissions = permissions.stream().distinct().toList();
|
||||||
|
roles = roles.stream().distinct().toList();
|
||||||
|
|
||||||
|
return new UserAuthInfo(roles, permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String calculateExpires(long readMeDay) {
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.now();
|
||||||
|
LocalDateTime plusDay = localDateTime.plusDays(readMeDay);
|
||||||
|
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS_SLASH);
|
||||||
|
return plusDay.format(dateTimeFormatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value
|
||||||
|
private static class UserAuthInfo {
|
||||||
|
List<String> roles;
|
||||||
|
List<String> permissions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ClearAllUserCacheEvent extends ApplicationEvent {
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
public ClearAllUserCacheEvent(Object source, String key) {
|
||||||
|
super(source);
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UpdateUserinfoByPermissionIdsEvent extends ApplicationEvent {
|
||||||
|
private final List<Long> permissionIds;
|
||||||
|
|
||||||
|
public UpdateUserinfoByPermissionIdsEvent(Object source, List<Long> permissionIds) {
|
||||||
|
super(source);
|
||||||
|
this.permissionIds = permissionIds;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UpdateUserinfoByRoleIdsEvent extends ApplicationEvent {
|
||||||
|
private final List<Long> roleIds;
|
||||||
|
|
||||||
|
public UpdateUserinfoByRoleIdsEvent(Object source, List<Long> roleIds) {
|
||||||
|
super(source);
|
||||||
|
this.roleIds = roleIds;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UpdateUserinfoByUserIdsEvent extends ApplicationEvent {
|
||||||
|
private final List<Long> userIds;
|
||||||
|
|
||||||
|
public UpdateUserinfoByUserIdsEvent(Object source, List<Long> userIds) {
|
||||||
|
super(source);
|
||||||
|
this.userIds = userIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.excel;
|
package cn.bunny.services.core.event.listener.excel;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.excel;
|
package cn.bunny.services.core.event.listener.excel;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
||||||
import cn.bunny.services.domain.system.system.entity.Permission;
|
import cn.bunny.services.domain.system.system.entity.Permission;
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.bunny.services.excel;
|
package cn.bunny.services.core.event.listener.excel;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.domain.system.system.entity.Role;
|
import cn.bunny.services.domain.system.system.entity.Role;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.service.system.RoleService;
|
import cn.bunny.services.service.system.RoleService;
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cn.bunny.services.core.event.listener.user;
|
||||||
|
|
||||||
|
import cn.bunny.services.core.cache.UserCacheCleaner;
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
|
import cn.bunny.services.mapper.system.UserMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Component("AbstractUserInfoUpdateHandler")
|
||||||
|
public abstract class AbstractUserInfoUpdateHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected UserMapper userMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected UserCacheCleaner userCacheCleaner;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
public void processUserUpdate(List<Long> userIds, Consumer<AdminUser> postProcess) {
|
||||||
|
if (userIds.isEmpty()) return;
|
||||||
|
|
||||||
|
List<AdminUser> adminUsers = userMapper.selectBatchIds(userIds);
|
||||||
|
adminUsers.stream()
|
||||||
|
.filter(user -> redisTemplate.hasKey(RedisUserConstant.getUserLoginInfoPrefix(user.getUsername())))
|
||||||
|
.forEach(postProcess);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package cn.bunny.services.core.event.listener.user;
|
||||||
|
|
||||||
|
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
|
||||||
|
import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
|
||||||
|
import cn.bunny.services.core.event.event.UpdateUserinfoByPermissionIdsEvent;
|
||||||
|
import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
|
||||||
|
import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.RolePermission;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.UserRole;
|
||||||
|
import cn.bunny.services.mapper.system.RolePermissionMapper;
|
||||||
|
import cn.bunny.services.mapper.system.UserRoleMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component("UserinfoUpdateListener")
|
||||||
|
public class UserinfoUpdateListener extends AbstractUserInfoUpdateHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserLoginVoBuilderCacheService userLoginVoBuilderCacheService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserRoleMapper userRoleMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RolePermissionMapper rolePermissionMapper;
|
||||||
|
|
||||||
|
/* 根据用户id更新用户信息,重新生成LoginVo对象 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerUpdateUserinfoByUserIds(UpdateUserinfoByUserIdsEvent event) {
|
||||||
|
List<Long> userIds = event.getUserIds();
|
||||||
|
processUserUpdate(userIds, user -> {
|
||||||
|
userCacheCleaner.cleanAllUserCache(user.getUsername());
|
||||||
|
userLoginVoBuilderCacheService.buildLoginUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据角色id更新用户信息,重新生成LoginVo对象 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerUserinfoUpdateByRoleId(UpdateUserinfoByRoleIdsEvent event) {
|
||||||
|
List<Long> roleIds = event.getRoleIds();
|
||||||
|
List<UserRole> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
|
||||||
|
List<Long> userIds = userRoles.stream().map(UserRole::getUserId).toList();
|
||||||
|
|
||||||
|
UpdateUserinfoByUserIdsEvent userIdsEvent = new UpdateUserinfoByUserIdsEvent(event.getSource(), userIds);
|
||||||
|
handlerUpdateUserinfoByUserIds(userIdsEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据角色id更新用户信息,重新生成LoginVo对象 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerUserinfoUpdateByPermissionId(UpdateUserinfoByPermissionIdsEvent event) {
|
||||||
|
List<Long> permissionIds = event.getPermissionIds();
|
||||||
|
List<RolePermission> rolePermissions = rolePermissionMapper.selectRolePermissionListByPermissionIds(permissionIds);
|
||||||
|
List<Long> roleIds = rolePermissions.stream().map(RolePermission::getRoleId).toList();
|
||||||
|
|
||||||
|
UpdateUserinfoByRoleIdsEvent roleIdsEvent = new UpdateUserinfoByRoleIdsEvent(event.getSource(), roleIds);
|
||||||
|
handlerUserinfoUpdateByRoleId(roleIdsEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 清除用户登录、角色、权限所有缓存 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerDeleteAllUserCache(ClearAllUserCacheEvent event) {
|
||||||
|
userCacheCleaner.cleanAllUserCache(event.getKey());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cn.bunny.services.core.strategy.export;
|
||||||
|
|
||||||
|
import com.alibaba.excel.EasyExcel;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
public class ExcelExportStrategy implements ExportStrategy<List<?>> {
|
||||||
|
|
||||||
|
private final Class<?> clazz;
|
||||||
|
private final String sheetName;
|
||||||
|
|
||||||
|
public ExcelExportStrategy(Class<?> clazz, String sheetName) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.sheetName = sheetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void export(List<?> data, ZipOutputStream zipOutputStream, String filename) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream excelOutputStream = new ByteArrayOutputStream();
|
||||||
|
EasyExcel.write(excelOutputStream, clazz).sheet(sheetName).doWrite(data);
|
||||||
|
|
||||||
|
// 将Excel写入到Zip中
|
||||||
|
ZipEntry zipEntry = new ZipEntry(filename);
|
||||||
|
zipOutputStream.putNextEntry(zipEntry);
|
||||||
|
zipOutputStream.write(excelOutputStream.toByteArray());
|
||||||
|
zipOutputStream.closeEntry();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package cn.bunny.services.core.strategy.export;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
public interface ExportStrategy<T> {
|
||||||
|
void export(T data, ZipOutputStream zipOutputStream, String filename) throws IOException;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.bunny.services.core.strategy.export;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
public class JsonExportStrategy implements ExportStrategy<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void export(Object data, ZipOutputStream zipOutputStream, String filename) {
|
||||||
|
try {
|
||||||
|
ZipEntry zipEntry = new ZipEntry(filename);
|
||||||
|
zipOutputStream.putNextEntry(zipEntry);
|
||||||
|
zipOutputStream.write(JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8));
|
||||||
|
zipOutputStream.closeEntry();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.service.system.helper.login;
|
package cn.bunny.services.core.strategy.login;
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
|
@ -1,23 +1,22 @@
|
||||||
package cn.bunny.services.service.system.helper.login;
|
package cn.bunny.services.core.strategy.login;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
import cn.bunny.services.core.cache.EmailCacheService;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
import cn.bunny.services.mapper.system.UserMapper;
|
import cn.bunny.services.mapper.system.UserMapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邮箱登录策略
|
* 邮箱登录策略
|
||||||
*/
|
*/
|
||||||
public class EmailLoginStrategy implements LoginStrategy {
|
public class EmailLoginStrategy implements LoginStrategy {
|
||||||
private final RedisTemplate<String, Object> redisTemplate;
|
private final EmailCacheService emailCacheService;
|
||||||
private final UserMapper userMapper;
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
public EmailLoginStrategy(RedisTemplate<String, Object> redisTemplate, UserMapper userMapper) {
|
public EmailLoginStrategy(EmailCacheService emailCacheService, UserMapper userMapper) {
|
||||||
this.redisTemplate = redisTemplate;
|
this.emailCacheService = emailCacheService;
|
||||||
this.userMapper = userMapper;
|
this.userMapper = userMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +37,10 @@ public class EmailLoginStrategy implements LoginStrategy {
|
||||||
String emailCode = loginDto.getEmailCode().toLowerCase();
|
String emailCode = loginDto.getEmailCode().toLowerCase();
|
||||||
|
|
||||||
// 查找Redis中的验证码
|
// 查找Redis中的验证码
|
||||||
Object redisEmailCode = redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username));
|
String redisEmailCode = emailCacheService.getEmailCode(username);
|
||||||
if (redisEmailCode == null) {
|
|
||||||
throw new UsernameNotFoundException(ResultCodeEnum.EMAIL_CODE_EMPTY.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断用户邮箱验证码是否和Redis中发送的验证码
|
// 判断用户邮箱验证码是否和Redis中发送的验证码
|
||||||
if (!emailCode.equals(redisEmailCode.toString().toLowerCase())) {
|
if (!emailCode.equals(redisEmailCode.toLowerCase())) {
|
||||||
throw new UsernameNotFoundException(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING.getMessage());
|
throw new UsernameNotFoundException(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +59,7 @@ public class EmailLoginStrategy implements LoginStrategy {
|
||||||
@Override
|
@Override
|
||||||
public void authenticateAfter(LoginDto loginDto, AdminUser adminUser) {
|
public void authenticateAfter(LoginDto loginDto, AdminUser adminUser) {
|
||||||
// 将Redis中验证码删除
|
// 将Redis中验证码删除
|
||||||
String emailCodePrefix = RedisUserConstant.getAdminUserEmailCodePrefix(loginDto.getUsername());
|
emailCacheService.deleteEmailCodeCache(loginDto.getUsername());
|
||||||
redisTemplate.delete(emailCodePrefix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.service.system.helper.login;
|
package cn.bunny.services.core.strategy.login;
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.service.system.helper.login;
|
package cn.bunny.services.core.strategy.login;
|
||||||
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
||||||
|
@ -21,7 +21,7 @@ public interface LoginStrategy {
|
||||||
* 登录完成后的内容
|
* 登录完成后的内容
|
||||||
*
|
*
|
||||||
* @param loginDto 登录参数
|
* @param loginDto 登录参数
|
||||||
* @param adminUser
|
* @param adminUser {@link AdminUser}
|
||||||
*/
|
*/
|
||||||
void authenticateAfter(LoginDto loginDto, AdminUser adminUser);
|
void authenticateAfter(LoginDto loginDto, AdminUser adminUser);
|
||||||
}
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package cn.bunny.services.core.template;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
||||||
|
import cn.bunny.services.processor.TreeProcessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class PermissionTreeProcessor extends TreeProcessor<PermissionExcel> {
|
||||||
|
@Override
|
||||||
|
public List<PermissionExcel> findRoots(List<PermissionExcel> list) {
|
||||||
|
return list.stream()
|
||||||
|
.filter(p -> p.getParentId() == null || p.getParentId() == 0)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildChildren(PermissionExcel parent, List<PermissionExcel> list) {
|
||||||
|
List<PermissionExcel> children = list.stream()
|
||||||
|
.filter(p -> parent.getId().equals(p.getParentId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!children.isEmpty()) {
|
||||||
|
parent.setChildren(children);
|
||||||
|
children.forEach(child -> buildChildren(child, list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package cn.bunny.services.service.configuration.helper.email;
|
package cn.bunny.services.core.template.email;
|
||||||
|
|
||||||
import cn.bunny.services.config.mail.MailSenderConfiguration;
|
import cn.bunny.services.config.mail.MailSenderConfiguration;
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.email.EmailSend;
|
import cn.bunny.services.domain.common.model.dto.email.EmailSend;
|
||||||
import cn.bunny.services.domain.common.model.dto.email.EmailSendInit;
|
import cn.bunny.services.domain.common.model.dto.email.EmailSendInit;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailUsers;
|
import cn.bunny.services.domain.system.email.entity.EmailUsers;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.service.configuration.helper.email;
|
package cn.bunny.services.core.template.email;
|
||||||
|
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
||||||
import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
|
import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
|
|
@ -1,29 +1,13 @@
|
||||||
package cn.bunny.services.service.system.helper.role;
|
package cn.bunny.services.core.utils;
|
||||||
|
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
|
||||||
import cn.bunny.services.domain.common.constant.SecurityConfigConstant;
|
import cn.bunny.services.domain.common.constant.SecurityConfigConstant;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
import cn.bunny.services.mapper.system.UserMapper;
|
|
||||||
import cn.bunny.services.service.system.helper.UserLoginHelper;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Component
|
|
||||||
public class RoleHelper {
|
public class RoleHelper {
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserMapper userMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserLoginHelper userloginHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断用户是否具有管理员权限
|
* 判断用户是否具有管理员权限
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -80,45 +64,4 @@ public class RoleHelper {
|
||||||
// 判断是否是 admin
|
// 判断是否是 admin
|
||||||
return roleList.stream().anyMatch(permissionList::contains);
|
return roleList.stream().anyMatch(permissionList::contains);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量更新Redis中用户权限信息
|
|
||||||
*
|
|
||||||
* <p><b>使用场景</b>:当用户角色或权限变更时,同步更新Redis中的用户权限数据</p>
|
|
||||||
*
|
|
||||||
* <p><b>实现策略</b>:</p>
|
|
||||||
* <ol>
|
|
||||||
* <li><b>主动更新(当前实现)</b>:重新构建用户权限信息并更新Redis缓存</li>
|
|
||||||
* <li><b>强制下线</b>:删除用户登录态,强制重新认证获取最新权限</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* <p><b>技术实现</b>:</p>
|
|
||||||
* <ul>
|
|
||||||
* <li>采用Spring事件驱动机制触发更新</li>
|
|
||||||
* <li>使用并行流(parallelStream)提高批量处理效率</li>
|
|
||||||
* <li>仅更新Redis中存在登录态的用户</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param userIds 需要更新的用户ID集合
|
|
||||||
* (仅处理集合中存在的有效用户)
|
|
||||||
* @see RedisUserConstant Redis键前缀常量
|
|
||||||
* @see UserLoginHelper#buildLoginUserVo 用户登录信息构建方法
|
|
||||||
*/
|
|
||||||
public void updateUserRedisInfo(List<Long> userIds) {
|
|
||||||
if (userIds.isEmpty()) return;
|
|
||||||
|
|
||||||
// 批量查询用户
|
|
||||||
List<AdminUser> adminUsers = userMapper.selectBatchIds(userIds);
|
|
||||||
|
|
||||||
// 并行处理用户更新
|
|
||||||
adminUsers.parallelStream()
|
|
||||||
.filter(user -> redisTemplate.hasKey(RedisUserConstant.getAdminLoginInfoPrefix(user.getUsername())))
|
|
||||||
.forEach(user -> {
|
|
||||||
// 策略1: 更新用户权限信息
|
|
||||||
userloginHelper.buildLoginUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
|
||||||
|
|
||||||
// 或者策略2: 强制用户下线
|
|
||||||
// redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(user.getUsername()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.service.system.helper;
|
package cn.bunny.services.core.utils;
|
||||||
|
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
import cn.bunny.services.domain.system.system.entity.RouterRole;
|
import cn.bunny.services.domain.system.system.entity.RouterRole;
|
||||||
|
@ -8,7 +8,6 @@ import cn.bunny.services.domain.system.system.views.ViewRolePermission;
|
||||||
import cn.bunny.services.domain.system.system.views.ViewRouterRole;
|
import cn.bunny.services.domain.system.system.views.ViewRouterRole;
|
||||||
import cn.bunny.services.domain.system.system.vo.router.WebUserRouterVo;
|
import cn.bunny.services.domain.system.system.vo.router.WebUserRouterVo;
|
||||||
import cn.bunny.services.service.system.RouterRoleService;
|
import cn.bunny.services.service.system.RouterRoleService;
|
||||||
import cn.bunny.services.service.system.helper.role.RoleHelper;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -21,7 +20,7 @@ import java.util.*;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class RouterHelper {
|
public class RouterServiceHelper {
|
||||||
@Resource
|
@Resource
|
||||||
private RouterRoleService routerRoleService;
|
private RouterRoleService routerRoleService;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.security.config;
|
package cn.bunny.services.security.config;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
import cn.bunny.services.mapper.system.UserMapper;
|
import cn.bunny.services.mapper.system.UserMapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.security.exception;
|
package cn.bunny.services.security.exception;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.bunny.services.security.handelr;
|
package cn.bunny.services.security.handelr;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.bunny.services.security.handelr;
|
package cn.bunny.services.security.handelr;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
||||||
import cn.bunny.services.utils.ResponseUtil;
|
import cn.bunny.services.utils.ResponseUtil;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cn.bunny.services.security.service;
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
|
import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package cn.bunny.services.security.service;
|
package cn.bunny.services.security.service;
|
||||||
|
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
|
import cn.bunny.services.core.cache.UserAuthorizationCacheService;
|
||||||
|
import cn.bunny.services.core.utils.RoleHelper;
|
||||||
import cn.bunny.services.domain.system.system.entity.Permission;
|
import cn.bunny.services.domain.system.system.entity.Permission;
|
||||||
import cn.bunny.services.domain.system.system.entity.Role;
|
import cn.bunny.services.domain.system.system.entity.Role;
|
||||||
import cn.bunny.services.mapper.system.PermissionMapper;
|
|
||||||
import cn.bunny.services.mapper.system.RoleMapper;
|
|
||||||
import cn.bunny.services.security.config.WebSecurityConfig;
|
import cn.bunny.services.security.config.WebSecurityConfig;
|
||||||
import cn.bunny.services.service.system.helper.role.RoleHelper;
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
@ -23,10 +22,7 @@ import java.util.Objects;
|
||||||
public class PermissionCheckService {
|
public class PermissionCheckService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PermissionMapper permissionMapper;
|
private UserAuthorizationCacheService authorizationCacheService;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RoleMapper roleMapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户所属的角色信息
|
* 查询用户所属的角色信息
|
||||||
|
@ -38,7 +34,9 @@ public class PermissionCheckService {
|
||||||
|
|
||||||
// 根据用户ID查询角色数据
|
// 根据用户ID查询角色数据
|
||||||
Long userId = BaseContext.getUserId();
|
Long userId = BaseContext.getUserId();
|
||||||
List<Role> roleList = roleMapper.selectListByUserId(userId);
|
String username = BaseContext.getUsername();
|
||||||
|
// List<Role> roleList = roleMapper.selectListByUserId(userId);
|
||||||
|
List<Role> roleList = authorizationCacheService.getRolesByUser(userId, username);
|
||||||
|
|
||||||
// 角色代码
|
// 角色代码
|
||||||
List<String> roleCodeList = roleList.stream().map(Role::getRoleCode).toList();
|
List<String> roleCodeList = roleList.stream().map(Role::getRoleCode).toList();
|
||||||
|
@ -54,7 +52,8 @@ public class PermissionCheckService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据角色列表查询权限信息
|
// 根据角色列表查询权限信息
|
||||||
List<Permission> permissionList = permissionMapper.selectListByUserId(userId);
|
// List<Permission> permissionList = permissionMapper.selectListByUserId(userId);
|
||||||
|
List<Permission> permissionList = authorizationCacheService.getPermissionsByUser(userId, username);
|
||||||
|
|
||||||
// 判断是否与请求路径匹配
|
// 判断是否与请求路径匹配
|
||||||
return permissionList.stream()
|
return permissionList.stream()
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
package cn.bunny.services.security.service;
|
package cn.bunny.services.security.service;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
|
import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
||||||
import cn.bunny.services.utils.JwtTokenUtil;
|
import cn.bunny.services.utils.JwtTokenUtil;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理Token相关逻辑
|
* 处理Token相关逻辑
|
||||||
*/
|
*/
|
||||||
@Component
|
@Service
|
||||||
public class TokenValidationService {
|
public class TokenValidationService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -39,7 +39,7 @@ public class TokenValidationService {
|
||||||
Long userId = JwtTokenUtil.getUserId(token);
|
Long userId = JwtTokenUtil.getUserId(token);
|
||||||
|
|
||||||
// 查找 Redis
|
// 查找 Redis
|
||||||
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getAdminLoginInfoPrefix(username));
|
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
|
||||||
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
||||||
|
|
||||||
return TokenInfo.builder().userId(userId).username(username).token(token).loginVo(loginVo).build();
|
return TokenInfo.builder().userId(userId).username(username).token(token).loginVo(loginVo).build();
|
||||||
|
|
|
@ -1,122 +0,0 @@
|
||||||
package cn.bunny.services.service.configuration.helper.i18n;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
|
||||||
import cn.bunny.services.service.configuration.impl.I18nServiceImpl;
|
|
||||||
import com.alibaba.excel.EasyExcel;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
public class I18nHelper {
|
|
||||||
/**
|
|
||||||
* 将国际化资源列表写入Excel并打包到ZIP输出流
|
|
||||||
*
|
|
||||||
* <p>处理流程:</p>
|
|
||||||
* <ol>
|
|
||||||
* <li>按资源类型(typeName)分组 --- 多语言的类型,英文?中文?</li>
|
|
||||||
* <li>每组数据生成单独多语言 key的Excel工作表</li>
|
|
||||||
* <li>将Excel文件写入ZIP输出流</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @param i18nList 国际化资源列表,包含key-value对和类型信息
|
|
||||||
* @param zipOutputStream ZIP输出流,用于写入打包后的Excel文件
|
|
||||||
* @throws RuntimeException 当IO操作失败时抛出
|
|
||||||
*/
|
|
||||||
public static void writeExcel(List<I18n> i18nList, ZipOutputStream zipOutputStream) {
|
|
||||||
Map<String, List<I18nExcel>> hashMap = i18nList.stream()
|
|
||||||
.collect(Collectors.groupingBy(
|
|
||||||
I18n::getTypeName,
|
|
||||||
Collectors.mapping((I18n i18n) -> {
|
|
||||||
String keyName = i18n.getKeyName();
|
|
||||||
String translation = i18n.getTranslation();
|
|
||||||
return I18nExcel.builder().keyName(keyName).translation(translation).build();
|
|
||||||
}, Collectors.toList())
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
hashMap.forEach((key, value) -> {
|
|
||||||
try {
|
|
||||||
// 创建临时ByteArrayOutputStream
|
|
||||||
ByteArrayOutputStream excelOutputStream = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
ZipEntry zipEntry = new ZipEntry(key + ".xlsx");
|
|
||||||
zipOutputStream.putNextEntry(zipEntry);
|
|
||||||
|
|
||||||
// 先写入到临时流
|
|
||||||
EasyExcel.write(excelOutputStream, I18nExcel.class).sheet(key).doWrite(value);
|
|
||||||
zipOutputStream.write(excelOutputStream.toByteArray());
|
|
||||||
zipOutputStream.closeEntry();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将国际化资源列表写入JSON并打包到ZIP输出流
|
|
||||||
*
|
|
||||||
* <p>处理流程:</p>
|
|
||||||
* <ol>
|
|
||||||
* <li>按资源类型(typeName)分组 --- 多语言的类型,英文?中文?</li>
|
|
||||||
* <li>每组数据生成单独多语言 key的Excel工作表</li>
|
|
||||||
* <li>将JSON文件写入ZIP输出流</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @param i18nList 国际化资源列表
|
|
||||||
* @param zipOutputStream ZIP输出流
|
|
||||||
* @throws RuntimeException 当IO操作失败时抛出
|
|
||||||
*/
|
|
||||||
public static void writeJson(List<I18n> i18nList, ZipOutputStream zipOutputStream) {
|
|
||||||
HashMap<String, Object> hashMap = getMapByI18nList(i18nList);
|
|
||||||
|
|
||||||
hashMap.forEach((k, v) -> {
|
|
||||||
try {
|
|
||||||
ZipEntry zipEntry = new ZipEntry(k + ".json");
|
|
||||||
zipOutputStream.putNextEntry(zipEntry);
|
|
||||||
|
|
||||||
zipOutputStream.write(JSON.toJSONString(v).getBytes(StandardCharsets.UTF_8));
|
|
||||||
zipOutputStream.closeEntry();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将国际化资源列表转换为结构化Map
|
|
||||||
*
|
|
||||||
* <p>转换规则:</p>
|
|
||||||
* <ul>
|
|
||||||
* <li>外层Key: 资源类型(typeName)</li>
|
|
||||||
* <li>内层Key: 资源键名(keyName)</li>
|
|
||||||
* <li>值: 翻译文本(translation)</li>
|
|
||||||
* </ul>
|
|
||||||
* <p>详细结构和结果示例看前端传递的 {@link I18nServiceImpl#getI18nMap} 控制器</p>
|
|
||||||
* <p>/api/i18n/public</p>
|
|
||||||
*
|
|
||||||
* @param i18nList 国际化资源列表
|
|
||||||
* @return 结构化Map {typeName: {keyName: translation}}
|
|
||||||
* @throws IllegalArgumentException 当参数为null时抛出
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static HashMap<String, Object> getMapByI18nList(@NotNull List<I18n> i18nList) {
|
|
||||||
// 整理集合
|
|
||||||
Map<String, Map<String, String>> map = i18nList.stream()
|
|
||||||
.collect(Collectors.groupingBy(
|
|
||||||
I18n::getTypeName,
|
|
||||||
Collectors.toMap(I18n::getKeyName, I18n::getTranslation)));
|
|
||||||
|
|
||||||
// 返回集合
|
|
||||||
return new HashMap<>(map);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ package cn.bunny.services.service.configuration.impl;
|
||||||
import cn.bunny.services.domain.system.configuration.dto.WebConfigurationDto;
|
import cn.bunny.services.domain.system.configuration.dto.WebConfigurationDto;
|
||||||
import cn.bunny.services.domain.system.configuration.entity.WebConfiguration;
|
import cn.bunny.services.domain.system.configuration.entity.WebConfiguration;
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.service.configuration.ConfigurationService;
|
import cn.bunny.services.service.configuration.ConfigurationService;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
||||||
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
||||||
import cn.bunny.services.domain.common.enums.EmailTemplateEnums;
|
import cn.bunny.services.domain.common.enums.EmailTemplateEnums;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
|
import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
|
||||||
import cn.bunny.services.service.configuration.EmailTemplateService;
|
import cn.bunny.services.service.configuration.EmailTemplateService;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import cn.bunny.services.domain.system.email.dto.EmailUsersUpdateDto;
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailUsers;
|
import cn.bunny.services.domain.system.email.entity.EmailUsers;
|
||||||
import cn.bunny.services.domain.system.email.vo.EmailUsersVo;
|
import cn.bunny.services.domain.system.email.vo.EmailUsersVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.mapper.configuration.EmailUsersMapper;
|
import cn.bunny.services.mapper.configuration.EmailUsersMapper;
|
||||||
import cn.bunny.services.service.configuration.EmailUsersService;
|
import cn.bunny.services.service.configuration.EmailUsersService;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package cn.bunny.services.service.configuration.impl;
|
package cn.bunny.services.service.configuration.impl;
|
||||||
|
|
||||||
|
import cn.bunny.services.core.event.listener.excel.I18nExcelListener;
|
||||||
|
import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
|
||||||
|
import cn.bunny.services.core.strategy.export.JsonExportStrategy;
|
||||||
import cn.bunny.services.domain.common.constant.FileType;
|
import cn.bunny.services.domain.common.constant.FileType;
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
||||||
import cn.bunny.services.domain.common.model.entity.BaseEntity;
|
import cn.bunny.services.domain.common.model.entity.BaseEntity;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nAddDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nAddDto;
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nDto;
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nUpdateByFileDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nUpdateByFileDto;
|
||||||
|
@ -12,12 +15,10 @@ import cn.bunny.services.domain.system.i18n.dto.I18nUpdateDto;
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18nType;
|
import cn.bunny.services.domain.system.i18n.entity.I18nType;
|
||||||
import cn.bunny.services.domain.system.i18n.vo.I18nVo;
|
import cn.bunny.services.domain.system.i18n.vo.I18nVo;
|
||||||
import cn.bunny.services.excel.I18nExcelListener;
|
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.mapper.configuration.I18nMapper;
|
import cn.bunny.services.mapper.configuration.I18nMapper;
|
||||||
import cn.bunny.services.mapper.configuration.I18nTypeMapper;
|
import cn.bunny.services.mapper.configuration.I18nTypeMapper;
|
||||||
import cn.bunny.services.service.configuration.I18nService;
|
import cn.bunny.services.service.configuration.I18nService;
|
||||||
import cn.bunny.services.service.configuration.helper.i18n.I18nHelper;
|
|
||||||
import cn.bunny.services.utils.FileUtil;
|
import cn.bunny.services.utils.FileUtil;
|
||||||
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.EasyExcel;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
@ -29,6 +30,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
@ -47,6 +49,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,6 +63,7 @@ import java.util.zip.ZipOutputStream;
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I18nService {
|
public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I18nService {
|
||||||
|
private static final String CACHE_NAMES = "i18n";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private I18nTypeMapper i18nTypeMapper;
|
private I18nTypeMapper i18nTypeMapper;
|
||||||
|
@ -70,13 +74,13 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
* @return 多语言返回内容
|
* @return 多语言返回内容
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Cacheable(cacheNames = "i18n", key = "'i18n'", cacheManager = "cacheManagerWithMouth")
|
@Cacheable(cacheNames = CACHE_NAMES, key = "'i18nMap'", cacheManager = "cacheManagerWithMouth")
|
||||||
public HashMap<String, Object> getI18nMap() {
|
public HashMap<String, Object> getI18nMap() {
|
||||||
// 查找默认语言内容
|
// 查找默认语言内容
|
||||||
I18nType i18nType = i18nTypeMapper.selectOne(Wrappers.<I18nType>lambdaQuery().eq(I18nType::getIsDefault, true));
|
I18nType i18nType = i18nTypeMapper.selectOne(Wrappers.<I18nType>lambdaQuery().eq(I18nType::getIsDefault, true));
|
||||||
List<I18n> i18nList = list();
|
List<I18n> i18nList = list();
|
||||||
|
|
||||||
HashMap<String, Object> hashMap = I18nHelper.getMapByI18nList(i18nList);
|
HashMap<String, Object> hashMap = getMapByI18nList(i18nList);
|
||||||
hashMap.put("local", Objects.requireNonNull(i18nType.getTypeName(), "zh"));
|
hashMap.put("local", Objects.requireNonNull(i18nType.getTypeName(), "zh"));
|
||||||
|
|
||||||
return hashMap;
|
return hashMap;
|
||||||
|
@ -105,7 +109,7 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
* @param dto 添加表单
|
* @param dto 添加表单
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true)
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true)
|
||||||
public void addI18n(@Valid I18nAddDto dto) {
|
public void addI18n(@Valid I18nAddDto dto) {
|
||||||
String keyName = dto.getKeyName();
|
String keyName = dto.getKeyName();
|
||||||
String typeName = dto.getTypeName();
|
String typeName = dto.getTypeName();
|
||||||
|
@ -126,7 +130,7 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
* @param dto 更新表单
|
* @param dto 更新表单
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true)
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true)
|
||||||
public void updateI18n(@Valid I18nUpdateDto dto) {
|
public void updateI18n(@Valid I18nUpdateDto dto) {
|
||||||
Long id = dto.getId();
|
Long id = dto.getId();
|
||||||
|
|
||||||
|
@ -146,7 +150,7 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
* @param ids 删除id列表
|
* @param ids 删除id列表
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true)
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true)
|
||||||
public void deleteI18n(List<Long> ids) {
|
public void deleteI18n(List<Long> ids) {
|
||||||
// 判断数据请求是否为空
|
// 判断数据请求是否为空
|
||||||
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
||||||
|
@ -163,18 +167,35 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<byte[]> downloadI18n(String type) {
|
public ResponseEntity<byte[]> downloadI18n(String type) {
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
|
|
||||||
|
|
||||||
|
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
|
||||||
// 查找默认语言内容
|
// 查找默认语言内容
|
||||||
List<I18n> i18nList = list();
|
List<I18n> i18nList = list();
|
||||||
|
|
||||||
// 类型是Excel写入Excel
|
// 类型是Excel写入Excel
|
||||||
if (type.equals(FileType.EXCEL)) {
|
if (type.equals(FileType.EXCEL)) {
|
||||||
I18nHelper.writeExcel(i18nList, zipOutputStream);
|
i18nList.stream()
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
I18n::getTypeName,
|
||||||
|
Collectors.mapping((I18n i18n) -> {
|
||||||
|
String keyName = i18n.getKeyName();
|
||||||
|
String translation = i18n.getTranslation();
|
||||||
|
return I18nExcel.builder().keyName(keyName).translation(translation).build();
|
||||||
|
}, Collectors.toList())
|
||||||
|
))
|
||||||
|
.forEach((key, value) -> {
|
||||||
|
ExcelExportStrategy excelExportStrategy = new ExcelExportStrategy(I18nExcel.class, key);
|
||||||
|
excelExportStrategy.export(value, zipOutputStream, key + ".xlsx");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// 其他格式写入JSON
|
// 其他格式写入JSON
|
||||||
else {
|
else {
|
||||||
I18nHelper.writeJson(i18nList, zipOutputStream);
|
HashMap<String, Object> hashMap = getMapByI18nList(i18nList);
|
||||||
|
|
||||||
|
hashMap.forEach((k, v) -> {
|
||||||
|
JsonExportStrategy jsonExportStrategy = new JsonExportStrategy();
|
||||||
|
jsonExportStrategy.export(v, zipOutputStream, k + ".json");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置响应头
|
// 设置响应头
|
||||||
|
@ -193,7 +214,7 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
* @param dto 文件更新对象
|
* @param dto 文件更新对象
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true)
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true)
|
||||||
public void uploadI18nFile(I18nUpdateByFileDto dto) {
|
public void uploadI18nFile(I18nUpdateByFileDto dto) {
|
||||||
String type = dto.getType();
|
String type = dto.getType();
|
||||||
MultipartFile file = dto.getFile();
|
MultipartFile file = dto.getFile();
|
||||||
|
@ -240,4 +261,32 @@ public class I18nServiceImpl extends ServiceImpl<I18nMapper, I18n> implements I1
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将国际化资源列表转换为结构化Map
|
||||||
|
*
|
||||||
|
* <p>转换规则:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>外层Key: 资源类型(typeName)</li>
|
||||||
|
* <li>内层Key: 资源键名(keyName)</li>
|
||||||
|
* <li>值: 翻译文本(translation)</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>详细结构和结果示例看前端传递的 {@link I18nServiceImpl#getI18nMap} 控制器</p>
|
||||||
|
* <p>/api/i18n/public</p>
|
||||||
|
*
|
||||||
|
* @param i18nList 国际化资源列表
|
||||||
|
* @return 结构化Map {typeName: {keyName: translation}}
|
||||||
|
* @throws IllegalArgumentException 当参数为null时抛出
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public HashMap<String, Object> getMapByI18nList(@NotNull List<I18n> i18nList) {
|
||||||
|
// 整理集合
|
||||||
|
Map<String, Map<String, String>> map = i18nList.stream()
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
I18n::getTypeName,
|
||||||
|
Collectors.toMap(I18n::getKeyName, I18n::getTranslation)));
|
||||||
|
|
||||||
|
// 返回集合
|
||||||
|
return new HashMap<>(map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
package cn.bunny.services.service.configuration.impl;
|
package cn.bunny.services.service.configuration.impl;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nTypeAddDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nTypeAddDto;
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nTypeDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nTypeDto;
|
||||||
import cn.bunny.services.domain.system.i18n.dto.I18nTypeUpdateDto;
|
import cn.bunny.services.domain.system.i18n.dto.I18nTypeUpdateDto;
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18nType;
|
import cn.bunny.services.domain.system.i18n.entity.I18nType;
|
||||||
import cn.bunny.services.domain.system.i18n.vo.I18nTypeVo;
|
import cn.bunny.services.domain.system.i18n.vo.I18nTypeVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.mapper.configuration.I18nTypeMapper;
|
import cn.bunny.services.mapper.configuration.I18nTypeMapper;
|
||||||
import cn.bunny.services.service.configuration.I18nTypeService;
|
import cn.bunny.services.service.configuration.I18nTypeService;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.cache.annotation.Caching;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@ -28,6 +31,7 @@ import java.util.List;
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
public class I18nTypeServiceImpl extends ServiceImpl<I18nTypeMapper, I18nType> implements I18nTypeService {
|
public class I18nTypeServiceImpl extends ServiceImpl<I18nTypeMapper, I18nType> implements I18nTypeService {
|
||||||
|
private static final String CACHE_NAMES = "i18n";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取多语言类型
|
* 获取多语言类型
|
||||||
|
@ -35,6 +39,7 @@ public class I18nTypeServiceImpl extends ServiceImpl<I18nTypeMapper, I18nType> i
|
||||||
* @return 多语言类型列表
|
* @return 多语言类型列表
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Cacheable(cacheNames = CACHE_NAMES, key = "'i18nTypeList'", cacheManager = "cacheManagerWithMouth")
|
||||||
public List<I18nTypeVo> getI18nTypeList(I18nTypeDto dto) {
|
public List<I18nTypeVo> getI18nTypeList(I18nTypeDto dto) {
|
||||||
List<I18nType> i18nTypeList = baseMapper.selectListByPage(dto);
|
List<I18nType> i18nTypeList = baseMapper.selectListByPage(dto);
|
||||||
return i18nTypeList.stream().map(i18nType -> {
|
return i18nTypeList.stream().map(i18nType -> {
|
||||||
|
@ -50,6 +55,10 @@ public class I18nTypeServiceImpl extends ServiceImpl<I18nTypeMapper, I18nType> i
|
||||||
* @param dto 多语言类型添加
|
* @param dto 多语言类型添加
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Caching(evict = {
|
||||||
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true),
|
||||||
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nTypeList'", beforeInvocation = true),
|
||||||
|
})
|
||||||
public void addI18nType(I18nTypeAddDto dto) {
|
public void addI18nType(I18nTypeAddDto dto) {
|
||||||
String typeName = dto.getTypeName();
|
String typeName = dto.getTypeName();
|
||||||
Boolean isDefault = dto.getIsDefault();
|
Boolean isDefault = dto.getIsDefault();
|
||||||
|
@ -77,14 +86,18 @@ public class I18nTypeServiceImpl extends ServiceImpl<I18nTypeMapper, I18nType> i
|
||||||
* @param dto 多语言类型更新
|
* @param dto 多语言类型更新
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Caching(evict = {
|
||||||
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true),
|
||||||
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nTypeList'", beforeInvocation = true),
|
||||||
|
})
|
||||||
public void updateI18nType(I18nTypeUpdateDto dto) {
|
public void updateI18nType(I18nTypeUpdateDto dto) {
|
||||||
Long id = dto.getId();
|
Long id = dto.getId();
|
||||||
Boolean isDefault = dto.getIsDefault();
|
Boolean isDefault = dto.getIsDefault();
|
||||||
I18nType i18nType = new I18nType();
|
I18nType i18nType = new I18nType();
|
||||||
|
|
||||||
// 查询更新的内容是否存在
|
// 查询更新的内容是否存在
|
||||||
List<I18nType> i18nTypeList = list(Wrappers.<I18nType>lambdaQuery().eq(I18nType::getId, id));
|
I18nType dbI18nType = getOne(Wrappers.<I18nType>lambdaQuery().eq(I18nType::getId, id));
|
||||||
if (i18nTypeList.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.DATA_NOT_EXIST);
|
if (dbI18nType == null) throw new AuthCustomerException(ResultCodeEnum.DATA_NOT_EXIST);
|
||||||
|
|
||||||
// 如果是默认,将其它内容设为false
|
// 如果是默认,将其它内容设为false
|
||||||
if (isDefault) {
|
if (isDefault) {
|
||||||
|
@ -104,6 +117,10 @@ public class I18nTypeServiceImpl extends ServiceImpl<I18nTypeMapper, I18nType> i
|
||||||
* @param ids 删除id列表
|
* @param ids 删除id列表
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Caching(evict = {
|
||||||
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nMap'", beforeInvocation = true),
|
||||||
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'i18nTypeList'", beforeInvocation = true),
|
||||||
|
})
|
||||||
public void deleteI18nType(List<Long> ids) {
|
public void deleteI18nType(List<Long> ids) {
|
||||||
// 判断数据请求是否为空
|
// 判断数据请求是否为空
|
||||||
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue