Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { Injectable, Logger } from '@nestjs/common';

import { parse } from 'path';

import { isDefined } from 'twenty-shared/utils';
import { HTTPMethod, Sources } from 'twenty-shared/types';
import {
ApplicationManifest,
FieldManifest,
Expand All @@ -12,6 +10,8 @@ import {
ServerlessFunctionManifest,
ServerlessFunctionTriggerManifest,
} from 'twenty-shared/application';
import { HTTPMethod, Sources } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';

import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import {
Expand All @@ -29,21 +29,21 @@ import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-e
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { getFlatEntitiesByApplicationId } from 'src/engine/metadata-modules/flat-entity/utils/get-flat-entities-by-application-id.util';
import { findFlatEntitiesByApplicationId } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entities-by-application-id.util';
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { buildObjectIdByNameMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/build-object-id-by-name-maps.util';
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';
import { ObjectPermissionService } from 'src/engine/metadata-modules/object-permission/object-permission.service';
import { PermissionFlagService } from 'src/engine/metadata-modules/permission-flag/permission-flag.service';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { RouteTriggerV2Service } from 'src/engine/metadata-modules/route-trigger/services/route-trigger-v2.service';
import { FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger/types/flat-route-trigger.type';
import { ServerlessFunctionLayerService } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.service';
import { ServerlessFunctionV2Service } from 'src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service';
import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
import { computeMetadataNameFromLabelOrThrow } from 'src/engine/metadata-modules/utils/compute-metadata-name-from-label-or-throw.util';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { ObjectPermissionService } from 'src/engine/metadata-modules/object-permission/object-permission.service';
import { PermissionFlagService } from 'src/engine/metadata-modules/permission-flag/permission-flag.service';
import { buildObjectIdByNameMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/build-object-id-by-name-maps.util';
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';

@Injectable()
export class ApplicationSyncService {
Expand Down Expand Up @@ -1172,20 +1172,22 @@ export class ApplicationSyncService {
}

const flatObjectMetadataMapsByApplicationId =
getFlatEntitiesByApplicationId(
existingFlatObjectMetadataMaps,
application.id,
);
findFlatEntitiesByApplicationId({
flatEntityMaps: existingFlatObjectMetadataMaps,
applicationId: application.id,
});

const flatIndexMetadataMapsByApplicationId = getFlatEntitiesByApplicationId(
existingFlatIndexMetadataMaps,
application.id,
);
const flatIndexMetadataMapsByApplicationId =
findFlatEntitiesByApplicationId({
flatEntityMaps: existingFlatIndexMetadataMaps,
applicationId: application.id,
});

const flatFieldMetadataMapsByApplicationId = getFlatEntitiesByApplicationId(
existingFlatFieldMetadataMaps,
application.id,
);
const flatFieldMetadataMapsByApplicationId =
findFlatEntitiesByApplicationId({
flatEntityMaps: existingFlatFieldMetadataMaps,
applicationId: application.id,
});

await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,33 +54,6 @@ export class AiAgentRoleService {
});
}

public async assignStandardRoleToAgent({
workspaceId,
agentId,
standardRoleId,
}: {
workspaceId: string;
agentId: string;
standardRoleId: string;
}) {
const role = await this.roleRepository.findOne({
where: { standardId: standardRoleId, workspaceId },
});

if (!isDefined(role)) {
throw new AgentException(
`Standard role with standard ID ${standardRoleId} not found in workspace`,
AgentExceptionCode.ROLE_NOT_FOUND,
);
}

await this.assignRoleToAgent({
workspaceId,
agentId,
roleId: role.id,
});
}

public async removeRoleFromAgent({
workspaceId,
agentId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,29 @@ import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';

export const getFlatEntitiesByApplicationId = <T extends SyncableFlatEntity>(
maps: FlatEntityMaps<T>,
applicationId: string,
): T[] => {
export const findFlatEntitiesByApplicationId = <T extends SyncableFlatEntity>({
applicationId,
flatEntityMaps,
}: {
flatEntityMaps: FlatEntityMaps<T>;
applicationId: string;
}): T[] => {
const universalIdentifiers =
maps.universalIdentifiersByApplicationId[applicationId];
flatEntityMaps.universalIdentifiersByApplicationId[applicationId];

if (!isDefined(universalIdentifiers)) {
return [];
}

return universalIdentifiers
.map((universalId) => {
const id = maps.idByUniversalIdentifier[universalId];
const id = flatEntityMaps.idByUniversalIdentifier[universalId];

if (!isDefined(id)) {
return undefined;
}

const entity = maps.byId[id];
const entity = flatEntityMaps.byId[id];

if (!isDefined(entity)) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';

export const getFlatEntityByUniversalIdentifier = <
export const findFlatEntityByUniversalIdentifier = <
T extends SyncableFlatEntity,
>(
maps: FlatEntityMaps<T>,
universalIdentifier: string,
): T | undefined => {
const flatEntityId = maps.idByUniversalIdentifier[universalIdentifier];
>({
flatEntityMaps,
universalIdentifier,
}: {
flatEntityMaps: FlatEntityMaps<T>;
universalIdentifier: string;
}): T | undefined => {
const flatEntityId =
flatEntityMaps.idByUniversalIdentifier[universalIdentifier];

if (!isDefined(flatEntityId)) {
return;
}

return maps.byId[flatEntityId];
return flatEntityMaps.byId[flatEntityId];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { findFlatEntitiesByApplicationId } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entities-by-application-id.util';
import { getSubFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util';

export const getSubFlatEntityMapsByApplicationIdOrThrow = <
T extends SyncableFlatEntity,
>({
applicationId,
flatEntityMaps,
}: {
applicationId: string;
flatEntityMaps: FlatEntityMaps<T>;
}) => {
const allApplicationFlatEntity = findFlatEntitiesByApplicationId({
applicationId,
flatEntityMaps,
});

return getSubFlatEntityMapsOrThrow({
flatEntityIds: allApplicationFlatEntity.map((flatEntity) => flatEntity.id),
flatEntityMaps,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Repository } from 'typeorm';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { getFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/get-flat-entities-by-universal-identifier.util';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { fromCreateRoleInputToFlatRoleToCreate } from 'src/engine/metadata-modules/flat-role/utils/from-create-role-input-to-flat-role-to-create.util';
import { fromDeleteRoleInputToFlatRoleOrThrow } from 'src/engine/metadata-modules/flat-role/utils/from-delete-role-input-to-flat-role-or-throw.util';
import { fromUpdateRoleInputToFlatRoleToUpdateOrThrow } from 'src/engine/metadata-modules/flat-role/utils/from-update-role-input-to-flat-role-to-update-or-throw.util';
Expand Down Expand Up @@ -86,10 +86,10 @@ export class RoleService {
},
);

const flatRoleEntity = getFlatEntityByUniversalIdentifier(
flatRoleMaps,
const flatRoleEntity = findFlatEntityByUniversalIdentifier({
flatEntityMaps: flatRoleMaps,
universalIdentifier,
);
});

return isDefined(flatRoleEntity)
? fromFlatRoleToRoleDto(flatRoleEntity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { DataSource, Repository } from 'typeorm';

import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';
Expand All @@ -13,7 +13,6 @@ import { RoleTargetService } from 'src/engine/metadata-modules/role-target/servi
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 { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import {
SEED_APPLE_WORKSPACE_ID,
SEED_YCOMBINATOR_WORKSPACE_ID,
Expand All @@ -23,7 +22,7 @@ import {
USER_WORKSPACE_DATA_SEED_IDS,
} from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-user-workspaces.util';
import { API_KEY_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/api-key-data-seeds.constant';
import { ADMIN_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/admin-role';
import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-role.constant';

@Injectable()
export class DevSeederPermissionsService {
Expand All @@ -37,23 +36,22 @@ export class DevSeederPermissionsService {
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly fieldPermissionService: FieldPermissionService,
private readonly roleTargetService: RoleTargetService,
@InjectDataSource()
private readonly coreDataSource: DataSource,
) {}

public async initPermissions({
twentyStandardApplication,
twentyStandardFlatApplication,
workspaceId,
}: {
workspaceId: string;
twentyStandardApplication: ApplicationEntity;
twentyStandardFlatApplication: FlatApplication;
}) {
const adminRole = await this.roleRepository.findOne({
where: {
standardId: ADMIN_ROLE.standardId,
universalIdentifier: STANDARD_ROLE.admin.universalIdentifier,
workspaceId,
},
});
Expand All @@ -64,21 +62,15 @@ export class DevSeederPermissionsService {
);
}

try {
await this.roleTargetService.create({
createRoleTargetInput: {
roleId: adminRole.id,
targetId: API_KEY_DATA_SEED_IDS.ID_1,
targetMetadataForeignKey: 'apiKeyId',
applicationId: twentyStandardApplication.id,
},
workspaceId,
});
} catch (error) {
this.logger.error(
`Could not assign role to test API key: ${error.message}`,
);
}
await this.roleTargetService.create({
createRoleTargetInput: {
roleId: adminRole.id,
targetId: API_KEY_DATA_SEED_IDS.ID_1,
targetMetadataForeignKey: 'apiKeyId',
applicationId: twentyStandardFlatApplication.id,
},
workspaceId,
});

let adminUserWorkspaceId: string | undefined;
let memberUserWorkspaceIds: string[] = [];
Expand All @@ -96,7 +88,7 @@ export class DevSeederPermissionsService {

const guestRole = await this.roleService.createGuestRole({
workspaceId,
applicationId: twentyStandardApplication.id,
applicationId: twentyStandardFlatApplication.id,
});

await this.userRoleService.assignRoleToManyUserWorkspace({
Expand All @@ -107,7 +99,7 @@ export class DevSeederPermissionsService {

const limitedRole = await this.createLimitedRoleForSeedWorkspace({
workspaceId,
applicationId: twentyStandardApplication.id,
applicationId: twentyStandardFlatApplication.id,
});

await this.userRoleService.assignRoleToManyUserWorkspace({
Expand All @@ -124,17 +116,21 @@ export class DevSeederPermissionsService {
];
}

if (adminUserWorkspaceId) {
await this.userRoleService.assignRoleToManyUserWorkspace({
workspaceId,
userWorkspaceIds: [adminUserWorkspaceId],
roleId: adminRole.id,
});
if (!adminUserWorkspaceId) {
throw new Error(
'Should never occur, no eligible user workspace for admin has been found',
);
}

await this.userRoleService.assignRoleToManyUserWorkspace({
workspaceId,
userWorkspaceIds: [adminUserWorkspaceId],
roleId: adminRole.id,
});

const memberRole = await this.roleService.createMemberRole({
workspaceId,
applicationId: twentyStandardApplication.id,
applicationId: twentyStandardFlatApplication.id,
});

await this.coreDataSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import { DevSeederDataService } from 'src/engine/workspace-manager/dev-seeder/da
import { TimelineActivitySeederService } from 'src/engine/workspace-manager/dev-seeder/data/services/timeline-activity-seeder.service';
import { DevSeederMetadataService } from 'src/engine/workspace-manager/dev-seeder/metadata/services/dev-seeder-metadata.service';
import { DevSeederService } from 'src/engine/workspace-manager/dev-seeder/services/dev-seeder.service';
import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module';
import { TwentyStandardApplicationModule } from 'src/engine/workspace-manager/twenty-standard-application/twenty-standard-application.module';
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';

@Module({
imports: [
Expand All @@ -41,11 +42,12 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
ApplicationModule,
FeatureFlagModule,
FileStorageModule,
WorkspaceSyncMetadataModule,
TypeOrmModule.forFeature([WorkspaceEntity, ObjectMetadataEntity]),
ObjectPermissionModule,
WorkspaceManyOrAllFlatEntityMapsCacheModule,
WorkspaceCacheModule,
WorkspaceMigrationV2Module,
TwentyStandardApplicationModule,
],
exports: [DevSeederService],
providers: [
Expand Down
Loading
Loading