[1/3] Rename permissionFlag to rolePermissionFlag + add permissionFlag catalog/backfill (#20481)
Split of #20377. ## Summary This PR separates available permission flags from per-role permission flag grants. Previously, `core.permissionFlag` stored the role assignment directly: `roleId + flag`. This PR renames that legacy grant table to `core.rolePermissionFlag`, then recreates `core.permissionFlag` as the catalog of available permission flags. ## What changed - Rename the existing `core.permissionFlag` grant table to `core.rolePermissionFlag`. - Add the new syncable `core.permissionFlag` catalog entity with key, label, description, icon, permission type, relevance flags, and custom/standard metadata. - Add stable `SystemPermissionFlag` universal identifiers for the built-in `PermissionFlagType` values. - Seed the standard permission flags for every workspace under the Twenty standard application. - Backfill existing role grants: - create missing catalog rows for existing grant keys, - add `rolePermissionFlag.permissionFlagId`, - migrate grants from the old string `flag` column to the new catalog FK, - replace the old `(flag, roleId)` uniqueness with `(permissionFlagId, roleId)`. - Rewire role permission flag caches, permission checks, role DTO mapping, and `upsertPermissionFlags` to resolve through the catalog. - Keep the existing public role permission API shape: product/app surfaces still talk about `permissionFlags` and return `{ id, roleId, flag }`. - Update metadata flat-entity machinery, migration builders, validators, action handlers, snapshots, generated schemas, docs, and app fixtures for the new `permissionFlag` / `rolePermissionFlag` split. ## Behavior after this PR - Existing permission flag grants keep working. - Existing GraphQL role permission flows keep the same public naming. - Standard permission flags are represented as catalog rows. - Permission checks now compare grants through catalog universal identifiers instead of the legacy `flag` column. - Workspace deletion cleanup now verifies both `permissionFlag` and `rolePermissionFlag`. ## What is not in this PR - Public GraphQL CRUD for custom permission flags. - App manifest support for declaring new custom permission flags. - Frontend UI for creating or assigning custom permission flags beyond the existing role permission flow. --------- Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
+1
@@ -167,6 +167,7 @@ export const enrichCreateWorkspaceMigrationActionsWithIds = ({
|
||||
case 'navigationMenuItem':
|
||||
case 'frontComponent':
|
||||
case 'viewSort':
|
||||
case 'rolePermissionFlag':
|
||||
case 'permissionFlag':
|
||||
case 'objectPermission':
|
||||
case 'fieldPermission':
|
||||
|
||||
+37
@@ -29,6 +29,7 @@ import { WorkspaceMigrationPageLayoutTabActionsBuilderService } from 'src/engine
|
||||
import { WorkspaceMigrationPageLayoutWidgetActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/workspace-migration-page-layout-widget-actions-builder.service';
|
||||
import { WorkspaceMigrationPageLayoutActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout/workspace-migration-page-layout-actions-builder.service';
|
||||
import { WorkspaceMigrationPermissionFlagActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/permission-flag/workspace-migration-permission-flag-actions-builder.service';
|
||||
import { WorkspaceMigrationRolePermissionFlagActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role-permission-flag/workspace-migration-role-permission-flag-actions-builder.service';
|
||||
import { WorkspaceMigrationRoleTargetActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role-target/workspace-migration-role-target-actions-builder.service';
|
||||
import { WorkspaceMigrationRoleActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role/workspace-migration-role-actions-builder.service';
|
||||
import { WorkspaceMigrationRowLevelPermissionPredicateGroupActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate-group/workspace-migration-row-level-permission-predicate-group-actions-builder.service';
|
||||
@@ -58,6 +59,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
private readonly workspaceMigrationViewSortActionsBuilderService: WorkspaceMigrationViewSortActionsBuilderService,
|
||||
private readonly workspaceMigrationFieldPermissionActionsBuilderService: WorkspaceMigrationFieldPermissionActionsBuilderService,
|
||||
private readonly workspaceMigrationObjectPermissionActionsBuilderService: WorkspaceMigrationObjectPermissionActionsBuilderService,
|
||||
private readonly workspaceMigrationRolePermissionFlagActionsBuilderService: WorkspaceMigrationRolePermissionFlagActionsBuilderService,
|
||||
private readonly workspaceMigrationPermissionFlagActionsBuilderService: WorkspaceMigrationPermissionFlagActionsBuilderService,
|
||||
private readonly workspaceMigrationLogicFunctionActionsBuilderService: WorkspaceMigrationLogicFunctionActionsBuilderService,
|
||||
private readonly workspaceMigrationRoleTargetActionsBuilderService: WorkspaceMigrationRoleTargetActionsBuilderService,
|
||||
@@ -158,6 +160,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
flatRoleMaps,
|
||||
flatObjectPermissionMaps,
|
||||
flatFieldPermissionMaps,
|
||||
flatRolePermissionFlagMaps,
|
||||
flatPermissionFlagMaps,
|
||||
flatRoleTargetMaps,
|
||||
flatAgentMaps,
|
||||
@@ -558,6 +561,34 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatRolePermissionFlagMaps)) {
|
||||
const {
|
||||
from: fromFlatRolePermissionFlagMaps,
|
||||
to: toFlatRolePermissionFlagMaps,
|
||||
} = flatRolePermissionFlagMaps;
|
||||
|
||||
const rolePermissionFlagResult =
|
||||
await this.workspaceMigrationRolePermissionFlagActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
additionalCacheDataMaps,
|
||||
from: fromFlatRolePermissionFlagMaps,
|
||||
to: toFlatRolePermissionFlagMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: optimisticAllFlatEntityMaps,
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (rolePermissionFlagResult.status === 'fail') {
|
||||
orchestratorFailureReport.rolePermissionFlag.push(
|
||||
...rolePermissionFlagResult.errors,
|
||||
);
|
||||
} else {
|
||||
orchestratorActionsReport.rolePermissionFlag =
|
||||
rolePermissionFlagResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatPermissionFlagMaps)) {
|
||||
const { from: fromFlatPermissionFlagMaps, to: toFlatPermissionFlagMaps } =
|
||||
flatPermissionFlagMaps;
|
||||
@@ -986,6 +1017,12 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
///
|
||||
|
||||
// Permission flags
|
||||
...aggregatedOrchestratorActionsReport.rolePermissionFlag.delete,
|
||||
...aggregatedOrchestratorActionsReport.rolePermissionFlag.create,
|
||||
...aggregatedOrchestratorActionsReport.rolePermissionFlag.update,
|
||||
///
|
||||
|
||||
// Permission flag definitions
|
||||
...aggregatedOrchestratorActionsReport.permissionFlag.delete,
|
||||
...aggregatedOrchestratorActionsReport.permissionFlag.create,
|
||||
...aggregatedOrchestratorActionsReport.permissionFlag.update,
|
||||
|
||||
Reference in New Issue
Block a user