Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe16b86190 | ||
|
|
fb30c88742 | ||
|
|
e798fe0314 | ||
|
|
f5b45f3641 |
@@ -1,4 +1,4 @@
|
||||
import { PermissionFlag, defineRole } from 'twenty-sdk/define';
|
||||
import { PermissionFlagGrant, defineRole } from 'twenty-sdk/define';
|
||||
import {
|
||||
CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
@@ -36,5 +36,5 @@ export default defineRole({
|
||||
canUpdateFieldValue: true,
|
||||
},
|
||||
],
|
||||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||||
permissionFlagGrants: [PermissionFlagGrant.APPLICATIONS],
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PermissionFlag, defineRole } from 'twenty-sdk/define';
|
||||
import { PermissionFlagGrant, defineRole } from 'twenty-sdk/define';
|
||||
import {
|
||||
CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
@@ -36,5 +36,5 @@ export default defineRole({
|
||||
canUpdateFieldValue: false,
|
||||
},
|
||||
],
|
||||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||||
permissionFlagGrants: [PermissionFlagGrant.APPLICATIONS],
|
||||
});
|
||||
|
||||
@@ -12,5 +12,5 @@ export default defineRole({
|
||||
canUpdateAllObjectRecords: true,
|
||||
canSoftDeleteAllObjectRecords: true,
|
||||
canDestroyAllObjectRecords: false,
|
||||
permissionFlags: [PermissionFlagType.UPLOAD_FILE, PermissionFlagType.AI],
|
||||
permissionFlagGrants: [PermissionFlagType.UPLOAD_FILE, PermissionFlagType.AI],
|
||||
});
|
||||
|
||||
@@ -21,5 +21,5 @@ export default defineRole({
|
||||
canBeAssignedToApiKeys: false,
|
||||
objectPermissions: [],
|
||||
fieldPermissions: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
});
|
||||
|
||||
@@ -18,5 +18,5 @@ export default defineRole({
|
||||
canBeAssignedToApiKeys: false,
|
||||
objectPermissions: [],
|
||||
fieldPermissions: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
});
|
||||
|
||||
@@ -138,7 +138,7 @@ type UserWorkspace {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
permissionFlags: [PermissionFlagType!]
|
||||
permissionFlagGrants: [PermissionFlagType!]
|
||||
objectPermissions: [ObjectPermission!]
|
||||
objectsPermissions: [ObjectPermission!]
|
||||
twoFactorAuthenticationMethodSummary: [TwoFactorAuthenticationMethodSummary!]
|
||||
@@ -244,7 +244,7 @@ type FieldPermission {
|
||||
canUpdateFieldValue: Boolean
|
||||
}
|
||||
|
||||
type PermissionFlag {
|
||||
type PermissionFlagGrant {
|
||||
id: UUID!
|
||||
roleId: UUID!
|
||||
flag: PermissionFlagType!
|
||||
@@ -276,7 +276,7 @@ type Role {
|
||||
canUpdateAllObjectRecords: Boolean!
|
||||
canSoftDeleteAllObjectRecords: Boolean!
|
||||
canDestroyAllObjectRecords: Boolean!
|
||||
permissionFlags: [PermissionFlag!]
|
||||
permissionFlagGrants: [PermissionFlagGrant!]
|
||||
objectPermissions: [ObjectPermission!]
|
||||
fieldPermissions: [FieldPermission!]
|
||||
rowLevelPermissionPredicates: [RowLevelPermissionPredicate!]
|
||||
@@ -1756,6 +1756,7 @@ enum FeatureFlagKey {
|
||||
IS_JUNCTION_RELATIONS_ENABLED
|
||||
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED
|
||||
IS_BILLING_V2_ENABLED
|
||||
IS_CUSTOM_PERMISSION_FLAGS_ENABLED
|
||||
}
|
||||
|
||||
type WorkspaceUrls {
|
||||
@@ -2879,6 +2880,7 @@ enum AllMetadataName {
|
||||
pageLayoutTab
|
||||
commandMenuItem
|
||||
navigationMenuItem
|
||||
permissionFlagGrant
|
||||
permissionFlag
|
||||
objectPermission
|
||||
fieldPermission
|
||||
@@ -3233,7 +3235,7 @@ type Mutation {
|
||||
updateOneRole(updateRoleInput: UpdateRoleInput!): Role!
|
||||
deleteOneRole(roleId: UUID!): String!
|
||||
upsertObjectPermissions(upsertObjectPermissionsInput: UpsertObjectPermissionsInput!): [ObjectPermission!]!
|
||||
upsertPermissionFlags(upsertPermissionFlagsInput: UpsertPermissionFlagsInput!): [PermissionFlag!]!
|
||||
upsertPermissionFlagGrants(upsertPermissionFlagGrantsInput: UpsertPermissionFlagGrantsInput!): [PermissionFlagGrant!]!
|
||||
upsertFieldPermissions(upsertFieldPermissionsInput: UpsertFieldPermissionsInput!): [FieldPermission!]!
|
||||
upsertRowLevelPermissionPredicates(input: UpsertRowLevelPermissionPredicatesInput!): UpsertRowLevelPermissionPredicatesResult!
|
||||
assignRoleToAgent(agentId: UUID!, roleId: UUID!): Boolean!
|
||||
@@ -4016,9 +4018,9 @@ input ObjectPermissionInput {
|
||||
canDestroyObjectRecords: Boolean
|
||||
}
|
||||
|
||||
input UpsertPermissionFlagsInput {
|
||||
input UpsertPermissionFlagGrantsInput {
|
||||
roleId: UUID!
|
||||
permissionFlagKeys: [PermissionFlagType!]!
|
||||
permissionFlagGrantKeys: [PermissionFlagType!]!
|
||||
}
|
||||
|
||||
input UpsertFieldPermissionsInput {
|
||||
|
||||
@@ -117,7 +117,7 @@ export interface UserWorkspace {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
permissionFlags?: PermissionFlagType[]
|
||||
permissionFlagGrants?: PermissionFlagType[]
|
||||
objectPermissions?: ObjectPermission[]
|
||||
objectsPermissions?: ObjectPermission[]
|
||||
twoFactorAuthenticationMethodSummary?: TwoFactorAuthenticationMethodSummary[]
|
||||
@@ -190,11 +190,11 @@ export interface FieldPermission {
|
||||
__typename: 'FieldPermission'
|
||||
}
|
||||
|
||||
export interface PermissionFlag {
|
||||
export interface PermissionFlagGrant {
|
||||
id: Scalars['UUID']
|
||||
roleId: Scalars['UUID']
|
||||
flag: PermissionFlagType
|
||||
__typename: 'PermissionFlag'
|
||||
__typename: 'PermissionFlagGrant'
|
||||
}
|
||||
|
||||
export interface ApiKeyForRole {
|
||||
@@ -224,7 +224,7 @@ export interface Role {
|
||||
canUpdateAllObjectRecords: Scalars['Boolean']
|
||||
canSoftDeleteAllObjectRecords: Scalars['Boolean']
|
||||
canDestroyAllObjectRecords: Scalars['Boolean']
|
||||
permissionFlags?: PermissionFlag[]
|
||||
permissionFlagGrants?: PermissionFlagGrant[]
|
||||
objectPermissions?: ObjectPermission[]
|
||||
fieldPermissions?: FieldPermission[]
|
||||
rowLevelPermissionPredicates?: RowLevelPermissionPredicate[]
|
||||
@@ -1389,7 +1389,7 @@ export interface FeatureFlag {
|
||||
__typename: 'FeatureFlag'
|
||||
}
|
||||
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_EMAIL_GROUP_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_BILLING_V2_ENABLED'
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_EMAIL_GROUP_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_BILLING_V2_ENABLED' | 'IS_CUSTOM_PERMISSION_FLAGS_ENABLED'
|
||||
|
||||
export interface WorkspaceUrls {
|
||||
customUrl?: Scalars['String']
|
||||
@@ -2508,7 +2508,7 @@ export interface CollectionHash {
|
||||
__typename: 'CollectionHash'
|
||||
}
|
||||
|
||||
export type AllMetadataName = 'fieldMetadata' | 'objectMetadata' | 'view' | 'viewField' | 'viewFieldGroup' | 'viewGroup' | 'viewSort' | 'rowLevelPermissionPredicate' | 'rowLevelPermissionPredicateGroup' | 'viewFilterGroup' | 'index' | 'logicFunction' | 'viewFilter' | 'role' | 'roleTarget' | 'agent' | 'skill' | 'pageLayout' | 'pageLayoutWidget' | 'pageLayoutTab' | 'commandMenuItem' | 'navigationMenuItem' | 'permissionFlag' | 'objectPermission' | 'fieldPermission' | 'frontComponent' | 'webhook' | 'applicationVariable' | 'connectionProvider'
|
||||
export type AllMetadataName = 'fieldMetadata' | 'objectMetadata' | 'view' | 'viewField' | 'viewFieldGroup' | 'viewGroup' | 'viewSort' | 'rowLevelPermissionPredicate' | 'rowLevelPermissionPredicateGroup' | 'viewFilterGroup' | 'index' | 'logicFunction' | 'viewFilter' | 'role' | 'roleTarget' | 'agent' | 'skill' | 'pageLayout' | 'pageLayoutWidget' | 'pageLayoutTab' | 'commandMenuItem' | 'navigationMenuItem' | 'permissionFlagGrant' | 'permissionFlag' | 'objectPermission' | 'fieldPermission' | 'frontComponent' | 'webhook' | 'applicationVariable' | 'connectionProvider'
|
||||
|
||||
export interface MinimalObjectMetadata {
|
||||
id: Scalars['UUID']
|
||||
@@ -2765,7 +2765,7 @@ export interface Mutation {
|
||||
updateOneRole: Role
|
||||
deleteOneRole: Scalars['String']
|
||||
upsertObjectPermissions: ObjectPermission[]
|
||||
upsertPermissionFlags: PermissionFlag[]
|
||||
upsertPermissionFlagGrants: PermissionFlagGrant[]
|
||||
upsertFieldPermissions: FieldPermission[]
|
||||
upsertRowLevelPermissionPredicates: UpsertRowLevelPermissionPredicatesResult
|
||||
assignRoleToAgent: Scalars['Boolean']
|
||||
@@ -3003,7 +3003,7 @@ export interface UserWorkspaceGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
permissionFlags?: boolean | number
|
||||
permissionFlagGrants?: boolean | number
|
||||
objectPermissions?: ObjectPermissionGenqlSelection
|
||||
objectsPermissions?: ObjectPermissionGenqlSelection
|
||||
twoFactorAuthenticationMethodSummary?: TwoFactorAuthenticationMethodSummaryGenqlSelection
|
||||
@@ -3067,7 +3067,7 @@ export interface FieldPermissionGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface PermissionFlagGenqlSelection{
|
||||
export interface PermissionFlagGrantGenqlSelection{
|
||||
id?: boolean | number
|
||||
roleId?: boolean | number
|
||||
flag?: boolean | number
|
||||
@@ -3103,7 +3103,7 @@ export interface RoleGenqlSelection{
|
||||
canUpdateAllObjectRecords?: boolean | number
|
||||
canSoftDeleteAllObjectRecords?: boolean | number
|
||||
canDestroyAllObjectRecords?: boolean | number
|
||||
permissionFlags?: PermissionFlagGenqlSelection
|
||||
permissionFlagGrants?: PermissionFlagGrantGenqlSelection
|
||||
objectPermissions?: ObjectPermissionGenqlSelection
|
||||
fieldPermissions?: FieldPermissionGenqlSelection
|
||||
rowLevelPermissionPredicates?: RowLevelPermissionPredicateGenqlSelection
|
||||
@@ -5835,7 +5835,7 @@ export interface MutationGenqlSelection{
|
||||
updateOneRole?: (RoleGenqlSelection & { __args: {updateRoleInput: UpdateRoleInput} })
|
||||
deleteOneRole?: { __args: {roleId: Scalars['UUID']} }
|
||||
upsertObjectPermissions?: (ObjectPermissionGenqlSelection & { __args: {upsertObjectPermissionsInput: UpsertObjectPermissionsInput} })
|
||||
upsertPermissionFlags?: (PermissionFlagGenqlSelection & { __args: {upsertPermissionFlagsInput: UpsertPermissionFlagsInput} })
|
||||
upsertPermissionFlagGrants?: (PermissionFlagGrantGenqlSelection & { __args: {upsertPermissionFlagGrantsInput: UpsertPermissionFlagGrantsInput} })
|
||||
upsertFieldPermissions?: (FieldPermissionGenqlSelection & { __args: {upsertFieldPermissionsInput: UpsertFieldPermissionsInput} })
|
||||
upsertRowLevelPermissionPredicates?: (UpsertRowLevelPermissionPredicatesResultGenqlSelection & { __args: {input: UpsertRowLevelPermissionPredicatesInput} })
|
||||
assignRoleToAgent?: { __args: {agentId: Scalars['UUID'], roleId: Scalars['UUID']} }
|
||||
@@ -6175,7 +6175,7 @@ export interface UpsertObjectPermissionsInput {roleId: Scalars['UUID'],objectPer
|
||||
|
||||
export interface ObjectPermissionInput {objectMetadataId: Scalars['UUID'],canReadObjectRecords?: (Scalars['Boolean'] | null),canUpdateObjectRecords?: (Scalars['Boolean'] | null),canSoftDeleteObjectRecords?: (Scalars['Boolean'] | null),canDestroyObjectRecords?: (Scalars['Boolean'] | null)}
|
||||
|
||||
export interface UpsertPermissionFlagsInput {roleId: Scalars['UUID'],permissionFlagKeys: PermissionFlagType[]}
|
||||
export interface UpsertPermissionFlagGrantsInput {roleId: Scalars['UUID'],permissionFlagGrantKeys: PermissionFlagType[]}
|
||||
|
||||
export interface UpsertFieldPermissionsInput {roleId: Scalars['UUID'],fieldPermissions: FieldPermissionInput[]}
|
||||
|
||||
@@ -6416,10 +6416,10 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const PermissionFlag_possibleTypes: string[] = ['PermissionFlag']
|
||||
export const isPermissionFlag = (obj?: { __typename?: any } | null): obj is PermissionFlag => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isPermissionFlag"')
|
||||
return PermissionFlag_possibleTypes.includes(obj.__typename)
|
||||
const PermissionFlagGrant_possibleTypes: string[] = ['PermissionFlagGrant']
|
||||
export const isPermissionFlagGrant = (obj?: { __typename?: any } | null): obj is PermissionFlagGrant => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isPermissionFlagGrant"')
|
||||
return PermissionFlagGrant_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
@@ -8730,7 +8730,8 @@ export const enumFeatureFlagKey = {
|
||||
IS_EMAIL_GROUP_ENABLED: 'IS_EMAIL_GROUP_ENABLED' as const,
|
||||
IS_JUNCTION_RELATIONS_ENABLED: 'IS_JUNCTION_RELATIONS_ENABLED' as const,
|
||||
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED: 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' as const,
|
||||
IS_BILLING_V2_ENABLED: 'IS_BILLING_V2_ENABLED' as const
|
||||
IS_BILLING_V2_ENABLED: 'IS_BILLING_V2_ENABLED' as const,
|
||||
IS_CUSTOM_PERMISSION_FLAGS_ENABLED: 'IS_CUSTOM_PERMISSION_FLAGS_ENABLED' as const
|
||||
}
|
||||
|
||||
export const enumIdentityProviderType = {
|
||||
@@ -8892,6 +8893,7 @@ export const enumAllMetadataName = {
|
||||
pageLayoutTab: 'pageLayoutTab' as const,
|
||||
commandMenuItem: 'commandMenuItem' as const,
|
||||
navigationMenuItem: 'navigationMenuItem' as const,
|
||||
permissionFlagGrant: 'permissionFlagGrant' as const,
|
||||
permissionFlag: 'permissionFlag' as const,
|
||||
objectPermission: 'objectPermission' as const,
|
||||
fieldPermission: 'fieldPermission' as const,
|
||||
|
||||
@@ -351,7 +351,7 @@ export default {
|
||||
"deletedAt": [
|
||||
4
|
||||
],
|
||||
"permissionFlags": [
|
||||
"permissionFlagGrants": [
|
||||
18
|
||||
],
|
||||
"objectPermissions": [
|
||||
@@ -500,7 +500,7 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"PermissionFlag": {
|
||||
"PermissionFlagGrant": {
|
||||
"id": [
|
||||
3
|
||||
],
|
||||
@@ -586,7 +586,7 @@ export default {
|
||||
"canDestroyAllObjectRecords": [
|
||||
6
|
||||
],
|
||||
"permissionFlags": [
|
||||
"permissionFlagGrants": [
|
||||
27
|
||||
],
|
||||
"objectPermissions": [
|
||||
@@ -7611,12 +7611,12 @@ export default {
|
||||
]
|
||||
}
|
||||
],
|
||||
"upsertPermissionFlags": [
|
||||
"upsertPermissionFlagGrants": [
|
||||
27,
|
||||
{
|
||||
"upsertPermissionFlagsInput": [
|
||||
"upsertPermissionFlagGrantsInput": [
|
||||
413,
|
||||
"UpsertPermissionFlagsInput!"
|
||||
"UpsertPermissionFlagGrantsInput!"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -10251,11 +10251,11 @@ export default {
|
||||
1
|
||||
]
|
||||
},
|
||||
"UpsertPermissionFlagsInput": {
|
||||
"UpsertPermissionFlagGrantsInput": {
|
||||
"roleId": [
|
||||
3
|
||||
],
|
||||
"permissionFlagKeys": [
|
||||
"permissionFlagGrantKeys": [
|
||||
18
|
||||
],
|
||||
"__typename": [
|
||||
|
||||
@@ -9,7 +9,7 @@ A **role** is a permission set: which objects an app can read or write, which fi
|
||||
```ts src/roles/restricted-company-role.ts
|
||||
import {
|
||||
defineRole,
|
||||
PermissionFlag,
|
||||
PermissionFlagGrant,
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
||||
} from 'twenty-sdk/define';
|
||||
|
||||
@@ -45,7 +45,7 @@ export default defineRole({
|
||||
canUpdateFieldValue: false,
|
||||
},
|
||||
],
|
||||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||||
permissionFlagGrants: [PermissionFlagGrant.APPLICATIONS],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -54,7 +54,7 @@ export default defineRole({
|
||||
When you scaffold a new app, the CLI creates a default role file declared with `defineApplicationRole()`:
|
||||
|
||||
```ts src/roles/default-role.ts
|
||||
import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define';
|
||||
import { defineApplicationRole, PermissionFlagGrant } from 'twenty-sdk/define';
|
||||
|
||||
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
|
||||
'b648f87b-1d26-4961-b974-0908fd991061';
|
||||
@@ -73,7 +73,7 @@ export default defineApplicationRole({
|
||||
canBeAssignedToApiKeys: false,
|
||||
objectPermissions: [],
|
||||
fieldPermissions: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -88,5 +88,5 @@ Notes:
|
||||
|
||||
- Start from the scaffolded role, then progressively restrict it — the default grants broad read access, which is rarely what you want in production.
|
||||
- Replace `objectPermissions` and `fieldPermissions` with the exact objects and fields your functions actually need.
|
||||
- `permissionFlags` control access to platform-level capabilities. Keep them minimal.
|
||||
- `permissionFlagGrants` control access to platform-level capabilities. Keep them minimal.
|
||||
- See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
|
||||
@@ -57,7 +57,7 @@ const GET_ROLES_QUERY = `
|
||||
expiresAt
|
||||
revokedAt
|
||||
}
|
||||
permissionFlags {
|
||||
permissionFlagGrants {
|
||||
__typename
|
||||
id
|
||||
flag
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -19,7 +19,7 @@ import {
|
||||
filterAttachmentsWithFile,
|
||||
} from '@/activities/files/utils/filterAttachmentsWithFile';
|
||||
import { getAttachmentUrl } from '@/activities/utils/getAttachmentUrl';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -129,11 +129,11 @@ export const AttachmentList = ({
|
||||
isAttachmentPreviewEnabledState,
|
||||
);
|
||||
|
||||
const hasDownloadPermission = useHasPermissionFlag(
|
||||
const hasDownloadPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.DOWNLOAD_FILE,
|
||||
);
|
||||
|
||||
const hasUploadPermission = useHasPermissionFlag(
|
||||
const hasUploadPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.UPLOAD_FILE,
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { getSafeUrl, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AttachmentWithFile } from '@/activities/files/utils/filterAttachmentsWithFile';
|
||||
import { FileIcon } from '@/file/components/FileIcon';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { IconCalendar, OverflowingTextWithTooltip } from 'twenty-ui/display';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
@@ -83,7 +83,7 @@ export const AttachmentRow = ({
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
|
||||
const hasDownloadPermission = useHasPermissionFlag(
|
||||
const hasDownloadPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.DOWNLOAD_FILE,
|
||||
);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useAttachments } from '@/activities/files/hooks/useAttachments';
|
||||
import { useUploadAttachmentFile } from '@/activities/files/hooks/useUploadAttachmentFile';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -82,7 +82,7 @@ export const FilesCard = () => {
|
||||
|
||||
const hasObjectUpdatePermissions = objectPermissions.canUpdateObjectRecords;
|
||||
|
||||
const hasUploadPermission = useHasPermissionFlag(
|
||||
const hasUploadPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.UPLOAD_FILE,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { useNumberFormat } from '@/localization/hooks/useNumberFormat';
|
||||
import { useEndSubscriptionTrialPeriod } from '@/settings/billing/hooks/useEndSubscriptionTrialPeriod';
|
||||
import { useGetNextResourceCreditPrice } from '@/settings/billing/hooks/useGetNextResourceCreditPrice';
|
||||
import { useGetNextMeteredBillingPrice } from '@/settings/billing/hooks/useGetNextMeteredBillingPrice';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
@@ -52,7 +52,7 @@ export const AIChatNoMoreBillingCreditsBanner = () => {
|
||||
);
|
||||
|
||||
const { [PermissionFlagType.WORKSPACE]: hasPermissionToManageBilling } =
|
||||
usePermissionFlagMap();
|
||||
usePermissionFlagGrantMap();
|
||||
|
||||
if (!hasPermissionToManageBilling) {
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateF
|
||||
import { sortChatThreadsByLastActivityDesc } from '@/ai/utils/sortChatThreadsByLastActivityDesc';
|
||||
import { useUpdateMetadataStoreDraft } from '@/metadata-store/hooks/useUpdateMetadataStoreDraft';
|
||||
import { metadataStoreState } from '@/metadata-store/states/metadataStoreState';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
export const AgentChatThreadInitializationEffect = () => {
|
||||
const client = useApolloClient();
|
||||
const { replaceDraft, applyChanges } = useUpdateMetadataStoreDraft();
|
||||
const hasAiSettingsPermission = useHasPermissionFlag(
|
||||
const hasAiSettingsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.AI_SETTINGS,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AiChatBanner } from '@/ai/components/AiChatBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
@@ -17,7 +17,7 @@ export const AiChatCreditsExhaustedMessage = () => {
|
||||
const isTrialing = subscriptionStatus === SubscriptionStatus.Trialing;
|
||||
|
||||
const { [PermissionFlagType.WORKSPACE]: hasPermissionToManageBilling } =
|
||||
usePermissionFlagMap();
|
||||
usePermissionFlagGrantMap();
|
||||
|
||||
const handleUpgradeClick = () => {
|
||||
navigateSettings(SettingsPath.Billing);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { type UserWorkspace } from '~/generated-metadata/graphql';
|
||||
|
||||
export type CurrentUserWorkspace = Pick<
|
||||
UserWorkspace,
|
||||
'permissionFlags' | 'twoFactorAuthenticationMethodSummary'
|
||||
'permissionFlagGrants' | 'twoFactorAuthenticationMethodSummary'
|
||||
> & {
|
||||
objectsPermissions: Array<ObjectPermissions & { objectMetadataId: string }>;
|
||||
};
|
||||
|
||||
+5
-5
@@ -40,10 +40,10 @@ export const StandalonePageCommandMenu = () => {
|
||||
featureFlags[flag.key] = flag.value === true;
|
||||
}
|
||||
|
||||
const permissionFlags: Record<string, boolean> = {};
|
||||
const permissionFlagGrants: Record<string, boolean> = {};
|
||||
|
||||
for (const flag of currentUserWorkspace?.permissionFlags ?? []) {
|
||||
permissionFlags[flag] = true;
|
||||
for (const flag of currentUserWorkspace?.permissionFlagGrants ?? []) {
|
||||
permissionFlagGrants[flag] = true;
|
||||
}
|
||||
|
||||
const targetObjectReadPermissions: Record<string, boolean> = {};
|
||||
@@ -82,7 +82,7 @@ export const StandalonePageCommandMenu = () => {
|
||||
},
|
||||
selectedRecords: [],
|
||||
featureFlags,
|
||||
permissionFlags,
|
||||
permissionFlagGrants,
|
||||
targetObjectReadPermissions,
|
||||
targetObjectWritePermissions,
|
||||
objectMetadataItem: {},
|
||||
@@ -90,7 +90,7 @@ export const StandalonePageCommandMenu = () => {
|
||||
};
|
||||
}, [
|
||||
currentWorkspace?.featureFlags,
|
||||
currentUserWorkspace?.permissionFlags,
|
||||
currentUserWorkspace?.permissionFlagGrants,
|
||||
isLayoutCustomizationModeEnabled,
|
||||
objectMetadataItems,
|
||||
store,
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ export const EMPTY_COMMAND_MENU_CONTEXT_API: CommandMenuContextApi = {
|
||||
},
|
||||
selectedRecords: [],
|
||||
featureFlags: {},
|
||||
permissionFlags: {},
|
||||
permissionFlagGrants: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
objectMetadataItem: {},
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ const getWrapper =
|
||||
},
|
||||
selectedRecords: [],
|
||||
featureFlags: {},
|
||||
permissionFlags: {},
|
||||
permissionFlagGrants: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
objectMetadataItem: {},
|
||||
|
||||
+4
-4
@@ -145,10 +145,10 @@ export const useCurrentCommandMenuContextApi = (): CommandMenuContextApi => {
|
||||
|
||||
const currentUserWorkspace = useAtomStateValue(currentUserWorkspaceState);
|
||||
|
||||
const permissionFlags: Record<string, boolean> = {};
|
||||
const permissionFlagGrants: Record<string, boolean> = {};
|
||||
|
||||
for (const flag of currentUserWorkspace?.permissionFlags ?? []) {
|
||||
permissionFlags[flag] = true;
|
||||
for (const flag of currentUserWorkspace?.permissionFlagGrants ?? []) {
|
||||
permissionFlagGrants[flag] = true;
|
||||
}
|
||||
|
||||
const targetObjectReadPermissions: Record<string, boolean> = {};
|
||||
@@ -185,7 +185,7 @@ export const useCurrentCommandMenuContextApi = (): CommandMenuContextApi => {
|
||||
objectPermissions,
|
||||
selectedRecords,
|
||||
featureFlags,
|
||||
permissionFlags,
|
||||
permissionFlagGrants,
|
||||
targetObjectReadPermissions,
|
||||
targetObjectWritePermissions,
|
||||
objectMetadataItem: objectMetadataItem ?? {},
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import { InformationBannerInvalidEnterpriseKey } from '@/information-banner/comp
|
||||
import { InformationBannerMaintenance } from '@/information-banner/components/maintenance/InformationBannerMaintenance';
|
||||
import { InformationBannerReconnectAccountEmailAliases } from '@/information-banner/components/reconnect-account/InformationBannerReconnectAccountEmailAliases';
|
||||
import { InformationBannerReconnectAccountInsufficientPermissions } from '@/information-banner/components/reconnect-account/InformationBannerReconnectAccountInsufficientPermissions';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useIsWorkspaceActivationStatusEqualsTo } from '@/workspace/hooks/useIsWorkspaceActivationStatusEqualsTo';
|
||||
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
|
||||
@@ -32,7 +32,7 @@ const StyledInformationBannerWrapper = styled.div`
|
||||
|
||||
export const InformationBannerWrapper = () => {
|
||||
const subscriptionStatus = useSubscriptionStatus();
|
||||
const permissionMap = usePermissionFlagMap();
|
||||
const permissionMap = usePermissionFlagGrantMap();
|
||||
const isAccountSyncEnabled =
|
||||
permissionMap[PermissionFlagType.CONNECTED_ACCOUNTS];
|
||||
const isWorkspaceSuspended = useIsWorkspaceActivationStatusEqualsTo(
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { useSnackBarOnQueryError } from '@/apollo/hooks/useSnackBarOnQueryError';
|
||||
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
|
||||
@@ -24,7 +24,7 @@ export const InformationBannerBillingSubscriptionPaused = () => {
|
||||
|
||||
const {
|
||||
[PermissionFlagType.WORKSPACE]: hasPermissionToUpdateBillingDetails,
|
||||
} = usePermissionFlagMap();
|
||||
} = usePermissionFlagGrantMap();
|
||||
|
||||
const openBillingPortal = () => {
|
||||
if (isDefined(data) && isDefined(data.billingPortalSession.url)) {
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useEndSubscriptionTrialPeriod } from '@/settings/billing/hooks/useEndSubscriptionTrialPeriod';
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
|
||||
@@ -9,7 +9,7 @@ export const InformationBannerEndTrialPeriod = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const { [PermissionFlagType.WORKSPACE]: hasPermissionToEndTrialPeriod } =
|
||||
usePermissionFlagMap();
|
||||
usePermissionFlagGrantMap();
|
||||
|
||||
return (
|
||||
<InformationBanner
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
|
||||
@@ -21,7 +21,7 @@ export const InformationBannerFailPaymentInfo = () => {
|
||||
|
||||
const {
|
||||
[PermissionFlagType.WORKSPACE]: hasPermissionToUpdateBillingDetails,
|
||||
} = usePermissionFlagMap();
|
||||
} = usePermissionFlagGrantMap();
|
||||
|
||||
const openBillingPortal = () => {
|
||||
if (isDefined(data) && isDefined(data.billingPortalSession.url)) {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { BILLING_CHECKOUT_SESSION_DEFAULT_VALUE } from '@/settings/billing/constants/BillingCheckoutSessionDefaultValue';
|
||||
import { useHandleCheckoutSession } from '@/settings/billing/hooks/useHandleCheckoutSession';
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
@@ -16,7 +16,7 @@ export const InformationBannerNoBillingSubscription = () => {
|
||||
});
|
||||
|
||||
const { [PermissionFlagType.WORKSPACE]: hasPermissionToSubscribe } =
|
||||
usePermissionFlagMap();
|
||||
usePermissionFlagGrantMap();
|
||||
|
||||
return (
|
||||
<InformationBanner
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
@@ -9,7 +9,7 @@ export const InformationBannerNoMoreCredits = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const { [PermissionFlagType.WORKSPACE]: hasPermissionToUpdateCreditPlan } =
|
||||
usePermissionFlagMap();
|
||||
usePermissionFlagGrantMap();
|
||||
|
||||
const navigateSettings = useNavigateSettings();
|
||||
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ export const useMetadataErrorHandler = () => {
|
||||
viewFilter: t`view filter`,
|
||||
index: t`index`,
|
||||
logicFunction: t`logic function`,
|
||||
permissionFlagGrant: t`permission flag grant`,
|
||||
permissionFlag: t`permission flag`,
|
||||
objectPermission: t`object permission`,
|
||||
fieldPermission: t`field permission`,
|
||||
|
||||
+3
-2
@@ -104,8 +104,9 @@ export const UserMetadataProviderInitialEffect = () => {
|
||||
|
||||
if (isDefined(userQueryData.currentUser.currentUserWorkspace)) {
|
||||
setCurrentUserWorkspace({
|
||||
permissionFlags:
|
||||
userQueryData.currentUser.currentUserWorkspace.permissionFlags ?? [],
|
||||
permissionFlagGrants:
|
||||
userQueryData.currentUser.currentUserWorkspace.permissionFlagGrants ??
|
||||
[],
|
||||
twoFactorAuthenticationMethodSummary:
|
||||
userQueryData.currentUser.currentUserWorkspace
|
||||
.twoFactorAuthenticationMethodSummary ?? [],
|
||||
|
||||
@@ -7,7 +7,7 @@ export type FlatRole = Omit<
|
||||
| 'workspaceMembers'
|
||||
| 'fieldPermissions'
|
||||
| 'objectPermissions'
|
||||
| 'permissionFlags'
|
||||
| 'permissionFlagGrants'
|
||||
| 'rowLevelPermissionPredicateGroups'
|
||||
| 'rowLevelPermissionPredicates'
|
||||
>;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { NavigationDrawerAiChatContent } from '@/ai/components/NavigationDrawerAiChatContent';
|
||||
import { MainNavigationDrawerNavigationContent } from '@/navigation/components/MainNavigationDrawerNavigationContent';
|
||||
import { MainNavigationDrawerTabsRow } from '@/navigation/components/MainNavigationDrawerTabsRow';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
|
||||
import { NavigationDrawerFixedContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent';
|
||||
import { NavigationDrawerScrollableContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent';
|
||||
@@ -16,7 +16,7 @@ export const MainNavigationDrawer = ({ className }: { className?: string }) => {
|
||||
navigationDrawerActiveTabState,
|
||||
);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const hasAiSettingsPermission = useHasPermissionFlag(
|
||||
const hasAiSettingsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.AI_SETTINGS,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import { useIsMobile } from 'twenty-ui/utilities';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { useSwitchToNewAiChat } from '@/ai/hooks/useSwitchToNewAiChat';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { NavigationDrawerAnimatedCollapseWrapper } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { navigationDrawerActiveTabState } from '@/ui/navigation/states/navigationDrawerActiveTabState';
|
||||
@@ -144,7 +144,7 @@ export const MainNavigationDrawerTabsRow = () => {
|
||||
const setIsNavigationDrawerExpanded = useSetAtomState(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
const hasAiSettingsPermission = useHasPermissionFlag(
|
||||
const hasAiSettingsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.AI_SETTINGS,
|
||||
);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePat
|
||||
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
||||
import { currentMobileNavigationDrawerState } from '@/navigation/states/currentMobileNavigationDrawerState';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useOpenRecordsSearchPageInSidePanel } from '@/side-panel/hooks/useOpenRecordsSearchPageInSidePanel';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState';
|
||||
@@ -39,7 +39,7 @@ export const MobileNavigationBar = () => {
|
||||
const { switchToNewChat } = useSwitchToNewAiChat();
|
||||
const { alphaSortedActiveNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const hasAiSettingsPermission = useHasPermissionFlag(
|
||||
const hasAiSettingsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.AI_SETTINGS,
|
||||
);
|
||||
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ export const responseData = {
|
||||
},
|
||||
workspaceMembers: [],
|
||||
currentUserWorkspace: {
|
||||
permissionFlags: ['DATA_MODEL'],
|
||||
permissionFlagGrants: ['DATA_MODEL'],
|
||||
},
|
||||
currentWorkspace: {
|
||||
id: 'test-workspace-id',
|
||||
|
||||
+4
-2
@@ -1,6 +1,6 @@
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
@@ -36,7 +36,9 @@ export const ObjectOptionsDropdownVisibilityContent = () => {
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
const { updateCurrentView } = useUpdateCurrentView();
|
||||
const { copyToClipboard } = useCopyToClipboard();
|
||||
const hasViewsPermission = useHasPermissionFlag(PermissionFlagType.VIEWS);
|
||||
const hasViewsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.VIEWS,
|
||||
);
|
||||
const { canPersistChanges } = useCanPersistViewChanges();
|
||||
|
||||
const selectedItemId = useAtomComponentStateValue(
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
@@ -6,7 +6,7 @@ import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
export const useCanAddSelectOption = (fieldName: string) => {
|
||||
const { objectNamePlural } = useParams();
|
||||
|
||||
const userHasPermissionToEditDataModel = useHasPermissionFlag(
|
||||
const userHasPermissionToEditDataModel = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.DATA_MODEL,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import { type RecordGroupAction } from '@/object-record/record-group/types/Recor
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { recordIndexGroupFieldMetadataItemComponentState } from '@/object-record/record-index/states/recordIndexGroupFieldMetadataComponentState';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useAtomComponentFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilySelectorValue';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
@@ -90,7 +90,7 @@ export const useRecordGroupActions = ({
|
||||
recordIndexGroupFieldMetadataItem,
|
||||
]);
|
||||
|
||||
const hasAccessToDataModelSettings = useHasPermissionFlag(
|
||||
const hasAccessToDataModelSettings = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.DATA_MODEL,
|
||||
);
|
||||
const currentIndex = visibleRecordGroupIds.findIndex(
|
||||
|
||||
+3
-2
@@ -31,7 +31,8 @@ const renderHooks = (
|
||||
onboardingStatus: OnboardingStatus,
|
||||
withCurrentBillingSubscription: boolean,
|
||||
withOneWorkspaceMember = true,
|
||||
permissionFlags = mockedUserData.currentUserWorkspace.permissionFlags,
|
||||
permissionFlagGrants = mockedUserData.currentUserWorkspace
|
||||
.permissionFlagGrants,
|
||||
) => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
@@ -57,7 +58,7 @@ const renderHooks = (
|
||||
result.current.setCurrentUser({ ...mockedUserData, onboardingStatus });
|
||||
result.current.setCurrentUserWorkspace({
|
||||
...mockedUserData.currentUserWorkspace,
|
||||
permissionFlags,
|
||||
permissionFlagGrants,
|
||||
});
|
||||
result.current.setCurrentWorkspace({
|
||||
...mockCurrentWorkspace,
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
currentWorkspaceState,
|
||||
} from '@/auth/states/currentWorkspaceState';
|
||||
import { calendarBookingPageIdState } from '@/client-config/states/calendarBookingPageIdState';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
import { useCallback } from 'react';
|
||||
@@ -67,7 +67,7 @@ export const useSetNextOnboardingStatus = () => {
|
||||
const currentUser = useAtomStateValue(currentUserState);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const calendarBookingPageId = useAtomStateValue(calendarBookingPageIdState);
|
||||
const permissionMap = usePermissionFlagMap();
|
||||
const permissionMap = usePermissionFlagGrantMap();
|
||||
const isAccountSyncEnabled =
|
||||
permissionMap[PermissionFlagType.CONNECTED_ACCOUNTS];
|
||||
|
||||
|
||||
+2
-2
@@ -1708,7 +1708,7 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
// currentUserWorkspaceState is now a Jotai state, set it directly
|
||||
if (isRestricted === true) {
|
||||
jotaiStore.set(currentUserWorkspaceState.atom, {
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
twoFactorAuthenticationMethodSummary: null,
|
||||
objectsPermissions: [
|
||||
{
|
||||
@@ -1725,7 +1725,7 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
});
|
||||
} else {
|
||||
jotaiStore.set(currentUserWorkspaceState.atom, {
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
twoFactorAuthenticationMethodSummary: null,
|
||||
objectsPermissions: [
|
||||
{
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import { useNextBillingPhase } from '@/settings/billing/hooks/useNextBillingPhas
|
||||
import { useNextBillingSeats } from '@/settings/billing/hooks/useNextBillingSeats';
|
||||
import { useNextPlan } from '@/settings/billing/hooks/useNextPlan';
|
||||
import { useSplitPhaseItemsInPrices } from '@/settings/billing/hooks/useSplitPhaseItemsInPrices';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
@@ -190,7 +190,7 @@ export const SettingsBillingSubscriptionInfo = ({
|
||||
useEndSubscriptionTrialPeriod();
|
||||
|
||||
const { [PermissionFlagType.WORKSPACE]: hasPermissionToEndTrialPeriod } =
|
||||
usePermissionFlagMap();
|
||||
usePermissionFlagGrantMap();
|
||||
|
||||
const seats = currentBillingSubscription.billingSubscriptionItems?.find(
|
||||
(item) =>
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { useHasAccessTokenPair } from '@/auth/hooks/useHasAccessTokenPair';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { type ReactNode } from 'react';
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
@@ -22,7 +22,7 @@ export const SettingsProtectedRouteWrapper = ({
|
||||
requiredFeatureFlag,
|
||||
}: SettingsProtectedRouteWrapperProps) => {
|
||||
const hasAccessTokenPair = useHasAccessTokenPair();
|
||||
const hasPermission = useHasPermissionFlag(settingsPermission);
|
||||
const hasPermission = useHasPermissionFlagGrant(settingsPermission);
|
||||
const requiredFeatureFlagEnabled = useIsFeatureEnabled(
|
||||
requiredFeatureFlag || null,
|
||||
);
|
||||
|
||||
+6
-6
@@ -12,7 +12,7 @@ import {
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { SnackBarComponentInstanceContext } from '@/ui/feedback/snack-bar-manager/contexts/SnackBarComponentInstanceContext';
|
||||
import {
|
||||
jotaiStore,
|
||||
@@ -65,8 +65,8 @@ const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
</MockedProvider>
|
||||
);
|
||||
|
||||
jest.mock('@/settings/roles/hooks/usePermissionFlagMap', () => ({
|
||||
usePermissionFlagMap: jest.fn(),
|
||||
jest.mock('@/settings/roles/hooks/usePermissionFlagGrantMap', () => ({
|
||||
usePermissionFlagGrantMap: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/domain-manager/hooks/useRedirectToWorkspaceDomain', () => ({
|
||||
@@ -83,7 +83,7 @@ describe('useSettingsNavigationItems', () => {
|
||||
});
|
||||
|
||||
it('should hide workspace settings when no permissions', () => {
|
||||
(usePermissionFlagMap as jest.Mock).mockImplementation(() => ({
|
||||
(usePermissionFlagGrantMap as jest.Mock).mockImplementation(() => ({
|
||||
[PermissionFlagType.WORKSPACE]: false,
|
||||
[PermissionFlagType.WORKSPACE_MEMBERS]: false,
|
||||
[PermissionFlagType.DATA_MODEL]: false,
|
||||
@@ -105,7 +105,7 @@ describe('useSettingsNavigationItems', () => {
|
||||
});
|
||||
|
||||
it('should show workspace settings when has permissions', () => {
|
||||
(usePermissionFlagMap as jest.Mock).mockImplementation(() => ({
|
||||
(usePermissionFlagGrantMap as jest.Mock).mockImplementation(() => ({
|
||||
[PermissionFlagType.WORKSPACE]: true,
|
||||
[PermissionFlagType.WORKSPACE_MEMBERS]: true,
|
||||
[PermissionFlagType.DATA_MODEL]: true,
|
||||
@@ -127,7 +127,7 @@ describe('useSettingsNavigationItems', () => {
|
||||
});
|
||||
|
||||
it('should show user section items regardless of permissions', () => {
|
||||
(usePermissionFlagMap as jest.Mock).mockImplementation(() => ({
|
||||
(usePermissionFlagGrantMap as jest.Mock).mockImplementation(() => ({
|
||||
[PermissionFlagType.WORKSPACE]: false,
|
||||
[PermissionFlagType.WORKSPACE_MEMBERS]: false,
|
||||
[PermissionFlagType.DATA_MODEL]: false,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
import { usePermissionFlagGrantMap } from '@/settings/roles/hooks/usePermissionFlagGrantMap';
|
||||
import { getDocumentationUrl } from '@/support/utils/getDocumentationUrl';
|
||||
import {
|
||||
type NavigationDrawerItemIndentationLevel,
|
||||
@@ -72,7 +72,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
|
||||
supportChat?.supportDriver === 'FRONT' &&
|
||||
isNonEmptyString(supportChat.supportFrontChatId);
|
||||
|
||||
const permissionMap = usePermissionFlagMap();
|
||||
const permissionMap = usePermissionFlagGrantMap();
|
||||
return [
|
||||
{
|
||||
label: t`User`,
|
||||
|
||||
@@ -14,9 +14,10 @@ export const useCanChangePassword = () => {
|
||||
return { canChangePassword: true };
|
||||
}
|
||||
|
||||
const hasBypassPermission = currentUserWorkspace?.permissionFlags?.includes(
|
||||
PermissionFlagType.SSO_BYPASS,
|
||||
);
|
||||
const hasBypassPermission =
|
||||
currentUserWorkspace?.permissionFlagGrants?.includes(
|
||||
PermissionFlagType.SSO_BYPASS,
|
||||
);
|
||||
|
||||
if (!hasBypassPermission) {
|
||||
return { canChangePassword: false };
|
||||
|
||||
@@ -23,8 +23,8 @@ export const useCanEditProfileField = (field: EditableProfileField) => {
|
||||
const editableFields = currentWorkspace.editableProfileFields ?? [];
|
||||
const workspaceAllowsField = editableFields.includes(field);
|
||||
|
||||
const permissionFlags = currentUserWorkspace.permissionFlags ?? [];
|
||||
const hasProfilePermission = permissionFlags.includes(
|
||||
const permissionFlagGrants = currentUserWorkspace.permissionFlagGrants ?? [];
|
||||
const hasProfilePermission = permissionFlagGrants.includes(
|
||||
PermissionFlagType.PROFILE_INFORMATION,
|
||||
);
|
||||
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const PERMISSION_FLAG_FRAGMENT = gql`
|
||||
fragment PermissionFlagFragment on PermissionFlag {
|
||||
id
|
||||
flag
|
||||
roleId
|
||||
}
|
||||
`;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const PERMISSION_FLAG_GRANT_FRAGMENT = gql`
|
||||
fragment PermissionFlagGrantFragment on PermissionFlagGrant {
|
||||
id
|
||||
flag
|
||||
roleId
|
||||
}
|
||||
`;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { PERMISSION_FLAG_GRANT_FRAGMENT } from '@/settings/roles/graphql/fragments/permissionFlagGrantFragment';
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPSERT_PERMISSION_FLAG_GRANTS = gql`
|
||||
${PERMISSION_FLAG_GRANT_FRAGMENT}
|
||||
mutation UpsertPermissionFlagGrants(
|
||||
$upsertPermissionFlagGrantsInput: UpsertPermissionFlagGrantsInput!
|
||||
) {
|
||||
upsertPermissionFlagGrants(
|
||||
upsertPermissionFlagGrantsInput: $upsertPermissionFlagGrantsInput
|
||||
) {
|
||||
...PermissionFlagGrantFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
import { PERMISSION_FLAG_FRAGMENT } from '@/settings/roles/graphql/fragments/permissionFlagFragment';
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPSERT_PERMISSION_FLAGS = gql`
|
||||
${PERMISSION_FLAG_FRAGMENT}
|
||||
mutation UpsertPermissionFlags(
|
||||
$upsertPermissionFlagsInput: UpsertPermissionFlagsInput!
|
||||
) {
|
||||
upsertPermissionFlags(
|
||||
upsertPermissionFlagsInput: $upsertPermissionFlagsInput
|
||||
) {
|
||||
...PermissionFlagFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -2,7 +2,7 @@ import { AGENT_FRAGMENT } from '@/ai/graphql/fragments/agentFragment';
|
||||
import { API_KEY_FOR_ROLE_FRAGMENT } from '@/settings/roles/graphql/fragments/apiKeyForRoleFragment';
|
||||
import { FIELD_PERMISSION_FRAGMENT } from '@/settings/roles/graphql/fragments/fieldPermissionFragment';
|
||||
import { OBJECT_PERMISSION_FRAGMENT } from '@/settings/roles/graphql/fragments/objectPermissionFragment';
|
||||
import { PERMISSION_FLAG_FRAGMENT } from '@/settings/roles/graphql/fragments/permissionFlagFragment';
|
||||
import { PERMISSION_FLAG_GRANT_FRAGMENT } from '@/settings/roles/graphql/fragments/permissionFlagGrantFragment';
|
||||
import { ROLE_FRAGMENT } from '@/settings/roles/graphql/fragments/roleFragment';
|
||||
import { ROW_LEVEL_PERMISSION_PREDICATE_FRAGMENT } from '@/settings/roles/graphql/fragments/rowLevelPermissionPredicateFragment';
|
||||
import { ROW_LEVEL_PERMISSION_PREDICATE_GROUP_FRAGMENT } from '@/settings/roles/graphql/fragments/rowLevelPermissionPredicateGroupFragment';
|
||||
@@ -14,7 +14,7 @@ export const GET_ROLES = gql`
|
||||
${ROLE_FRAGMENT}
|
||||
${AGENT_FRAGMENT}
|
||||
${API_KEY_FOR_ROLE_FRAGMENT}
|
||||
${PERMISSION_FLAG_FRAGMENT}
|
||||
${PERMISSION_FLAG_GRANT_FRAGMENT}
|
||||
${OBJECT_PERMISSION_FRAGMENT}
|
||||
${FIELD_PERMISSION_FRAGMENT}
|
||||
${ROW_LEVEL_PERMISSION_PREDICATE_FRAGMENT}
|
||||
@@ -31,8 +31,8 @@ export const GET_ROLES = gql`
|
||||
apiKeys {
|
||||
...ApiKeyForRoleFragment
|
||||
}
|
||||
permissionFlags {
|
||||
...PermissionFlagFragment
|
||||
permissionFlagGrants {
|
||||
...PermissionFlagGrantFragment
|
||||
}
|
||||
objectPermissions {
|
||||
...ObjectPermissionFragment
|
||||
|
||||
+7
-5
@@ -6,22 +6,24 @@ import {
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
export const useHasPermissionFlag = (permissionFlag?: PermissionFlagType) => {
|
||||
export const useHasPermissionFlagGrant = (
|
||||
permissionFlagKey?: PermissionFlagType,
|
||||
) => {
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const currentUserWorkspace = useAtomStateValue(currentUserWorkspaceState);
|
||||
|
||||
if (!permissionFlag) {
|
||||
if (!permissionFlagKey) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
permissionFlag === PermissionFlagType.WORKSPACE &&
|
||||
permissionFlagKey === PermissionFlagType.WORKSPACE &&
|
||||
currentWorkspace?.activationStatus ===
|
||||
WorkspaceActivationStatus.PENDING_CREATION
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const userFlags = currentUserWorkspace?.permissionFlags ?? [];
|
||||
return userFlags.includes(permissionFlag);
|
||||
const userFlags = currentUserWorkspace?.permissionFlagGrants ?? [];
|
||||
return userFlags.includes(permissionFlagKey);
|
||||
};
|
||||
+5
-2
@@ -3,11 +3,14 @@ import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
import { buildRecordFromKeysWithSameValue } from '~/utils/array/buildRecordFromKeysWithSameValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
export const usePermissionFlagMap = (): Record<PermissionFlagType, boolean> => {
|
||||
export const usePermissionFlagGrantMap = (): Record<
|
||||
PermissionFlagType,
|
||||
boolean
|
||||
> => {
|
||||
const currentUserWorkspace = useAtomStateValue(currentUserWorkspaceState);
|
||||
|
||||
const currentUserWorkspaceSettingsPermissions =
|
||||
currentUserWorkspace?.permissionFlags;
|
||||
currentUserWorkspace?.permissionFlagGrants;
|
||||
|
||||
const initialPermissions = buildRecordFromKeysWithSameValue(
|
||||
Object.values(PermissionFlagType),
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { SettingsRolePermissionsSettingsTableHeader } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsTableHeader';
|
||||
import { SettingsRolePermissionsSettingsTableRow } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsTableRow';
|
||||
import { useSettingsRolePermissionFlagConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig';
|
||||
import { useSettingsRolePermissionFlagGrantConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagGrantConfig';
|
||||
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
||||
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
||||
import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
|
||||
@@ -42,7 +42,7 @@ export const SettingsRolePermissionsSettingsSection = ({
|
||||
roleId,
|
||||
);
|
||||
|
||||
const settingsPermissionsConfig = useSettingsRolePermissionFlagConfig({
|
||||
const settingsPermissionsConfig = useSettingsRolePermissionFlagGrantConfig({
|
||||
assignmentCapabilities: {
|
||||
canBeAssignedToAgents: settingsDraftRole.canBeAssignedToAgents,
|
||||
canBeAssignedToUsers: settingsDraftRole.canBeAssignedToUsers,
|
||||
|
||||
+5
-5
@@ -31,15 +31,15 @@ export const SettingsRolePermissionsSettingsTableHeader = ({
|
||||
);
|
||||
const allSettingsPermissionsEnabled = settingsPermissionsConfig.every(
|
||||
(permission) =>
|
||||
settingsDraftRole.permissionFlags?.some(
|
||||
(permissionFlag) => permissionFlag.flag === permission.key,
|
||||
settingsDraftRole.permissionFlagGrants?.some(
|
||||
(permissionFlagGrant) => permissionFlagGrant.flag === permission.key,
|
||||
),
|
||||
);
|
||||
|
||||
const someSettingsPermissionsEnabled = settingsPermissionsConfig.some(
|
||||
(permission) =>
|
||||
settingsDraftRole.permissionFlags?.some(
|
||||
(permissionFlag) => permissionFlag.flag === permission.key,
|
||||
settingsDraftRole.permissionFlagGrants?.some(
|
||||
(permissionFlagGrant) => permissionFlagGrant.flag === permission.key,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -64,7 +64,7 @@ export const SettingsRolePermissionsSettingsTableHeader = ({
|
||||
|
||||
setSettingsDraftRole({
|
||||
...settingsDraftRole,
|
||||
permissionFlags: newValue
|
||||
permissionFlagGrants: newValue
|
||||
? settingsPermissionsConfig.map((permission) => ({
|
||||
id: v4(),
|
||||
flag: permission.key,
|
||||
|
||||
+5
-5
@@ -47,8 +47,8 @@ export const SettingsRolePermissionsSettingsTableRow = ({
|
||||
);
|
||||
|
||||
const isPermissionEnabled =
|
||||
settingsDraftRole.permissionFlags?.some(
|
||||
(permissionFlag) => permissionFlag.flag === permission.key,
|
||||
settingsDraftRole.permissionFlagGrants?.some(
|
||||
(permissionFlagGrant) => permissionFlagGrant.flag === permission.key,
|
||||
) ?? false;
|
||||
|
||||
const isAllSettingsOverride =
|
||||
@@ -64,12 +64,12 @@ export const SettingsRolePermissionsSettingsTableRow = ({
|
||||
);
|
||||
|
||||
const handleChange = (value: boolean) => {
|
||||
const currentPermissions = settingsDraftRole.permissionFlags ?? [];
|
||||
const currentPermissions = settingsDraftRole.permissionFlagGrants ?? [];
|
||||
|
||||
if (value === true) {
|
||||
setSettingsDraftRole({
|
||||
...settingsDraftRole,
|
||||
permissionFlags: [
|
||||
permissionFlagGrants: [
|
||||
...currentPermissions,
|
||||
{
|
||||
id: v4(),
|
||||
@@ -81,7 +81,7 @@ export const SettingsRolePermissionsSettingsTableRow = ({
|
||||
} else {
|
||||
setSettingsDraftRole({
|
||||
...settingsDraftRole,
|
||||
permissionFlags: currentPermissions.filter(
|
||||
permissionFlagGrants: currentPermissions.filter(
|
||||
(p) => p.flag !== permission.key,
|
||||
),
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { SettingsRolePermissionsSettingsTableHeader } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsTableHeader';
|
||||
import { SettingsRolePermissionsSettingsTableRow } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsTableRow';
|
||||
import { useActionRolePermissionFlagConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useActionRolePermissionFlagConfig';
|
||||
import { useActionRolePermissionFlagGrantConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useActionRolePermissionFlagGrantConfig';
|
||||
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
||||
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
||||
import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
|
||||
@@ -43,7 +43,7 @@ export const SettingsRolePermissionsToolSection = ({
|
||||
roleId,
|
||||
);
|
||||
|
||||
const toolPermissionsConfig = useActionRolePermissionFlagConfig({
|
||||
const toolPermissionsConfig = useActionRolePermissionFlagGrantConfig({
|
||||
assignmentCapabilities: {
|
||||
canBeAssignedToAgents: settingsDraftRole.canBeAssignedToAgents,
|
||||
canBeAssignedToUsers: settingsDraftRole.canBeAssignedToUsers,
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
|
||||
type UseActionRolePermissionFlagConfigParams = {
|
||||
type UseActionRolePermissionFlagGrantConfigParams = {
|
||||
assignmentCapabilities?: {
|
||||
canBeAssignedToAgents?: boolean;
|
||||
canBeAssignedToUsers?: boolean;
|
||||
@@ -23,9 +23,9 @@ type UseActionRolePermissionFlagConfigParams = {
|
||||
};
|
||||
};
|
||||
|
||||
export const useActionRolePermissionFlagConfig = ({
|
||||
export const useActionRolePermissionFlagGrantConfig = ({
|
||||
assignmentCapabilities,
|
||||
}: UseActionRolePermissionFlagConfigParams = {}): SettingsRolePermissionsSettingPermission[] => {
|
||||
}: UseActionRolePermissionFlagGrantConfigParams = {}): SettingsRolePermissionsSettingPermission[] => {
|
||||
const {
|
||||
canBeAssignedToAgents = false,
|
||||
canBeAssignedToUsers = false,
|
||||
+3
-3
@@ -18,7 +18,7 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
import { PermissionFlagType } from '~/generated-metadata/graphql';
|
||||
|
||||
type UseSettingsRolePermissionFlagConfigParams = {
|
||||
type UseSettingsRolePermissionFlagGrantConfigParams = {
|
||||
assignmentCapabilities?: {
|
||||
canBeAssignedToAgents?: boolean;
|
||||
canBeAssignedToUsers?: boolean;
|
||||
@@ -26,9 +26,9 @@ type UseSettingsRolePermissionFlagConfigParams = {
|
||||
};
|
||||
};
|
||||
|
||||
export const useSettingsRolePermissionFlagConfig = ({
|
||||
export const useSettingsRolePermissionFlagGrantConfig = ({
|
||||
assignmentCapabilities,
|
||||
}: UseSettingsRolePermissionFlagConfigParams = {}): SettingsRolePermissionsSettingPermission[] => {
|
||||
}: UseSettingsRolePermissionFlagGrantConfigParams = {}): SettingsRolePermissionsSettingPermission[] => {
|
||||
const {
|
||||
canBeAssignedToAgents = false,
|
||||
canBeAssignedToUsers = false,
|
||||
+16
-14
@@ -19,7 +19,7 @@ import {
|
||||
UpdateOneRoleDocument,
|
||||
UpsertFieldPermissionsDocument,
|
||||
UpsertObjectPermissionsDocument,
|
||||
UpsertPermissionFlagsDocument,
|
||||
UpsertPermissionFlagGrantsDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { getDirtyFields } from '~/utils/getDirtyFields';
|
||||
|
||||
@@ -49,7 +49,9 @@ export const useSaveDraftRoleToDB = ({
|
||||
}) => {
|
||||
const [createRole] = useMutation(CreateOneRoleDocument);
|
||||
const [updateRole] = useMutation(UpdateOneRoleDocument);
|
||||
const [upsertPermissionFlags] = useMutation(UpsertPermissionFlagsDocument);
|
||||
const [upsertPermissionFlagGrants] = useMutation(
|
||||
UpsertPermissionFlagGrantsDocument,
|
||||
);
|
||||
const [upsertObjectPermissions] = useMutation(
|
||||
UpsertObjectPermissionsDocument,
|
||||
);
|
||||
@@ -164,14 +166,14 @@ export const useSaveDraftRoleToDB = ({
|
||||
};
|
||||
|
||||
const updateExistingRole = async () => {
|
||||
if (isDefined(dirtyFields.permissionFlags)) {
|
||||
await upsertPermissionFlags({
|
||||
if (isDefined(dirtyFields.permissionFlagGrants)) {
|
||||
await upsertPermissionFlagGrants({
|
||||
variables: {
|
||||
upsertPermissionFlagsInput: {
|
||||
upsertPermissionFlagGrantsInput: {
|
||||
roleId: roleId,
|
||||
permissionFlagKeys:
|
||||
settingsDraftRole.permissionFlags?.map(
|
||||
(permissionFlag) => permissionFlag.flag,
|
||||
permissionFlagGrantKeys:
|
||||
settingsDraftRole.permissionFlagGrants?.map(
|
||||
(permissionFlagGrant) => permissionFlagGrant.flag,
|
||||
) ?? [],
|
||||
},
|
||||
},
|
||||
@@ -361,14 +363,14 @@ export const useSaveDraftRoleToDB = ({
|
||||
};
|
||||
|
||||
const upsertRolePermissions = async (targetRoleId: string) => {
|
||||
if (isDefined(dirtyFields.permissionFlags)) {
|
||||
await upsertPermissionFlags({
|
||||
if (isDefined(dirtyFields.permissionFlagGrants)) {
|
||||
await upsertPermissionFlagGrants({
|
||||
variables: {
|
||||
upsertPermissionFlagsInput: {
|
||||
upsertPermissionFlagGrantsInput: {
|
||||
roleId: targetRoleId,
|
||||
permissionFlagKeys:
|
||||
settingsDraftRole.permissionFlags?.map(
|
||||
(permissionFlag) => permissionFlag.flag,
|
||||
permissionFlagGrantKeys:
|
||||
settingsDraftRole.permissionFlagGrants?.map(
|
||||
(permissionFlagGrant) => permissionFlagGrant.flag,
|
||||
) ?? [],
|
||||
},
|
||||
},
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ export const settingsDraftRoleFamilyState = createAtomFamilyState<
|
||||
canAccessAllTools: false,
|
||||
isEditable: false,
|
||||
workspaceMembers: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
objectPermissions: [],
|
||||
fieldPermissions: [],
|
||||
rowLevelPermissionPredicates: [],
|
||||
|
||||
@@ -34,7 +34,7 @@ export const USER_QUERY_FRAGMENT = gql`
|
||||
}
|
||||
currentUserWorkspace {
|
||||
id
|
||||
permissionFlags
|
||||
permissionFlagGrants
|
||||
objectsPermissions {
|
||||
...ObjectPermissionFragment
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ export const useLoadCurrentUser = () => {
|
||||
|
||||
if (isDefined(user.currentUserWorkspace)) {
|
||||
setCurrentUserWorkspace({
|
||||
permissionFlags: user.currentUserWorkspace.permissionFlags ?? [],
|
||||
permissionFlagGrants:
|
||||
user.currentUserWorkspace.permissionFlagGrants ?? [],
|
||||
twoFactorAuthenticationMethodSummary:
|
||||
user.currentUserWorkspace.twoFactorAuthenticationMethodSummary ?? [],
|
||||
objectsPermissions:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import {
|
||||
ViewVisibility,
|
||||
@@ -7,7 +7,9 @@ import {
|
||||
|
||||
export const useCanPersistViewChanges = () => {
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
const hasViewsPermission = useHasPermissionFlag(PermissionFlagType.VIEWS);
|
||||
const hasViewsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.VIEWS,
|
||||
);
|
||||
|
||||
if (!currentView) {
|
||||
return { canPersistChanges: false };
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
@@ -77,7 +77,7 @@ export const ViewPickerContentEffect = () => {
|
||||
const { availableFieldsForGrouping } =
|
||||
useGetAvailableFieldsToGroupRecordsBy();
|
||||
const { availableFieldsForCalendar } = useGetAvailableFieldsForCalendar();
|
||||
const hasViewPermission = useHasPermissionFlag(PermissionFlagType.VIEWS);
|
||||
const hasViewPermission = useHasPermissionFlagGrant(PermissionFlagType.VIEWS);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
||||
+4
-2
@@ -1,6 +1,6 @@
|
||||
import { useCreateManyNavigationMenuItems } from '@/navigation-menu-item/common/hooks/useCreateManyNavigationMenuItems';
|
||||
import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
@@ -53,7 +53,9 @@ export const ViewPickerOptionDropdown = ({
|
||||
const setViewPickerReferenceViewId = useSetAtomComponentState(
|
||||
viewPickerReferenceViewIdComponentState,
|
||||
);
|
||||
const hasViewsPermission = useHasPermissionFlag(PermissionFlagType.VIEWS);
|
||||
const hasViewsPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.VIEWS,
|
||||
);
|
||||
|
||||
const { createManyNavigationMenuItems } = useCreateManyNavigationMenuItems();
|
||||
const { navigationMenuItems, currentWorkspaceMemberId } =
|
||||
|
||||
+11
-9
@@ -6,21 +6,21 @@ import { WorkflowAiAgentPermissionsFlagRow } from './WorkflowAiAgentPermissionsF
|
||||
type WorkflowAiAgentPermissionsFlagListProps = {
|
||||
title: string;
|
||||
permissions: SettingsRolePermissionsSettingPermission[];
|
||||
enabledPermissionFlagKeys: PermissionFlagType[];
|
||||
enabledPermissionFlagGrantKeys: PermissionFlagType[];
|
||||
readonly: boolean;
|
||||
showDeleteButton?: boolean;
|
||||
onAddPermissionFlag?: (permissionKey: PermissionFlagType) => void;
|
||||
onDeletePermissionFlag?: (permissionKey: PermissionFlagType) => void;
|
||||
onAddPermissionFlagGrant?: (permissionKey: PermissionFlagType) => void;
|
||||
onDeletePermissionFlagGrant?: (permissionKey: PermissionFlagType) => void;
|
||||
};
|
||||
|
||||
export const WorkflowAiAgentPermissionsFlagList = ({
|
||||
title,
|
||||
permissions,
|
||||
enabledPermissionFlagKeys,
|
||||
enabledPermissionFlagGrantKeys,
|
||||
readonly,
|
||||
showDeleteButton = false,
|
||||
onAddPermissionFlag,
|
||||
onDeletePermissionFlag,
|
||||
onAddPermissionFlagGrant,
|
||||
onDeletePermissionFlagGrant,
|
||||
}: WorkflowAiAgentPermissionsFlagListProps) => {
|
||||
if (permissions.length === 0) {
|
||||
return null;
|
||||
@@ -29,7 +29,9 @@ export const WorkflowAiAgentPermissionsFlagList = ({
|
||||
return (
|
||||
<SidePanelGroup heading={title}>
|
||||
{permissions.map((permission) => {
|
||||
const isEnabled = enabledPermissionFlagKeys.includes(permission.key);
|
||||
const isEnabled = enabledPermissionFlagGrantKeys.includes(
|
||||
permission.key,
|
||||
);
|
||||
|
||||
return (
|
||||
<WorkflowAiAgentPermissionsFlagRow
|
||||
@@ -38,8 +40,8 @@ export const WorkflowAiAgentPermissionsFlagList = ({
|
||||
isEnabled={isEnabled}
|
||||
readonly={readonly}
|
||||
showDeleteButton={showDeleteButton}
|
||||
onAdd={() => onAddPermissionFlag?.(permission.key)}
|
||||
onDelete={() => onDeletePermissionFlag?.(permission.key)}
|
||||
onAdd={() => onAddPermissionFlagGrant?.(permission.key)}
|
||||
onDelete={() => onDeletePermissionFlagGrant?.(permission.key)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
+15
-13
@@ -1,5 +1,5 @@
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useActionRolePermissionFlagConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useActionRolePermissionFlagConfig';
|
||||
import { useActionRolePermissionFlagGrantConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useActionRolePermissionFlagGrantConfig';
|
||||
import { SidePanelSubPageNavigationHeader } from '@/side-panel/pages/common/components/SidePanelSubPageNavigationHeader';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
@@ -98,12 +98,14 @@ export const WorkflowAiAgentPermissionsTab = ({
|
||||
(item) => item.id === workflowAiAgentActionAgent?.roleId,
|
||||
);
|
||||
const objectPermissions = role?.objectPermissions || [];
|
||||
const permissionFlagKeys =
|
||||
role?.permissionFlags?.map((permissionFlag) => permissionFlag.flag) ?? [];
|
||||
const permissionFlagGrantKeys =
|
||||
role?.permissionFlagGrants?.map(
|
||||
(permissionFlagGrant) => permissionFlagGrant.flag,
|
||||
) ?? [];
|
||||
const hasRoleWithPermissions =
|
||||
isDefined(workflowAiAgentActionAgent?.roleId) &&
|
||||
(objectPermissions.length > 0 || permissionFlagKeys.length > 0);
|
||||
const actionPermissionsConfig = useActionRolePermissionFlagConfig({
|
||||
(objectPermissions.length > 0 || permissionFlagGrantKeys.length > 0);
|
||||
const actionPermissionsConfig = useActionRolePermissionFlagGrantConfig({
|
||||
assignmentCapabilities: { canBeAssignedToAgents: true },
|
||||
});
|
||||
|
||||
@@ -119,7 +121,7 @@ export const WorkflowAiAgentPermissionsTab = ({
|
||||
filteredEnabledPermissions: filteredEnabledActionPermissions,
|
||||
} = getFilteredPermissions({
|
||||
permissions: actionPermissionsConfig,
|
||||
permissionFlagKeys,
|
||||
permissionFlagGrantKeys,
|
||||
searchQuery,
|
||||
});
|
||||
|
||||
@@ -134,12 +136,12 @@ export const WorkflowAiAgentPermissionsTab = ({
|
||||
const {
|
||||
handleAddPermission,
|
||||
handleDeletePermission,
|
||||
handleAddPermissionFlag,
|
||||
handleDeletePermissionFlag,
|
||||
handleAddPermissionFlagGrant,
|
||||
handleDeletePermissionFlagGrant,
|
||||
} = useWorkflowAiAgentPermissionActions({
|
||||
readonly,
|
||||
objectPermissions,
|
||||
permissionFlagKeys,
|
||||
permissionFlagGrantKeys,
|
||||
refetchAgentAndRoles,
|
||||
});
|
||||
|
||||
@@ -237,9 +239,9 @@ export const WorkflowAiAgentPermissionsTab = ({
|
||||
<WorkflowAiAgentPermissionsFlagList
|
||||
title={t`Actions`}
|
||||
permissions={filteredActionPermissions}
|
||||
enabledPermissionFlagKeys={permissionFlagKeys}
|
||||
enabledPermissionFlagGrantKeys={permissionFlagGrantKeys}
|
||||
readonly={readonly}
|
||||
onAddPermissionFlag={handleAddPermissionFlag}
|
||||
onAddPermissionFlagGrant={handleAddPermissionFlagGrant}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -255,10 +257,10 @@ export const WorkflowAiAgentPermissionsTab = ({
|
||||
<WorkflowAiAgentPermissionsFlagList
|
||||
title={t`Actions`}
|
||||
permissions={filteredEnabledActionPermissions}
|
||||
enabledPermissionFlagKeys={permissionFlagKeys}
|
||||
enabledPermissionFlagGrantKeys={permissionFlagGrantKeys}
|
||||
readonly={readonly}
|
||||
showDeleteButton={!readonly}
|
||||
onDeletePermissionFlag={handleDeletePermissionFlag}
|
||||
onDeletePermissionFlagGrant={handleDeletePermissionFlagGrant}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
+3
-3
@@ -10,11 +10,11 @@ export const getFilteredPermissions = <
|
||||
T extends { key: PermissionFlagType; name: string },
|
||||
>({
|
||||
permissions,
|
||||
permissionFlagKeys,
|
||||
permissionFlagGrantKeys,
|
||||
searchQuery,
|
||||
}: {
|
||||
permissions: T[];
|
||||
permissionFlagKeys: PermissionFlagType[];
|
||||
permissionFlagGrantKeys: PermissionFlagType[];
|
||||
searchQuery: string;
|
||||
}): FilteredPermissionsResult<T> => {
|
||||
const filteredPermissions = filterBySearchQuery<T>({
|
||||
@@ -24,7 +24,7 @@ export const getFilteredPermissions = <
|
||||
});
|
||||
|
||||
const enabledPermissions = permissions.filter((permission) =>
|
||||
permissionFlagKeys.includes(permission.key),
|
||||
permissionFlagGrantKeys.includes(permission.key),
|
||||
);
|
||||
|
||||
const filteredEnabledPermissions = filterBySearchQuery<T>({
|
||||
|
||||
+34
-26
@@ -1,7 +1,7 @@
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { type SettingsRoleObjectPermissionKey } from '@/settings/roles/role-permissions/objects-permissions/constants/SettingsRoleObjectPermissionIconConfig';
|
||||
import { useActionRolePermissionFlagConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useActionRolePermissionFlagConfig';
|
||||
import { useSettingsRolePermissionFlagConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig';
|
||||
import { useActionRolePermissionFlagGrantConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useActionRolePermissionFlagGrantConfig';
|
||||
import { useSettingsRolePermissionFlagGrantConfig } from '@/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagGrantConfig';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CRUD_PERMISSIONS } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/constants/WorkflowAiAgentCrudPermissions';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
@@ -20,20 +20,20 @@ import {
|
||||
AssignRoleToAgentDocument,
|
||||
CreateOneRoleDocument,
|
||||
UpsertObjectPermissionsDocument,
|
||||
UpsertPermissionFlagsDocument,
|
||||
UpsertPermissionFlagGrantsDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type UseWorkflowAiAgentPermissionActionsParams = {
|
||||
readonly: boolean;
|
||||
objectPermissions: ObjectPermission[];
|
||||
permissionFlagKeys: PermissionFlagType[];
|
||||
permissionFlagGrantKeys: PermissionFlagType[];
|
||||
refetchAgentAndRoles: () => Promise<{ refetchedAgent?: Agent }>;
|
||||
};
|
||||
|
||||
export const useWorkflowAiAgentPermissionActions = ({
|
||||
readonly,
|
||||
objectPermissions,
|
||||
permissionFlagKeys,
|
||||
permissionFlagGrantKeys,
|
||||
refetchAgentAndRoles,
|
||||
}: UseWorkflowAiAgentPermissionActionsParams) => {
|
||||
const { enqueueSuccessSnackBar } = useSnackBar();
|
||||
@@ -41,10 +41,10 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
useAtomState(workflowAiAgentActionAgentState);
|
||||
const { alphaSortedActiveNonSystemObjectMetadataItems: objectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const settingsPermissionsConfig = useSettingsRolePermissionFlagConfig({
|
||||
const settingsPermissionsConfig = useSettingsRolePermissionFlagGrantConfig({
|
||||
assignmentCapabilities: { canBeAssignedToAgents: true },
|
||||
});
|
||||
const actionPermissionsConfig = useActionRolePermissionFlagConfig({
|
||||
const actionPermissionsConfig = useActionRolePermissionFlagGrantConfig({
|
||||
assignmentCapabilities: { canBeAssignedToAgents: true },
|
||||
});
|
||||
|
||||
@@ -60,11 +60,13 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
const [upsertObjectPermissions] = useMutation(
|
||||
UpsertObjectPermissionsDocument,
|
||||
);
|
||||
const [upsertPermissionFlags] = useMutation(UpsertPermissionFlagsDocument);
|
||||
const [upsertPermissionFlagGrants] = useMutation(
|
||||
UpsertPermissionFlagGrantsDocument,
|
||||
);
|
||||
|
||||
const roleId = workflowAiAgentActionAgent?.roleId;
|
||||
|
||||
const permissionFlagLabelMap = useMemo(
|
||||
const permissionFlagGrantLabelMap = useMemo(
|
||||
() =>
|
||||
[...settingsPermissionsConfig, ...actionPermissionsConfig].reduce<
|
||||
Partial<Record<PermissionFlagType, string>>
|
||||
@@ -296,8 +298,8 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddPermissionFlag = async (
|
||||
permissionFlagKey: PermissionFlagType,
|
||||
const handleAddPermissionFlagGrant = async (
|
||||
permissionFlagGrantKey: PermissionFlagType,
|
||||
) => {
|
||||
if (readonly) {
|
||||
return;
|
||||
@@ -305,15 +307,21 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
|
||||
const ensuredRoleId = await ensureRoleId();
|
||||
|
||||
if (!ensuredRoleId || permissionFlagKeys.includes(permissionFlagKey)) {
|
||||
if (
|
||||
!ensuredRoleId ||
|
||||
permissionFlagGrantKeys.includes(permissionFlagGrantKey)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await upsertPermissionFlags({
|
||||
await upsertPermissionFlagGrants({
|
||||
variables: {
|
||||
upsertPermissionFlagsInput: {
|
||||
upsertPermissionFlagGrantsInput: {
|
||||
roleId: ensuredRoleId,
|
||||
permissionFlagKeys: [...permissionFlagKeys, permissionFlagKey],
|
||||
permissionFlagGrantKeys: [
|
||||
...permissionFlagGrantKeys,
|
||||
permissionFlagGrantKey,
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -323,33 +331,33 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
setWorkflowAiAgentPermissionsSelectedObjectId(undefined);
|
||||
};
|
||||
|
||||
const handleDeletePermissionFlag = async (
|
||||
permissionFlagKey: PermissionFlagType,
|
||||
const handleDeletePermissionFlagGrant = async (
|
||||
permissionFlagGrantKey: PermissionFlagType,
|
||||
) => {
|
||||
if (!isDefined(roleId) || readonly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!permissionFlagKeys.includes(permissionFlagKey)) {
|
||||
if (!permissionFlagGrantKeys.includes(permissionFlagGrantKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const permissionFlagKeysAfterRemoval = permissionFlagKeys.filter(
|
||||
(flag) => flag !== permissionFlagKey,
|
||||
const permissionFlagGrantKeysAfterRemoval = permissionFlagGrantKeys.filter(
|
||||
(flag) => flag !== permissionFlagGrantKey,
|
||||
);
|
||||
|
||||
await upsertPermissionFlags({
|
||||
await upsertPermissionFlagGrants({
|
||||
variables: {
|
||||
upsertPermissionFlagsInput: {
|
||||
upsertPermissionFlagGrantsInput: {
|
||||
roleId,
|
||||
permissionFlagKeys: permissionFlagKeysAfterRemoval,
|
||||
permissionFlagGrantKeys: permissionFlagGrantKeysAfterRemoval,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await refetchAgentAndRoles();
|
||||
|
||||
const permissionLabel = permissionFlagLabelMap[permissionFlagKey];
|
||||
const permissionLabel = permissionFlagGrantLabelMap[permissionFlagGrantKey];
|
||||
|
||||
if (isDefined(permissionLabel)) {
|
||||
enqueueSuccessSnackBar({
|
||||
@@ -361,7 +369,7 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
return {
|
||||
handleAddPermission,
|
||||
handleDeletePermission,
|
||||
handleAddPermissionFlag,
|
||||
handleDeletePermissionFlag,
|
||||
handleAddPermissionFlagGrant,
|
||||
handleDeletePermissionFlagGrant,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -130,7 +130,7 @@ export const SettingsAgentRoleTab = ({
|
||||
apiKeys: [],
|
||||
objectPermissions: [],
|
||||
fieldPermissions: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
rowLevelPermissionPredicateGroups: [],
|
||||
rowLevelPermissionPredicates: [],
|
||||
});
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useUpgradeApplication } from '@/marketplace/hooks/useUpgradeApplication';
|
||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
@@ -112,7 +112,7 @@ export const SettingsApplicationDetails = () => {
|
||||
|
||||
const { upgrade, isUpgrading } = useUpgradeApplication();
|
||||
|
||||
const canInstallMarketplaceApps = useHasPermissionFlag(
|
||||
const canInstallMarketplaceApps = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.MARKETPLACE_APPS,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
@@ -22,7 +22,7 @@ const APPLICATIONS_TAB_LIST_ID = 'applications-tab-list';
|
||||
export const SettingsApplications = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const hasDeveloperAccess = useHasPermissionFlag(
|
||||
const hasDeveloperAccess = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.API_KEYS_AND_WEBHOOKS,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ import { CurrentApplicationContext } from '@/applications/contexts/CurrentApplic
|
||||
import { useInstallMarketplaceApp } from '@/marketplace/hooks/useInstallMarketplaceApp';
|
||||
import { useUpgradeApplication } from '@/marketplace/hooks/useUpgradeApplication';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
@@ -46,7 +46,7 @@ export const SettingsAvailableApplicationDetails = () => {
|
||||
const { install, isInstalling } = useInstallMarketplaceApp();
|
||||
const { upgrade, isUpgrading } = useUpgradeApplication();
|
||||
|
||||
const canInstallMarketplaceApps = useHasPermissionFlag(
|
||||
const canInstallMarketplaceApps = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.MARKETPLACE_APPS,
|
||||
);
|
||||
|
||||
|
||||
+4
-4
@@ -121,12 +121,12 @@ const buildSyntheticRole = (
|
||||
canReadFieldValue: permission.canReadFieldValue,
|
||||
canUpdateFieldValue: permission.canUpdateFieldValue,
|
||||
})),
|
||||
permissionFlags: (defaultRole.permissionFlags ?? []).map(
|
||||
(permissionFlag) => ({
|
||||
__typename: 'PermissionFlag' as const,
|
||||
permissionFlagGrants: (defaultRole.permissionFlagGrants ?? []).map(
|
||||
(permissionFlagGrant) => ({
|
||||
__typename: 'PermissionFlagGrant' as const,
|
||||
id: uuidv4(),
|
||||
roleId: defaultRole.universalIdentifier,
|
||||
flag: permissionFlag.flag,
|
||||
flag: permissionFlagGrant.flag,
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { useImpersonationSession } from '@/auth/hooks/useImpersonationSession';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsRolesQueryEffect } from '@/settings/roles/components/SettingsRolesQueryEffect';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
@@ -54,7 +54,8 @@ export const SettingsWorkspaceMember = () => {
|
||||
const [impersonate] = useMutation(ImpersonateDocument);
|
||||
const isImpersonating = useAtomStateValue(isImpersonatingState);
|
||||
const canImpersonate =
|
||||
useHasPermissionFlag(PermissionFlagType.IMPERSONATE) && !isImpersonating;
|
||||
useHasPermissionFlagGrant(PermissionFlagType.IMPERSONATE) &&
|
||||
!isImpersonating;
|
||||
|
||||
const {
|
||||
roles,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { IconLock, IconUserPlus, IconUsers } from 'twenty-ui/display';
|
||||
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useHasPermissionFlagGrant } from '@/settings/roles/hooks/useHasPermissionFlagGrant';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
@@ -23,7 +23,9 @@ const MEMBERS_TAB_ROLES_ID = 'roles';
|
||||
export const SettingsWorkspaceMembers = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const hasRolesPermission = useHasPermissionFlag(PermissionFlagType.ROLES);
|
||||
const hasRolesPermission = useHasPermissionFlagGrant(
|
||||
PermissionFlagType.ROLES,
|
||||
);
|
||||
|
||||
const activeTabId = useAtomComponentStateValue(
|
||||
activeTabIdComponentState,
|
||||
|
||||
+1
-1
@@ -743,7 +743,7 @@ export const mockedMinimalMetadata: MinimalMetadata =
|
||||
"hash": "b022456a-bd5b-4314-9fb5-0111c80a8649"
|
||||
},
|
||||
{
|
||||
"collectionName": "permissionFlag",
|
||||
"collectionName": "permissionFlagGrant",
|
||||
"hash": "2de6c5b6-3b5c-4f61-8426-92c3d4c5daac"
|
||||
},
|
||||
{
|
||||
|
||||
+4
-4
@@ -23,7 +23,7 @@ export const mockedRoles: Role[] =
|
||||
"canBeAssignedToUsers": true,
|
||||
"canBeAssignedToAgents": false,
|
||||
"canBeAssignedToApiKeys": true,
|
||||
"permissionFlags": [],
|
||||
"permissionFlagGrants": [],
|
||||
"objectPermissions": [],
|
||||
"fieldPermissions": [],
|
||||
"rowLevelPermissionPredicates": [],
|
||||
@@ -68,7 +68,7 @@ export const mockedRoles: Role[] =
|
||||
"canBeAssignedToUsers": true,
|
||||
"canBeAssignedToAgents": false,
|
||||
"canBeAssignedToApiKeys": false,
|
||||
"permissionFlags": [],
|
||||
"permissionFlagGrants": [],
|
||||
"objectPermissions": [],
|
||||
"fieldPermissions": [],
|
||||
"rowLevelPermissionPredicates": [],
|
||||
@@ -105,7 +105,7 @@ export const mockedRoles: Role[] =
|
||||
"canBeAssignedToUsers": true,
|
||||
"canBeAssignedToAgents": true,
|
||||
"canBeAssignedToApiKeys": true,
|
||||
"permissionFlags": [],
|
||||
"permissionFlagGrants": [],
|
||||
"objectPermissions": [
|
||||
{
|
||||
"__typename": "ObjectPermission",
|
||||
@@ -184,7 +184,7 @@ export const mockedRoles: Role[] =
|
||||
"canBeAssignedToUsers": true,
|
||||
"canBeAssignedToAgents": false,
|
||||
"canBeAssignedToApiKeys": false,
|
||||
"permissionFlags": [],
|
||||
"permissionFlagGrants": [],
|
||||
"objectPermissions": [],
|
||||
"fieldPermissions": [],
|
||||
"rowLevelPermissionPredicates": [],
|
||||
|
||||
@@ -199,7 +199,7 @@ export const mockedUserData: MockedUser = {
|
||||
workspaceMember: mockedWorkspaceMemberData,
|
||||
currentWorkspace: mockCurrentWorkspace,
|
||||
currentUserWorkspace: {
|
||||
permissionFlags: [
|
||||
permissionFlagGrants: [
|
||||
PermissionFlagType.WORKSPACE_MEMBERS,
|
||||
PermissionFlagType.CONNECTED_ACCOUNTS,
|
||||
],
|
||||
@@ -269,7 +269,7 @@ export const mockedOnboardingUserData = (
|
||||
workspaceMembers: [],
|
||||
currentWorkspace: mockCurrentWorkspace,
|
||||
currentUserWorkspace: {
|
||||
permissionFlags: [PermissionFlagType.WORKSPACE_MEMBERS],
|
||||
permissionFlagGrants: [PermissionFlagType.WORKSPACE_MEMBERS],
|
||||
objectPermissions: getTestEnrichedObjectMetadataItemsMock().map(
|
||||
(item) => ({
|
||||
objectMetadataId: item.id,
|
||||
|
||||
+1
-1
@@ -330,7 +330,7 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
canBeAssignedToApiKeys: false,
|
||||
fieldPermissions: [],
|
||||
objectPermissions: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+2
-2
@@ -1385,7 +1385,7 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
universalIdentifier: 'c0c1c2c3-c4c5-4000-8000-000000000001',
|
||||
fieldPermissions: [],
|
||||
objectPermissions: [],
|
||||
permissionFlags: [],
|
||||
permissionFlagGrants: [],
|
||||
},
|
||||
{
|
||||
canBeAssignedToAgents: false,
|
||||
@@ -1417,7 +1417,7 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
objectUniversalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
},
|
||||
],
|
||||
permissionFlags: [
|
||||
permissionFlagGrants: [
|
||||
{
|
||||
universalIdentifier: '01d7865a-7700-5d49-b2aa-62623c2cbac7',
|
||||
flag: PermissionFlagType.APPLICATIONS,
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ const buildMockCommandMenuContextApi = (
|
||||
},
|
||||
selectedRecords: [],
|
||||
featureFlags: {},
|
||||
permissionFlags: {},
|
||||
permissionFlagGrants: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
objectMetadataItem: {},
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ exports[`stub-twenty-sdk-define plugin > matches the recorded export partition 1
|
||||
"ObjectRecordGroupByDateGranularity",
|
||||
"OnDeleteAction",
|
||||
"PageLayoutTabLayoutMode",
|
||||
"PermissionFlag",
|
||||
"PermissionFlagGrant",
|
||||
"RelationType",
|
||||
"STANDARD_OBJECT",
|
||||
"STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS",
|
||||
|
||||
+4
-4
@@ -28,13 +28,13 @@ export const fromRoleConfigToRoleManifest = (
|
||||
),
|
||||
}),
|
||||
),
|
||||
permissionFlags: (roleConfig.permissionFlags ?? []).map(
|
||||
(permissionFlag) => ({
|
||||
permissionFlagGrants: (roleConfig.permissionFlagGrants ?? []).map(
|
||||
(permissionFlagGrant) => ({
|
||||
universalIdentifier: uuidv5(
|
||||
`${roleConfig.universalIdentifier}:${permissionFlag}`,
|
||||
`${roleConfig.universalIdentifier}:${permissionFlagGrant}`,
|
||||
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
|
||||
),
|
||||
flag: permissionFlag,
|
||||
flag: permissionFlagGrant,
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
@@ -86,7 +86,7 @@ export type {
|
||||
|
||||
export { defineApplicationRole } from '@/sdk/define/roles/define-application-role';
|
||||
export { defineRole } from '@/sdk/define/roles/define-role';
|
||||
export { PermissionFlag } from '@/sdk/define/roles/permission-flag-type';
|
||||
export { PermissionFlagGrant } from '@/sdk/define/roles/permission-flag-type';
|
||||
|
||||
export { defineSkill } from '@/sdk/define/skills/define-skill';
|
||||
|
||||
|
||||
@@ -32,16 +32,16 @@ describe('defineApplicationRole', () => {
|
||||
expect(result.config?.canReadAllObjectRecords).toBe(true);
|
||||
});
|
||||
|
||||
it('should accept permissionFlags', () => {
|
||||
it('should accept permissionFlagGrants', () => {
|
||||
const config = {
|
||||
...validConfig,
|
||||
permissionFlags: ['UPLOAD_FILE'],
|
||||
permissionFlagGrants: ['UPLOAD_FILE'],
|
||||
};
|
||||
|
||||
const result = defineApplicationRole(config as any);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.config?.permissionFlags).toHaveLength(1);
|
||||
expect(result.config?.permissionFlagGrants).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should return error when universalIdentifier is missing', () => {
|
||||
|
||||
@@ -32,16 +32,16 @@ describe('defineRole', () => {
|
||||
expect(result.config?.canReadAllObjectRecords).toBe(true);
|
||||
});
|
||||
|
||||
it('should accept permissionFlags', () => {
|
||||
it('should accept permissionFlagGrants', () => {
|
||||
const config = {
|
||||
...validConfig,
|
||||
permissionFlags: ['UPLOAD_FILE', 'DOWNLOAD_FILE'],
|
||||
permissionFlagGrants: ['UPLOAD_FILE', 'DOWNLOAD_FILE'],
|
||||
};
|
||||
|
||||
const result = defineRole(config as any);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.config?.permissionFlags).toHaveLength(2);
|
||||
expect(result.config?.permissionFlagGrants).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('should return error when universalIdentifier is missing', () => {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { PermissionFlagType as PermissionFlag } from 'twenty-shared/constants';
|
||||
export { PermissionFlagType as PermissionFlagGrant } from 'twenty-shared/constants';
|
||||
|
||||
@@ -7,9 +7,9 @@ import { type PermissionFlagType } from 'twenty-shared/constants';
|
||||
|
||||
export type RoleConfig = Omit<
|
||||
RoleManifest,
|
||||
'objectPermissions' | 'fieldPermissions' | 'permissionFlags'
|
||||
'objectPermissions' | 'fieldPermissions' | 'permissionFlagGrants'
|
||||
> & {
|
||||
objectPermissions?: Omit<ObjectPermissionManifest, 'universalIdentifier'>[];
|
||||
fieldPermissions?: Omit<FieldPermissionManifest, 'universalIdentifier'>[];
|
||||
permissionFlags?: PermissionFlagType[];
|
||||
permissionFlagGrants?: PermissionFlagType[];
|
||||
};
|
||||
|
||||
+3
-1
@@ -33,6 +33,7 @@ import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permi
|
||||
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
|
||||
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
|
||||
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { PermissionFlagGrantEntity } from 'src/engine/metadata-modules/permission-flag-grant/permission-flag-grant.entity';
|
||||
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
|
||||
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
@@ -67,7 +68,7 @@ const WORKSPACE_RELATED_ENTITIES: EntityTarget<ObjectLiteral>[] = [
|
||||
ViewFilterGroupEntity,
|
||||
FieldPermissionEntity,
|
||||
ObjectPermissionEntity,
|
||||
PermissionFlagEntity,
|
||||
PermissionFlagGrantEntity,
|
||||
RoleTargetEntity,
|
||||
SearchFieldMetadataEntity,
|
||||
RowLevelPermissionPredicateEntity,
|
||||
@@ -82,6 +83,7 @@ const WORKSPACE_RELATED_ENTITIES: EntityTarget<ObjectLiteral>[] = [
|
||||
// Level 2: Children that depend on core entities
|
||||
FieldMetadataEntity,
|
||||
PageLayoutEntity,
|
||||
PermissionFlagEntity,
|
||||
SkillEntity,
|
||||
LogicFunctionEntity,
|
||||
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
|
||||
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
|
||||
|
||||
@RegisteredInstanceCommand('2.5.0', 1778235340020)
|
||||
export class RenamePermissionFlagToPermissionFlagGrantFastInstanceCommand
|
||||
implements FastInstanceCommand
|
||||
{
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlag" RENAME TO "permissionFlagGrant"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" RENAME CONSTRAINT "IDX_PERMISSION_FLAG_FLAG_ROLE_ID_UNIQUE" TO "IDX_PERMISSION_FLAG_GRANT_FLAG_ROLE_ID_UNIQUE"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER INDEX "core"."IDX_PERMISSION_FLAG_ROLE_ID" RENAME TO "IDX_PERMISSION_FLAG_GRANT_ROLE_ID"`,
|
||||
);
|
||||
|
||||
// Re-hash inherited constraints/indexes so TypeORM's schema diff matches
|
||||
// the renamed table. Original names were derived from "permissionFlag"
|
||||
// and stay free for the new catalog table created by the next migration.
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" DROP CONSTRAINT "FK_13f8ca9c517976733a1ce4c10eb"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" DROP CONSTRAINT "FK_835bc9f7ef959debfc5cd268049"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" DROP CONSTRAINT "FK_b26a9d39a88d0e72373c677c6c5"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "core"."IDX_da8ffd3c24b4a819430a861067"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX "IDX_49d4aa416a11933e35263390ad" ON "core"."permissionFlagGrant" ("workspaceId", "universalIdentifier")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" ADD CONSTRAINT "FK_272c63f634c6b9364c8ab0e94c9" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" ADD CONSTRAINT "FK_6090c1bb1c94b4e7260acb4d435" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" ADD CONSTRAINT "FK_d19956ecbc979cf2e67df6fbd50" FOREIGN KEY ("roleId") REFERENCES "core"."role"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" DROP CONSTRAINT "FK_d19956ecbc979cf2e67df6fbd50"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" DROP CONSTRAINT "FK_6090c1bb1c94b4e7260acb4d435"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" DROP CONSTRAINT "FK_272c63f634c6b9364c8ab0e94c9"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "core"."IDX_49d4aa416a11933e35263390ad"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX "IDX_da8ffd3c24b4a819430a861067" ON "core"."permissionFlagGrant" ("workspaceId", "universalIdentifier")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" ADD CONSTRAINT "FK_b26a9d39a88d0e72373c677c6c5" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" ADD CONSTRAINT "FK_835bc9f7ef959debfc5cd268049" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" ADD CONSTRAINT "FK_13f8ca9c517976733a1ce4c10eb" FOREIGN KEY ("roleId") REFERENCES "core"."role"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER INDEX "core"."IDX_PERMISSION_FLAG_GRANT_ROLE_ID" RENAME TO "IDX_PERMISSION_FLAG_ROLE_ID"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" RENAME CONSTRAINT "IDX_PERMISSION_FLAG_GRANT_FLAG_ROLE_ID_UNIQUE" TO "IDX_PERMISSION_FLAG_FLAG_ROLE_ID_UNIQUE"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagGrant" RENAME TO "permissionFlag"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
|
||||
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
|
||||
|
||||
@RegisteredInstanceCommand('2.5.0', 1778235340021)
|
||||
export class PermissionFlagSyncableEntityFastInstanceCommand
|
||||
implements FastInstanceCommand
|
||||
{
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "core"."permissionFlag" (
|
||||
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||
"workspaceId" uuid NOT NULL,
|
||||
"applicationId" uuid NOT NULL,
|
||||
"universalIdentifier" uuid NOT NULL,
|
||||
"key" varchar NOT NULL,
|
||||
"label" varchar NOT NULL,
|
||||
"description" text,
|
||||
"iconKey" varchar,
|
||||
"permissionType" varchar NOT NULL,
|
||||
"isRelevantForAgents" boolean NOT NULL DEFAULT false,
|
||||
"isRelevantForUsers" boolean NOT NULL DEFAULT false,
|
||||
"isRelevantForApiKeys" boolean NOT NULL DEFAULT false,
|
||||
"isCustom" boolean NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "IDX_PERMISSION_FLAG_KEY_WORKSPACE_ID_UNIQUE" UNIQUE ("key", "workspaceId"),
|
||||
CONSTRAINT "PK_permissionFlag_id" PRIMARY KEY ("id")
|
||||
)`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_PERMISSION_FLAG_APPLICATION_ID" ON "core"."permissionFlag" ("applicationId")`,
|
||||
);
|
||||
|
||||
// Reuses canonical hash names freed by the rename migration so TypeORM's
|
||||
// schema diff matches without further intervention.
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX "IDX_da8ffd3c24b4a819430a861067" ON "core"."permissionFlag" ("workspaceId", "universalIdentifier")`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlag"
|
||||
ADD CONSTRAINT "FK_835bc9f7ef959debfc5cd268049"
|
||||
FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id")
|
||||
ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlag"
|
||||
ADD CONSTRAINT "FK_b26a9d39a88d0e72373c677c6c5"
|
||||
FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id")
|
||||
ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlag" DROP CONSTRAINT IF EXISTS "FK_b26a9d39a88d0e72373c677c6c5"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlag" DROP CONSTRAINT IF EXISTS "FK_835bc9f7ef959debfc5cd268049"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS "core"."IDX_da8ffd3c24b4a819430a861067"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS "core"."IDX_PERMISSION_FLAG_APPLICATION_ID"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "core"."permissionFlag"`);
|
||||
}
|
||||
}
|
||||
+4
@@ -29,6 +29,8 @@ import { AddToolAndWorkflowActionTriggerSettingsFastInstanceCommand } from 'src/
|
||||
import { BackfillApplicationVariableUniversalIdentifierSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-3/2-3-instance-command-slow-1777966965588-backfill-application-variable-universal-identifier';
|
||||
import { MigrateToolTriggerSettingsSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-3/2-3-instance-command-slow-1797000002000-migrate-tool-trigger-settings';
|
||||
import { AddMetadataToBillingPriceFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-4/2-4-instance-command-fast-1777100000000-add-metadata-to-billing-price';
|
||||
import { RenamePermissionFlagToPermissionFlagGrantFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-5/2-5-instance-command-fast-1778235340020-rename-permission-flag-to-permission-flag-grant';
|
||||
import { PermissionFlagSyncableEntityFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-5/2-5-instance-command-fast-1778235340021-permission-flag-syncable-entity';
|
||||
import { AddEmailGroupChannelTypeFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-4/2-4-instance-command-fast-1778256809018-add-email-group-channel-type';
|
||||
import { AddApplicationIdToPublicDomainFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-4/2-4-instance-command-fast-1798000003000-add-application-id-to-public-domain';
|
||||
import { AddIsInternalMessagesImportEnabledFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-5/2-5-instance-command-fast-1778525104406-add-is-internal-messages-import-enabled';
|
||||
@@ -64,6 +66,8 @@ export const INSTANCE_COMMANDS = [
|
||||
RemoveUserDefaultAvatarUrlFastInstanceCommand,
|
||||
TransformApplicationVariableToSyncableEntityFastInstanceCommand,
|
||||
BackfillApplicationVariableUniversalIdentifierSlowInstanceCommand,
|
||||
RenamePermissionFlagToPermissionFlagGrantFastInstanceCommand,
|
||||
PermissionFlagSyncableEntityFastInstanceCommand,
|
||||
AddEmailGroupChannelTypeFastInstanceCommand,
|
||||
AddApplicationIdToPublicDomainFastInstanceCommand,
|
||||
AddIsInternalMessagesImportEnabledFastInstanceCommand,
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type UniversalFlatPermissionFlagGrant } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-permission-flag-grant.type';
|
||||
import { PermissionFlagGrantManifest } from 'twenty-shared/application';
|
||||
|
||||
export const fromPermissionFlagGrantToUniversalFlatPermissionFlagGrant = ({
|
||||
permissionFlagGrant,
|
||||
roleUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}: {
|
||||
permissionFlagGrant: PermissionFlagGrantManifest;
|
||||
roleUniversalIdentifier: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
now: string;
|
||||
}): UniversalFlatPermissionFlagGrant => {
|
||||
return {
|
||||
universalIdentifier: permissionFlagGrant.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
flag: permissionFlagGrant.flag,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
import { type UniversalFlatPermissionFlag } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-permission-flag.type';
|
||||
import { PermissionFlagManifest } from 'twenty-shared/application';
|
||||
|
||||
export const fromPermissionFlagToUniversalFlatPermissionFlag = ({
|
||||
permissionFlag,
|
||||
roleUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}: {
|
||||
permissionFlag: PermissionFlagManifest;
|
||||
roleUniversalIdentifier: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
now: string;
|
||||
}): UniversalFlatPermissionFlag => {
|
||||
return {
|
||||
universalIdentifier: permissionFlag.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
flag: permissionFlag.flag,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
+1
-1
@@ -32,7 +32,7 @@ export const fromRoleManifestToUniversalFlatRole = ({
|
||||
roleTargetUniversalIdentifiers: [],
|
||||
objectPermissionUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
permissionFlagUniversalIdentifiers: [],
|
||||
permissionFlagGrantUniversalIdentifiers: [],
|
||||
rowLevelPermissionPredicateUniversalIdentifiers: [],
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifiers: [],
|
||||
createdAt: now,
|
||||
|
||||
+10
-9
@@ -17,7 +17,7 @@ import { fromObjectPermissionManifestToUniversalFlatObjectPermission } from 'src
|
||||
import { fromPageLayoutManifestToUniversalFlatPageLayout } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-manifest-to-universal-flat-page-layout.util';
|
||||
import { fromPageLayoutTabManifestToUniversalFlatPageLayoutTab } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util';
|
||||
import { fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util';
|
||||
import { fromPermissionFlagToUniversalFlatPermissionFlag } from 'src/engine/core-modules/application/application-manifest/converters/from-permission-flag-to-universal-flat-permission-flag.util';
|
||||
import { fromPermissionFlagGrantToUniversalFlatPermissionFlagGrant } from 'src/engine/core-modules/application/application-manifest/converters/from-permission-flag-grant-to-universal-flat-permission-flag-grant.util';
|
||||
import { fromRoleManifestToUniversalFlatRole } from 'src/engine/core-modules/application/application-manifest/converters/from-role-manifest-to-universal-flat-role.util';
|
||||
import { fromSkillManifestToUniversalFlatSkill } from 'src/engine/core-modules/application/application-manifest/converters/from-skill-manifest-to-universal-flat-skill.util';
|
||||
import { computeSearchVectorUniversalSettingsFromObjectManifest } from 'src/engine/core-modules/application/application-manifest/utils/compute-search-vector-universal-settings-from-object-manifest.util';
|
||||
@@ -212,16 +212,17 @@ export const computeApplicationManifestAllUniversalFlatEntityMaps = ({
|
||||
});
|
||||
}
|
||||
|
||||
for (const permissionFlag of roleManifest.permissionFlags ?? []) {
|
||||
for (const permissionFlagGrant of roleManifest.permissionFlagGrants ?? []) {
|
||||
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
|
||||
universalFlatEntity: fromPermissionFlagToUniversalFlatPermissionFlag({
|
||||
permissionFlag,
|
||||
roleUniversalIdentifier: roleManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}),
|
||||
universalFlatEntity:
|
||||
fromPermissionFlagGrantToUniversalFlatPermissionFlagGrant({
|
||||
permissionFlagGrant,
|
||||
roleUniversalIdentifier: roleManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}),
|
||||
universalFlatEntityMapsToMutate:
|
||||
allUniversalFlatEntityMaps.flatPermissionFlagMaps,
|
||||
allUniversalFlatEntityMaps.flatPermissionFlagGrantMaps,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ export const USER_WORKSPACE_ENTITY_NON_CACHED_PROPERTIES = [
|
||||
'workspace',
|
||||
'user',
|
||||
'twoFactorAuthenticationMethods',
|
||||
'permissionFlags',
|
||||
'permissionFlagGrants',
|
||||
'objectPermissions',
|
||||
'objectsPermissions',
|
||||
'twoFactorAuthenticationMethodSummary',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user