diff --git a/src/main/java/com/cool/core/security/AppOrgAuthFilter.java b/src/main/java/com/cool/core/security/AppOrgAuthFilter.java index e10de58..f7390bf 100644 --- a/src/main/java/com/cool/core/security/AppOrgAuthFilter.java +++ b/src/main/java/com/cool/core/security/AppOrgAuthFilter.java @@ -34,7 +34,7 @@ public class AppOrgAuthFilter extends OncePerRequestFilter { "/app/book/", "book", "/app/ticket/", "ticket", "/app/product/", "product", - "/app/agent/", "proxy" + "/app/agent/", "agent" ); @Override diff --git a/src/main/java/com/cool/modules/org/controller/admin/AdminAppOrgController.java b/src/main/java/com/cool/modules/org/controller/admin/AdminAppOrgController.java index 4bc9f1e..5101b60 100644 --- a/src/main/java/com/cool/modules/org/controller/admin/AdminAppOrgController.java +++ b/src/main/java/com/cool/modules/org/controller/admin/AdminAppOrgController.java @@ -63,7 +63,13 @@ public class AdminAppOrgController extends BaseController { void authorizeModules(Long orgId, List moduleKeys); Dict switchOrg(Long userId, Long orgId, boolean isAdmin); + + List listForSwitch(Long userId); } diff --git a/src/main/java/com/cool/modules/org/service/impl/AppModuleServiceImpl.java b/src/main/java/com/cool/modules/org/service/impl/AppModuleServiceImpl.java index 5dbd46e..0a4bac3 100644 --- a/src/main/java/com/cool/modules/org/service/impl/AppModuleServiceImpl.java +++ b/src/main/java/com/cool/modules/org/service/impl/AppModuleServiceImpl.java @@ -1,12 +1,134 @@ package com.cool.modules.org.service.impl; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.ModifyEnum; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.mapper.sys.BaseSysMenuMapper; +import com.cool.modules.base.service.sys.BaseSysPermsService; import com.cool.modules.org.mapper.AppModuleMapper; import com.cool.modules.org.entity.AppModuleEntity; import com.cool.modules.org.service.AppModuleService; +import com.mybatisflex.annotation.Table; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.core.annotation.AnnotatedElementUtils; +@Slf4j @Service +@RequiredArgsConstructor public class AppModuleServiceImpl extends BaseServiceImpl implements AppModuleService { + + private final BaseSysMenuMapper baseSysMenuMapper; + private final BaseSysPermsService baseSysPermsService; + + @Override + public void modifyAfter(JSONObject requestParams, AppModuleEntity entity, ModifyEnum type) { + if (type == ModifyEnum.ADD) { + createMenusForModule(entity); + } + } + + private void createMenusForModule(AppModuleEntity module) { + String moduleKey = module.getModuleKey(); + if (StrUtil.isBlank(moduleKey)) { + return; + } + + String basePackage = "com.cool.modules." + moduleKey + ".controller.admin"; + Set> controllerClasses = ClassUtil.scanPackageBySuper(basePackage, Object.class); + + if (controllerClasses.isEmpty()) { + log.info("[AppModuleService] 未找到模块 {} 的Admin Controller,跳过菜单创建", moduleKey); + return; + } + + BaseSysMenuEntity dirMenu = new BaseSysMenuEntity(); + dirMenu.setName(module.getName()); + dirMenu.setType(0); + dirMenu.setIcon(module.getIcon()); + dirMenu.setRouter("/" + moduleKey); + dirMenu.setOrderNum(0); + dirMenu.setKeepAlive(true); + dirMenu.setIsShow(true); + baseSysMenuMapper.insertSelective(dirMenu); + + List menuIds = new ArrayList<>(); + menuIds.add(dirMenu.getId()); + + for (Class controllerClass : controllerClasses) { + String controllerName = controllerClass.getSimpleName(); + if (!controllerName.startsWith("Admin")) { + continue; + } + + String entityPath = resolveEntityPath(controllerName, moduleKey); + String menuName = resolveMenuName(controllerClass, entityPath); + + BaseSysMenuEntity pageMenu = new BaseSysMenuEntity(); + pageMenu.setName(menuName); + pageMenu.setType(1); + pageMenu.setRouter("/" + moduleKey + "/" + entityPath); + pageMenu.setViewPath(moduleKey + "/" + entityPath + "/list.vue"); + pageMenu.setParentId(dirMenu.getId()); + pageMenu.setOrderNum(0); + pageMenu.setKeepAlive(true); + pageMenu.setIsShow(true); + baseSysMenuMapper.insertSelective(pageMenu); + + menuIds.add(pageMenu.getId()); + } + + module.setMenuIds(new cn.hutool.json.JSONArray(menuIds).toString()); + this.update(module); + + baseSysPermsService.refreshPermsByMenuId(null); + + log.info("[AppModuleService] 模块 {} 自动创建菜单完成,menuIds={}", moduleKey, menuIds); + } + + private String resolveEntityPath(String controllerName, String moduleKey) { + String name = controllerName; + if (name.startsWith("Admin")) { + name = name.substring(5); + } + if (name.endsWith("Controller")) { + name = name.substring(0, name.length() - 10); + } + + String modulePrefix = StrUtil.upperFirst(moduleKey); + if (name.startsWith(modulePrefix)) { + name = name.substring(modulePrefix.length()); + } + + return StrUtil.toCamelCase(name).toLowerCase(); + } + + private String resolveMenuName(Class controllerClass, String entityPath) { + io.swagger.v3.oas.annotations.tags.Tag tag = + AnnotatedElementUtils.findMergedAnnotation(controllerClass, io.swagger.v3.oas.annotations.tags.Tag.class); + if (tag != null && StrUtil.isNotBlank(tag.name())) { + return tag.name(); + } + + try { + java.lang.reflect.ParameterizedType pt = + (java.lang.reflect.ParameterizedType) controllerClass.getGenericSuperclass(); + Class entityClass = (Class) pt.getActualTypeArguments()[1]; + Table tableAnno = AnnotatedElementUtils.findMergedAnnotation(entityClass, Table.class); + if (tableAnno != null && StrUtil.isNotBlank(tableAnno.comment())) { + return tableAnno.comment().replace("表", ""); + } + } catch (Exception ignored) {} + + return entityPath; + } } diff --git a/src/main/java/com/cool/modules/org/service/impl/AppOrgServiceImpl.java b/src/main/java/com/cool/modules/org/service/impl/AppOrgServiceImpl.java index 75c69a2..9c3287a 100644 --- a/src/main/java/com/cool/modules/org/service/impl/AppOrgServiceImpl.java +++ b/src/main/java/com/cool/modules/org/service/impl/AppOrgServiceImpl.java @@ -150,14 +150,22 @@ public class AppOrgServiceImpl extends BaseServiceImpl userRoles = baseSysUserRoleMapper.selectListByQuery( + QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userId) + ); + boolean hasAccess = false; + for (BaseSysUserRoleEntity ur : userRoles) { + BaseSysRoleEntity role = baseSysRoleMapper.selectOneById(ur.getRoleId()); + if (role != null && orgId.equals(role.getTenantId())) { + hasAccess = true; + break; + } + } + CoolPreconditions.check(!hasAccess, "无权切换到该组织"); + } } else { CoolPreconditions.check(!appOrgUserService.isOrgMember(userId, orgId), "未加入该组织"); } @@ -166,18 +174,29 @@ public class AppOrgServiceImpl extends BaseServiceImpl authorities = new java.util.ArrayList<>(); + if (roleIds != null) { + for (Long rid : roleIds) { + authorities.add(new SimpleGrantedAuthority("ROLE_" + rid)); + } + } + JwtUser jwtUser = new JwtUser(userId, adminUser.getUsername(), adminUser.getPassword(), + authorities, true); - coolCache.set("app:userDetails:" + userId, jwtUser); + coolCache.set("admin:userDetails:" + adminUser.getUsername(), jwtUser); return Dict.create() .set("token", token) @@ -186,7 +205,52 @@ public class AppOrgServiceImpl extends BaseServiceImpl listForSwitch(Long userId) { + if (com.cool.core.util.CoolSecurityUtil.isSuperAdmin()) { + return this.list(QueryWrapper.create() + .eq(AppOrgEntity::getStatus, 1) + .orderBy(AppOrgEntity::getId, true)); + } + + List userRoles = baseSysUserRoleMapper.selectListByQuery( + QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userId) + ); + List orgIds = new java.util.ArrayList<>(); + for (BaseSysUserRoleEntity ur : userRoles) { + BaseSysRoleEntity role = baseSysRoleMapper.selectOneById(ur.getRoleId()); + if (role != null && role.getTenantId() != null && role.getStatus() != 0) { + orgIds.add(role.getTenantId()); + } + } + if (orgIds.isEmpty()) { + return List.of(); + } + return this.list(QueryWrapper.create() + .in(AppOrgEntity::getId, orgIds) + .eq(AppOrgEntity::getStatus, 1) + .orderBy(AppOrgEntity::getId, true)); } private String generateInviteCode() {