Add definePermissionFlag for app-defined permission flags (#20887)
## Context
Adds the SDK plumbing for apps to declare custom permission flags and
the server-side manifest pipeline to persist them.
```typescript
import { definePermissionFlag } from 'twenty-sdk/define';
export const MANAGE_INVOICES_PERMISSION_FLAG_UNIVERSAL_IDENTIFIER = '…';
export default definePermissionFlag({
universalIdentifier: MANAGE_INVOICES_PERMISSION_FLAG_UNIVERSAL_IDENTIFIER,
key: 'MANAGE_INVOICES',
label: 'Manage Invoices',
description: 'Create, edit, and delete invoices',
icon: 'IconReceipt',
});
```
```typescript
import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define';
import { MANAGE_INVOICES_PERMISSION_FLAG_UNIVERSAL_IDENTIFIER } from './permission-flags/manage-invoices';
export default defineApplicationRole({
universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
label: `${APP_DISPLAY_NAME} default function role`,
// ...
permissionFlagUniversalIdentifiers: [
SystemPermissionFlag.UPLOAD_FILE,
MANAGE_INVOICES_PERMISSION_FLAG_UNIVERSAL_IDENTIFIER,
],
});
```
The flag can then be referenced by UUID in a role's
permissionFlagUniversalIdentifiers. On sync, the catalog row lands in
core.permissionFlag and the link in core.rolePermissionFlag.
## Not in this PR
- Runtime permission checks.
PermissionsService.getUserWorkspacePermissions still builds its result
from Object.values(PermissionFlagType), so custom flags are stored but
not yet enforced, code asking "does this role have MANAGE_INVOICES?"
won't get a meaningful answer. Widening PermissionsService and
UserWorkspacePermissions.permissionFlags to support arbitrary flag keys
is the next PR.
- PermissionFlag from apps can only define "tool" permissions and not
"settings" as a permissionType, this parameter is not mutable. This is
because "settings" are for settings page (until we might decide to
separate both type of permissions into 2 different entities) and apps
can't declare settings page or interact with them so this parameter
would be unnecessary.
This commit is contained in:
+5
-5
@@ -55,9 +55,9 @@ export class FlatPermissionFlagValidatorService {
|
||||
});
|
||||
}
|
||||
|
||||
const duplicateKey = Object.values(
|
||||
const collidingPermissionFlag = Object.values(
|
||||
optimisticFlatPermissionFlagMaps.byUniversalIdentifier,
|
||||
).filter(
|
||||
).find(
|
||||
(definition) =>
|
||||
isDefined(definition) &&
|
||||
definition.key === flatPermissionFlagToValidate.key &&
|
||||
@@ -65,11 +65,11 @@ export class FlatPermissionFlagValidatorService {
|
||||
flatPermissionFlagToValidate.universalIdentifier,
|
||||
);
|
||||
|
||||
if (duplicateKey.length > 0) {
|
||||
if (isDefined(collidingPermissionFlag)) {
|
||||
validationResult.errors.push({
|
||||
code: PermissionFlagExceptionCode.PERMISSION_FLAG_ALREADY_EXISTS,
|
||||
message: t`Permission flag definition with key ${flatPermissionFlagToValidate.key} already exists in this workspace`,
|
||||
userFriendlyMessage: msg`A permission flag with this key already exists`,
|
||||
message: t`Permission flag definition with key "${flatPermissionFlagToValidate.key}" is already registered in this workspace.`,
|
||||
userFriendlyMessage: msg`Another application in this workspace has already registered a permission flag with this key.`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user