From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master
---
jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsResourceService.java | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 312 insertions(+), 0 deletions(-)
diff --git a/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsResourceService.java b/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsResourceService.java
new file mode 100644
index 0000000..7f675b8
--- /dev/null
+++ b/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsResourceService.java
@@ -0,0 +1,312 @@
+package jnpf.dmsService;
+
+import jnpf.base.UserInfo;
+import jnpf.dmsEntity.permission.entity.DmsDocumentEntity;
+import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
+import jnpf.dmsEntity.permission.entity.DmsFolderEntity;
+import jnpf.dmsEntity.permission.entity.DmsPermissionResourceEntity;
+import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
+import jnpf.dmsEntity.permission.enums.DmsResourceType;
+import jnpf.dmsEntity.permission.form.DocumentCreateForm;
+import jnpf.dmsEntity.permission.form.FileVersionCreateForm;
+import jnpf.dmsEntity.permission.form.FolderCreateForm;
+import jnpf.dmsEntity.permission.form.FolderCreateUserForm;
+import jnpf.dmsEntity.permission.vo.DmsPermissionResourceVO;
+import jnpf.dmsIntegration.audit.DmsAuditAdapter;
+import jnpf.dmsMapper.DmsDocumentMapper;
+import jnpf.dmsMapper.DmsFileVersionMapper;
+import jnpf.dmsMapper.DmsFolderMapper;
+import jnpf.dmsMapper.DmsPermissionResourceMapper;
+import jnpf.dmsPermission.DmsCurrentIdentity;
+import jnpf.dmsPermission.DmsPermissionError;
+import jnpf.dmsPermission.DmsPermissionException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.UUID;
+
+@Service
+@RequiredArgsConstructor
+public class DmsResourceService {
+ private static final String WEB_FOLDER_REGISTRAR = "jnpf-dms-web";
+ private static final String WEB_FOLDER_SOURCE_PREFIX = "web-folder:";
+
+ private final DmsCurrentIdentity currentIdentity;
+ private final DmsPermissionDecisionService decisionService;
+ private final DmsFolderMapper folderMapper;
+ private final DmsDocumentMapper documentMapper;
+ private final DmsFileVersionMapper fileVersionMapper;
+ private final DmsPermissionResourceMapper resourceMapper;
+ private final DmsPermissionGrantService permissionGrantService;
+ private final DmsAuditAdapter auditAdapter;
+
+ @Transactional
+ public DmsPermissionResourceVO createFolder(FolderCreateUserForm form) {
+ UserInfo user = currentIdentity.requireUser();
+ String tenantId = currentIdentity.tenantId(user);
+ if (form.getParentId() == null) {
+ throw DmsPermissionException.of(DmsPermissionError.INVALID_RESOURCE_PARENT,
+ "缃戦〉绔彧鑳藉湪宸叉湁 Folder 涓嬪垱寤哄瓙鐩綍");
+ }
+ decisionService.requireAllowed(DmsResourceType.FOLDER, form.getParentId(),
+ DmsPermissionAction.CREATE);
+
+ String sourceId = WEB_FOLDER_SOURCE_PREFIX + form.getSourceId().trim();
+ String name = form.getName().trim();
+ resourceMapper.lockSource(tenantId, "SYSTEM", sourceId);
+ DmsPermissionResourceEntity existingRegistry = resourceMapper.selectBySource(
+ tenantId, "SYSTEM", sourceId);
+ if (existingRegistry != null) {
+ DmsPermissionResourceVO existing = existingWebFolder(tenantId, user.getUserId(), form.getParentId(), name,
+ sourceId, existingRegistry);
+ permissionGrantService.ensureFolderCreatorCreatePermission(
+ tenantId, existingRegistry.getId(), user.getUserId());
+ return existing;
+ }
+
+ UUID folderId = resourceMapper.nextUuidV7();
+ DmsFolderEntity folder = new DmsFolderEntity();
+ folder.setId(folderId);
+ folder.setTenantId(tenantId);
+ folder.setParentId(form.getParentId());
+ folder.setName(name);
+ folder.setCreatedBy(user.getUserId());
+ try {
+ folderMapper.insert(folder);
+ insertRegistry(tenantId, folderId, DmsResourceType.FOLDER, sourceId,
+ WEB_FOLDER_REGISTRAR);
+ permissionGrantService.ensureFolderCreatorCreatePermission(
+ tenantId, folderId, user.getUserId());
+ } catch (DuplicateKeyException ex) {
+ throw conflict("Folder ID 鎴� source_id 宸茶鍏朵粬璧勬簮鍗犵敤", ex);
+ }
+ auditAdapter.dataChange("CREATE", "缃戦〉鍒涘缓 DMS 瀛愮洰褰�", "dms_folders",
+ folderId.toString(), null, null);
+ return requireView(tenantId, folderId);
+ }
+
+ @Transactional
+ public DmsPermissionResourceVO createFolder(FolderCreateForm form, String serviceId) {
+ UserInfo user = currentIdentity.requireUser();
+ String tenantId = currentIdentity.tenantId(user);
+ validateFolderMode(form);
+ if (form.getParentId() != null) {
+ decisionService.requireAllowed(DmsResourceType.FOLDER, form.getParentId(), DmsPermissionAction.CREATE);
+ }
+ DmsFolderEntity desired = new DmsFolderEntity();
+ desired.setId(form.getId());
+ desired.setTenantId(tenantId);
+ desired.setParentId(form.getParentId());
+ desired.setName(form.getName().trim());
+ desired.setCreatedBy(user.getUserId());
+
+ DmsPermissionResourceVO existing = existingFolder(desired, form.getSourceId(), serviceId);
+ if (existing != null) {
+ return existing;
+ }
+ try {
+ folderMapper.insert(desired);
+ insertRegistry(tenantId, form.getId(), DmsResourceType.FOLDER,
+ form.getSourceId(), serviceId);
+ } catch (DuplicateKeyException ex) {
+ throw conflict("Folder ID銆佺埗绾с�佸悕绉版垨 source_id 宸茶鍏朵粬璧勬簮鍗犵敤", ex);
+ }
+ auditAdapter.dataChange("CREATE", "鍒涘缓 DMS Folder", "dms_folders", form.getId().toString(),
+ null, null);
+ return requireView(tenantId, form.getId());
+ }
+
+ @Transactional
+ public DmsPermissionResourceVO createDocument(DocumentCreateForm form, String serviceId) {
+ UserInfo user = currentIdentity.requireUser();
+ String tenantId = currentIdentity.tenantId(user);
+ decisionService.requireAllowed(DmsResourceType.FOLDER, form.getFolderId(), DmsPermissionAction.CREATE);
+ DmsDocumentEntity desired = new DmsDocumentEntity();
+ desired.setId(form.getId());
+ desired.setTenantId(tenantId);
+ desired.setFolderId(form.getFolderId());
+ desired.setName(form.getName().trim());
+ desired.setCreatedBy(user.getUserId());
+
+ DmsPermissionResourceVO existing = existingDocument(desired, form.getSourceId(), serviceId);
+ if (existing != null) {
+ return existing;
+ }
+ try {
+ documentMapper.insert(desired);
+ insertRegistry(tenantId, form.getId(), DmsResourceType.DOCUMENT,
+ form.getSourceId(), serviceId);
+ } catch (DuplicateKeyException ex) {
+ throw conflict("Document ID銆佹墍灞� Folder 鎴� source_id 鍐茬獊", ex);
+ }
+ auditAdapter.dataChange("CREATE", "鍒涘缓 DMS Document", "dms_documents", form.getId().toString(),
+ null, null);
+ return requireView(tenantId, form.getId());
+ }
+
+ @Transactional
+ public DmsPermissionResourceVO createFileVersion(FileVersionCreateForm form, String serviceId) {
+ UserInfo user = currentIdentity.requireUser();
+ String tenantId = currentIdentity.tenantId(user);
+ decisionService.requireAllowed(DmsResourceType.DOCUMENT, form.getDocumentId(), DmsPermissionAction.UPDATE);
+ DmsFileVersionEntity desired = new DmsFileVersionEntity();
+ desired.setId(form.getId());
+ desired.setTenantId(tenantId);
+ desired.setDocumentId(form.getDocumentId());
+ desired.setVersionNo(form.getVersionNo());
+ desired.setFileName(form.getFileName().trim());
+ desired.setMimeType(trimToNull(form.getMimeType()));
+ desired.setSizeBytes(form.getSizeBytes());
+ desired.setChecksumSha256(form.getChecksumSha256() == null ? null
+ : form.getChecksumSha256().toLowerCase(Locale.ROOT));
+ desired.setCreatedBy(user.getUserId());
+
+ DmsPermissionResourceVO existing = existingFileVersion(desired, form.getSourceId(), serviceId);
+ if (existing != null) {
+ return existing;
+ }
+ try {
+ fileVersionMapper.insert(desired);
+ insertRegistry(tenantId, form.getId(), DmsResourceType.FILE_VERSION,
+ form.getSourceId(), serviceId);
+ } catch (DuplicateKeyException ex) {
+ throw conflict("FileVersion ID銆佺増鏈彿鎴� source_id 鍐茬獊", ex);
+ }
+ auditAdapter.dataChange("CREATE", "鍒涘缓 DMS FileVersion", "dms_file_versions",
+ form.getId().toString(), null, null);
+ return requireView(tenantId, form.getId());
+ }
+
+ private DmsPermissionResourceVO existingFolder(DmsFolderEntity desired, String sourceId, String serviceId) {
+ DmsFolderEntity actual = folderMapper.selectByTenantAndId(desired.getTenantId(), desired.getId());
+ DmsPermissionResourceEntity registry = existingRegistry(desired.getTenantId(), desired.getId(), sourceId);
+ if (actual == null && registry == null) {
+ return null;
+ }
+ if (actual == null || registry == null || !Objects.equals(actual.getParentId(), desired.getParentId())
+ || !Objects.equals(actual.getName(), desired.getName())
+ || !sameRegistry(registry, DmsResourceType.FOLDER, sourceId, serviceId)) {
+ throw conflict("Folder 鍒涘缓閲嶈瘯鍐呭涓庡師璇锋眰涓嶄竴鑷�", null);
+ }
+ return requireView(desired.getTenantId(), desired.getId());
+ }
+
+ private DmsPermissionResourceVO existingWebFolder(String tenantId, String userId, UUID parentId,
+ String name, String sourceId,
+ DmsPermissionResourceEntity registry) {
+ DmsFolderEntity folder = folderMapper.selectByTenantAndId(tenantId, registry.getId());
+ if (folder == null
+ || !DmsResourceType.FOLDER.name().equals(registry.getResourceType())
+ || !"SYSTEM".equals(registry.getSourceType())
+ || !sourceId.equals(registry.getSourceId())
+ || !WEB_FOLDER_REGISTRAR.equals(registry.getRegisteredBy())
+ || !userId.equals(folder.getCreatedBy())
+ || !Objects.equals(parentId, folder.getParentId())
+ || !name.equals(folder.getName())) {
+ throw conflict("source_id 宸插瓨鍦紝浣嗗瓙鐩綍鍒涘缓鍐呭涓庡師璇锋眰涓嶄竴鑷�", null);
+ }
+ return requireView(tenantId, registry.getId());
+ }
+
+ private DmsPermissionResourceVO existingDocument(DmsDocumentEntity desired, String sourceId, String serviceId) {
+ DmsDocumentEntity actual = documentMapper.selectByTenantAndId(desired.getTenantId(), desired.getId());
+ DmsPermissionResourceEntity registry = existingRegistry(desired.getTenantId(), desired.getId(), sourceId);
+ if (actual == null && registry == null) {
+ return null;
+ }
+ if (actual == null || registry == null || !Objects.equals(actual.getFolderId(), desired.getFolderId())
+ || !Objects.equals(actual.getName(), desired.getName())
+ || !sameRegistry(registry, DmsResourceType.DOCUMENT, sourceId, serviceId)) {
+ throw conflict("Document 鍒涘缓閲嶈瘯鍐呭涓庡師璇锋眰涓嶄竴鑷�", null);
+ }
+ return requireView(desired.getTenantId(), desired.getId());
+ }
+
+ private DmsPermissionResourceVO existingFileVersion(DmsFileVersionEntity desired, String sourceId,
+ String serviceId) {
+ DmsFileVersionEntity actual = fileVersionMapper.selectByTenantAndId(desired.getTenantId(), desired.getId());
+ DmsPermissionResourceEntity registry = existingRegistry(desired.getTenantId(), desired.getId(), sourceId);
+ if (actual == null && registry == null) {
+ return null;
+ }
+ if (actual == null || registry == null
+ || !Objects.equals(actual.getDocumentId(), desired.getDocumentId())
+ || !Objects.equals(actual.getVersionNo(), desired.getVersionNo())
+ || !Objects.equals(actual.getFileName(), desired.getFileName())
+ || !Objects.equals(actual.getMimeType(), desired.getMimeType())
+ || !Objects.equals(actual.getSizeBytes(), desired.getSizeBytes())
+ || !equalsIgnoreCase(actual.getChecksumSha256(), desired.getChecksumSha256())
+ || !sameRegistry(registry, DmsResourceType.FILE_VERSION, sourceId, serviceId)) {
+ throw conflict("FileVersion 鍒涘缓閲嶈瘯鍐呭涓庡師璇锋眰涓嶄竴鑷�", null);
+ }
+ return requireView(desired.getTenantId(), desired.getId());
+ }
+
+ private DmsPermissionResourceEntity existingRegistry(String tenantId, UUID id, String sourceId) {
+ DmsPermissionResourceEntity byId = resourceMapper.selectByTenantAndId(tenantId, id);
+ DmsPermissionResourceEntity bySource = resourceMapper.selectBySource(tenantId, "SYSTEM", sourceId.trim());
+ if (bySource != null && !id.equals(bySource.getId())) {
+ throw conflict("source_id 宸茬粦瀹氬埌鍙︿竴涓潈闄愯祫婧�", null);
+ }
+ return byId;
+ }
+
+ private boolean sameRegistry(DmsPermissionResourceEntity registry, DmsResourceType type,
+ String sourceId, String serviceId) {
+ return type.name().equals(registry.getResourceType())
+ && "SYSTEM".equals(registry.getSourceType())
+ && sourceId.trim().equals(registry.getSourceId())
+ && serviceId.equals(registry.getRegisteredBy());
+ }
+
+ private void insertRegistry(String tenantId, UUID id, DmsResourceType type, String sourceId,
+ String serviceId) {
+ DmsPermissionResourceEntity registry = new DmsPermissionResourceEntity();
+ registry.setId(id);
+ registry.setTenantId(tenantId);
+ registry.setResourceType(type.name());
+ registry.setSourceType("SYSTEM");
+ registry.setSourceId(sourceId.trim());
+ registry.setRegisteredBy(serviceId);
+ resourceMapper.insert(registry);
+ }
+
+ private DmsPermissionResourceVO requireView(String tenantId, UUID id) {
+ DmsPermissionResourceVO view = resourceMapper.selectView(tenantId, id);
+ if (view == null) {
+ throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
+ "鏉冮檺璧勬簮鍒涘缓鍚庢棤娉曡鍙�: " + id);
+ }
+ return view;
+ }
+
+ private void validateFolderMode(FolderCreateForm form) {
+ if (form.isRootInitialization() != (form.getParentId() == null)) {
+ throw DmsPermissionException.of(DmsPermissionError.INVALID_RESOURCE_PARENT,
+ "浠� rootInitialization=true 鐨� Folder 鍙互涓嶆彁渚� parentId");
+ }
+ }
+
+ private String trimToNull(String value) {
+ if (value == null || value.trim().isEmpty()) {
+ return null;
+ }
+ return value.trim();
+ }
+
+ private boolean equalsIgnoreCase(String left, String right) {
+ return left == null ? right == null : right != null && left.equalsIgnoreCase(right);
+ }
+
+ private DmsPermissionException conflict(String message, Throwable cause) {
+ DmsPermissionException exception = DmsPermissionException.of(DmsPermissionError.SOURCE_CONFLICT, message);
+ if (cause != null) {
+ exception.initCause(cause);
+ }
+ return exception;
+ }
+}
--
Gitblit v1.8.0