Files
twenty/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts
T
Paul Rastoin a39efeb1ab [BREAKING_CHANGE/GRAPHQL/OBJECT_METADATA_CREATE_ONE] Remove object/fields/view-fields v1 implementation (#15823)
# Introduction
Remove the v2 feature flag for view-field field-metadata and
object-metadata metadata entities

## Some details
- Disabled nestjs-query for object metadata creation and explicitly
calling it
- removed all v1 integration tests files

## Remarks
Not remove v2 referencing in both filenaming right now will handle that
globally later

## Breaking change
Due to object metadata resolver createOne standardization had to rename
the input from `CreateObjectInput` to `CreateOneObjectInput`
2025-11-17 10:55:19 +01:00

190 lines
7.0 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { DataSource, Repository } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { type DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { ObjectMetadataServiceV2 } from 'src/engine/metadata-modules/object-metadata/object-metadata-v2.service';
import { RoleTargetsEntity } from 'src/engine/metadata-modules/role/role-targets.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
import { prefillCoreViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views';
import { standardObjectsPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data';
import { ADMIN_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/admin-role';
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
@Injectable()
export class WorkspaceManagerService {
private readonly logger = new Logger(WorkspaceManagerService.name);
constructor(
@InjectDataSource()
private readonly coreDataSource: DataSource,
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
private readonly workspaceMigrationService: WorkspaceMigrationService,
private readonly objectMetadataServiceV2: ObjectMetadataServiceV2,
private readonly dataSourceService: DataSourceService,
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
@InjectRepository(UserWorkspaceEntity)
private readonly userWorkspaceRepository: Repository<UserWorkspaceEntity>,
private readonly roleService: RoleService,
private readonly userRoleService: UserRoleService,
private readonly featureFlagService: FeatureFlagService,
@InjectRepository(WorkspaceEntity)
private readonly workspaceRepository: Repository<WorkspaceEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectRepository(RoleTargetsEntity)
private readonly roleTargetsRepository: Repository<RoleTargetsEntity>,
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly applicationService: ApplicationService,
) {}
public async init({
workspace,
userId,
}: {
workspace: WorkspaceEntity;
userId: string;
}): Promise<void> {
const workspaceId = workspace.id;
const schemaCreationStart = performance.now();
const schemaName =
await this.workspaceDataSourceService.createWorkspaceDBSchema(
workspaceId,
);
const schemaCreationEnd = performance.now();
this.logger.log(
`Schema creation took ${schemaCreationEnd - schemaCreationStart}ms`,
);
const dataSourceMetadataCreationStart = performance.now();
const dataSourceMetadata =
await this.dataSourceService.createDataSourceMetadata(
workspaceId,
schemaName,
);
const featureFlags =
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
await this.applicationService.createTwentyStandardApplication({
workspaceId,
});
// TODO later replace by twenty-standard installation aka workspaceMigration run
await this.workspaceSyncMetadataService.synchronize({
workspaceId,
dataSourceId: dataSourceMetadata.id,
featureFlags,
});
const dataSourceMetadataCreationEnd = performance.now();
this.logger.log(
`Metadata creation took ${dataSourceMetadataCreationEnd - dataSourceMetadataCreationStart}ms`,
);
await this.setupDefaultRoles(workspaceId, userId);
const prefillStandardObjectsStart = performance.now();
await this.prefillWorkspaceWithStandardObjectsRecords(
dataSourceMetadata,
workspaceId,
featureFlags,
);
const prefillStandardObjectsEnd = performance.now();
this.logger.log(
`Prefill standard objects took ${prefillStandardObjectsEnd - prefillStandardObjectsStart}ms`,
);
}
private async prefillWorkspaceWithStandardObjectsRecords(
dataSourceMetadata: DataSourceEntity,
workspaceId: string,
featureFlags: Record<string, boolean>,
) {
const createdObjectMetadata =
await this.objectMetadataServiceV2.findManyWithinWorkspace(workspaceId);
await standardObjectsPrefillData(
this.coreDataSource,
dataSourceMetadata.schema,
createdObjectMetadata,
);
await prefillCoreViews({
coreDataSource: this.coreDataSource,
workspaceId,
objectMetadataItems: createdObjectMetadata,
workspaceSchemaName: dataSourceMetadata.schema,
featureFlags,
});
}
// TODO investigate why some entities are not on cascade delete
// Are foreign keys correctly applied ?
public async delete(workspaceId: string): Promise<void> {
await this.roleTargetsRepository.delete({
workspaceId,
});
await this.roleRepository.delete({
workspaceId,
});
await this.objectMetadataServiceV2.deleteWorkspaceAllObjectMetadata({
workspaceId,
});
await this.workspaceMigrationService.deleteAllWithinWorkspace(workspaceId);
await this.dataSourceService.delete(workspaceId);
await this.workspaceDataSourceService.deleteWorkspaceDBSchema(workspaceId);
}
private async setupDefaultRoles(
workspaceId: string,
userId: string,
): Promise<void> {
const adminRole = await this.roleRepository.findOne({
where: {
standardId: ADMIN_ROLE.standardId,
workspaceId,
},
});
if (adminRole) {
const userWorkspace = await this.userWorkspaceRepository.findOneOrFail({
where: { workspaceId, userId },
});
await this.userRoleService.assignRoleToUserWorkspace({
workspaceId,
userWorkspaceId: userWorkspace.id,
roleId: adminRole.id,
});
}
const memberRole = await this.roleService.createMemberRole({
workspaceId,
});
await this.workspaceRepository.update(workspaceId, {
defaultRoleId: memberRole.id,
});
}
}