docs(product): 删除产品管理SQL口径和业务设计文档
- 移除02-产品管理SQL已确认口径文档 - 移除02-产品管理业务设计文档 - 清理产品管理模块的详细设计说明 - 删除产品需求状态字段口径定义 - 移除来源承接与需求拆分口径说明 - 清理需求终态原因承接口径内容 - 删除产品生命周期管理设计 - 移除产品团队权限管理规范 - 清理产品与项目关系约束说明 - 删除轻量需求管理业务规则 - 移除产品状态机与流程设计 - 清理权限与动作矩阵定义
This commit is contained in:
@@ -26,7 +26,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.njcn.rdms.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
|
||||
@@ -79,13 +82,26 @@ public class DictDataController {
|
||||
|
||||
@GetMapping(value = {"/list-all-simple", "simple-list"})
|
||||
@Operation(summary = "获得全部字典数据列表", description = "一般用于管理后台缓存字典数据在本地")
|
||||
// 无需添加权限认证,因为前端全局都需要
|
||||
// 不额外校验菜单权限,前端在登录后可直接拉取并缓存
|
||||
public CommonResult<List<DictDataSimpleRespVO>> getSimpleDictDataList() {
|
||||
List<DictDataDO> list = dictDataService.getDictDataList(
|
||||
CommonStatusEnum.ENABLE.getStatus(), null);
|
||||
return success(BeanUtils.toBean(list, DictDataSimpleRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/frontend-cache")
|
||||
@Operation(summary = "获得前端运行时字典缓存")
|
||||
public CommonResult<Map<String, List<DictDataSimpleRespVO>>> getFrontendCache() {
|
||||
List<DictDataSimpleRespVO> list = BeanUtils.toBean(
|
||||
dictDataService.getDictDataList(CommonStatusEnum.ENABLE.getStatus(), null),
|
||||
DictDataSimpleRespVO.class);
|
||||
Map<String, List<DictDataSimpleRespVO>> result = new LinkedHashMap<>();
|
||||
// 基于 service 已排好序的结果分组,保证每个字典组内仍按 sort 升序返回。
|
||||
list.forEach(dictData -> result.computeIfAbsent(dictData.getDictType(),
|
||||
key -> new ArrayList<>()).add(dictData));
|
||||
return success(result);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得字典类型的分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:dict:query')")
|
||||
|
||||
@@ -16,6 +16,9 @@ public class DictDataSimpleRespVO {
|
||||
@Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "男")
|
||||
private String label;
|
||||
|
||||
@Schema(description = "排序值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
|
||||
private String colorType;
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.njcn.rdms.module.system.framework.cache;
|
||||
|
||||
import com.njcn.rdms.module.system.dal.redis.RedisKeyConstants;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统启动后清理权限相关缓存,避免 SQL 直改后继续命中旧权限数据。
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class PermissionCacheStartupCleaner implements ApplicationRunner {
|
||||
|
||||
private static final List<String> CACHE_NAMES = List.of(
|
||||
RedisKeyConstants.ROLE,
|
||||
RedisKeyConstants.USER_ROLE_ID_LIST,
|
||||
RedisKeyConstants.MENU_ROLE_ID_LIST,
|
||||
RedisKeyConstants.PERMISSION_MENU_ID_LIST
|
||||
);
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
CACHE_NAMES.forEach(this::clearCacheQuietly);
|
||||
}
|
||||
|
||||
private void clearCacheQuietly(String cacheName) {
|
||||
Cache cache = cacheManager.getCache(cacheName);
|
||||
if (cache == null) {
|
||||
log.debug("[clearCacheQuietly][cacheName({}) 未注册,跳过清理]", cacheName);
|
||||
return;
|
||||
}
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,6 @@ package com.njcn.rdms.module.system.service.permission;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
/**
|
||||
* 权限 Service 接口
|
||||
* <p>
|
||||
@@ -61,9 +59,7 @@ public interface PermissionService {
|
||||
* @param roleId 角色编号
|
||||
* @return 菜单编号集合
|
||||
*/
|
||||
default Set<Long> getRoleMenuListByRoleId(Long roleId) {
|
||||
return getRoleMenuListByRoleId(singleton(roleId));
|
||||
}
|
||||
Set<Long> getRoleMenuListByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 获得角色们拥有的菜单编号集合
|
||||
|
||||
@@ -28,7 +28,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.njcn.rdms.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.ROLE_IS_DISABLE;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.ROLE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 权限 Service 实现类
|
||||
@@ -179,8 +182,7 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
allEntries = true) // allEntries 清空所有缓存,主要一次更新涉及到的 menuIds 较多,反倒批量会更快
|
||||
})
|
||||
public void assignRoleMenu(Long roleId, Set<Long> menuIds) {
|
||||
roleService.validateRoleList(Collections.singleton(roleId), GLOBAL_SCOPE_TYPE, GLOBAL_OBJECT_TYPE);
|
||||
RoleDO role = roleService.getRole(roleId);
|
||||
RoleDO role = getEnabledRole(roleId);
|
||||
menuService.validateMenuList(menuIds, role.getScopeType(), role.getObjectType());
|
||||
// 获得角色拥有菜单编号
|
||||
Set<Long> dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId), RoleMenuDO::getMenuId);
|
||||
@@ -224,6 +226,12 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
roleMenuMapper.deleteListByMenuId(menuId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getRoleMenuListByRoleId(Long roleId) {
|
||||
RoleDO role = getEnabledRole(roleId);
|
||||
return getRoleMenuListByRoleId(Collections.singleton(roleId), role.getScopeType(), role.getObjectType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getRoleMenuListByRoleId(Collection<Long> roleIds) {
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
@@ -338,6 +346,17 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
return CollUtil.isEmpty(menus) ? null : menus.get(0);
|
||||
}
|
||||
|
||||
private RoleDO getEnabledRole(Long roleId) {
|
||||
RoleDO role = roleService.getRole(roleId);
|
||||
if (role == null) {
|
||||
throw exception(ROLE_NOT_EXISTS);
|
||||
}
|
||||
if (!CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())) {
|
||||
throw exception(ROLE_IS_DISABLE, role.getName());
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
private PermissionServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.njcn.rdms.module.system.framework.cache;
|
||||
|
||||
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import com.njcn.rdms.module.system.dal.redis.RedisKeyConstants;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class PermissionCacheStartupCleanerTest extends BaseMockitoUnitTest {
|
||||
|
||||
@Mock
|
||||
private CacheManager cacheManager;
|
||||
@Mock
|
||||
private Cache roleCache;
|
||||
@Mock
|
||||
private Cache userRoleCache;
|
||||
@Mock
|
||||
private Cache menuRoleCache;
|
||||
@Mock
|
||||
private Cache permissionMenuCache;
|
||||
|
||||
@InjectMocks
|
||||
private PermissionCacheStartupCleaner cleaner;
|
||||
|
||||
@Test
|
||||
void run_shouldClearPermissionRelatedCaches() throws Exception {
|
||||
when(cacheManager.getCache(RedisKeyConstants.ROLE)).thenReturn(roleCache);
|
||||
when(cacheManager.getCache(RedisKeyConstants.USER_ROLE_ID_LIST)).thenReturn(userRoleCache);
|
||||
when(cacheManager.getCache(RedisKeyConstants.MENU_ROLE_ID_LIST)).thenReturn(menuRoleCache);
|
||||
when(cacheManager.getCache(RedisKeyConstants.PERMISSION_MENU_ID_LIST)).thenReturn(permissionMenuCache);
|
||||
|
||||
cleaner.run(mock(ApplicationArguments.class));
|
||||
|
||||
verify(roleCache).clear();
|
||||
verify(userRoleCache).clear();
|
||||
verify(menuRoleCache).clear();
|
||||
verify(permissionMenuCache).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void run_shouldIgnoreMissingCaches() {
|
||||
when(cacheManager.getCache(RedisKeyConstants.ROLE)).thenReturn(roleCache);
|
||||
|
||||
assertDoesNotThrow(() -> cleaner.run(mock(ApplicationArguments.class)));
|
||||
|
||||
verify(roleCache).clear();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user