新需求更新 同步更新
This commit is contained in:
+17
@@ -128,6 +128,23 @@ public class PermissionMenuController {
|
||||
return ApiResponse.success("视频任务权限已更新", grantedCount);
|
||||
}
|
||||
|
||||
@GetMapping("/shop-data-crawl-task-permissions")
|
||||
@Operation(summary = "查询店铺数据任务数据权限用户")
|
||||
public ApiResponse<List<ImageVideoDataPermissionUserVo>> listShopDataCrawlDataPermissionUsers(
|
||||
HttpServletRequest request) {
|
||||
return ApiResponse.success(permissionMenuService.listShopDataCrawlDataPermissionUsers(requireAdmin(request)));
|
||||
}
|
||||
|
||||
@PutMapping("/shop-data-crawl-task-permissions")
|
||||
@Operation(summary = "更新店铺数据任务数据权限用户")
|
||||
public ApiResponse<Integer> updateShopDataCrawlDataPermissionUsers(
|
||||
HttpServletRequest request,
|
||||
@RequestBody(required = false) ImageVideoDataPermissionUpdateRequest body) {
|
||||
int grantedCount = permissionMenuService.updateShopDataCrawlDataPermissionUsers(
|
||||
requireAdmin(request), body == null ? List.of() : body.getUserIds());
|
||||
return ApiResponse.success("店铺数据任务权限已更新", grantedCount);
|
||||
}
|
||||
|
||||
private AdminUserEntity requireAdmin(HttpServletRequest request) {
|
||||
try {
|
||||
return adminAuthSupport.requireAdmin(request);
|
||||
|
||||
+45
@@ -86,6 +86,7 @@ public class PermissionMenuSchemaInitializer {
|
||||
executeQuietly("UPDATE columns SET sort_order = id WHERE sort_order IS NULL OR sort_order = 0");
|
||||
executeQuietly("ALTER TABLE columns ADD UNIQUE KEY uk_menu_type_route_path (menu_type, route_path)");
|
||||
ensureDefaultAdminMenus();
|
||||
boolean shopDataCrawlDataPermissionCreated = ensureShopDataCrawlAdminDefaults();
|
||||
ensureDefaultAppMenus();
|
||||
ensureDefaultAppChildMenus();
|
||||
ensureInternalDataPermissions();
|
||||
@@ -98,6 +99,9 @@ public class PermissionMenuSchemaInitializer {
|
||||
FOREIGN KEY (column_id) REFERENCES columns(id) ON DELETE CASCADE
|
||||
)
|
||||
""");
|
||||
if (shopDataCrawlDataPermissionCreated) {
|
||||
grantInitialShopDataCrawlDataPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureDefaultAdminMenus() {
|
||||
@@ -172,6 +176,38 @@ public class PermissionMenuSchemaInitializer {
|
||||
""");
|
||||
}
|
||||
|
||||
private boolean ensureShopDataCrawlAdminDefaults() {
|
||||
executeQuietly("""
|
||||
INSERT INTO columns (name, column_key, menu_type, route_path, sort_order)
|
||||
SELECT '店铺数据任务管理', 'admin_shop_data_crawl_tasks', 'admin', 'shop-data-crawl-tasks', 82
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM columns WHERE column_key = 'admin_shop_data_crawl_tasks'
|
||||
)
|
||||
""");
|
||||
return executeUpdateQuietly("""
|
||||
INSERT INTO columns (name, column_key, menu_type, route_path, sort_order)
|
||||
SELECT '店铺数据任务数据查看', 'admin_shop_data_crawl_task_data', 'internal', 'shop-data-crawl-task-data', 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM columns WHERE column_key = 'admin_shop_data_crawl_task_data'
|
||||
)
|
||||
""") > 0;
|
||||
}
|
||||
|
||||
private void grantInitialShopDataCrawlDataPermissions() {
|
||||
executeQuietly("""
|
||||
INSERT IGNORE INTO user_column_permission (user_id, column_id)
|
||||
SELECT old_perm.user_id, data_col.id
|
||||
FROM user_column_permission old_perm
|
||||
INNER JOIN columns old_col ON old_col.id = old_perm.column_id
|
||||
INNER JOIN columns data_col ON data_col.column_key = 'admin_shop_data_crawl_task_data'
|
||||
LEFT JOIN user_column_permission existing
|
||||
ON existing.user_id = old_perm.user_id
|
||||
AND existing.column_id = data_col.id
|
||||
WHERE old_col.column_key = 'admin_shop_data_crawl_tasks'
|
||||
AND existing.user_id IS NULL
|
||||
""");
|
||||
}
|
||||
|
||||
private void executeQuietly(String sql) {
|
||||
try {
|
||||
jdbcTemplate.execute(sql);
|
||||
@@ -180,6 +216,15 @@ public class PermissionMenuSchemaInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
private int executeUpdateQuietly(String sql) {
|
||||
try {
|
||||
return jdbcTemplate.update(sql);
|
||||
} catch (Exception ex) {
|
||||
log.debug("[permission-menu] schema init skipped: {}", ex.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private record DefaultAdminMenu(String name, String columnKey, String routePath, int sortOrder) {
|
||||
}
|
||||
|
||||
|
||||
+109
-18
@@ -47,6 +47,7 @@ public class PermissionMenuService {
|
||||
public static final String MENU_TYPE_APP = "app";
|
||||
public static final String MENU_TYPE_ADMIN = "admin";
|
||||
private static final String IMAGE_VIDEO_DATA_PERMISSION_KEY = "admin_image_video_task_data";
|
||||
private static final String SHOP_DATA_CRAWL_DATA_PERMISSION_KEY = "admin_shop_data_crawl_task_data";
|
||||
|
||||
private final PermissionMenuMapper permissionMenuMapper;
|
||||
private final UserColumnPermissionMapper userColumnPermissionMapper;
|
||||
@@ -243,9 +244,8 @@ public class PermissionMenuService {
|
||||
.filter(user -> user.getId() != null && !isSuperAdmin(user))
|
||||
.collect(Collectors.toMap(AdminUserEntity::getId, Function.identity(), (left, right) -> left));
|
||||
if (requestedIds.stream().anyMatch(id -> !grantableUsers.containsKey(id))) {
|
||||
throw new BusinessException("包含不存在或不可授权的用户");
|
||||
throw new BusinessException("contains unknown or non-grantable user");
|
||||
}
|
||||
|
||||
userColumnPermissionMapper.deleteByMap(Map.of("column_id", dataPermission.getId()));
|
||||
for (Long userId : requestedIds) {
|
||||
UserColumnPermissionEntity grant = new UserColumnPermissionEntity();
|
||||
@@ -256,6 +256,68 @@ public class PermissionMenuService {
|
||||
return requestedIds.size();
|
||||
}
|
||||
|
||||
public List<ImageVideoDataPermissionUserVo> listShopDataCrawlDataPermissionUsers(AdminUserEntity operator) {
|
||||
ensureSuperAdminOperator(operator, "店铺数据任务");
|
||||
PermissionMenuEntity dataPermission = requireDataPermission(
|
||||
SHOP_DATA_CRAWL_DATA_PERMISSION_KEY, "店铺数据任务数据");
|
||||
Set<Long> grantedUserIds = userColumnPermissionMapper.selectList(
|
||||
new LambdaQueryWrapper<UserColumnPermissionEntity>()
|
||||
.eq(UserColumnPermissionEntity::getColumnId, dataPermission.getId()))
|
||||
.stream()
|
||||
.map(UserColumnPermissionEntity::getUserId)
|
||||
.filter(id -> id != null && id > 0)
|
||||
.collect(Collectors.toSet());
|
||||
return adminUserMapper.selectList(new LambdaQueryWrapper<AdminUserEntity>()
|
||||
.orderByAsc(AdminUserEntity::getUsername)
|
||||
.orderByAsc(AdminUserEntity::getId))
|
||||
.stream()
|
||||
.filter(user -> !isSuperAdmin(user))
|
||||
.map(user -> toImageVideoDataPermissionUserVo(user, grantedUserIds.contains(user.getId())))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int updateShopDataCrawlDataPermissionUsers(AdminUserEntity operator, List<Long> userIds) {
|
||||
ensureSuperAdminOperator(operator, "店铺数据任务");
|
||||
PermissionMenuEntity dataPermission = requireDataPermission(
|
||||
SHOP_DATA_CRAWL_DATA_PERMISSION_KEY, "店铺数据任务数据");
|
||||
List<Long> requestedIds = normalizeColumnIds(userIds);
|
||||
List<AdminUserEntity> users = adminUserMapper.selectList(new LambdaQueryWrapper<AdminUserEntity>());
|
||||
Map<Long, AdminUserEntity> grantableUsers = users.stream()
|
||||
.filter(user -> user.getId() != null && !isSuperAdmin(user))
|
||||
.collect(Collectors.toMap(AdminUserEntity::getId, Function.identity(), (left, right) -> left));
|
||||
if (requestedIds.stream().anyMatch(id -> !grantableUsers.containsKey(id))) {
|
||||
throw new BusinessException("contains unknown or non-grantable user");
|
||||
}
|
||||
userColumnPermissionMapper.deleteByMap(Map.of("column_id", dataPermission.getId()));
|
||||
for (Long userId : requestedIds) {
|
||||
UserColumnPermissionEntity grant = new UserColumnPermissionEntity();
|
||||
grant.setUserId(userId);
|
||||
grant.setColumnId(dataPermission.getId());
|
||||
userColumnPermissionMapper.insert(grant);
|
||||
}
|
||||
return requestedIds.size();
|
||||
}
|
||||
|
||||
/** Verifies both the visible admin menu and its separately managed data grant. */
|
||||
public void requireShopDataCrawlTaskAccess(AdminUserEntity operator) {
|
||||
ensureAdminOperatorIfPresent(operator);
|
||||
if (operator == null || operator.getId() == null || operator.getId() <= 0) {
|
||||
throw new BusinessException(403, "需要管理员权限");
|
||||
}
|
||||
if (isSuperAdmin(operator)) {
|
||||
return;
|
||||
}
|
||||
PermissionMenuEntity taskMenu = requireDataPermission(
|
||||
"admin_shop_data_crawl_tasks", "店铺数据任务管理菜单");
|
||||
PermissionMenuEntity dataPermission = requireDataPermission(
|
||||
SHOP_DATA_CRAWL_DATA_PERMISSION_KEY, "店铺数据任务数据");
|
||||
if (!hasEffectiveColumnPermission(operator.getId(), taskMenu.getId())
|
||||
|| !hasEffectiveColumnPermission(operator.getId(), dataPermission.getId())) {
|
||||
throw new BusinessException(403, "无权查看店铺数据任务");
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateUserColumnPermissions(Long userId, UserColumnPermissionUpdateRequest request) {
|
||||
updateUserColumnPermissions(null, userId, request);
|
||||
@@ -304,26 +366,36 @@ public class PermissionMenuService {
|
||||
}
|
||||
}
|
||||
|
||||
PermissionMenuEntity imageVideoDataPermission = normalizedType == null
|
||||
? findImageVideoDataPermission()
|
||||
: null;
|
||||
Long protectedId = imageVideoDataPermission == null ? null : imageVideoDataPermission.getId();
|
||||
Set<Long> protectedIds = new LinkedHashSet<>();
|
||||
if (normalizedType == null) {
|
||||
PermissionMenuEntity imageVideoDataPermission = findImageVideoDataPermission();
|
||||
PermissionMenuEntity shopDataCrawlDataPermission =
|
||||
findDataPermission(SHOP_DATA_CRAWL_DATA_PERMISSION_KEY);
|
||||
if (imageVideoDataPermission != null && imageVideoDataPermission.getId() != null) {
|
||||
protectedIds.add(imageVideoDataPermission.getId());
|
||||
}
|
||||
if (shopDataCrawlDataPermission != null && shopDataCrawlDataPermission.getId() != null) {
|
||||
protectedIds.add(shopDataCrawlDataPermission.getId());
|
||||
}
|
||||
}
|
||||
List<Long> grantIds = requestedIds;
|
||||
if (normalizedType == null && protectedId != null) {
|
||||
if (!protectedIds.isEmpty()) {
|
||||
grantIds = requestedIds.stream()
|
||||
.filter(id -> !protectedId.equals(id))
|
||||
.filter(id -> !protectedIds.contains(id))
|
||||
.toList();
|
||||
}
|
||||
Set<Long> operatorEffectiveIds = ensureGrantable(operator, grantIds);
|
||||
LinkedHashSet<Long> finalGrantIds = new LinkedHashSet<>(grantIds);
|
||||
|
||||
if (normalizedType == null && protectedId != null) {
|
||||
Long existingCount = userColumnPermissionMapper.selectCount(
|
||||
new LambdaQueryWrapper<UserColumnPermissionEntity>()
|
||||
.eq(UserColumnPermissionEntity::getUserId, userId)
|
||||
.eq(UserColumnPermissionEntity::getColumnId, protectedId));
|
||||
if (existingCount != null && existingCount > 0) {
|
||||
finalGrantIds.add(protectedId);
|
||||
if (!protectedIds.isEmpty()) {
|
||||
for (Long protectedId : protectedIds) {
|
||||
Long existingCount = userColumnPermissionMapper.selectCount(
|
||||
new LambdaQueryWrapper<UserColumnPermissionEntity>()
|
||||
.eq(UserColumnPermissionEntity::getUserId, userId)
|
||||
.eq(UserColumnPermissionEntity::getColumnId, protectedId));
|
||||
if (existingCount != null && existingCount > 0) {
|
||||
finalGrantIds.add(protectedId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (operatorEffectiveIds != null) {
|
||||
@@ -526,9 +598,7 @@ public class PermissionMenuService {
|
||||
}
|
||||
|
||||
private PermissionMenuEntity findImageVideoDataPermission() {
|
||||
return permissionMenuMapper.selectOne(new LambdaQueryWrapper<PermissionMenuEntity>()
|
||||
.eq(PermissionMenuEntity::getColumnKey, IMAGE_VIDEO_DATA_PERMISSION_KEY)
|
||||
.last("LIMIT 1"));
|
||||
return findDataPermission(IMAGE_VIDEO_DATA_PERMISSION_KEY);
|
||||
}
|
||||
|
||||
private PermissionMenuEntity requireImageVideoDataPermission() {
|
||||
@@ -546,6 +616,27 @@ public class PermissionMenuService {
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureSuperAdminOperator(AdminUserEntity operator, String resourceName) {
|
||||
ensureAdminOperatorIfPresent(operator);
|
||||
if (operator == null || !isSuperAdmin(operator)) {
|
||||
throw new BusinessException(403, "仅超级管理员可以配置" + resourceName + "权限");
|
||||
}
|
||||
}
|
||||
|
||||
private PermissionMenuEntity findDataPermission(String columnKey) {
|
||||
return permissionMenuMapper.selectOne(new LambdaQueryWrapper<PermissionMenuEntity>()
|
||||
.eq(PermissionMenuEntity::getColumnKey, columnKey)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
private PermissionMenuEntity requireDataPermission(String columnKey, String displayName) {
|
||||
PermissionMenuEntity permission = findDataPermission(columnKey);
|
||||
if (permission == null || permission.getId() == null) {
|
||||
throw new BusinessException(displayName + "权限尚未初始化");
|
||||
}
|
||||
return permission;
|
||||
}
|
||||
|
||||
private ImageVideoDataPermissionUserVo toImageVideoDataPermissionUserVo(AdminUserEntity user,
|
||||
boolean granted) {
|
||||
ImageVideoDataPermissionUserVo vo = new ImageVideoDataPermissionUserVo();
|
||||
|
||||
Reference in New Issue
Block a user