Update suspended cleaning command (#10195)
closes https://github.com/twentyhq/core-team-issues/issues/382
This commit is contained in:
@ -877,13 +877,23 @@ export class EnvironmentVariables {
|
||||
})
|
||||
@CastToPositiveNumber()
|
||||
@IsNumber()
|
||||
@ValidateIf((env) => env.WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION > 0)
|
||||
@IsStrictlyLowerThan('WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION', {
|
||||
message:
|
||||
'"WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION" should be strictly lower than "WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION"',
|
||||
})
|
||||
WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION = 7;
|
||||
|
||||
@EnvironmentVariablesMetadata({
|
||||
group: EnvironmentVariablesGroup.Other,
|
||||
description: 'Number of inactive days before soft deleting workspaces',
|
||||
})
|
||||
@CastToPositiveNumber()
|
||||
@IsNumber()
|
||||
@IsStrictlyLowerThan('WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION', {
|
||||
message:
|
||||
'"WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION" should be strictly lower than "WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION"',
|
||||
'"WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION" should be strictly lower than "WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION"',
|
||||
})
|
||||
@ValidateIf((env) => env.WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION > 0)
|
||||
WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION = 7;
|
||||
WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION = 14;
|
||||
|
||||
@EnvironmentVariablesMetadata({
|
||||
group: EnvironmentVariablesGroup.Other,
|
||||
@ -891,8 +901,7 @@ export class EnvironmentVariables {
|
||||
})
|
||||
@CastToPositiveNumber()
|
||||
@IsNumber()
|
||||
@ValidateIf((env) => env.WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION > 0)
|
||||
WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION = 14;
|
||||
WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION = 21;
|
||||
|
||||
@EnvironmentVariablesMetadata({
|
||||
group: EnvironmentVariablesGroup.Other,
|
||||
|
||||
@ -5,6 +5,7 @@ import { SettingsFeatures } from 'twenty-shared';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
@ -63,7 +64,7 @@ export class UserWorkspace {
|
||||
updatedAt: Date;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt: Date;
|
||||
|
||||
@OneToMany(
|
||||
|
||||
@ -3,9 +3,11 @@ import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
import { EmailService } from 'src/engine/core-modules/email/email.service';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
@ -15,9 +17,8 @@ import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service';
|
||||
|
||||
import { WorkspaceService } from './workspace.service';
|
||||
|
||||
@ -96,6 +97,10 @@ describe('WorkspaceService', () => {
|
||||
provide: PermissionsService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceCacheStorageService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ import { Repository } from 'typeorm';
|
||||
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
@ -35,9 +36,9 @@ import {
|
||||
PermissionsExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
import { DEFAULT_FEATURE_FLAGS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/default-feature-flags';
|
||||
import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service';
|
||||
|
||||
@Injectable()
|
||||
// eslint-disable-next-line @nx/workspace-inject-workspace-repository
|
||||
@ -61,6 +62,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||
private readonly permissionsService: PermissionsService,
|
||||
private readonly customDomainService: CustomDomainService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
) {
|
||||
super(workspaceRepository);
|
||||
}
|
||||
@ -259,43 +261,71 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
||||
});
|
||||
}
|
||||
|
||||
async softDeleteWorkspace(id: string) {
|
||||
const workspace = await this.workspaceRepository.findOneBy({ id });
|
||||
|
||||
assert(workspace, 'Workspace not found');
|
||||
|
||||
await this.userWorkspaceRepository.delete({ workspaceId: id });
|
||||
async deleteMetadataSchemaCacheAndUserWorkspace(workspace: Workspace) {
|
||||
await this.userWorkspaceRepository.delete({ workspaceId: workspace.id });
|
||||
|
||||
if (this.billingService.isBillingEnabled()) {
|
||||
await this.billingSubscriptionService.deleteSubscriptions(workspace.id);
|
||||
}
|
||||
|
||||
await this.workspaceManagerService.delete(id);
|
||||
await this.workspaceManagerService.delete(workspace.id);
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async deleteWorkspace(id: string) {
|
||||
const userWorkspaces = await this.userWorkspaceRepository.findBy({
|
||||
workspaceId: id,
|
||||
async deleteWorkspace(id: string, softDelete = false) {
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: { id },
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
const workspace = await this.softDeleteWorkspace(id);
|
||||
assert(workspace, 'Workspace not found');
|
||||
|
||||
const userWorkspaces = await this.userWorkspaceRepository.find({
|
||||
where: {
|
||||
workspaceId: id,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
for (const userWorkspace of userWorkspaces) {
|
||||
await this.handleRemoveWorkspaceMember(id, userWorkspace.userId);
|
||||
await this.handleRemoveWorkspaceMember(
|
||||
id,
|
||||
userWorkspace.userId,
|
||||
softDelete,
|
||||
);
|
||||
}
|
||||
|
||||
await this.workspaceRepository.delete(id);
|
||||
await this.workspaceCacheStorageService.flush(
|
||||
workspace.id,
|
||||
workspace.metadataVersion,
|
||||
);
|
||||
|
||||
return workspace;
|
||||
if (softDelete) {
|
||||
return await this.workspaceRepository.softDelete({ id });
|
||||
}
|
||||
|
||||
await this.deleteMetadataSchemaCacheAndUserWorkspace(workspace);
|
||||
|
||||
return await this.workspaceRepository.delete(id);
|
||||
}
|
||||
|
||||
async handleRemoveWorkspaceMember(workspaceId: string, userId: string) {
|
||||
await this.userWorkspaceRepository.delete({
|
||||
userId,
|
||||
workspaceId,
|
||||
});
|
||||
async handleRemoveWorkspaceMember(
|
||||
workspaceId: string,
|
||||
userId: string,
|
||||
softDelete = false,
|
||||
) {
|
||||
if (softDelete) {
|
||||
await this.userWorkspaceRepository.softDelete({
|
||||
userId,
|
||||
workspaceId,
|
||||
});
|
||||
} else {
|
||||
await this.userWorkspaceRepository.delete({
|
||||
userId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
const userWorkspaces = await this.userWorkspaceRepository.find({
|
||||
where: {
|
||||
|
||||
@ -21,6 +21,7 @@ import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.r
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||
|
||||
import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts';
|
||||
@ -51,6 +52,7 @@ import { WorkspaceService } from './services/workspace.service';
|
||||
OnboardingModule,
|
||||
TypeORMModule,
|
||||
PermissionsModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
],
|
||||
services: [WorkspaceService],
|
||||
resolvers: workspaceAutoResolverOpts,
|
||||
|
||||
Reference in New Issue
Block a user