|
@@ -1,5 +1,7 @@
|
|
|
package cn.reghao.oss.mgr.service;
|
|
package cn.reghao.oss.mgr.service;
|
|
|
|
|
|
|
|
|
|
+import cn.reghao.jutil.jdk.web.result.Result;
|
|
|
|
|
+import cn.reghao.jutil.jdk.web.result.WebResult;
|
|
|
import cn.reghao.oss.api.constant.ObjectAction;
|
|
import cn.reghao.oss.api.constant.ObjectAction;
|
|
|
import cn.reghao.oss.api.constant.ObjectScope;
|
|
import cn.reghao.oss.api.constant.ObjectScope;
|
|
|
import cn.reghao.oss.api.constant.UploadStatus;
|
|
import cn.reghao.oss.api.constant.UploadStatus;
|
|
@@ -7,18 +9,19 @@ import cn.reghao.oss.api.dto.*;
|
|
|
import cn.reghao.oss.api.dto.media.VideoInfo;
|
|
import cn.reghao.oss.api.dto.media.VideoInfo;
|
|
|
import cn.reghao.oss.api.iface.StoreService;
|
|
import cn.reghao.oss.api.iface.StoreService;
|
|
|
import cn.reghao.oss.api.util.JwtUtils;
|
|
import cn.reghao.oss.api.util.JwtUtils;
|
|
|
|
|
+import cn.reghao.oss.api.util.SignatureUtils;
|
|
|
import cn.reghao.oss.mgr.config.UserContext;
|
|
import cn.reghao.oss.mgr.config.UserContext;
|
|
|
import cn.reghao.oss.mgr.db.mapper.DataBlockMapper;
|
|
import cn.reghao.oss.mgr.db.mapper.DataBlockMapper;
|
|
|
import cn.reghao.oss.mgr.db.mapper.FileMetaMapper;
|
|
import cn.reghao.oss.mgr.db.mapper.FileMetaMapper;
|
|
|
import cn.reghao.oss.mgr.db.mapper.UploadTaskMapper;
|
|
import cn.reghao.oss.mgr.db.mapper.UploadTaskMapper;
|
|
|
|
|
+import cn.reghao.oss.mgr.db.mapper.UserKeyMapper;
|
|
|
import cn.reghao.oss.mgr.db.repository.ObjectRepository;
|
|
import cn.reghao.oss.mgr.db.repository.ObjectRepository;
|
|
|
import cn.reghao.oss.mgr.model.po.*;
|
|
import cn.reghao.oss.mgr.model.po.*;
|
|
|
import cn.reghao.oss.mgr.rpc.RpcService;
|
|
import cn.reghao.oss.mgr.rpc.RpcService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
-import java.util.HashMap;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* cn.reghao.oss.sdk.OssClient 的后端实现
|
|
* cn.reghao.oss.sdk.OssClient 的后端实现
|
|
@@ -38,12 +41,13 @@ public class OssClientService {
|
|
|
private final UploadTaskMapper uploadTaskMapper;
|
|
private final UploadTaskMapper uploadTaskMapper;
|
|
|
private final FileMetaMapper fileMetaMapper;
|
|
private final FileMetaMapper fileMetaMapper;
|
|
|
private final DataBlockMapper dataBlockMapper;
|
|
private final DataBlockMapper dataBlockMapper;
|
|
|
|
|
+ private final UserKeyService userKeyService;
|
|
|
|
|
|
|
|
public OssClientService(StoreNodeService storeNodeService, ObjectRepository objectRepository,
|
|
public OssClientService(StoreNodeService storeNodeService, ObjectRepository objectRepository,
|
|
|
UploadChannelService uploadChannelService, UserNodeService userNodeService,
|
|
UploadChannelService uploadChannelService, UserNodeService userNodeService,
|
|
|
StoreConfigService storeConfigService, RpcService rpcService,
|
|
StoreConfigService storeConfigService, RpcService rpcService,
|
|
|
UploadTaskMapper uploadTaskMapper, FileMetaMapper fileMetaMapper,
|
|
UploadTaskMapper uploadTaskMapper, FileMetaMapper fileMetaMapper,
|
|
|
- DataBlockMapper dataBlockMapper) {
|
|
|
|
|
|
|
+ DataBlockMapper dataBlockMapper, UserKeyService userKeyService) {
|
|
|
this.storeNodeService = storeNodeService;
|
|
this.storeNodeService = storeNodeService;
|
|
|
this.objectRepository = objectRepository;
|
|
this.objectRepository = objectRepository;
|
|
|
this.uploadChannelService = uploadChannelService;
|
|
this.uploadChannelService = uploadChannelService;
|
|
@@ -53,8 +57,72 @@ public class OssClientService {
|
|
|
this.uploadTaskMapper = uploadTaskMapper;
|
|
this.uploadTaskMapper = uploadTaskMapper;
|
|
|
this.fileMetaMapper = fileMetaMapper;
|
|
this.fileMetaMapper = fileMetaMapper;
|
|
|
this.dataBlockMapper = dataBlockMapper;
|
|
this.dataBlockMapper = dataBlockMapper;
|
|
|
|
|
+ this.userKeyService = userKeyService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public Result getSignedUrl(String objectId, String action) {
|
|
|
|
|
+ long loginUser = UserContext.getUserId();
|
|
|
|
|
+ ObjectMeta objectMeta = objectRepository.getObjectMetaById(objectId, loginUser);
|
|
|
|
|
+ if (objectMeta == null) {
|
|
|
|
|
+ return Result.fail("Object not exist");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 24h
|
|
|
|
|
+ int durationInMinutes = 1440;
|
|
|
|
|
+ // 2. 计算过期时间(当前时间 + 持续分钟数)
|
|
|
|
|
+ long expires = (System.currentTimeMillis() / 1000) + (durationInMinutes * 60L);
|
|
|
|
|
+
|
|
|
|
|
+ UserKey userKey = userKeyService.getUserKey(loginUser);
|
|
|
|
|
+ if (userKey == null) {
|
|
|
|
|
+ return Result.fail("UserKey not exist");
|
|
|
|
|
+ }
|
|
|
|
|
+ String accessKeyId = userKey.getAccessKeyId();
|
|
|
|
|
+
|
|
|
|
|
+ // 生成一个短随机数,例如 UUID 的前 8 位或随机 16 进制字符串
|
|
|
|
|
+ // 避免重放攻击, 使 url 只能访问一次
|
|
|
|
|
+ String nonce = UUID.randomUUID().toString().substring(0, 8);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 调用工具类生成签名
|
|
|
|
|
+ String sign = SignatureUtils.calculateSignature(accessKeyId, expires, objectId);
|
|
|
|
|
+
|
|
|
|
|
+ String objectName = objectMeta.getObjectName();
|
|
|
|
|
+ UploadChannel uploadChannel = getUploadChannel(loginUser, objectName);
|
|
|
|
|
+ if (uploadChannel == null) {
|
|
|
|
|
+ return Result.fail("UploadChannel not found");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int userNodeId = uploadChannel.getUserNodeId();
|
|
|
|
|
+ UserNode userNode = userNodeService.getUserNode(userNodeId);
|
|
|
|
|
+ if (userNode == null) {
|
|
|
|
|
+ return Result.fail("UserNode not found");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String protocol = userNode.getProtocol();
|
|
|
|
|
+ String domain = userNode.getDomain();
|
|
|
|
|
+ String ossUrl = String.format("%s://%s", protocol, domain);
|
|
|
|
|
+ String signedParams = String.format("ak=%s&t=%s&nonce=%s&sign=%s", accessKeyId, expires, nonce, sign);;
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 拼接最终的公网访问 URL
|
|
|
|
|
+ // 格式:域名 + objectId + 参数
|
|
|
|
|
+ String signedUrl = String.format("%s/%s?%s", ossUrl, objectName, signedParams);
|
|
|
|
|
+ return Result.success(signedUrl);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private UploadChannel getUploadChannel(long loginUser, String objectName) {
|
|
|
|
|
+ List<UploadChannel> uploadChannelList = uploadChannelService.getUploadChannelsByCreateBy(loginUser);
|
|
|
|
|
+ Collections.reverse(uploadChannelList);
|
|
|
|
|
+
|
|
|
|
|
+ UploadChannel uploadChannel0 = null;
|
|
|
|
|
+ for (UploadChannel uploadChannel : uploadChannelList) {
|
|
|
|
|
+ String prefix = uploadChannel.getPrefix();
|
|
|
|
|
+ if (objectName.startsWith(prefix)) {
|
|
|
|
|
+ uploadChannel0 = uploadChannel;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return uploadChannel0;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
public ObjectChannel getChannelByCode(int channelCode) {
|
|
public ObjectChannel getChannelByCode(int channelCode) {
|
|
|
long loginUser = UserContext.getUserId();
|
|
long loginUser = UserContext.getUserId();
|
|
@@ -114,12 +182,15 @@ public class OssClientService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void checkAndSetScope(String objectId, int scope) {
|
|
public void checkAndSetScope(String objectId, int scope) {
|
|
|
- ObjectScope objectScope = ObjectScope.getByCode(scope);
|
|
|
|
|
|
|
+ if (scope != ObjectScope.PUBLIC.getCode()) {
|
|
|
|
|
+ scope = ObjectScope.PRIVATE.getCode();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
FileMeta fileMeta = fileMetaMapper.findByObjectId(objectId);
|
|
FileMeta fileMeta = fileMetaMapper.findByObjectId(objectId);
|
|
|
if (fileMeta != null) {
|
|
if (fileMeta != null) {
|
|
|
int currentScope = fileMeta.getScope();
|
|
int currentScope = fileMeta.getScope();
|
|
|
if (currentScope != scope) {
|
|
if (currentScope != scope) {
|
|
|
- fileMetaMapper.updateScopeByObjectId(objectId, objectScope.getCode());
|
|
|
|
|
|
|
+ fileMetaMapper.updateScopeByObjectId(objectId, scope);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|