diff --git a/cool-dependencies/pom.xml b/cool-dependencies/pom.xml index 861b87e8ec9cdaadf9dc9af826feddfff48b803e..fc34f0303b05746901ac45779bba72458e6a9a18 100644 --- a/cool-dependencies/pom.xml +++ b/cool-dependencies/pom.xml @@ -24,7 +24,7 @@ 3.2.4 8.3.0 - 1.8.3 + 1.8.6 33.1.0-jre 1.18.32 1.6.0.Beta1 diff --git a/cool-framework/cool-common/src/main/java/com/xgblack/cool/framework/common/pojo/dto/Command.java b/cool-framework/cool-common/src/main/java/com/xgblack/cool/framework/common/pojo/dto/Command.java index 34811ac3e799daf23b66af45938468b3bcbc4c98..dbc21a53c2f7159fdd902206d4be1122ec8c5316 100644 --- a/cool-framework/cool-common/src/main/java/com/xgblack/cool/framework/common/pojo/dto/Command.java +++ b/cool-framework/cool-common/src/main/java/com/xgblack/cool/framework/common/pojo/dto/Command.java @@ -1,5 +1,7 @@ package com.xgblack.cool.framework.common.pojo.dto; +import org.dromara.hutool.json.JSONUtil; + import java.io.Serial; /** @@ -12,4 +14,8 @@ public abstract class Command extends DTO { @Serial private static final long serialVersionUID = 1L; + public String toJson() { + return JSONUtil.toJsonStr(this); + } + } diff --git a/cool-framework/cool-spring-boot-starter-security-api/src/main/java/com/xgblack/cool/framework/security/service/RemoteUserService.java b/cool-framework/cool-spring-boot-starter-security-api/src/main/java/com/xgblack/cool/framework/security/service/RemoteUserService.java index ce6caaa114b90239d05b7ab7e77a9d91b62d8ced..5bbe53916718eefbdeefd8edd7de09cf4da4fcd9 100644 --- a/cool-framework/cool-spring-boot-starter-security-api/src/main/java/com/xgblack/cool/framework/security/service/RemoteUserService.java +++ b/cool-framework/cool-spring-boot-starter-security-api/src/main/java/com/xgblack/cool/framework/security/service/RemoteUserService.java @@ -25,4 +25,10 @@ public interface RemoteUserService { boolean lockUser(String username); + /** + * 根据用户id查询用户信息 + * @param userId + * @return + */ + UserInfo info(Long userId); } diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolAuthorizationServerConfiguration.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolAuthorizationServerConfiguration.java index 09e129e9b083ae445c595cf0f2fd07c65f94b10d..e541f9a25ea087078d358c9de7ffe9aacd431644 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolAuthorizationServerConfiguration.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolAuthorizationServerConfiguration.java @@ -10,7 +10,6 @@ import com.xgblack.cool.framework.security.core.authentication.support.mobile.Mo import com.xgblack.cool.framework.security.core.authentication.support.password.PasswordGrantAuthenticationConverter; import com.xgblack.cool.framework.security.core.authentication.support.password.PasswordGrantAuthenticationProvider; import com.xgblack.cool.framework.security.core.component.CoolBearerTokenExtractor; -import com.xgblack.cool.framework.security.core.component.PermitAllUrlProperties; import com.xgblack.cool.framework.security.core.component.ResourceAuthExceptionEntryPoint; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerAutoConfiguration.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerAutoConfiguration.java index f44f6befa899bdd37ea46fd220800d6fa7e1fe42..c0dbae664e4d6d21c0ed856a9c91abe8d4dceac2 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerAutoConfiguration.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerAutoConfiguration.java @@ -3,8 +3,8 @@ package com.xgblack.cool.framework.security.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.xgblack.cool.framework.security.core.component.CoolBearerTokenExtractor; import com.xgblack.cool.framework.security.core.component.CoolOpaqueTokenIntrospector; -import com.xgblack.cool.framework.security.core.component.PermitAllUrlProperties; import com.xgblack.cool.framework.security.core.component.ResourceAuthExceptionEntryPoint; +import com.xgblack.cool.framework.security.core.service.CoolUserDetailsService; import com.xgblack.cool.framework.security.core.service.PermissionService; import lombok.RequiredArgsConstructor; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -18,7 +18,7 @@ import org.springframework.security.oauth2.server.resource.introspection.OpaqueT * @author xg black */ @RequiredArgsConstructor -@EnableConfigurationProperties(PermitAllUrlProperties.class) +@EnableConfigurationProperties({PermitAllUrlProperties.class, MockSecurityProperties.class}) public class CoolResourceServerAutoConfiguration { /** * 鉴权具体的实现逻辑 @@ -52,11 +52,14 @@ public class CoolResourceServerAutoConfiguration { /** * 资源服务器toke内省处理器 + * * @param authorizationService token 存储实现 + * @param mockSecurityProperties 模拟模式配置 + * @param userDetailsService 用户信息 * @return TokenIntrospect */ @Bean - public OpaqueTokenIntrospector opaqueTokenIntrospector(OAuth2AuthorizationService authorizationService) { - return new CoolOpaqueTokenIntrospector(authorizationService); + public OpaqueTokenIntrospector opaqueTokenIntrospector(OAuth2AuthorizationService authorizationService, MockSecurityProperties mockSecurityProperties, CoolUserDetailsService userDetailsService) { + return new CoolOpaqueTokenIntrospector(authorizationService, mockSecurityProperties, userDetailsService); } } diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerConfiguration.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerConfiguration.java index 7a20a318614cd88c057d8341788d59dc79330ef4..a14e9ee4e25b91652b56c63fdbd6347bd8905347 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerConfiguration.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/CoolResourceServerConfiguration.java @@ -1,7 +1,6 @@ package com.xgblack.cool.framework.security.config; import com.xgblack.cool.framework.security.core.component.CoolBearerTokenExtractor; -import com.xgblack.cool.framework.security.core.component.PermitAllUrlProperties; import com.xgblack.cool.framework.security.core.component.ResourceAuthExceptionEntryPoint; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/MockSecurityProperties.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/MockSecurityProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..7332220f42d7be904a60b764ce6a32e745f9ce1f --- /dev/null +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/MockSecurityProperties.java @@ -0,0 +1,35 @@ +package com.xgblack.cool.framework.security.config; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +/** + * @author xg black + */ + +@Validated +@Data +@ConfigurationProperties(prefix = "cc.security") +public class MockSecurityProperties { + + /** + * mock 模式的开关 + */ + @NotNull(message = "mock 模式的开关不能为空") + private Boolean mockEnable = false; + /** + * mock 模式的密钥 + * 一定要配置密钥,保证安全性 + */ + @NotEmpty(message = "mock 模式的密钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。 + private String mockSecret = "test"; + + /** + * mock 模式的超级短信验证码 + */ + private String mockSmsCode; + +} diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/PermitAllUrlProperties.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/PermitAllUrlProperties.java similarity index 97% rename from cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/PermitAllUrlProperties.java rename to cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/PermitAllUrlProperties.java index 5ba59b406783c0b4afc170f8d29ae55251b87a64..0a9ef8d7b64b4060cb76ee38eba4a0b795c2b84b 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/PermitAllUrlProperties.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/config/PermitAllUrlProperties.java @@ -1,4 +1,4 @@ -package com.xgblack.cool.framework.security.core.component; +package com.xgblack.cool.framework.security.config; import com.xgblack.cool.framework.security.annotation.Inner; import lombok.Getter; diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java index 02e481406bae99f01b194f2a61505816f721c70d..17e8017b99702bad86e95950cf0e0541937533a1 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java @@ -1,5 +1,6 @@ package com.xgblack.cool.framework.security.core.component; +import com.xgblack.cool.framework.security.config.PermitAllUrlProperties; import jakarta.servlet.http.HttpServletRequest; import org.dromara.hutool.core.text.StrUtil; import org.springframework.http.HttpHeaders; diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolOpaqueTokenIntrospector.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolOpaqueTokenIntrospector.java index 59e4aca08dbe209d7fdf4fd9ce5f1293dd93cf03..6de2b733873de0a6c4ae0ed67a5b823a70b54a3e 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolOpaqueTokenIntrospector.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolOpaqueTokenIntrospector.java @@ -1,11 +1,15 @@ package com.xgblack.cool.framework.security.core.component; -import org.dromara.hutool.extra.spring.SpringUtil; import com.xgblack.cool.framework.common.constants.SecurityConstants; +import com.xgblack.cool.framework.security.config.MockSecurityProperties; import com.xgblack.cool.framework.security.core.service.CoolUserDetailsService; import com.xgblack.cool.framework.security.dto.LoginUser; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.hutool.core.convert.Convert; +import org.dromara.hutool.core.math.NumberUtil; +import org.dromara.hutool.core.text.StrUtil; +import org.dromara.hutool.extra.spring.SpringUtil; import org.springframework.core.Ordered; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.AuthorityUtils; @@ -37,10 +41,36 @@ public class CoolOpaqueTokenIntrospector implements OpaqueTokenIntrospector { private final OAuth2AuthorizationService authorizationService; + private final MockSecurityProperties mockSecurityProperties; + + private final CoolUserDetailsService userDetailsService; + @Override public OAuth2AuthenticatedPrincipal introspect(String token) { OAuth2Authorization oldAuthorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + if (Objects.isNull(oldAuthorization)) { + if (mockSecurityProperties.getMockEnable() && StrUtil.isNotBlank(token) && token.startsWith(mockSecurityProperties.getMockSecret())) { + // 判断 为模拟登录 + // 构建模拟用户 + String userIdStr = StrUtil.subAfter(token, mockSecurityProperties.getMockSecret(), true).trim(); + if (StrUtil.isBlank(userIdStr) || !NumberUtil.isNumber(userIdStr)) { + log.error("mock模式token错误,请使用固定token+数字(用户id)"); + throw new InvalidBearerTokenException(token); + } + Long userId = Convert.toLong(userIdStr); + try { + UserDetails userDetails = userDetailsService.loadUserById(userId); + if (Objects.isNull(userDetails)) { + log.error("mock模式token错误,加载用户失败,用户id={}", userId); + throw new InvalidBearerTokenException(token); + } + return (LoginUser) userDetails; + } catch (Exception e) { + log.error("mock模式token错误,加载用户失败,用户id={}", userId); + throw new InvalidBearerTokenException(token); + } + } throw new InvalidBearerTokenException(token); } @@ -73,6 +103,7 @@ public class CoolOpaqueTokenIntrospector implements OpaqueTokenIntrospector { } catch (Exception ex) { log.error("资源服务器 introspect Token error {}", ex.getLocalizedMessage()); + //TODO 抛出异常? } // 注入客户端信息,方便上下文中获取 diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolAppUserDetailsServiceImpl.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolAppUserDetailsServiceImpl.java index b449e5b3490cd642f8d6ed0a811da6323bc0ec94..b8578e464e506f167363e8fa9337bf21a8da5d1a 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolAppUserDetailsServiceImpl.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolAppUserDetailsServiceImpl.java @@ -55,6 +55,12 @@ public class CoolAppUserDetailsServiceImpl implements CoolUserDetailsService { return this.loadUserByUsername(loginUser.getPhone()); } + @Override + public UserDetails loadUserById(Long userId) { + // TODO + return null; + } + /** * 是否支持此客户端校验 * @param clientId 目标客户端 diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsService.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsService.java index 674b3d173398680dcb74dedafadcab204b7e23be..895a1887856507c11fc21a396c0695bef3ed3dd8 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsService.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsService.java @@ -61,7 +61,7 @@ public interface CoolUserDetailsService extends UserDetailsService, Ordered { Collection authorities = AuthorityUtils.createAuthorityList(dbAuthsSet.toArray(new String[0])); SysUser user = info.getSysUser(); - // 构造security用户 TODO + // 构造security用户 //由于密码默认使用BCRYPT加密,所以这里需要添加前缀,DelegatingPasswordEncoder能够根据密码前缀来确定密码编码器 return new LoginUser(user.getId(), user.getDeptId(), user.getTenantId(), user.getUsername(), SecurityConstants.BCRYPT + user.getPassword(), user.getPhone(), true, true, true, @@ -77,4 +77,5 @@ public interface CoolUserDetailsService extends UserDetailsService, Ordered { return this.loadUserByUsername(user.getUsername()); } + UserDetails loadUserById(Long userId); } diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsServiceImpl.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsServiceImpl.java index 921f99cceabd2952e897c582498d70fc661b03b5..b33039c9655002b5900149063528e19cdd340ef9 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsServiceImpl.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/service/CoolUserDetailsServiceImpl.java @@ -56,4 +56,10 @@ public class CoolUserDetailsServiceImpl implements CoolUserDetailsService { return Integer.MIN_VALUE; } + @Override + public UserDetails loadUserById(Long userId) { + UserInfo info = remoteUserService.info(userId); + return getUserDetails(info); + } + } diff --git a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/DeptController.java b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/DeptController.java index 3c78fc91d32f87ef20c5081b3f45b39c88fb5cf7..64d87876159d2d5d1435e45f7cab0cd8b65cfb8b 100644 --- a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/DeptController.java +++ b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/DeptController.java @@ -1,6 +1,8 @@ package com.xgblack.cool.module.system.web; +import com.mzt.logapi.starter.annotation.LogRecord; import com.xgblack.cool.module.system.api.DeptServiceI; +import com.xgblack.cool.module.system.common.constans.ModuleType; import com.xgblack.cool.module.system.dto.company.dept.DeptAddCmd; import com.xgblack.cool.module.system.dto.company.dept.DeptEditCmd; import com.xgblack.cool.module.system.dto.company.dept.DeptListQry; @@ -32,19 +34,24 @@ public class DeptController { * @return */ @PostMapping - //@Operation(summary = "创建部门") //@PreAuthorize("@ss.hasPermission('system:dept:create')") + @LogRecord(success = "创建部门, 名称「{{#cmd.name}}」", + fail = "创建部门失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.DEPT, bizNo = "{{#_ret}}") public Long add(@Valid @RequestBody DeptAddCmd cmd) { return deptService.add(cmd); } /** - * 更新部门 + * 修改部门 * @param cmd */ @PutMapping - //@Operation(summary = "更新部门") //@PreAuthorize("@ss.hasPermission('system:dept:update')") + @LogRecord(success = "修改部门, 名称「{{#cmd.name}}」", + fail = "修改部门失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.DEPT, bizNo = "{{#cmd.id}}") public void edit(@Valid @RequestBody DeptEditCmd cmd) { deptService.edit(cmd); } @@ -54,9 +61,10 @@ public class DeptController { * @param id */ @DeleteMapping("{id}") - //@Operation(summary = "删除部门") - //@Parameter(name = "id", description = "编号", required = true, example = "1024") //@PreAuthorize("@ss.hasPermission('system:dept:delete')") + @LogRecord(success = "删除部门, 编号「{{#id}}」", + fail = "删除部门失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.DEPT, bizNo = "{{#id}}") public void remove(@PathVariable("id") Long id) { deptService.remove(id); } @@ -67,7 +75,6 @@ public class DeptController { * @return */ @GetMapping("/list") - //@Operation(summary = "获取部门列表") //@PreAuthorize("@ss.hasPermission('system:dept:query')") public List getDeptList(DeptListQry qry) { return deptService.list(qry); @@ -89,8 +96,6 @@ public class DeptController { * @return */ @GetMapping("detail/{id}") - //@Operation(summary = "获得部门信息") - //@Parameter(name = "id", description = "编号", required = true, example = "1024") //@PreAuthorize("@ss.hasPermission('system:dept:query')") public DeptCO detail(@PathVariable("id") Long id) { return deptService.detail(id); diff --git a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/MenuController.java b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/MenuController.java index f3256efe3b421ef6e4c0864d6e98c7da02682307..7c057b938bb66a24486449686a9c0a5d5ca694c2 100644 --- a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/MenuController.java +++ b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/MenuController.java @@ -1,6 +1,8 @@ package com.xgblack.cool.module.system.web; +import com.mzt.logapi.starter.annotation.LogRecord; import com.xgblack.cool.module.system.api.MenuServiceI; +import com.xgblack.cool.module.system.common.constans.ModuleType; import com.xgblack.cool.module.system.dto.permission.MenuAddCmd; import com.xgblack.cool.module.system.dto.permission.MenuEditCmd; import com.xgblack.cool.module.system.dto.permission.MenuListQry; @@ -33,6 +35,9 @@ public class MenuController { */ @PostMapping //@PreAuthorize("@ss.hasPermission('system:menu:add')") + @LogRecord(success = "创建菜单, 名称「{{#cmd.name}}」", + fail = "创建菜单失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.MENU, bizNo = "{{#_ret}}") public Long add(@Valid @RequestBody MenuAddCmd cmd) { return menuService.add(cmd); } @@ -43,6 +48,10 @@ public class MenuController { */ @PutMapping //@PreAuthorize("@ss.hasPermission('system:menu:edit')") + @LogRecord(success = "修改菜单, 名称「{{#cmd.name}}」", + fail = "修改菜单失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.MENU, bizNo = "{{#cmd.id}}") public void edit(@Valid @RequestBody MenuEditCmd cmd) { menuService.edit(cmd); } @@ -52,14 +61,17 @@ public class MenuController { * @param id */ @DeleteMapping("{id}") - //@Parameter(name = "id", description = "菜单编号", required= true, example = "1024") //@PreAuthorize("@ss.hasPermission('system:menu:remove')") + @LogRecord(success = "删除菜单, 编号「{{#id}}」", + fail = "删除菜单失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.MENU, bizNo = "{{#id}}") public void remove(@PathVariable("id") Long id) { menuService.remove(id); } /** * 获取菜单列表 + *

用于【菜单管理】界面 * @param qry * @return */ @@ -72,16 +84,17 @@ public class MenuController { /** * 获取菜单精简信息列表 + *

+ * 只包含被开启的菜单,用于【角色分配菜单】功能的选项。 + * 在多租户的场景下,会只返回租户所在套餐有的菜单 * @return */ @GetMapping({"/list-all-simple", "simple-list"}) - //@Operation(summary = "获取菜单精简信息列表", description = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" + "在多租户的场景下,会只返回租户所在套餐有的菜单") public List getSimpleList() { return menuService.getSimpleListByTenant(); } @GetMapping("detail/{id}") - //@Operation(summary = "获取菜单信息") //@PreAuthorize("@ss.hasPermission('system:menu:query')") public MenuCO detail(@PathVariable Long id) { return menuService.detail(id); diff --git a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/PostController.java b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/PostController.java index 1f28e3b8d068e65c136917bb00f38170e36fd416..865ab49ee4867bc36a2015aa3ddf35f796472355 100644 --- a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/PostController.java +++ b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/PostController.java @@ -1,7 +1,9 @@ package com.xgblack.cool.module.system.web; +import com.mzt.logapi.starter.annotation.LogRecord; import com.xgblack.cool.framework.common.pojo.dto.PageResult; import com.xgblack.cool.module.system.api.PostServiceI; +import com.xgblack.cool.module.system.common.constans.ModuleType; import com.xgblack.cool.module.system.dto.company.post.PostAddCmd; import com.xgblack.cool.module.system.dto.company.post.PostEditCmd; import com.xgblack.cool.module.system.dto.company.post.PostPageQry; @@ -31,8 +33,10 @@ public class PostController { * @param cmd */ @PostMapping - //@Operation(summary = "创建岗位") //@PreAuthorize("@ss.hasPermission('system:post:create')") + @LogRecord(success = "创建岗位, 名称「{{#cmd.name}}」", + fail = "创建岗位失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.POST, bizNo = "{{#_ret}}") public Long add(@Valid @RequestBody PostAddCmd cmd) { return postService.add(cmd); } @@ -42,8 +46,11 @@ public class PostController { * @param cmd */ @PutMapping - //@Operation(summary = "修改岗位") //@PreAuthorize("@ss.hasPermission('system:post:update')") + @LogRecord(success = "修改岗位, 名称「{{#cmd.name}}」", + fail = "修改岗位失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.POST, bizNo = "{{#cmd.id}}") public void edit(@Valid @RequestBody PostEditCmd cmd) { postService.edit(cmd); } @@ -53,8 +60,10 @@ public class PostController { * @param id */ @DeleteMapping("{id}") - //@Operation(summary = "删除岗位") //@PreAuthorize("@ss.hasPermission('system:post:delete')") + @LogRecord(success = "删除岗位, 编号「{{#id}}」", + fail = "删除岗位失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.POST, bizNo = "{{#id}}") public void remove(@PathVariable("id") Long id) { postService.remove(id); } @@ -65,7 +74,6 @@ public class PostController { * @return */ @GetMapping(value = "detail/{id}") - //@Operation(summary = "获得岗位信息") //@Parameter(name = "id", description = "岗位编号", required = true, example = "1024") //@PreAuthorize("@ss.hasPermission('system:post:query')") public PostCO detail(@PathVariable("id") Long id) { @@ -74,10 +82,10 @@ public class PostController { /** * 获取岗位精简列表 + *

只包含被开启的岗位,主要用于前端的下拉选项 * @return */ @GetMapping(value = {"/list-all-simple", "simple-list"}) - //@Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") public List getSimpleList() { // 获得岗位列表,只要开启状态的 return postService.getSimpleList(); @@ -89,7 +97,6 @@ public class PostController { * @return */ @GetMapping("/page") - //@Operation(summary = "获得岗位分页列表") //@PreAuthorize("@ss.hasPermission('system:post:query')") public PageResult page(@Validated PostPageQry qry) { return postService.page(qry); diff --git a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/RoleController.java b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/RoleController.java index 6f80bf7fc247594b1df91f25a4510a124465f227..4c840e4de378663b4edd0eb5da2aeddb46b2f0fd 100644 --- a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/RoleController.java +++ b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/RoleController.java @@ -1,14 +1,15 @@ package com.xgblack.cool.module.system.web; +import com.mzt.logapi.starter.annotation.LogRecord; import com.xgblack.cool.framework.common.pojo.dto.PageResult; import com.xgblack.cool.module.system.api.RoleServiceI; +import com.xgblack.cool.module.system.common.constans.ModuleType; import com.xgblack.cool.module.system.dto.permission.RoleAddCmd; import com.xgblack.cool.module.system.dto.permission.RoleEditCmd; import com.xgblack.cool.module.system.dto.permission.RoleEditStatusCmd; import com.xgblack.cool.module.system.dto.permission.RolePageQry; import com.xgblack.cool.module.system.dto.permission.clientobject.RoleCO; import com.xgblack.cool.module.system.dto.permission.clientobject.RoleSimpleCO; -import com.xgblack.cool.module.system.gateway.database.dataobject.RoleDO; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; @@ -36,6 +37,9 @@ public class RoleController { */ @PostMapping //@PreAuthorize("@ss.hasPermission('system:role:create')") + @LogRecord(success = "创建角色, 名称「{{#cmd.name}}」", + fail = "创建角色失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.ROLE, bizNo = "{{#_ret}}") public Long add(@Valid @RequestBody RoleAddCmd cmd) { return roleService.add(cmd); } @@ -46,6 +50,10 @@ public class RoleController { */ @PutMapping //@PreAuthorize("@ss.hasPermission('system:role:update')") + @LogRecord(success = "修改角色, 名称「{{#cmd.name}}」", + fail = "修改角色失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.ROLE, bizNo = "{{#cmd.id}}") public void edit(@Valid @RequestBody RoleEditCmd cmd) { roleService.edit(cmd); } @@ -56,6 +64,10 @@ public class RoleController { */ @PutMapping("/update-status") //@PreAuthorize("@ss.hasPermission('system:role:update')") + @LogRecord(success = "修改角色状态, 名称「{{#cmd.name}}」", + fail = "修改角色状态失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.ROLE, bizNo = "{{#cmd.id}}") public void editStatus(@Valid @RequestBody RoleEditStatusCmd cmd) { roleService.editStatus(cmd); } @@ -66,6 +78,9 @@ public class RoleController { */ @DeleteMapping("{id}") //@PreAuthorize("@ss.hasPermission('system:role:delete')") + @LogRecord(success = "删除角色, 编号「{{#id}}」", + fail = "删除角色失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.ROLE, bizNo = "{{#id}}") public void remove(@PathVariable("id") Long id) { roleService.remove(id); } @@ -92,8 +107,12 @@ public class RoleController { return roleService.page(qry); } + /** + * 获取角色精简信息列表 + *

只包含被开启的角色,主要用于前端的下拉选项 + * @return + */ @GetMapping({"/list-all-simple", "/simple-list"}) - //@Operation(summary = "获取角色精简信息列表", description = "只包含被开启的角色,主要用于前端的下拉选项") public List getSimpleList() { return roleService.getSimpleList(); } diff --git a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/UserController.java b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/UserController.java index e154f52f7cb50fd7451c36f949e381bd956d6e2b..1db31e55ddeffc0f4c1ad12aeff6f9851fc6489c 100644 --- a/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/UserController.java +++ b/cool-module-system/cool-module-system-adapter/src/main/java/com/xgblack/cool/module/system/web/UserController.java @@ -1,7 +1,9 @@ package com.xgblack.cool.module.system.web; +import com.mzt.logapi.starter.annotation.LogRecord; import com.xgblack.cool.framework.common.pojo.dto.PageResult; import com.xgblack.cool.module.system.api.UserServiceI; +import com.xgblack.cool.module.system.common.constans.ModuleType; import com.xgblack.cool.module.system.dto.user.*; import com.xgblack.cool.module.system.dto.user.clientobject.UserCO; import com.xgblack.cool.module.system.dto.user.clientobject.UserSimpleDTO; @@ -31,6 +33,9 @@ public class UserController { */ @PostMapping //@PreAuthorize("@ss.hasPermission('system:user:create')") + @LogRecord(success = "新增用户, 用户名「{{#cmd.username}}」,昵称「{{#cmd.nickname}}」", + fail = "新增用户失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.USER, bizNo = "{{#_ret}}") public Long add(@Validated @RequestBody UserAddCmd cmd) { return userService.add(cmd); } @@ -40,8 +45,11 @@ public class UserController { * @param cmd */ @PutMapping - //@Operation(summary = "修改用户") //@PreAuthorize("@ss.hasPermission('system:user:update')") + @LogRecord(success = "修改用户, 名称「{{#cmd.name}}」", + fail = "修改用户失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.USER, bizNo = "{{#cmd.id}}") public void edit(@Validated @RequestBody UserEditCmd cmd) { userService.edit(cmd); } @@ -51,8 +59,10 @@ public class UserController { * @param id 用户id */ @DeleteMapping("{id}") - //@Operation(summary = "删除用户") //@PreAuthorize("@ss.hasPermission('system:user:delete')") + @LogRecord(success = "删除用户, 编号「{{#id}}」", + fail = "删除用户失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.USER, bizNo = "{{#id}}") public void delete(@PathVariable Long id) { userService.remove(id); } @@ -62,8 +72,10 @@ public class UserController { * @param cmd */ @PutMapping("/update-password") - //@Operation(summary = "重置用户密码") //@PreAuthorize("@ss.hasPermission('system:user:update-password')") + @LogRecord(success = "修改用户密码, 编号「{{#cmd.id}}」", + fail = "修改用户密码失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.USER, bizNo = "{{#cmd.id}}") public void editPassword(@Validated @RequestBody UserEditPasswordCmd cmd) { userService.editPassword(cmd); } @@ -73,19 +85,21 @@ public class UserController { * @param cmd */ @PutMapping("/update-locked") - //@Operation(summary = "修改用户状态") //@PreAuthorize("@ss.hasPermission('system:user:update')") + @LogRecord(success = "修改用户锁定状态, 编号「{{#cmd.id}}」", + fail = "修改用户锁定状态失败,失败原因:「{{#_errorMsg}}」", + extra = "{{#cmd.toJson()}}", + type = ModuleType.USER, bizNo = "{{#cmd.id}}") public void editLocked(@Validated @RequestBody UserEditLockedCmd cmd) { userService.editLocked(cmd); } /** - * 分页查询 + * 获得用户分页列表 * @param qry * @return */ @GetMapping("/page") - //@Operation(summary = "获得用户分页列表") //@PreAuthorize("@ss.hasPermission('system:user:list')") public PageResult page(@Validated UserPageQry qry) { // 获得用户分页列表 @@ -103,10 +117,10 @@ public class UserController { /** * 获取用户精简信息列表 + *

只包含被开启的用户,主要用于前端的下拉选项 * @return */ @GetMapping({"/list-all-simple", "/simple-list"}) - //@Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项") public List getSimpleUserList() { //TODO //List list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -121,8 +135,6 @@ public class UserController { * @return */ @GetMapping("detail/{id}") - //@Operation(summary = "获得用户详情") - //@Parameter(name = "id", description = "编号", required = true, example = "1024") //@PreAuthorize("@ss.hasPermission('system:user:query')") public UserCO detail(@PathVariable("id") Long id) { /*AdminUserDO user = userService.getUser(id); @@ -152,7 +164,6 @@ public class UserController { * 获得导入用户模板 */ @GetMapping("/get-import-template") - //@Operation(summary = "获得导入用户模板") public void importTemplate(HttpServletResponse response) { // 手动创建导出 demo /*List list = Arrays.asList( @@ -174,6 +185,9 @@ public class UserController { */ @PostMapping("/import") //@PreAuthorize("@ss.hasPermission('system:user:import')") + @LogRecord(success = "导入用户, ",//TODO + fail = "导入用户失败,失败原因:「{{#_errorMsg}}」", + type = ModuleType.USER, bizNo = "") public Object importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { /*List list = ExcelUtils.read(file, UserImportExcelVO.class); return success(userService.importUserList(list, updateSupport));*/ diff --git a/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/common/constans/ModuleType.java b/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/common/constans/ModuleType.java new file mode 100644 index 0000000000000000000000000000000000000000..44d3d20fccabfe4129c6e897bf9e364395454142 --- /dev/null +++ b/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/common/constans/ModuleType.java @@ -0,0 +1,21 @@ +package com.xgblack.cool.module.system.common.constans; + +/** + * 功能模块常量 + * @author xg black + */ + +public interface ModuleType { + + String DEPT = "部门"; + + String ROLE = "角色"; + + String USER = "用户"; + + String MENU = "菜单"; + + String DICT = "字典"; + + String POST = "岗位"; +} diff --git a/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/dto/company/dept/DeptAddCmd.java b/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/dto/company/dept/DeptAddCmd.java index e3f227634e00fd77c7700dcdeef0e26247937c0b..e054121168d418ba7b1c5f06336214f36cdc02f8 100644 --- a/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/dto/company/dept/DeptAddCmd.java +++ b/cool-module-system/cool-module-system-client/src/main/java/com/xgblack/cool/module/system/dto/company/dept/DeptAddCmd.java @@ -20,9 +20,6 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class DeptAddCmd extends Command { - //@Schema(description = "部门编号", example = "1024") - //private Long id; - /** 部门名称 */ @NotBlank(message = "部门名称不能为空") @Size(max = 30, message = "部门名称长度不能超过 30 个字符") diff --git a/cool-module-system/cool-module-system-infrastructure/src/main/java/com/xgblack/cool/module/system/gateway/UserGatewayImpl.java b/cool-module-system/cool-module-system-infrastructure/src/main/java/com/xgblack/cool/module/system/gateway/UserGatewayImpl.java index a7ba83aa88483cf831415f8ce152dfb13e8159a2..b5fd9b8bdd033bde52acceeabf21370afb446ce1 100644 --- a/cool-module-system/cool-module-system-infrastructure/src/main/java/com/xgblack/cool/module/system/gateway/UserGatewayImpl.java +++ b/cool-module-system/cool-module-system-infrastructure/src/main/java/com/xgblack/cool/module/system/gateway/UserGatewayImpl.java @@ -89,6 +89,35 @@ public class UserGatewayImpl implements UserGateway, RemoteUserService { .update(); } + @Override + public UserInfo info(Long userId) { + SysUser sysUser = userMapper.selectOneWithRelationsByIdAs(userId, SysUser.class); + if (sysUser == null) { + log.error("用户不存在,用户id={}", userId); + return null; + } + UserInfo info = new UserInfo(); + // 设置角色列表 (ID) + Set roleIds = permissionGateway.getRoleIdsByUserId(sysUser.getId()); + // 权限列表(menu.permission) + Set permissions = new HashSet<>(); + Set menuIds = new HashSet<>(); + roleIds.forEach(roleId -> { + Set menuIdSet = permissionGateway.getMenuIdsByRoleId(roleId); + menuIds.addAll(menuIdSet); + }); + + if (CollUtil.isNotEmpty(menuIds)) { + List menuDOS = menuMapper.selectListByIds(menuIds); + permissions = menuDOS.stream().map(MenuDO::getPermission).collect(Collectors.toSet()); + } + info.setSysUser(sysUser) + .setRoles(roleIds) + .setPermissions(permissions); + + return info; + } + @Override public Long create(User user) { UserDO userDO = convertor.toDataObject(user); diff --git a/cool-server/src/main/resources/application.yaml b/cool-server/src/main/resources/application.yaml index c247fbb0ef42177811338f787c60d17c7211bb52..bb6d073bec5d2223c79a4990dfb2d60deadb04fb 100644 --- a/cool-server/src/main/resources/application.yaml +++ b/cool-server/src/main/resources/application.yaml @@ -29,6 +29,7 @@ cc: security: mock-enable: true mock-secret: coolcode + mock-sms-code: 223311 response: # 全局的参数校验错误码,默认等于default-error-code=-1 default-validate-error-code: -1