package jnpf.dmsService;
|
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.download.form.DmsFileDownloadTicketRequest;
|
import jnpf.dmsEntity.download.model.DmsFileDownloadTicket;
|
import jnpf.dmsEntity.download.vo.DmsFileDownloadTicketVO;
|
import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
|
import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
|
import jnpf.dmsEntity.permission.enums.DmsResourceType;
|
import jnpf.dmsEntity.storage.entity.DmsFileObjectEntity;
|
import jnpf.dmsMapper.DmsFileObjectMapper;
|
import jnpf.dmsMapper.DmsFileVersionMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.dmsPermission.DmsPermissionError;
|
import jnpf.dmsPermission.DmsPermissionException;
|
import jnpf.dmsPermission.DmsPermissionExecutionContext;
|
import jnpf.dmsPermission.DmsPermissionGuard;
|
import jnpf.dmsPermission.DmsPermissionOperation;
|
import jnpf.dmsService.pdf.DmsPersistentPdfSources;
|
import jnpf.dmsService.pdf.DmsPdfGenerationTaskService;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
|
import java.util.Date;
|
import java.util.UUID;
|
|
@Service
|
@RequiredArgsConstructor
|
public class DmsFileDownloadService {
|
static final long TICKET_TTL_SECONDS = 5L * 60L;
|
|
private final DmsCurrentIdentity currentIdentity;
|
private final DmsPermissionGuard permissionGuard;
|
private final DmsFileVersionMapper fileVersionMapper;
|
private final DmsFileObjectMapper fileObjectMapper;
|
private final DmsFileDownloadTicketIssuer ticketIssuer;
|
private final DmsFileOperationLogService operationLogService;
|
private final DmsWatermarkPreviewResolver watermarkResolver;
|
private final DmsPdfGenerationTaskService pdfGenerationTaskService;
|
|
public DmsFileDownloadTicketVO createTicket(DmsFileDownloadTicketRequest request) {
|
request.normalized();
|
UserInfo user = currentIdentity.requireUser();
|
String tenantId = currentIdentity.tenantId(user);
|
UUID fileVersionId = resolveFileVersionId(request, tenantId);
|
long expiresAtMillis = System.currentTimeMillis() + TICKET_TTL_SECONDS * 1000L;
|
|
DmsPermissionExecutionContext context = new DmsPermissionExecutionContext();
|
context.setResourceType(DmsResourceType.FILE_VERSION);
|
context.setResourceId(fileVersionId);
|
context.setActionCode(DmsPermissionAction.DOWNLOAD);
|
context.setWorkflowDownloadOnly(request.isWorkflowDownloadOnly());
|
context.setOperationId(request.getOperationId());
|
context.setSessionExpiresAt(new Date(expiresAtMillis));
|
|
DownloadSource source = permissionGuard.execute(context,
|
new DmsPermissionOperation<DownloadSource>() {
|
@Override
|
public DownloadSource execute() {
|
return loadDownloadSource(tenantId, fileVersionId);
|
}
|
|
@Override
|
public DownloadSource replay() {
|
return loadDownloadSource(tenantId, fileVersionId);
|
}
|
});
|
|
if (context.getSessionExpiresAt() != null) {
|
expiresAtMillis = Math.min(expiresAtMillis, context.getSessionExpiresAt().getTime());
|
}
|
DmsFileDownloadTicket payload = payload(user, tenantId, source, expiresAtMillis, request);
|
String accessTicket = ticketIssuer.issue(payload, TICKET_TTL_SECONDS);
|
DmsFileDownloadTicketVO result = new DmsFileDownloadTicketVO();
|
result.setFileVersionId(fileVersionId);
|
result.setFileName(source.version.getFileName());
|
result.setMimeType(source.version.getMimeType());
|
result.setSizeBytes(source.version.getSizeBytes());
|
result.setAccessTicket(accessTicket);
|
result.setExpiresAt(new Date(expiresAtMillis));
|
operationLogService.recordDownload(user, tenantId, source.version.getDocumentId(),
|
source.version.getId(), source.version.getFileName(), request.getOperationId());
|
return result;
|
}
|
|
private UUID resolveFileVersionId(DmsFileDownloadTicketRequest request, String tenantId) {
|
if (request.getResourceType() == DmsResourceType.DOCUMENT) {
|
DmsFileVersionEntity current = fileVersionMapper.selectCurrentEffective(tenantId,
|
request.getResourceId());
|
if (current == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
|
"文件没有现行有效版本");
|
}
|
return current.getId();
|
}
|
if (request.getResourceType() == DmsResourceType.FILE_VERSION) {
|
DmsFileVersionEntity version = fileVersionMapper.selectReadableByTenantAndId(tenantId,
|
request.getResourceId());
|
if (version == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
|
"可下载的文件版本不存在");
|
}
|
return version.getId();
|
}
|
throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST,
|
"仅支持下载 DOCUMENT 或 FILE_VERSION");
|
}
|
|
private DownloadSource loadDownloadSource(String tenantId, UUID fileVersionId) {
|
DmsFileVersionEntity version = fileVersionMapper.selectReadableByTenantAndId(
|
tenantId, fileVersionId);
|
DmsFileObjectEntity object = fileObjectMapper.selectByTenantAndFileVersionId(tenantId,
|
fileVersionId);
|
if (version == null || object == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
|
"文件版本或存储对象不存在");
|
}
|
return new DownloadSource(version, object);
|
}
|
|
private DmsFileDownloadTicket payload(UserInfo user, String tenantId, DownloadSource source,
|
long expiresAtMillis, DmsFileDownloadTicketRequest request) {
|
DmsFileDownloadTicket payload = new DmsFileDownloadTicket();
|
payload.setScope(DmsFileDownloadTicket.SCOPE);
|
payload.setTenantId(tenantId);
|
payload.setUserId(user.getUserId().trim());
|
payload.setFileVersionId(source.version.getId());
|
payload.setHistoricalAccess(source.version.getLifecycleStatus() != null
|
&& !"EFFECTIVE".equals(source.version.getLifecycleStatus()));
|
payload.setFileName(source.version.getFileName());
|
payload.setMimeType(source.version.getMimeType());
|
payload.setSizeBytes(source.version.getSizeBytes());
|
payload.setStoragePlatform(source.object.getStoragePlatform());
|
payload.setBucketName(source.object.getBucketName());
|
payload.setBasePath(source.object.getBasePath());
|
payload.setObjectPath(source.object.getObjectPath());
|
payload.setObjectName(source.object.getObjectName());
|
payload.setPdfSource(DmsPersistentPdfSources.valid(source.version, source.object));
|
if (payload.getPdfSource() == null) {
|
pdfGenerationTaskService.enqueueMissingEligible(tenantId, source.version.getId(),
|
source.version.getFileName(), source.version.getChecksumSha256());
|
}
|
payload.setWatermarks(watermarkResolver.resolveDownload(user, tenantId, source.version, request));
|
payload.setExpiresAt(expiresAtMillis);
|
return payload;
|
}
|
|
private static final class DownloadSource {
|
private final DmsFileVersionEntity version;
|
private final DmsFileObjectEntity object;
|
|
private DownloadSource(DmsFileVersionEntity version, DmsFileObjectEntity object) {
|
this.version = version;
|
this.object = object;
|
}
|
}
|
}
|