3.26 空间模块 重构之前代码,增加空间权限校验

This commit is contained in:
zhangsan 2025-03-26 17:26:38 +08:00
parent c2d8391166
commit 9651ef6790
3 changed files with 104 additions and 22 deletions

View File

@ -11,11 +11,13 @@ import edu.whut.smilepicturebackend.exception.ErrorCode;
import edu.whut.smilepicturebackend.exception.ThrowUtils;
import edu.whut.smilepicturebackend.model.dto.picture.*;
import edu.whut.smilepicturebackend.model.entity.Picture;
import edu.whut.smilepicturebackend.model.entity.Space;
import edu.whut.smilepicturebackend.model.entity.User;
import edu.whut.smilepicturebackend.model.enums.PictureReviewStatusEnum;
import edu.whut.smilepicturebackend.model.vo.PictureTagCategory;
import edu.whut.smilepicturebackend.model.vo.PictureVO;
import edu.whut.smilepicturebackend.service.PictureService;
import edu.whut.smilepicturebackend.service.SpaceService;
import edu.whut.smilepicturebackend.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -36,6 +38,7 @@ import java.util.List;
public class PictureController {
private final UserService userService;
private final PictureService pictureService;
private final SpaceService spaceService;
@ -157,6 +160,12 @@ public class PictureController {
Picture picture = pictureService.getById(id);
ThrowUtils.throwIf(picture == null, ErrorCode.NOT_FOUND_ERROR);
ThrowUtils.throwIf(PictureReviewStatusEnum.PASS.getValue()!=picture.getReviewStatus(),ErrorCode.NOT_FOUND_ERROR);
// 空间权限校验
Long spaceId = picture.getSpaceId();
if (spaceId != null) {
User loginUser = userService.getLoginUser(request);
pictureService.checkPictureAuth(loginUser, picture);
}
// 获取封装类
return ResultUtils.success(pictureService.getPictureVO(picture, request));
}
@ -185,8 +194,22 @@ public class PictureController {
long size = pictureQueryRequest.getPageSize();
// 限制爬虫一次不能请求超过20页
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
// 普通用户默认只能看到审核通过的数据
pictureQueryRequest.setReviewStatus(PictureReviewStatusEnum.PASS.getValue());
// 空间权限校验
Long spaceId = pictureQueryRequest.getSpaceId();
if (spaceId == null) {
// 公开图库
// 普通用户默认只能看到审核通过的数据
pictureQueryRequest.setReviewStatus(PictureReviewStatusEnum.PASS.getValue());
pictureQueryRequest.setNullSpaceId(true);
} else {
// 私有空间
User loginUser = userService.getLoginUser(request);
Space space = spaceService.getById(spaceId);
ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
if (!loginUser.getId().equals(space.getUserId())) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有空间权限");
}
}
// 查询数据库
Page<Picture> picturePage = pictureService.page(new Page<>(current, size),
pictureService.getQueryWrapper(pictureQueryRequest));

View File

@ -187,4 +187,21 @@ public class SpaceController {
return ResultUtils.success(true);
}
/**
* 获取空间级别列表便于前端展示
*
* @return
*/
@GetMapping("/list/level")
public BaseResponse<List<SpaceLevel>> listSpaceLevel() {
List<SpaceLevel> spaceLevelList = Arrays.stream(SpaceLevelEnum.values())
.map(spaceLevelEnum -> new SpaceLevel(
spaceLevelEnum.getValue(),
spaceLevelEnum.getText(),
spaceLevelEnum.getMaxCount(),
spaceLevelEnum.getMaxSize()
))
.collect(Collectors.toList());
return ResultUtils.success(spaceLevelList);
}
}

View File

@ -41,6 +41,7 @@ import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.DigestUtils;
@ -69,6 +70,7 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
private final MyCacheManager cacheManager;
private final CosManager cosManager;
private final SpaceService spaceService;
private final TransactionTemplate transactionTemplate;
@Override
public void validPicture(Picture picture) {
ThrowUtils.throwIf(picture == null, ErrorCode.PARAMS_ERROR);
@ -101,6 +103,13 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
if (!loginUser.getId().equals(space.getUserId())) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有空间权限");
}
// 校验额度
if (space.getTotalCount() >= space.getMaxCount()) {
throw new BusinessException(ErrorCode.OPERATION_ERROR, "空间条数不足");
}
if (space.getTotalSize() >= space.getMaxSize()) {
throw new BusinessException(ErrorCode.OPERATION_ERROR, "空间大小不足");
}
}
// 判断是创建还是替换
Long pictureId = pictureUploadRequest == null ? null : pictureUploadRequest.getId();
@ -166,8 +175,28 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
picture.setId(pictureId);
picture.setEditTime(new Date());
}
boolean result = this.saveOrUpdate(picture);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败,数据库操作失败");
// 计算差值保证 oldPicture 为空时不抛异常
long sizeDelta = picture.getPicSize() - (oldPicture == null ? 0 : oldPicture.getPicSize());
long countDelta = (oldPicture == null ? 1 : 0);
// 开启事务,图片上传成功和修改额度一定要同时成功或失败
Long finalSpaceId = spaceId;
transactionTemplate.execute(status -> {
// 插入数据
boolean result = this.saveOrUpdate(picture);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败,数据库操作失败");
if (finalSpaceId != null) {
// 更新空间的使用额度
boolean update = spaceService.lambdaUpdate()
.eq(Space::getId, finalSpaceId)
// 更新 total_size
.apply(sizeDelta != 0, "total_size = total_size + {0}", sizeDelta) // 占位符安全绑定[1][2]
// 更新 total_count只有新增才加 1
.apply(countDelta != 0, "total_count = total_count + {0}", countDelta)
.update();
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "额度更新失败");
}
return picture;
});
//如果是更新清理旧的图片
if (oldPicture != null) {
this.clearPictureFile(oldPicture);
@ -183,21 +212,23 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
}
// 精简版条件构造
qw.eq(ObjUtil.isNotEmpty(req.getId()), Picture::getId, req.getId())
.eq(ObjUtil.isNotEmpty(req.getUserId()), Picture::getUserId, req.getUserId())
.like(StrUtil.isNotBlank(req.getName()), Picture::getName, req.getName())
qw.eq(ObjUtil.isNotEmpty(req.getId()), Picture::getId, req.getId())
.eq(ObjUtil.isNotEmpty(req.getUserId()), Picture::getUserId, req.getUserId())
.eq(ObjUtil.isNotEmpty(req.getSpaceId()), Picture::getSpaceId, req.getSpaceId()) //指定 spaceId 查该空间图片
.isNull(req.isNullSpaceId(), Picture::getSpaceId) //不传则查公共图库
.like(StrUtil.isNotBlank(req.getName()), Picture::getName, req.getName())
.like(StrUtil.isNotBlank(req.getIntroduction()), Picture::getIntroduction, req.getIntroduction())
.like(StrUtil.isNotBlank(req.getPicFormat()), Picture::getPicFormat, req.getPicFormat())
.eq(ObjUtil.isNotEmpty(req.getReviewMessage()),Picture::getReviewMessage,req.getReviewMessage())
.eq(StrUtil.isNotBlank(req.getCategory()), Picture::getCategory, req.getCategory())
.eq(ObjUtil.isNotEmpty(req.getPicWidth()), Picture::getPicWidth, req.getPicWidth())
.eq(ObjUtil.isNotEmpty(req.getPicHeight()), Picture::getPicHeight, req.getPicHeight())
.eq(ObjUtil.isNotEmpty(req.getPicSize()), Picture::getPicSize, req.getPicSize())
.eq(ObjUtil.isNotEmpty(req.getPicScale()), Picture::getPicScale, req.getPicScale())
.eq(ObjUtil.isNotEmpty(req.getReviewStatus()),Picture::getReviewStatus,req.getReviewStatus())
.eq(ObjUtil.isNotEmpty(req.getReviewerId()),Picture::getReviewerId,req.getReviewerId())
.ge(ObjUtil.isNotEmpty(req.getStartEditTime()), Picture::getEditTime, req.getStartEditTime())
.lt(ObjUtil.isNotEmpty(req.getEndEditTime()), Picture::getEditTime, req.getEndEditTime());
.like(StrUtil.isNotBlank(req.getPicFormat()), Picture::getPicFormat, req.getPicFormat())
.eq(ObjUtil.isNotEmpty(req.getReviewMessage()), Picture::getReviewMessage, req.getReviewMessage())
.eq(StrUtil.isNotBlank(req.getCategory()), Picture::getCategory, req.getCategory())
.eq(ObjUtil.isNotEmpty(req.getPicWidth()), Picture::getPicWidth, req.getPicWidth())
.eq(ObjUtil.isNotEmpty(req.getPicHeight()), Picture::getPicHeight, req.getPicHeight())
.eq(ObjUtil.isNotEmpty(req.getPicSize()), Picture::getPicSize, req.getPicSize())
.eq(ObjUtil.isNotEmpty(req.getPicScale()), Picture::getPicScale, req.getPicScale())
.eq(ObjUtil.isNotEmpty(req.getReviewStatus()), Picture::getReviewStatus, req.getReviewStatus())
.eq(ObjUtil.isNotEmpty(req.getReviewerId()), Picture::getReviewerId, req.getReviewerId())
.ge(ObjUtil.isNotEmpty(req.getStartEditTime()), Picture::getEditTime, req.getStartEditTime())
.lt(ObjUtil.isNotEmpty(req.getEndEditTime()), Picture::getEditTime, req.getEndEditTime());
// 全字段模糊搜索
if (StrUtil.isNotBlank(req.getSearchText())) {
@ -236,9 +267,20 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
}
// 校验权限
checkPictureAuth(loginUser, oldPicture);
// 操作数据库
boolean result = this.removeById(pictureId);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
// 开启事务
transactionTemplate.execute(status -> {
// 操作数据库
boolean result = this.removeById(pictureId);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
// 更新空间的使用额度释放额度
boolean update = spaceService.lambdaUpdate()
.eq(Space::getId, oldPicture.getSpaceId())
.setSql("total_size = total_size - " + oldPicture.getPicSize())
.setSql("total_count = total_count - 1")
.update();
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "额度更新失败");
return true;
});
//清理图片资源
this.clearPictureFile(oldPicture);
}
@ -260,7 +302,7 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND_ERROR);
// 校验权限
checkPictureAuth(loginUser, oldPicture);
// 补充审核参数,每次编辑图片都要重新过审
// 补充审核 参数,每次编辑图片都要重新过审
this.fillReviewParams(picture, loginUser);
// 操作数据库
boolean result = this.updateById(picture);