fix:修复了过时的代码、新增自定义缓存、代码风格调整、性能优化,以及修复了一些问题。

This commit is contained in:
besscroft
2023-04-21 16:21:11 +08:00
parent a1ada205c9
commit eca4f011aa
28 changed files with 221 additions and 111 deletions

View File

@@ -0,0 +1,25 @@
package com.besscroft.diyfile.common.constant;
/**
* @Description 返回消息常量
* @Author Bess Croft
* @Date 2023/4/21 13:36
*/
public interface MessageConstants {
/** 通用成功消息 */
String SUCCESS = "操作成功!";
/** 通用失败消息 */
String ERROR = "操作失败!";
/** 通用新增成功消息 */
String ADD_SUCCESS = "新增成功!";
/** 通用更新成功消息 */
String UPDATE_SUCCESS = "更新成功!";
/** 通用删除成功消息 */
String DELETE_SUCCESS = "删除成功!";
}

View File

@@ -15,12 +15,12 @@ public class LoginParam {
/** 用户名 */
@NotBlank(message = "用户名未填!")
@Schema(title = "用户名", type = "String", required = true)
@Schema(title = "用户名", type = "String", requiredMode = Schema.RequiredMode.REQUIRED)
private String username;
/** 密码 */
@NotBlank(message = "密码未填!")
@Schema(title = "密码", type = "String", required = true)
@Schema(title = "密码", type = "String", requiredMode = Schema.RequiredMode.REQUIRED)
private String password;
}

View File

@@ -13,11 +13,11 @@ import lombok.Data;
@Schema(title = "新增用户请求参数")
public class UserAddParam {
@Schema(title = "用户名", type = "String", required = true)
@Schema(title = "用户名", type = "String", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "用户名不能为空!")
private String username;
@Schema(title = "密码", type = "String", required = true)
@Schema(title = "密码", type = "String", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "密码不能为空!")
private String password;

View File

@@ -13,7 +13,7 @@ import lombok.Data;
@Schema(title = "更新用户请求参数")
public class UserUpdateParam {
@Schema(title = "用户 id", type = "Long", required = true)
@Schema(title = "用户 id", type = "Long", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "用户 id 不能为空!")
private Long id;

View File

@@ -52,7 +52,9 @@ public class PathUtils {
*/
public static boolean isFolder(String path) {
// 不包含扩展名的 . 肯定为文件夹
if (!StrUtil.contains(path, ".") || StrUtil.equals(path, "/")) return true;
if (!StrUtil.contains(path, ".") || StrUtil.equals(path, "/")) {
return true;
}
int lastSlashIndex = path.lastIndexOf('/');
String realPath = path.substring(lastSlashIndex + 1);
return !realPath.contains(".");

View File

@@ -20,7 +20,7 @@ public class OpenApiConfiguration {
return new OpenAPI()
.info(new Info().title("DiyFile")
.description("一款好看的在线文件列表程序")
.version("v0.4.0")
.version("v0.5.0")
.license(new License().name("MIT license").url("https://github.com/besscroft/diyfile/blob/main/LICENSE")))
.externalDocs(new ExternalDocumentation()
.description("DiyFile 文档")

View File

@@ -0,0 +1,53 @@
package com.besscroft.diyfile.cache;
import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.date.DateUnit;
/**
* @Description
* @Author Bess Croft
* @Date 2023/4/21 15:36
*/
public class DiyCache {
private static final Cache<String, Object> DIY_CACHE = CacheUtil.newFIFOCache(100);
/**
* 新增缓存,默认 15 分钟过期
* @param key 键
* @param object 值
*/
public static void putDiyKey(String key, Object object) {
// 默认 15 分钟
putDiyKeyTimeOut(key, object, 60 * 15);
}
/**
* 获取缓存
* @param key 键
* @return 值
*/
public static Object getDiyKey(String key) {
return DIY_CACHE.get(key);
}
/**
* 新增缓存
* @param key 键
* @param object 值
* @param timeout 过期时间,单位秒
*/
public static void putDiyKeyTimeOut(String key, Object object, long timeout) {
DIY_CACHE.put(key, object, DateUnit.SECOND.getMillis() * timeout);
}
/**
* 删除缓存
* @param key 键
*/
public static void removeDiyKey(String key) {
DIY_CACHE.remove(key);
}
}

View File

@@ -1,10 +1,9 @@
package com.besscroft.diyfile.config;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.transaction.TransactionAwareCacheManagerProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -14,14 +13,16 @@ import org.springframework.context.annotation.Configuration;
* @Date 2023/1/22 20:49
*/
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
public class CacheConfig implements CachingConfigurer {
/**
* afterCommit在事务提交后执行
* @return CacheManager
*/
@Bean
public Cache<String, Object> caffeineCache(CacheProperties cacheProperties) {
String spec = cacheProperties.getCaffeine().getSpec();
CaffeineSpec caffeineSpec = CaffeineSpec.parse(spec);
Caffeine<Object, Object> caffeine = Caffeine.from(caffeineSpec);
return caffeine.build();
@Override
public CacheManager cacheManager() {
return new TransactionAwareCacheManagerProxy(new ConcurrentMapCacheManager());
}
}

View File

@@ -69,7 +69,7 @@ public class FlywayConfigure {
}
String databaseProductVersion = databaseMetaData.getDatabaseProductVersion();
log.info("当前数据库版本为:{}", databaseProductVersion);
if (StrUtil.sub(databaseProductVersion, 0, 1).equals("5")) {
if ("5".equals(StrUtil.sub(databaseProductVersion, 0, 1))) {
log.info("数据库版本不支持自动初始化,跳过初始化...");
return;
}

View File

@@ -25,7 +25,7 @@ public class StpInterfaceImpl implements StpInterface {
* 返回一个账号所拥有的权限码集合
* @param loginId 登录用户 id
* @param loginType 登录用户类型
* @return
* @return 账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
@@ -37,7 +37,7 @@ public class StpInterfaceImpl implements StpInterface {
* 返回一个账号所拥有的角色标识集合
* @param loginId 登录用户 id
* @param loginType 登录用户类型
* @return
* @return 账号所拥有的角色标识集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {

View File

@@ -3,6 +3,7 @@ package com.besscroft.diyfile.controller;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.annotation.SaMode;
import com.besscroft.diyfile.common.constant.MessageConstants;
import com.besscroft.diyfile.common.constant.RoleConstants;
import com.besscroft.diyfile.common.param.file.DeleteFileParam;
import com.besscroft.diyfile.common.param.file.GetFileInfoParam;
@@ -105,7 +106,7 @@ public class FileController {
// 校验路径
PathUtils.checkPath(param.getPath());
fileService.deleteFile(param.getStorageKey(), param.getPath());
return AjaxResult.success("删除成功!");
return AjaxResult.success(MessageConstants.DELETE_SUCCESS);
}
}

View File

@@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.util.StrUtil;
import com.besscroft.diyfile.common.constant.MessageConstants;
import com.besscroft.diyfile.common.constant.RoleConstants;
import com.besscroft.diyfile.common.entity.Storage;
import com.besscroft.diyfile.common.exception.DiyFileException;
@@ -67,7 +68,7 @@ public class StorageController {
@DeleteMapping("/delete/{storageId:[\\d]+}")
public AjaxResult delete(@PathVariable(name = "storageId") Long storageId) {
storageService.deleteStorage(storageId);
return AjaxResult.success("删除成功!");
return AjaxResult.success(MessageConstants.DELETE_SUCCESS);
}
@Operation(summary = "存储新增接口")
@@ -81,12 +82,14 @@ public class StorageController {
)
@PostMapping("/add")
public AjaxResult add(@RequestBody @Valid StorageAddParam param) {
if (Objects.equals("proxy", param.getStorageKey()))
if (Objects.equals("proxy", param.getStorageKey())) {
throw new DiyFileException("存储 key 不能为 proxy");
if (StrUtil.contains(param.getStorageKey(), "/"))
}
if (StrUtil.contains(param.getStorageKey(), "/")) {
throw new DiyFileException("存储 key 不能包含 /");
}
storageService.addStorage(param);
return AjaxResult.success("新增成功!");
return AjaxResult.success(MessageConstants.ADD_SUCCESS);
}
@Operation(summary = "存储更新接口")
@@ -101,7 +104,7 @@ public class StorageController {
@PutMapping("/update")
public AjaxResult update(@RequestBody @Valid StorageUpdateParam param) {
storageService.updateStorage(param);
return AjaxResult.success("更新成功!");
return AjaxResult.success(MessageConstants.UPDATE_SUCCESS);
}
@Operation(summary = "存储详情接口")
@@ -137,7 +140,7 @@ public class StorageController {
@PutMapping("/updateStatus")
public AjaxResult updateStatus(@RequestBody @Valid StorageUpdateStatusParam param) {
storageService.updateStatus(param.getStorageId(), param.getStatus());
return AjaxResult.success("更新成功!");
return AjaxResult.success(MessageConstants.UPDATE_SUCCESS);
}
@Operation(summary = "默认存储设置")
@@ -152,7 +155,7 @@ public class StorageController {
@PutMapping("/setDefault/{storageId:[\\d]+}")
public AjaxResult setDefault(@PathVariable(name = "storageId") Long storageId) {
storageService.setDefault(storageId);
return AjaxResult.success("设置成功!");
return AjaxResult.success(MessageConstants.UPDATE_SUCCESS);
}
@SaIgnore

View File

@@ -3,6 +3,7 @@ package com.besscroft.diyfile.controller;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.annotation.SaMode;
import com.besscroft.diyfile.common.constant.MessageConstants;
import com.besscroft.diyfile.common.constant.RoleConstants;
import com.besscroft.diyfile.common.param.system.SystemUpdateConfigParam;
import com.besscroft.diyfile.common.result.AjaxResult;
@@ -46,7 +47,7 @@ public class SystemConfigController {
@Operation(summary = "获取网站标题")
public AjaxResult getSiteTitle() {
String siteTitle = systemConfigService.getSiteTitle();
return AjaxResult.success("操作成功!", siteTitle);
return AjaxResult.success(MessageConstants.SUCCESS, siteTitle);
}
@GetMapping("/getSiteConfig")
@@ -69,7 +70,7 @@ public class SystemConfigController {
@Operation(summary = "获取备案信息")
public AjaxResult getBeian() {
String beian = systemConfigService.getBeian();
return AjaxResult.success("操作成功!", beian);
return AjaxResult.success(MessageConstants.SUCCESS, beian);
}
@PutMapping("/updateConfig")
@@ -77,7 +78,7 @@ public class SystemConfigController {
@Operation(summary = "更新配置接口")
public AjaxResult updateConfig(@RequestBody @Valid SystemUpdateConfigParam param) {
systemConfigService.updateConfig(param.getConfigKey(), param.getConfigValue());
return AjaxResult.success("操作成功!");
return AjaxResult.success(MessageConstants.SUCCESS);
}
@GetMapping("/getBarkId")
@@ -85,7 +86,7 @@ public class SystemConfigController {
@Operation(summary = "获取 Bark 推送 id")
public AjaxResult getBarkId() {
String barkId = systemConfigService.getBarkId();
return AjaxResult.success("操作成功!", barkId);
return AjaxResult.success(MessageConstants.SUCCESS, barkId);
}
}

View File

@@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.SaTokenInfo;
import com.besscroft.diyfile.common.constant.MessageConstants;
import com.besscroft.diyfile.common.constant.RoleConstants;
import com.besscroft.diyfile.common.entity.User;
import com.besscroft.diyfile.common.param.LoginParam;
@@ -75,7 +76,7 @@ public class UserController {
@DeleteMapping("/delete/{userId:[\\d]+}")
public AjaxResult delete(@PathVariable(name = "userId") Long userId) {
userService.deleteUser(userId);
return AjaxResult.success("删除成功!");
return AjaxResult.success(MessageConstants.DELETE_SUCCESS);
}
@Operation(summary = "用户信息获取接口")
@@ -122,14 +123,14 @@ public class UserController {
@PutMapping("/updateStatus")
public AjaxResult updateStatus(@RequestBody @Valid UserUpdateStatusParam param) {
userService.updateStatus(param.getUserId(), param.getStatus());
return AjaxResult.success("更新成功!");
return AjaxResult.success(MessageConstants.UPDATE_SUCCESS);
}
@Operation(summary = "用户密码更新接口")
@PutMapping("/updatePassword")
public AjaxResult updatePassword(@RequestBody @Valid UserUpdatePwdParam param) {
userService.updatePassword(param.getUserId(), param.getIsSelf(), param.getOldPassword(), param.getNewPassword());
return AjaxResult.success("更新成功!");
return AjaxResult.success(MessageConstants.UPDATE_SUCCESS);
}
}

View File

@@ -4,8 +4,6 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.besscroft.diyfile.message.PushService;
import com.ejlchina.okhttps.OkHttps;
import com.github.benmanes.caffeine.cache.Cache;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

View File

@@ -40,14 +40,18 @@ public class FileServiceImpl implements FileService {
@Cacheable(value = CacheConstants.DEFAULT_STORAGE, unless = "#result == null")
public StorageInfoVo defaultStorage() {
Storage storage = storageMapper.selectByDefault();
if (Objects.isNull(storage)) return new StorageInfoVo();
if (Objects.isNull(storage)) {
return new StorageInfoVo();
}
return StorageConverterMapper.INSTANCE.StorageToInfoVo(storage);
}
@Override
public List<FileInfoVo> defaultItem() {
Long storageId = storageService.getDefaultStorageId();
if (Objects.isNull(storageId)) return CollUtil.newArrayList();
if (Objects.isNull(storageId)) {
return CollUtil.newArrayList();
}
AbstractFileBaseService<FileInitParam> service = storageApplicationContext.getServiceByStorageId(storageId);
return service.getFileList(null);
}

View File

@@ -88,8 +88,9 @@ public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> impl
public void updateStorage(StorageUpdateParam param) {
Storage storage = StorageConverterMapper.INSTANCE.UpdateParamToStorage(param);
Storage oldStorage = this.baseMapper.selectById(storage.getId());
if (!Objects.equals(storage.getType(), oldStorage.getType()))
if (!Objects.equals(storage.getType(), oldStorage.getType())) {
throw new DiyFileException("存储类型不允许修改!");
}
storage.setStorageKey(oldStorage.getStorageKey());
this.baseMapper.updateById(storage);
// 如果是 OneDrive 存储,需要判断是否包含 ***,如果包含则不更新
@@ -135,9 +136,10 @@ public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> impl
StorageInfoVo vo = StorageConverterMapper.INSTANCE.StorageToInfoVo(storage);
List<StorageConfig> configs = CollUtil.newArrayList();
for (StorageConfig config: configList) {
if (Objects.equals(config.getStorageId(), storage.getId()))
if (Objects.equals(config.getStorageId(), storage.getId())) {
configs.add(config);
}
}
vo.setConfigList(configs);
voList.add(vo);
}
@@ -213,7 +215,9 @@ public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> impl
@Cacheable(value = CacheConstants.DEFAULT_STORAGE, unless = "#result == null")
public Long getDefaultStorageId() {
Storage storage = this.baseMapper.selectByDefault();
if (Objects.isNull(storage)) return null;
if (Objects.isNull(storage)) {
return null;
}
StorageInfoVo vo = StorageConverterMapper.INSTANCE.StorageToInfoVo(storage);
return vo.getId();
}
@@ -230,7 +234,9 @@ public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> impl
public void saveStorageInfoVoList(List<StorageInfoVo> storageInfoVoList) {
for (StorageInfoVo storageInfoVo : storageInfoVoList) {
Storage storage = StorageConverterMapper.INSTANCE.StorageInfoVoToStorage(storageInfoVo);
if (Objects.isNull(storage)) throw new DiyFileException("存储信息导入失败!");
if (Objects.isNull(storage)) {
throw new DiyFileException("存储信息导入失败!");
}
storage.setId(null);
this.save(storage);
List<StorageConfig> configList = storageInfoVo.getConfigList();

View File

@@ -28,7 +28,9 @@ public class SyncServiceImpl implements SyncService {
@Override
public void taskAdd(String beforeStorageKey, String beforePath, String afterStorageKey, String afterPath) {
// 判断被同步路径是否为文件夹路径
if (!PathUtils.isFolder(afterPath)) throw new DiyFileException("被同步路径必须为文件夹路径!");
if (!PathUtils.isFolder(afterPath)) {
throw new DiyFileException("被同步路径必须为文件夹路径!");
}
Long beforeStorageId = storageService.getStorageIdByStorageKey(afterStorageKey);
Long afterStorageId = storageService.getStorageIdByStorageKey(afterStorageKey);
log.info("同步任务参数:{} {} {} {}", beforeStorageKey, beforePath, afterStorageKey, afterPath);

View File

@@ -7,6 +7,7 @@ import com.besscroft.diyfile.common.constant.SystemConstants;
import com.besscroft.diyfile.common.entity.Storage;
import com.besscroft.diyfile.common.entity.SystemConfig;
import com.besscroft.diyfile.common.entity.User;
import com.besscroft.diyfile.common.exception.DiyFileException;
import com.besscroft.diyfile.common.vo.StorageInfoVo;
import com.besscroft.diyfile.mapper.SystemConfigMapper;
import com.besscroft.diyfile.mapper.UserMapper;
@@ -58,7 +59,9 @@ public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, Sys
@Cacheable(value = CacheConstants.SITE_CONFIG, unless = "#result == null")
public Map<String, String> getSiteConfig() {
List<SystemConfig> configList = this.baseMapper.queryAllByType(1);
if (CollectionUtils.isEmpty(configList)) return new HashMap<>();
if (CollectionUtils.isEmpty(configList)) {
return new HashMap<>();
}
return configList.stream().collect(Collectors.toMap(SystemConfig::getConfigKey, SystemConfig::getConfigValue));
}
@@ -129,7 +132,8 @@ public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, Sys
storageService.saveStorageInfoVoList(list);
}
} catch (IOException e) {
throw new RuntimeException(e);
log.error("还原数据异常:{}", e);
throw new DiyFileException("还原数据失败!");
}
}

View File

@@ -18,11 +18,11 @@ import com.besscroft.diyfile.mapper.UserMapper;
import com.besscroft.diyfile.message.PushService;
import com.besscroft.diyfile.service.SystemConfigService;
import com.besscroft.diyfile.service.UserService;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@@ -44,7 +44,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private final PushService pushService;
private final SystemConfigService systemConfigService;
private final Cache<String, Object> caffeineCache;
@Override
public SaTokenInfo login(String username, String password) {
@@ -52,10 +51,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
log.info("用户发起登录请求:{},请求 uri 为:{}", username, request.toUriString());
User user = this.baseMapper.selectByUsername(username);
Assert.notNull(user, "账号或密码错误!");
if (Objects.equals(user.getStatus(), SystemConstants.STATUS_NO))
if (Objects.equals(user.getStatus(), SystemConstants.STATUS_NO)) {
throw new DiyFileException(String.format("账号:%s 已被禁用,请联系管理员!", username));
if (!Objects.equals(SecureUtil.sha256(password), user.getPassword()))
}
if (!Objects.equals(SecureUtil.sha256(password), user.getPassword())) {
throw new DiyFileException("账号或密码错误!");
}
// 登录
StpUtil.login(user.getId());
// 设置最后登录时间
@@ -72,7 +73,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public Map<String, Object> info() {
long userId = StpUtil.getLoginIdAsLong();
User user = getCacheUserById(userId);
User user = getUserById(userId);
Assert.notNull(user, "暂未登录!");
Map<String, Object> map = new HashMap<>();
map.put("userName", user.getName());
@@ -94,10 +95,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
CacheConstants.STATISTICS
}, allEntries = true)
public void deleteUser(Long userId) {
User user = getCacheUserById(userId);
User user = getUserById(userId);
Assert.notNull(user, "用户不存在!");
if (Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN))
if (Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN)) {
throw new DiyFileException("超级管理员不允许被删除!");
}
Assert.isTrue(this.baseMapper.deleteById(userId) > 0, "用户删除失败!");
}
@@ -107,16 +109,19 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
}
@Override
public User getUserById(Long id) {
return getCacheUserById(id);
@Cacheable(value = CacheConstants.USER, key = "#userId", unless = "#result == null")
public User getUserById(Long userId) {
log.info("查询用户信息:{}", userId);
return this.baseMapper.selectById(userId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addUser(UserAddParam param) {
User user = UserConverterMapper.INSTANCE.AddParamToUser(param);
if (Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN))
if (Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN)) {
throw new DiyFileException("违反规则!超级管理员角色不允许被添加!");
}
user.setStatus(SystemConstants.STATUS_NO);
user.setPassword(SecureUtil.sha256(param.getPassword().trim()));
Assert.isTrue(this.baseMapper.insert(user) > 0, "新增用户失败!");
@@ -133,12 +138,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
User oldUser = this.baseMapper.selectById(user.getId());
// 如果原来不是超级管理员,现在是超级管理员,或者原来是超级管理员,现在不是超级管理员,抛出异常
if ((!Objects.equals(oldUser.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN) && Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN))
|| (Objects.equals(oldUser.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN) && !Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN)))
|| (Objects.equals(oldUser.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN) && !Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN))) {
throw new DiyFileException("违反规则!更新用户失败!");
}
// 非管理员只能修改自己的信息
if (!(Objects.equals(oldUser.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN) || Objects.equals(oldUser.getRole(), RoleConstants.PLATFORM_ADMIN))
&& !Objects.equals(oldUser.getId(), user.getId()))
&& !Objects.equals(oldUser.getId(), user.getId())) {
throw new DiyFileException("违反规则!更新用户失败!");
}
Assert.isTrue(this.baseMapper.updateById(user) > 0, "更新用户失败!");
}
@@ -150,8 +157,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
public void updateStatus(Long id, Integer status) {
User user = this.baseMapper.selectById(id);
Assert.notNull(user, "用户不存在!");
if (Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN))
if (Objects.equals(user.getRole(), RoleConstants.PLATFORM_SUPER_ADMIN)) {
throw new DiyFileException("超级管理员不允许被禁用!");
}
user.setStatus(status);
Assert.isTrue(this.baseMapper.updateById(user) > 0, "更新用户状态失败!");
}
@@ -168,24 +176,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
userId = StpUtil.getLoginIdAsLong();
}
String password = this.baseMapper.selectPasswordById(userId);
if (!Objects.equals(SecureUtil.sha256(oldPassword), password))
if (!Objects.equals(SecureUtil.sha256(oldPassword), password)) {
throw new DiyFileException("旧密码错误!");
}
String sha256Pwd = SecureUtil.sha256(newPassword);
this.baseMapper.updatePasswordById(userId, sha256Pwd);
}
/**
* 从缓存中获取用户信息
* @param userId 用户 id
* @return 用户信息
*/
private User getCacheUserById(Long userId) {
return (User) Optional.ofNullable(caffeineCache.getIfPresent(CacheConstants.USER + userId))
.orElseGet(() -> {
User user = this.baseMapper.selectById(userId);
caffeineCache.put(CacheConstants.USER + userId, user);
return user;
});
}
}

View File

@@ -78,10 +78,12 @@ public class StorageApplicationContext implements ApplicationContextAware {
* @param storage 存储对象
*/
public void init(Storage storage) {
if (Objects.equals("proxy", storage.getStorageKey()))
if (Objects.equals("proxy", storage.getStorageKey())) {
throw new DiyFileException("存储 key 不能为 proxy");
if (StrUtil.contains(storage.getStorageKey(), "/"))
}
if (StrUtil.contains(storage.getStorageKey(), "/")) {
throw new DiyFileException("存储 key 不能包含 /");
}
Long storageId = storage.getId();
String storageName = storage.getName();

View File

@@ -32,6 +32,7 @@ public abstract class AbstractFileBaseService<T extends FileInitParam> implement
/** 基础服务初始化方法 */
public abstract void init();
@Override
public abstract String getFileDownloadUrl(String fileName, String filePath);
@Override
@@ -41,7 +42,7 @@ public abstract class AbstractFileBaseService<T extends FileInitParam> implement
* 获取文件信息
* @param filePath 文件路径
* @param fileName 文件名
* @return
* @return 文件信息
*/
public abstract FileInfoVo getFileInfo(String filePath, String fileName);
@@ -87,26 +88,30 @@ public abstract class AbstractFileBaseService<T extends FileInitParam> implement
public abstract void moveItem(String startPath, String endPath);
public void setStorageId(Long storageId) {
if (Objects.nonNull(this.storageId))
if (Objects.nonNull(this.storageId)) {
throw new IllegalStateException("当前存储服务不允许重复初始化!");
}
this.storageId = storageId;
}
public void setStorageKey(String storageKey) {
if (Objects.nonNull(this.storageKey))
if (Objects.nonNull(this.storageKey)) {
throw new IllegalStateException("当前存储服务不允许重复初始化!");
}
this.storageKey = storageKey;
}
public void setName(String name) {
if (StrUtil.isNotBlank(this.name))
if (StrUtil.isNotBlank(this.name)) {
throw new IllegalStateException("当前存储服务不允许重复初始化!");
}
this.name = name;
}
public void setInitParam(T initParam) {
if (Objects.nonNull(this.initParam))
if (Objects.nonNull(this.initParam)) {
throw new IllegalStateException("当前存储服务不允许重复初始化!");
}
this.initParam = initParam;
}

View File

@@ -22,6 +22,7 @@ public abstract class AbstractOSSBaseService<T extends OssParam> extends Abstrac
* @param startPath 开始路径
* @param endPath 结束路径
*/
@Override
public abstract void moveItem(String startPath, String endPath);
}

View File

@@ -2,6 +2,7 @@ package com.besscroft.diyfile.storage.service.base;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.besscroft.diyfile.cache.DiyCache;
import com.besscroft.diyfile.common.constant.CacheConstants;
import com.besscroft.diyfile.common.constant.storage.OneDriveConstants;
import com.besscroft.diyfile.common.enums.StorageTypeEnum;
@@ -11,7 +12,6 @@ import com.ejlchina.okhttps.HttpResult;
import com.ejlchina.okhttps.OkHttps;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.benmanes.caffeine.cache.Cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -27,14 +27,8 @@ import java.util.Optional;
@Slf4j
public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> extends AbstractFileBaseService<T> {
private Cache<String, Object> caffeineCache;
private ObjectMapper objectMapper;
@Autowired
public void setCaffeineCache(Cache<String, Object> caffeineCache) {
this.caffeineCache = caffeineCache;
}
@Autowired
public void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
@@ -56,6 +50,7 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
* @param folderPath 文件路径
* @return 会话
*/
@Override
public abstract String getUploadSession(String folderPath);
/**
@@ -63,6 +58,7 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
* @param startPath 开始路径
* @param endPath 结束路径
*/
@Override
public abstract void moveItem(String startPath, String endPath);
/**
@@ -85,7 +81,7 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
* @return OneDrive 驱动 id
*/
protected String getDriveId() {
return Optional.ofNullable(caffeineCache.getIfPresent(CacheConstants.ONEDRIVE_DRIVE_ID + storageId))
return Optional.ofNullable(DiyCache.getDiyKey(CacheConstants.ONEDRIVE_DRIVE_ID + storageId))
.orElseGet(this::getDriveIdRest).toString();
}
@@ -101,7 +97,7 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
try {
Map map = objectMapper.readValue(result.getStr("parentReference"), Map.class);
String driveId = map.get("driveId").toString();
caffeineCache.put(CacheConstants.ONEDRIVE_DRIVE_ID + storageId, driveId);
DiyCache.putDiyKey(CacheConstants.ONEDRIVE_DRIVE_ID + storageId, driveId);
return driveId;
} catch (JsonProcessingException e) {
log.error("获取 OneDrive 驱动 id 失败!");
@@ -114,9 +110,8 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
* @return 新的 token
*/
protected String getAccessToken() {
Long storageId = getStorageId();
// 先从缓存中获取 token如果没有则从调用 REST API 获取
return Optional.ofNullable(caffeineCache.getIfPresent(CacheConstants.ONEDRIVE_TOKEN + storageId))
return Optional.ofNullable(DiyCache.getDiyKey(CacheConstants.ONEDRIVE_TOKEN + storageId))
.orElseGet(this::refreshAccessToken).toString();
}
@@ -138,7 +133,7 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
.post();
Map tokenResult = objectMapper.readValue(result.getBody().toString(), Map.class);
String accessToken = tokenResult.get("access_token").toString();
caffeineCache.put(CacheConstants.ONEDRIVE_TOKEN + getStorageId(), accessToken);
DiyCache.putDiyKey(CacheConstants.ONEDRIVE_TOKEN + getStorageId(), accessToken);
log.info("accessToken 刷新成功:{}", accessToken);
return accessToken;
} catch (Exception e) {

View File

@@ -28,6 +28,7 @@ public abstract class AbstractS3BaseService<T extends S3Param> extends AbstractF
/** S3 客户端 */
protected S3Client s3Client;
@Override
public abstract void init();
@Override
@@ -69,8 +70,9 @@ public abstract class AbstractS3BaseService<T extends S3Param> extends AbstractF
FileInfoVo fileInfoVo = new FileInfoVo();
if (object.key().contains("/")) {
int lastSlashIndex = object.key().lastIndexOf('/');
if (Objects.equals("", object.key().substring(lastSlashIndex + 1)))
if (Objects.equals("", object.key().substring(lastSlashIndex + 1))) {
continue;
}
fileInfoVo.setName(object.key().substring(lastSlashIndex + 1));
fileInfoVo.setPath(object.key().substring(0, lastSlashIndex));
} else {
@@ -94,6 +96,7 @@ public abstract class AbstractS3BaseService<T extends S3Param> extends AbstractF
return fileInfoVoList;
}
@Override
public abstract Integer getStorageType();
@Override

View File

@@ -107,7 +107,7 @@ public class AliYunOssServiceImpl extends AbstractOSSBaseService<AliYunOssParam>
@Override
public void deleteItem(String filePath) {
// 删除文件或目录。如果要删除目录,目录必须为空。
if (StrUtil.sub(filePath, 0, 2).equals("//")) {
if ("//".equals(StrUtil.sub(filePath, 0, 2))) {
ossClient.deleteObject(initParam.getBucketName(), StrUtil.sub(filePath, 2, filePath.length()));
} else {
ossClient.deleteObject(initParam.getBucketName(), StrUtil.sub(filePath, 1, filePath.length()));
@@ -136,8 +136,9 @@ public class AliYunOssServiceImpl extends AbstractOSSBaseService<AliYunOssParam>
for(OSSObjectSummary summary : summaryList) {
FileInfoVo fileInfoVo = new FileInfoVo();
int lastSlashIndex = summary.getKey().lastIndexOf('/');
if (Objects.equals("", summary.getKey().substring(lastSlashIndex + 1)))
if (Objects.equals("", summary.getKey().substring(lastSlashIndex + 1))) {
continue;
}
if (summary.getKey().contains("/")) {
fileInfoVo.setName(summary.getKey().substring(lastSlashIndex + 1));
} else {
@@ -195,19 +196,19 @@ public class AliYunOssServiceImpl extends AbstractOSSBaseService<AliYunOssParam>
// TODO 获取代理地址
try {
URL url = new URL(initParam.getEndpoint());
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(url.getProtocol())
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(url.getProtocol())
.append("://")
.append(bucketName)
.append(".")
.append(url.getHost());
if (StrUtil.sub(objectName, 0, 1).equals("/")) {
stringBuffer.append(objectName);
if ("/".equals(StrUtil.sub(objectName, 0, 1))) {
stringBuilder.append(objectName);
} else {
stringBuffer.append("/")
stringBuilder.append("/")
.append(objectName);
}
return stringBuffer.toString();
return stringBuilder.toString();
} catch (MalformedURLException e) {
log.error("地址获取失败:{}", e.getMessage());
throw new DiyFileException("地址获取失败!");

View File

@@ -5,6 +5,8 @@ import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.besscroft.diyfile.cache.DiyCache;
import com.besscroft.diyfile.common.constant.CacheConstants;
import com.besscroft.diyfile.common.constant.FileConstants;
import com.besscroft.diyfile.common.constant.storage.OneDriveConstants;
import com.besscroft.diyfile.common.exception.DiyFileException;
@@ -80,6 +82,7 @@ public class OneDriveServiceImpl extends AbstractOneDriveBaseService<OneDrivePar
int retryCount = ctx.getRetryCount();
if (retryCount > 0) {
log.info("获取 OneDrive 文件信息失败,正在进行第 {} 次重试", retryCount);
DiyCache.removeDiyKey(CacheConstants.ONEDRIVE_TOKEN + storageId);
refreshAccessToken();
}
try {
@@ -108,9 +111,10 @@ public class OneDriveServiceImpl extends AbstractOneDriveBaseService<OneDrivePar
.addHeader("Authorization", getAccessToken())
.setBodyPara(map)
.patch();
if (result.getStatus() != 200)
if (result.getStatus() != 200) {
throw new DiyFileException("文件重命名失败!");
}
}
@Override
public void deleteItem(String filePath) {
@@ -118,9 +122,10 @@ public class OneDriveServiceImpl extends AbstractOneDriveBaseService<OneDrivePar
HttpResult result = OkHttps.sync(url)
.addHeader("Authorization", getAccessToken())
.delete();
if (result.getStatus() != 204)
if (result.getStatus() != 204) {
throw new DiyFileException("删除文件失败!");
}
}
@Override
public void uploadItem(String folderPath, String fileName) {
@@ -267,7 +272,9 @@ public class OneDriveServiceImpl extends AbstractOneDriveBaseService<OneDrivePar
* @return 代理下载地址
*/
private String getProxyUrl(String url) {
if (StrUtil.isBlank(initParam.getProxyUrl())) return null;
if (StrUtil.isBlank(initParam.getProxyUrl())) {
return null;
}
try {
URI host = URLUtil.getHost(new URL(url));
return StrUtil.replace(url, host.toString(), initParam.getProxyUrl());

10
pom.xml
View File

@@ -17,7 +17,7 @@
<packaging>pom</packaging>
<properties>
<revision>0.4.0</revision>
<revision>0.5.0</revision>
<java.version>17</java.version>
<maven.compiler.release>17</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
@@ -25,16 +25,16 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.0.5</spring-boot.version>
<mapstruct.version>1.5.3.Final</mapstruct.version>
<mapstruct.version>1.5.4.Final</mapstruct.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<springdoc.version>2.0.4</springdoc.version>
<springdoc.version>2.1.0</springdoc.version>
<sa-token.version>1.34.0</sa-token.version>
<hutool-all.version>5.8.15</hutool-all.version>
<hutool-all.version>5.8.18</hutool-all.version>
<pagehelper.version>1.4.6</pagehelper.version>
<oshi.version>6.4.1</oshi.version>
<okhttps.version>3.5.3</okhttps.version>
<caffeine.version>3.1.5</caffeine.version>
<caffeine.version>3.1.6</caffeine.version>
<aliyun-sdk-oss.version>3.16.0</aliyun-sdk-oss.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<activation.version>1.1.1</activation.version>