feat(portal): land files platform and frontend workspace refresh
This commit is contained in:
@@ -9,11 +9,21 @@ import com.yoyuzh.auth.UserRole;
|
||||
import com.yoyuzh.common.BusinessException;
|
||||
import com.yoyuzh.common.PageResponse;
|
||||
import com.yoyuzh.files.core.FileBlobRepository;
|
||||
import com.yoyuzh.files.core.FileEntityRepository;
|
||||
import com.yoyuzh.files.core.FileService;
|
||||
import com.yoyuzh.files.core.StoredFile;
|
||||
import com.yoyuzh.files.core.StoredFileEntityRepository;
|
||||
import com.yoyuzh.files.core.StoredFileRepository;
|
||||
import com.yoyuzh.files.policy.StoragePolicy;
|
||||
import com.yoyuzh.files.policy.StoragePolicyCapabilities;
|
||||
import com.yoyuzh.files.policy.StoragePolicyCredentialMode;
|
||||
import com.yoyuzh.files.policy.StoragePolicyRepository;
|
||||
import com.yoyuzh.files.policy.StoragePolicyService;
|
||||
import com.yoyuzh.files.policy.StoragePolicyType;
|
||||
import com.yoyuzh.files.tasks.BackgroundTask;
|
||||
import com.yoyuzh.files.tasks.BackgroundTaskService;
|
||||
import com.yoyuzh.files.tasks.BackgroundTaskStatus;
|
||||
import com.yoyuzh.files.tasks.BackgroundTaskType;
|
||||
import com.yoyuzh.transfer.OfflineTransferSessionRepository;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -62,6 +72,12 @@ class AdminServiceTest {
|
||||
private StoragePolicyRepository storagePolicyRepository;
|
||||
@Mock
|
||||
private StoragePolicyService storagePolicyService;
|
||||
@Mock
|
||||
private FileEntityRepository fileEntityRepository;
|
||||
@Mock
|
||||
private StoredFileEntityRepository storedFileEntityRepository;
|
||||
@Mock
|
||||
private BackgroundTaskService backgroundTaskService;
|
||||
|
||||
private AdminService adminService;
|
||||
|
||||
@@ -71,7 +87,8 @@ class AdminServiceTest {
|
||||
userRepository, storedFileRepository, fileBlobRepository, fileService,
|
||||
passwordEncoder, refreshTokenService, registrationInviteService,
|
||||
offlineTransferSessionRepository, adminMetricsService,
|
||||
storagePolicyRepository, storagePolicyService);
|
||||
storagePolicyRepository, storagePolicyService,
|
||||
fileEntityRepository, storedFileEntityRepository, backgroundTaskService);
|
||||
}
|
||||
|
||||
// --- getSummary ---
|
||||
@@ -161,6 +178,133 @@ class AdminServiceTest {
|
||||
assertThat(response.items().get(0).ownerUsername()).isEqualTo("alice");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateStoragePolicy() {
|
||||
when(storagePolicyService.writeCapabilities(any(StoragePolicyCapabilities.class))).thenReturn("{\"maxObjectSize\":20480}");
|
||||
when(storagePolicyRepository.save(any(StoragePolicy.class))).thenAnswer(invocation -> {
|
||||
StoragePolicy policy = invocation.getArgument(0);
|
||||
policy.setId(9L);
|
||||
return policy;
|
||||
});
|
||||
when(storagePolicyService.readCapabilities(any(StoragePolicy.class))).thenReturn(defaultCapabilities(20_480L));
|
||||
|
||||
AdminStoragePolicyResponse response = adminService.createStoragePolicy(new AdminStoragePolicyUpsertRequest(
|
||||
" Archive Bucket ",
|
||||
StoragePolicyType.S3_COMPATIBLE,
|
||||
"archive-bucket",
|
||||
"https://s3.example.com",
|
||||
"auto",
|
||||
true,
|
||||
"archive/",
|
||||
StoragePolicyCredentialMode.STATIC,
|
||||
20_480L,
|
||||
defaultCapabilities(20_480L),
|
||||
true
|
||||
));
|
||||
|
||||
assertThat(response.name()).isEqualTo("Archive Bucket");
|
||||
assertThat(response.type()).isEqualTo(StoragePolicyType.S3_COMPATIBLE);
|
||||
assertThat(response.bucketName()).isEqualTo("archive-bucket");
|
||||
assertThat(response.endpoint()).isEqualTo("https://s3.example.com");
|
||||
assertThat(response.region()).isEqualTo("auto");
|
||||
assertThat(response.privateBucket()).isTrue();
|
||||
assertThat(response.prefix()).isEqualTo("archive/");
|
||||
assertThat(response.credentialMode()).isEqualTo(StoragePolicyCredentialMode.STATIC);
|
||||
assertThat(response.maxSizeBytes()).isEqualTo(20_480L);
|
||||
assertThat(response.enabled()).isTrue();
|
||||
assertThat(response.defaultPolicy()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateStoragePolicyFieldsWithoutChangingDefaultFlag() {
|
||||
StoragePolicy existingPolicy = createStoragePolicy(7L, "Archive Bucket");
|
||||
existingPolicy.setDefaultPolicy(false);
|
||||
when(storagePolicyService.writeCapabilities(any(StoragePolicyCapabilities.class))).thenReturn("{\"maxObjectSize\":40960}");
|
||||
when(storagePolicyRepository.findById(7L)).thenReturn(Optional.of(existingPolicy));
|
||||
when(storagePolicyRepository.save(existingPolicy)).thenReturn(existingPolicy);
|
||||
when(storagePolicyService.readCapabilities(existingPolicy)).thenReturn(defaultCapabilities(40_960L));
|
||||
|
||||
AdminStoragePolicyResponse response = adminService.updateStoragePolicy(7L, new AdminStoragePolicyUpsertRequest(
|
||||
"Hot Bucket",
|
||||
StoragePolicyType.S3_COMPATIBLE,
|
||||
"hot-bucket",
|
||||
"https://hot.example.com",
|
||||
"cn-north-1",
|
||||
false,
|
||||
"hot/",
|
||||
StoragePolicyCredentialMode.DOGECLOUD_TEMP,
|
||||
40_960L,
|
||||
defaultCapabilities(40_960L),
|
||||
true
|
||||
));
|
||||
|
||||
assertThat(existingPolicy.getName()).isEqualTo("Hot Bucket");
|
||||
assertThat(existingPolicy.getBucketName()).isEqualTo("hot-bucket");
|
||||
assertThat(existingPolicy.getEndpoint()).isEqualTo("https://hot.example.com");
|
||||
assertThat(existingPolicy.getRegion()).isEqualTo("cn-north-1");
|
||||
assertThat(existingPolicy.isPrivateBucket()).isFalse();
|
||||
assertThat(existingPolicy.getPrefix()).isEqualTo("hot/");
|
||||
assertThat(existingPolicy.getCredentialMode()).isEqualTo(StoragePolicyCredentialMode.DOGECLOUD_TEMP);
|
||||
assertThat(existingPolicy.getMaxSizeBytes()).isEqualTo(40_960L);
|
||||
assertThat(existingPolicy.isEnabled()).isTrue();
|
||||
assertThat(response.defaultPolicy()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectDisablingDefaultStoragePolicy() {
|
||||
StoragePolicy existingPolicy = createStoragePolicy(3L, "Default Local Storage");
|
||||
existingPolicy.setDefaultPolicy(true);
|
||||
existingPolicy.setEnabled(true);
|
||||
when(storagePolicyRepository.findById(3L)).thenReturn(Optional.of(existingPolicy));
|
||||
|
||||
assertThatThrownBy(() -> adminService.updateStoragePolicyStatus(3L, false))
|
||||
.isInstanceOf(BusinessException.class)
|
||||
.hasMessageContaining("默认存储策略不能停用");
|
||||
|
||||
verify(storagePolicyRepository, never()).save(any(StoragePolicy.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateStoragePolicyMigrationTaskSkeleton() {
|
||||
User adminUser = createUser(99L, "alice", "alice@example.com");
|
||||
StoragePolicy sourcePolicy = createStoragePolicy(3L, "Source Policy");
|
||||
StoragePolicy targetPolicy = createStoragePolicy(4L, "Target Policy");
|
||||
targetPolicy.setEnabled(true);
|
||||
when(storagePolicyRepository.findById(3L)).thenReturn(Optional.of(sourcePolicy));
|
||||
when(storagePolicyRepository.findById(4L)).thenReturn(Optional.of(targetPolicy));
|
||||
when(fileEntityRepository.countByStoragePolicyIdAndEntityType(3L, com.yoyuzh.files.core.FileEntityType.VERSION)).thenReturn(5L);
|
||||
when(storedFileEntityRepository.countDistinctStoredFilesByStoragePolicyIdAndEntityType(3L, com.yoyuzh.files.core.FileEntityType.VERSION)).thenReturn(8L);
|
||||
when(backgroundTaskService.createQueuedTask(eq(adminUser), eq(BackgroundTaskType.STORAGE_POLICY_MIGRATION), any(), any(), eq("migration-1")))
|
||||
.thenAnswer(invocation -> {
|
||||
BackgroundTask task = new BackgroundTask();
|
||||
task.setId(11L);
|
||||
task.setType(BackgroundTaskType.STORAGE_POLICY_MIGRATION);
|
||||
task.setStatus(BackgroundTaskStatus.QUEUED);
|
||||
task.setUserId(adminUser.getId());
|
||||
task.setPublicStateJson(new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(invocation.getArgument(2)));
|
||||
task.setPrivateStateJson(new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(invocation.getArgument(3)));
|
||||
task.setCorrelationId("migration-1");
|
||||
task.setCreatedAt(LocalDateTime.now());
|
||||
task.setUpdatedAt(LocalDateTime.now());
|
||||
return task;
|
||||
});
|
||||
|
||||
BackgroundTask task = adminService.createStoragePolicyMigrationTask(adminUser, new AdminStoragePolicyMigrationCreateRequest(
|
||||
3L,
|
||||
4L,
|
||||
"migration-1"
|
||||
));
|
||||
|
||||
assertThat(task.getType()).isEqualTo(BackgroundTaskType.STORAGE_POLICY_MIGRATION);
|
||||
assertThat(task.getStatus()).isEqualTo(BackgroundTaskStatus.QUEUED);
|
||||
assertThat(task.getPublicStateJson()).contains("\"sourcePolicyId\":3");
|
||||
assertThat(task.getPublicStateJson()).contains("\"targetPolicyId\":4");
|
||||
assertThat(task.getPublicStateJson()).contains("\"candidateEntityCount\":5");
|
||||
assertThat(task.getPublicStateJson()).contains("\"candidateStoredFileCount\":8");
|
||||
assertThat(task.getPublicStateJson()).contains("\"migrationPerformed\":false");
|
||||
assertThat(task.getPrivateStateJson()).contains("\"taskType\":\"STORAGE_POLICY_MIGRATION\"");
|
||||
}
|
||||
|
||||
// --- deleteFile ---
|
||||
|
||||
@Test
|
||||
@@ -297,4 +441,38 @@ class AdminServiceTest {
|
||||
file.setCreatedAt(LocalDateTime.now());
|
||||
return file;
|
||||
}
|
||||
|
||||
private StoragePolicy createStoragePolicy(Long id, String name) {
|
||||
StoragePolicy policy = new StoragePolicy();
|
||||
policy.setId(id);
|
||||
policy.setName(name);
|
||||
policy.setType(StoragePolicyType.S3_COMPATIBLE);
|
||||
policy.setBucketName("bucket");
|
||||
policy.setEndpoint("https://s3.example.com");
|
||||
policy.setRegion("auto");
|
||||
policy.setPrivateBucket(true);
|
||||
policy.setPrefix("files/");
|
||||
policy.setCredentialMode(StoragePolicyCredentialMode.STATIC);
|
||||
policy.setMaxSizeBytes(10_240L);
|
||||
policy.setCapabilitiesJson("{}");
|
||||
policy.setEnabled(true);
|
||||
policy.setDefaultPolicy(false);
|
||||
policy.setCreatedAt(LocalDateTime.now());
|
||||
policy.setUpdatedAt(LocalDateTime.now());
|
||||
return policy;
|
||||
}
|
||||
|
||||
private StoragePolicyCapabilities defaultCapabilities(long maxObjectSize) {
|
||||
return new StoragePolicyCapabilities(
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
maxObjectSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user