用户权限判断,默认继承目录权限
This commit is contained in:
14
data/pom.xml
14
data/pom.xml
@@ -123,6 +123,20 @@
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!-- 编译插件 parameters为了 切面PermissionCheckAspect能正确解析 #req.fileId、#fileId -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
|
||||
@@ -6,7 +6,12 @@ import com.sdm.data.service.IFileUserPermissionService;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
@@ -18,27 +23,80 @@ import java.nio.file.AccessDeniedException;
|
||||
@Aspect
|
||||
@Component
|
||||
public class PermissionCheckAspect {
|
||||
|
||||
|
||||
@Autowired
|
||||
private IFileUserPermissionService fileUserPermissionService;
|
||||
|
||||
|
||||
private final ExpressionParser parser = new SpelExpressionParser();
|
||||
private final EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
@Before("@annotation(filePermissionCheck)")
|
||||
public void checkPermission(JoinPoint joinPoint, FilePermissionCheck filePermissionCheck) throws AccessDeniedException {
|
||||
public void checkPermission(JoinPoint joinPoint, FilePermissionCheck filePermissionCheck){
|
||||
Long userId = ThreadLocalContext.getUserId();
|
||||
if (userId == null) {
|
||||
throw new RuntimeException("用户未登录");
|
||||
}
|
||||
|
||||
Object[] args = joinPoint.getArgs();
|
||||
// 解析 fileId
|
||||
Long fileId = resolveFileId(joinPoint, filePermissionCheck.fileIdExpression());
|
||||
if (fileId == null) {
|
||||
throw new RuntimeException("无法解析 fileId,请检查 @FilePermissionCheck.fileIdExpression()");
|
||||
}
|
||||
|
||||
Long fileId = 1L;
|
||||
// 检查权限
|
||||
if (!fileUserPermissionService.hasFilePermission(fileId, userId, filePermissionCheck.value())) {
|
||||
throw new AccessDeniedException("Permission denied");
|
||||
throw new RuntimeException("用户无操作文件和文件夹权限");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Long resolveFileId(JoinPoint joinPoint, String expression) {
|
||||
if (expression == null || expression.isEmpty()) {
|
||||
// 默认:假设第一个参数是 fileId(Long 类型)
|
||||
Object[] args = joinPoint.getArgs();
|
||||
if (args.length > 0 && args[0] instanceof Long) {
|
||||
return (Long) args[0];
|
||||
}
|
||||
throw new RuntimeException("未指定 fileIdExpression,且第一个参数不是 Long 类型");
|
||||
}
|
||||
|
||||
// 使用 SpEL 解析
|
||||
try {
|
||||
// 获取方法参数名(需要编译时保留参数名:-parameters 或 debug info)
|
||||
String[] paramNames = getParameterNames(joinPoint);
|
||||
Object[] args = joinPoint.getArgs();
|
||||
|
||||
// 构建变量映射
|
||||
for (int i = 0; i < paramNames.length && i < args.length; i++) {
|
||||
context.setVariable(paramNames[i], args[i]);
|
||||
}
|
||||
|
||||
Object result = parser.parseExpression(expression).getValue(context);
|
||||
if (result instanceof Number) {
|
||||
return ((Number) result).longValue();
|
||||
} else if (result instanceof String) {
|
||||
return Long.parseLong((String) result);
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("解析 fileId 失败: " + expression, e);
|
||||
}
|
||||
}
|
||||
|
||||
// 简单方式:依赖编译参数保留形参名(推荐加 -parameters 到 javac)
|
||||
private String[] getParameterNames(JoinPoint joinPoint) {
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
return methodSignature.getParameterNames(); // 需要 JDK 8+ 且编译时加 -parameters
|
||||
}
|
||||
|
||||
|
||||
// 自定义注解用于标记需要权限检查的方法
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface FilePermissionCheck {
|
||||
FilePermissionEnum value();
|
||||
|
||||
// 新增:指定 fileId 在哪个参数位置(从 0 开始),或通过 SpEL 表达式
|
||||
// 例如: "#fileId", "#req.fileId", "#delFileReq.delFileId"
|
||||
String fileIdExpression() default "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.sdm.data.service;
|
||||
|
||||
import com.sdm.common.common.SdmResponse;
|
||||
import com.sdm.common.entity.enums.FilePermissionEnum;
|
||||
import com.sdm.common.entity.req.data.*;
|
||||
import com.sdm.common.entity.req.system.LaunchApproveReq;
|
||||
import com.sdm.common.entity.resp.PageDataResp;
|
||||
import com.sdm.common.entity.resp.data.BatchAddFileInfoResp;
|
||||
import com.sdm.common.entity.resp.data.ChunkUploadMinioFileResp;
|
||||
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
|
||||
import com.sdm.data.aop.PermissionCheckAspect;
|
||||
import com.sdm.data.model.req.*;
|
||||
import com.sdm.data.model.resp.KKFileViewURLFromMinioResp;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.sdm.common.feign.inter.system.IApproveFeignClient;
|
||||
import com.sdm.common.log.CoreLogger;
|
||||
import com.sdm.common.utils.*;
|
||||
import com.sdm.common.utils.excel.ExcelUtil;
|
||||
import com.sdm.data.aop.PermissionCheckAspect;
|
||||
import com.sdm.data.model.bo.ApprovalFileDataContentsModel;
|
||||
import com.sdm.data.model.entity.*;
|
||||
import com.sdm.data.model.req.*;
|
||||
@@ -496,7 +497,6 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
* @param req 创建目录请求
|
||||
* @return 创建结果
|
||||
*/
|
||||
|
||||
public SdmResponse<?> createRootDir(CreateDirReq req) {
|
||||
if(ObjectUtils.isEmpty(req.getDirType())){
|
||||
log.error("请选择目录类型:1 知识库文件夹,2 项目节点文件夹,3 头像库文件夹,4 仿真参数库文件夹,5 训练模型文件夹");
|
||||
@@ -839,6 +839,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@PermissionCheckAspect.FilePermissionCheck(value = FilePermissionEnum.DELETE, fileIdExpression = "#req.delFileId")
|
||||
public SdmResponse delFile(DelFileReq req) {
|
||||
try {
|
||||
Long delFileId = req.getDelFileId();
|
||||
@@ -852,10 +853,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
|
||||
String deleteFileMinioObejctKey = deleteFileMetadataInfo.getObjectKey();
|
||||
|
||||
boolean hasDeletePermission = fileUserPermissionService.hasFilePermission(deleteFileMetadataInfo.getId(), ThreadLocalContext.getUserId(), FilePermissionEnum.DELETE);
|
||||
/*boolean hasDeletePermission = fileUserPermissionService.hasFilePermission(deleteFileMetadataInfo.getId(), ThreadLocalContext.getUserId(), FilePermissionEnum.DELETE);
|
||||
if (!hasDeletePermission) {
|
||||
return SdmResponse.failed("没有删除权限");
|
||||
}
|
||||
}*/
|
||||
|
||||
// 知识库
|
||||
if(dirMetadataInfo!=null&&Objects.equals(DirTypeEnum.KNOWLEDGE_BASE_DIR.getValue(), dirMetadataInfo.getDirType())){
|
||||
@@ -1047,6 +1048,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@PermissionCheckAspect.FilePermissionCheck(value = FilePermissionEnum.WRITE, fileIdExpression = "#req.fileId")
|
||||
public SdmResponse renameFile(RenameFileReq req) {
|
||||
String oldObjectKey = null;
|
||||
String newObjectKey = null;
|
||||
@@ -1056,10 +1058,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
if (ObjectUtils.isEmpty(oldFile)) {
|
||||
return SdmResponse.failed("文件不存在");
|
||||
}
|
||||
boolean hasDeletePermission = fileUserPermissionService.hasFilePermission(fileId, ThreadLocalContext.getUserId(), FilePermissionEnum.WRITE);
|
||||
/*boolean hasDeletePermission = fileUserPermissionService.hasFilePermission(fileId, ThreadLocalContext.getUserId(), FilePermissionEnum.WRITE);
|
||||
if (!hasDeletePermission){
|
||||
return SdmResponse.failed("没有修改权限");
|
||||
}
|
||||
}*/
|
||||
String newName = req.getNewName();
|
||||
oldObjectKey = oldFile.getObjectKey();
|
||||
newObjectKey = oldObjectKey.substring(0, oldObjectKey.lastIndexOf("/") + 1) + newName;
|
||||
@@ -1221,6 +1223,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@PermissionCheckAspect.FilePermissionCheck(value = FilePermissionEnum.DOWNLOAD, fileIdExpression = "#req.fileId")
|
||||
public void downloadFile(DownloadFileReq req, HttpServletResponse response) {
|
||||
try {
|
||||
FileMetadataInfo fileMetadataInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, req.getFileId()).one();
|
||||
@@ -1230,11 +1233,11 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
}
|
||||
String fileObjectKey = fileMetadataInfo.getObjectKey();
|
||||
|
||||
boolean hasDownloadPermission = fileUserPermissionService.hasFilePermission(fileMetadataInfo.getId(), ThreadLocalContext.getUserId(), FilePermissionEnum.DOWNLOAD);
|
||||
/* boolean hasDownloadPermission = fileUserPermissionService.hasFilePermission(fileMetadataInfo.getId(), ThreadLocalContext.getUserId(), FilePermissionEnum.DOWNLOAD);
|
||||
if (!hasDownloadPermission) {
|
||||
response.sendError(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION, "用户无权限");
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
// 从MinIO下载文件
|
||||
String encodedFileName = URLEncoder.encode(fileMetadataInfo.getOriginalName(), StandardCharsets.UTF_8);
|
||||
minioService.downloadFile(fileObjectKey,response,encodedFileName,false,"");
|
||||
@@ -1467,6 +1470,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@PermissionCheckAspect.FilePermissionCheck(value = FilePermissionEnum.UPLOAD, fileIdExpression = "#req.id")
|
||||
public SdmResponse updateFile(UpdateFileReq req) {
|
||||
FileMetadataInfo fileMetadataInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, req.getId()).one();
|
||||
if (fileMetadataInfo == null) {
|
||||
@@ -1474,10 +1478,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
}
|
||||
// 文件夹
|
||||
FileMetadataInfo dirMetadataInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, fileMetadataInfo.getParentId()).eq(FileMetadataInfo::getDataType, DataTypeEnum.DIRECTORY.getValue()).one();
|
||||
boolean hasUploadPermission = fileUserPermissionService.hasFilePermission(fileMetadataInfo.getId(), ThreadLocalContext.getUserId(), FilePermissionEnum.UPLOAD);
|
||||
/* boolean hasUploadPermission = fileUserPermissionService.hasFilePermission(fileMetadataInfo.getId(), ThreadLocalContext.getUserId(), FilePermissionEnum.UPLOAD);
|
||||
if (!hasUploadPermission) {
|
||||
return SdmResponse.failed("没有更新权限");
|
||||
}
|
||||
}*/
|
||||
String oldFileMinioObjectKey = fileMetadataInfo.getObjectKey();
|
||||
Long fileGroupId = fileMetadataInfo.getFileGroupId();
|
||||
Long versionNo = fileMetadataInfo.getVersionNo();
|
||||
|
||||
Reference in New Issue
Block a user