feat(workspace): delete custom domain on hard workspace delete (#10975)

Add logic to remove a workspace's custom domain during hard deletion.
Includes tests to verify behavior for both hard and soft deletion cases.

Fix #10351
This commit is contained in:
Antoine Moreaux
2025-03-18 14:06:24 +01:00
committed by GitHub
parent f5195433f3
commit ab9498b3de
2 changed files with 57 additions and 0 deletions

View File

@ -33,6 +33,7 @@ describe('WorkspaceService', () => {
let workspaceRepository: Repository<Workspace>;
let workspaceCacheStorageService: WorkspaceCacheStorageService;
let messageQueueService: MessageQueueService;
let customDomainService: CustomDomainService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
@ -112,6 +113,8 @@ describe('WorkspaceService', () => {
messageQueueService = module.get<MessageQueueService>(
getQueueToken(MessageQueue.deleteCascadeQueue),
);
customDomainService = module.get<CustomDomainService>(CustomDomainService);
customDomainService.deleteCustomHostnameByHostnameSilently = jest.fn();
});
afterEach(() => {
@ -224,5 +227,52 @@ describe('WorkspaceService', () => {
});
expect(workspaceRepository.delete).not.toHaveBeenCalled();
});
it('should delete the custom domain when hard deleting a workspace with a custom domain', async () => {
const customDomain = 'custom.example.com';
const mockWorkspace = {
id: 'workspace-id',
metadataVersion: 0,
customDomain,
} as Workspace;
jest
.spyOn(workspaceRepository, 'findOne')
.mockResolvedValue(mockWorkspace);
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
jest
.spyOn(service, 'deleteMetadataSchemaCacheAndUserWorkspace')
.mockResolvedValue({} as Workspace);
await service.deleteWorkspace(mockWorkspace.id, false);
expect(
customDomainService.deleteCustomHostnameByHostnameSilently,
).toHaveBeenCalledWith(customDomain);
expect(workspaceRepository.delete).toHaveBeenCalledWith(mockWorkspace.id);
});
it('should not delete the custom domain when soft deleting a workspace with a custom domain', async () => {
const customDomain = 'custom.example.com';
const mockWorkspace = {
id: 'workspace-id',
metadataVersion: 0,
customDomain,
} as Workspace;
jest
.spyOn(workspaceRepository, 'findOne')
.mockResolvedValue(mockWorkspace);
jest.spyOn(userWorkspaceRepository, 'find').mockResolvedValue([]);
await service.deleteWorkspace(mockWorkspace.id, true);
expect(
customDomainService.deleteCustomHostnameByHostnameSilently,
).not.toHaveBeenCalled();
expect(workspaceRepository.softDelete).toHaveBeenCalledWith({
id: mockWorkspace.id,
});
});
});
});

View File

@ -346,6 +346,13 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
FileWorkspaceFolderDeletionJob.name,
{ workspaceId: id },
);
if (workspace.customDomain) {
await this.customDomainService.deleteCustomHostnameByHostnameSilently(
workspace.customDomain,
);
}
await this.workspaceRepository.delete(id);
this.logger.log(`workspace ${id} hard deleted`);