Leverage workspace activationStatus to decide if a workspace is activated or not (#6497)
An ACTIVE workspace is a workspace that has a complete workspaceSchema and is authorized to be browsed by users. In this PR, I'm: - introducing a new activationStatus: PENDING_CREATION (existing ACTIVE / INACTIVE) - removing workspaceService.isWorkspaceActivated (based on workspaceSchema existence which is not robust and checking activationStatus.ACTIVE instead) - removing dynamic activationStatus field on worksapce resolver (we can use the postgres column directly now that data has been migrated) - on user sign up creating the workspace in PENDING_CREATION, and on workspace activation setting it to ACTIVE - only re-activating a workspace if the current activationStatus is INACTIVE through billing webhooks (a PENDING_CREATION should stay PENDING and ACTIVE should stay ACTIVE)
This commit is contained in:
@ -1054,7 +1054,7 @@ export type ServerlessFunctionExecutionResult = {
|
||||
status: ServerlessFunctionExecutionStatus;
|
||||
};
|
||||
|
||||
/** Status of the table */
|
||||
/** Status of the serverless function execution */
|
||||
export enum ServerlessFunctionExecutionStatus {
|
||||
Error = 'ERROR',
|
||||
Success = 'SUCCESS'
|
||||
@ -1397,7 +1397,8 @@ export type WorkspaceFeatureFlagsArgs = {
|
||||
|
||||
export enum WorkspaceActivationStatus {
|
||||
Active = 'ACTIVE',
|
||||
Inactive = 'INACTIVE'
|
||||
Inactive = 'INACTIVE',
|
||||
PendingCreation = 'PENDING_CREATION'
|
||||
}
|
||||
|
||||
export type WorkspaceEdge = {
|
||||
|
||||
@ -162,6 +162,17 @@ export type ClientConfig = {
|
||||
telemetry: Telemetry;
|
||||
};
|
||||
|
||||
export type CreateServerlessFunctionFromFileInput = {
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
name: Scalars['String'];
|
||||
};
|
||||
|
||||
export type CreateServerlessFunctionInput = {
|
||||
code: Scalars['String'];
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
name: Scalars['String'];
|
||||
};
|
||||
|
||||
export type CursorPaging = {
|
||||
/** Paginate after opaque cursor */
|
||||
after?: InputMaybe<Scalars['ConnectionCursor']>;
|
||||
@ -178,6 +189,11 @@ export type DeleteOneObjectInput = {
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type DeleteServerlessFunctionInput = {
|
||||
/** The id of the function. */
|
||||
id: Scalars['ID'];
|
||||
};
|
||||
|
||||
/** Schema update on a table */
|
||||
export enum DistantTableUpdate {
|
||||
ColumnsAdded = 'COLUMNS_ADDED',
|
||||
@ -310,14 +326,18 @@ export type Mutation = {
|
||||
checkoutSession: SessionEntity;
|
||||
createOneAppToken: AppToken;
|
||||
createOneObject: Object;
|
||||
createOneServerlessFunction: ServerlessFunction;
|
||||
createOneServerlessFunctionFromFile: ServerlessFunction;
|
||||
deleteCurrentWorkspace: Workspace;
|
||||
deleteOneObject: Object;
|
||||
deleteOneServerlessFunction: ServerlessFunction;
|
||||
deleteUser: User;
|
||||
disablePostgresProxy: PostgresCredentials;
|
||||
emailPasswordResetLink: EmailPasswordResetLink;
|
||||
enablePostgresProxy: PostgresCredentials;
|
||||
enableWorkflowTrigger: Scalars['Boolean'];
|
||||
exchangeAuthorizationCode: ExchangeAuthCode;
|
||||
executeOneServerlessFunction: ServerlessFunctionExecutionResult;
|
||||
generateApiKeyToken: ApiKeyToken;
|
||||
generateJWT: AuthTokens;
|
||||
generateTransientToken: TransientToken;
|
||||
@ -327,8 +347,10 @@ export type Mutation = {
|
||||
signUp: LoginToken;
|
||||
skipSyncEmailOnboardingStep: OnboardingStepSuccess;
|
||||
track: Analytics;
|
||||
triggerWorkflow: WorkflowTriggerResult;
|
||||
updateBillingSubscription: UpdateBillingEntity;
|
||||
updateOneObject: Object;
|
||||
updateOneServerlessFunction: ServerlessFunction;
|
||||
updatePasswordViaResetToken: InvalidatePassword;
|
||||
updateWorkspace: Workspace;
|
||||
uploadFile: Scalars['String'];
|
||||
@ -369,11 +391,27 @@ export type MutationCheckoutSessionArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateOneServerlessFunctionArgs = {
|
||||
input: CreateServerlessFunctionInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateOneServerlessFunctionFromFileArgs = {
|
||||
file: Scalars['Upload'];
|
||||
input: CreateServerlessFunctionFromFileInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationDeleteOneObjectArgs = {
|
||||
input: DeleteOneObjectInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationDeleteOneServerlessFunctionArgs = {
|
||||
input: DeleteServerlessFunctionInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationEmailPasswordResetLinkArgs = {
|
||||
email: Scalars['String'];
|
||||
};
|
||||
@ -391,6 +429,12 @@ export type MutationExchangeAuthorizationCodeArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationExecuteOneServerlessFunctionArgs = {
|
||||
id: Scalars['UUID'];
|
||||
payload?: InputMaybe<Scalars['JSON']>;
|
||||
};
|
||||
|
||||
|
||||
export type MutationGenerateApiKeyTokenArgs = {
|
||||
apiKeyId: Scalars['String'];
|
||||
expiresAt: Scalars['String'];
|
||||
@ -431,11 +475,21 @@ export type MutationTrackArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationTriggerWorkflowArgs = {
|
||||
workflowVersionId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationUpdateOneObjectArgs = {
|
||||
input: UpdateOneObjectInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationUpdateOneServerlessFunctionArgs = {
|
||||
input: UpdateServerlessFunctionInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationUpdatePasswordViaResetTokenArgs = {
|
||||
newPassword: Scalars['String'];
|
||||
passwordResetToken: Scalars['String'];
|
||||
@ -557,6 +611,8 @@ export type Query = {
|
||||
getTimelineThreadsFromPersonId: TimelineThreadsWithTotal;
|
||||
object: Object;
|
||||
objects: ObjectConnection;
|
||||
serverlessFunction: ServerlessFunction;
|
||||
serverlessFunctions: ServerlessFunctionConnection;
|
||||
validatePasswordResetToken: ValidatePasswordResetToken;
|
||||
};
|
||||
|
||||
@ -731,9 +787,21 @@ export type ServerlessFunctionEdge = {
|
||||
export type ServerlessFunctionExecutionResult = {
|
||||
__typename?: 'ServerlessFunctionExecutionResult';
|
||||
/** Execution result in JSON format */
|
||||
result: Scalars['JSON'];
|
||||
data?: Maybe<Scalars['JSON']>;
|
||||
/** Execution duration in milliseconds */
|
||||
duration: Scalars['Float'];
|
||||
/** Execution error in JSON format */
|
||||
error?: Maybe<Scalars['JSON']>;
|
||||
/** Execution status */
|
||||
status: ServerlessFunctionExecutionStatus;
|
||||
};
|
||||
|
||||
/** Status of the serverless function execution */
|
||||
export enum ServerlessFunctionExecutionStatus {
|
||||
Error = 'ERROR',
|
||||
Success = 'SUCCESS'
|
||||
}
|
||||
|
||||
/** SyncStatus of the serverlessFunction */
|
||||
export enum ServerlessFunctionSyncStatus {
|
||||
NotReady = 'NOT_READY',
|
||||
@ -896,6 +964,14 @@ export type UpdateOneObjectInput = {
|
||||
update: UpdateObjectPayload;
|
||||
};
|
||||
|
||||
export type UpdateServerlessFunctionInput = {
|
||||
code: Scalars['String'];
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
/** Id of the serverless function to execute */
|
||||
id: Scalars['UUID'];
|
||||
name: Scalars['String'];
|
||||
};
|
||||
|
||||
export type UpdateWorkspaceInput = {
|
||||
allowImpersonation?: InputMaybe<Scalars['Boolean']>;
|
||||
displayName?: InputMaybe<Scalars['String']>;
|
||||
@ -969,6 +1045,12 @@ export type Verify = {
|
||||
user: User;
|
||||
};
|
||||
|
||||
export type WorkflowTriggerResult = {
|
||||
__typename?: 'WorkflowTriggerResult';
|
||||
/** Execution result in JSON format */
|
||||
result?: Maybe<Scalars['JSON']>;
|
||||
};
|
||||
|
||||
export type Workspace = {
|
||||
__typename?: 'Workspace';
|
||||
activationStatus: WorkspaceActivationStatus;
|
||||
@ -1002,7 +1084,8 @@ export type WorkspaceFeatureFlagsArgs = {
|
||||
|
||||
export enum WorkspaceActivationStatus {
|
||||
Active = 'ACTIVE',
|
||||
Inactive = 'INACTIVE'
|
||||
Inactive = 'INACTIVE',
|
||||
PendingCreation = 'PENDING_CREATION'
|
||||
}
|
||||
|
||||
export type WorkspaceEdge = {
|
||||
|
||||
@ -128,6 +128,18 @@
|
||||
"parallel": false
|
||||
}
|
||||
},
|
||||
"database:migrate:revert": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
"options": {
|
||||
"cwd": "packages/twenty-server",
|
||||
"commands": [
|
||||
"nx typeorm -- migration:revert -d src/database/typeorm/metadata/metadata.datasource",
|
||||
"nx typeorm -- migration:revert -d src/database/typeorm/core/core.datasource"
|
||||
],
|
||||
"parallel": false
|
||||
}
|
||||
},
|
||||
"database:reset": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class UpdateActivationStatus1722256203540 implements MigrationInterface {
|
||||
name = 'UpdateActivationStatus1722256203540';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Set current column as text
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE text USING "activationStatus"::text`,
|
||||
);
|
||||
|
||||
// Drop default value
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" DROP DEFAULT`,
|
||||
);
|
||||
|
||||
// Drop the old enum type
|
||||
await queryRunner.query(
|
||||
`DROP TYPE "core"."workspace_activationstatus_enum"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "core"."workspace_activationStatus_enum" AS ENUM('PENDING_CREATION', 'ACTIVE', 'INACTIVE')`,
|
||||
);
|
||||
|
||||
// Re-apply the enum type
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE "core"."workspace_activationStatus_enum" USING "activationStatus"::"core"."workspace_activationStatus_enum"`,
|
||||
);
|
||||
|
||||
// Update default value
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DEFAULT 'INACTIVE'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// Set current column as text
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE text USING "activationStatus"::text`,
|
||||
);
|
||||
|
||||
// Drop default value
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" DROP DEFAULT`,
|
||||
);
|
||||
|
||||
// Drop the old enum type
|
||||
await queryRunner.query(
|
||||
`DROP TYPE "core"."workspace_activationStatus_enum"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "core"."workspace_activationstatus_enum" AS ENUM('ACTIVE', 'INACTIVE')`,
|
||||
);
|
||||
|
||||
// Re-apply the enum type
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE "core"."workspace_activationstatus_enum" USING "activationStatus"::"core"."workspace_activationstatus_enum"`,
|
||||
);
|
||||
|
||||
// Update default value
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DEFAULT 'INACTIVE'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -21,5 +21,13 @@ export class AddRuntimeColumnToServerlessFunction1721309629608
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."serverlessFunction" DROP COLUMN "runtime"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."serverlessFunction" DROP COLUMN "description"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."serverlessFunction" DROP COLUMN "sourceCodeFullPath"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +1,33 @@
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import {
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
|
||||
import FileType from 'file-type';
|
||||
import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
import FileType from 'file-type';
|
||||
|
||||
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
||||
|
||||
import { assert } from 'src/utils/assert';
|
||||
import {
|
||||
PASSWORD_REGEX,
|
||||
hashPassword,
|
||||
compareHash,
|
||||
hashPassword,
|
||||
} from 'src/engine/core-modules/auth/auth.util';
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { getImageBufferFromUrl } from 'src/utils/image';
|
||||
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import {
|
||||
Workspace,
|
||||
WorkspaceActivationStatus,
|
||||
} from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { assert } from 'src/utils/assert';
|
||||
import { getImageBufferFromUrl } from 'src/utils/image';
|
||||
|
||||
export type SignInUpServiceInput = {
|
||||
email: string;
|
||||
@ -144,11 +147,8 @@ export class SignInUpService {
|
||||
ForbiddenException,
|
||||
);
|
||||
|
||||
const isWorkspaceActivated =
|
||||
await this.workspaceService.isWorkspaceActivated(workspace.id);
|
||||
|
||||
assert(
|
||||
isWorkspaceActivated,
|
||||
workspace.activationStatus === WorkspaceActivationStatus.ACTIVE,
|
||||
'Workspace is not ready to welcome new members',
|
||||
ForbiddenException,
|
||||
);
|
||||
@ -203,6 +203,7 @@ export class SignInUpService {
|
||||
displayName: '',
|
||||
domainName: '',
|
||||
inviteHash: v4(),
|
||||
activationStatus: WorkspaceActivationStatus.PENDING_CREATION,
|
||||
});
|
||||
|
||||
const workspace = await this.workspaceRepository.save(workspaceToCreate);
|
||||
|
||||
@ -284,7 +284,7 @@ export class BillingWorkspaceService {
|
||||
| Stripe.CustomerSubscriptionCreatedEvent.Data
|
||||
| Stripe.CustomerSubscriptionDeletedEvent.Data,
|
||||
) {
|
||||
const workspace = this.workspaceRepository.find({
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: { id: workspaceId },
|
||||
});
|
||||
|
||||
@ -341,9 +341,10 @@ export class BillingWorkspaceService {
|
||||
}
|
||||
|
||||
if (
|
||||
data.object.status === SubscriptionStatus.Active ||
|
||||
data.object.status === SubscriptionStatus.Trialing ||
|
||||
data.object.status === SubscriptionStatus.PastDue
|
||||
(data.object.status === SubscriptionStatus.Active ||
|
||||
data.object.status === SubscriptionStatus.Trialing ||
|
||||
data.object.status === SubscriptionStatus.PastDue) &&
|
||||
workspace.activationStatus == WorkspaceActivationStatus.INACTIVE
|
||||
) {
|
||||
await this.workspaceRepository.update(workspaceId, {
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
|
||||
@ -45,23 +45,20 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
||||
if (!data.displayName || !data.displayName.length) {
|
||||
throw new BadRequestException("'displayName' not provided");
|
||||
}
|
||||
await this.workspaceRepository.update(user.defaultWorkspace.id, {
|
||||
displayName: data.displayName,
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
});
|
||||
|
||||
await this.workspaceManagerService.init(user.defaultWorkspace.id);
|
||||
await this.userWorkspaceService.createWorkspaceMember(
|
||||
user.defaultWorkspace.id,
|
||||
user,
|
||||
);
|
||||
await this.workspaceRepository.update(user.defaultWorkspace.id, {
|
||||
displayName: data.displayName,
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
});
|
||||
|
||||
return user.defaultWorkspace;
|
||||
}
|
||||
|
||||
async isWorkspaceActivated(id: string): Promise<boolean> {
|
||||
return await this.workspaceManagerService.doesDataSourceExist(id);
|
||||
}
|
||||
|
||||
async softDeleteWorkspace(id: string) {
|
||||
const workspace = await this.workspaceRepository.findOneBy({ id });
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-works
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
|
||||
export enum WorkspaceActivationStatus {
|
||||
PENDING_CREATION = 'PENDING_CREATION',
|
||||
ACTIVE = 'ACTIVE',
|
||||
INACTIVE = 'INACTIVE',
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/worksp
|
||||
import { assert } from 'src/utils/assert';
|
||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||
|
||||
import { Workspace, WorkspaceActivationStatus } from './workspace.entity';
|
||||
import { Workspace } from './workspace.entity';
|
||||
|
||||
import { WorkspaceService } from './services/workspace.service';
|
||||
|
||||
@ -100,21 +100,6 @@ export class WorkspaceResolver {
|
||||
return this.workspaceService.deleteWorkspace(id);
|
||||
}
|
||||
|
||||
@ResolveField(() => WorkspaceActivationStatus)
|
||||
async activationStatus(
|
||||
@Parent() workspace: Workspace,
|
||||
): Promise<WorkspaceActivationStatus> {
|
||||
if (workspace.activationStatus) {
|
||||
return workspace.activationStatus;
|
||||
}
|
||||
|
||||
if (await this.workspaceService.isWorkspaceActivated(workspace.id)) {
|
||||
return WorkspaceActivationStatus.ACTIVE;
|
||||
}
|
||||
|
||||
return WorkspaceActivationStatus.INACTIVE;
|
||||
}
|
||||
|
||||
@ResolveField(() => String, { nullable: true })
|
||||
async currentCacheVersion(
|
||||
@Parent() workspace: Workspace,
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { CalendarCreateCompanyAndContactAfterSyncJob } from 'src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job';
|
||||
@ -17,18 +19,17 @@ import { CalendarEventParticipantService } from 'src/modules/calendar/calendar-e
|
||||
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
|
||||
import { ContactCreationManagerModule } from 'src/modules/contact-creation-manager/contact-creation-manager.module';
|
||||
import { MatchParticipantModule } from 'src/modules/match-participant/match-participant.module';
|
||||
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceModule,
|
||||
TwentyORMModule.forFeature([CalendarEventParticipantWorkspaceEntity]),
|
||||
ObjectMetadataRepositoryModule.forFeature([PersonWorkspaceEntity]),
|
||||
TypeOrmModule.forFeature(
|
||||
[ObjectMetadataEntity, FieldMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
NestjsQueryTypeOrmModule.forFeature([Workspace], 'core'),
|
||||
ContactCreationManagerModule,
|
||||
MatchParticipantModule,
|
||||
],
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import { Scope } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||
@ -20,7 +23,8 @@ export type CalendarEventParticipantMatchParticipantJobData = {
|
||||
})
|
||||
export class CalendarEventParticipantMatchParticipantJob {
|
||||
constructor(
|
||||
private readonly workspaceService: WorkspaceService,
|
||||
@InjectRepository(Workspace, 'core')
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
private readonly matchParticipantService: MatchParticipantService<CalendarEventParticipantWorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
@ -30,7 +34,13 @@ export class CalendarEventParticipantMatchParticipantJob {
|
||||
): Promise<void> {
|
||||
const { workspaceId, email, personId, workspaceMemberId } = data;
|
||||
|
||||
if (!this.workspaceService.isWorkspaceActivated(workspaceId)) {
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: {
|
||||
id: workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (workspace?.activationStatus !== 'ACTIVE') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user