Decouple Send Email node from workflows (#13322)

- Renamed `WorkflowActionAdapter` to `ToolExecutorWorkflowAction`
- Renamed `settingPermission` table to `permissionFlag` and `setting`
column to `flag`
- Decoupled the send email logic from workflows to tools
- Add new `Tools Permission` section in FE

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Abdul Rahman
2025-07-24 16:01:33 +05:30
committed by GitHub
parent eb404478c3
commit e93adde4b8
98 changed files with 1076 additions and 705 deletions

View File

@ -548,6 +548,7 @@ export type CreateRemoteServerInput = {
};
export type CreateRoleInput = {
canAccessAllTools?: InputMaybe<Scalars['Boolean']>;
canDestroyAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canReadAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canSoftDeleteAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
@ -1202,7 +1203,7 @@ export type Mutation = {
uploadWorkspaceLogo: SignedFileDto;
upsertFieldPermissions: Array<FieldPermission>;
upsertObjectPermissions: Array<ObjectPermission>;
upsertSettingPermissions: Array<SettingPermission>;
upsertPermissionFlags: Array<PermissionFlag>;
userLookupAdminPanel: UserLookup;
validateApprovedAccessDomain: ApprovedAccessDomain;
verifyTwoFactorAuthenticationMethodForAuthenticatedUser: VerifyTwoFactorAuthenticationMethodOutput;
@ -1693,8 +1694,8 @@ export type MutationUpsertObjectPermissionsArgs = {
};
export type MutationUpsertSettingPermissionsArgs = {
upsertSettingPermissionsInput: UpsertSettingPermissionsInput;
export type MutationUpsertPermissionFlagsArgs = {
upsertPermissionFlagsInput: UpsertPermissionFlagsInput;
};
@ -1876,6 +1877,25 @@ export type PageInfo = {
startCursor?: Maybe<Scalars['ConnectionCursor']>;
};
export type PermissionFlag = {
__typename?: 'PermissionFlag';
flag: PermissionFlagType;
id: Scalars['String'];
roleId: Scalars['String'];
};
export enum PermissionFlagType {
ADMIN_PANEL = 'ADMIN_PANEL',
API_KEYS_AND_WEBHOOKS = 'API_KEYS_AND_WEBHOOKS',
DATA_MODEL = 'DATA_MODEL',
ROLES = 'ROLES',
SECURITY = 'SECURITY',
SEND_EMAIL_TOOL = 'SEND_EMAIL_TOOL',
WORKFLOWS = 'WORKFLOWS',
WORKSPACE = 'WORKSPACE',
WORKSPACE_MEMBERS = 'WORKSPACE_MEMBERS'
}
export enum PermissionsOnAllObjectRecords {
DESTROY_ALL_OBJECT_RECORDS = 'DESTROY_ALL_OBJECT_RECORDS',
READ_ALL_OBJECT_RECORDS = 'READ_ALL_OBJECT_RECORDS',
@ -2250,6 +2270,7 @@ export type RevokeApiKeyDto = {
export type Role = {
__typename?: 'Role';
canAccessAllTools: Scalars['Boolean'];
canDestroyAllObjectRecords: Scalars['Boolean'];
canReadAllObjectRecords: Scalars['Boolean'];
canSoftDeleteAllObjectRecords: Scalars['Boolean'];
@ -2261,7 +2282,7 @@ export type Role = {
isEditable: Scalars['Boolean'];
label: Scalars['String'];
objectPermissions?: Maybe<Array<ObjectPermission>>;
settingPermissions?: Maybe<Array<SettingPermission>>;
permissionFlags?: Maybe<Array<PermissionFlag>>;
workspaceMembers: Array<WorkspaceMember>;
};
@ -2381,24 +2402,6 @@ export type ServerlessFunctionIdInput = {
id: Scalars['ID'];
};
export type SettingPermission = {
__typename?: 'SettingPermission';
id: Scalars['String'];
roleId: Scalars['String'];
setting: SettingPermissionType;
};
export enum SettingPermissionType {
ADMIN_PANEL = 'ADMIN_PANEL',
API_KEYS_AND_WEBHOOKS = 'API_KEYS_AND_WEBHOOKS',
DATA_MODEL = 'DATA_MODEL',
ROLES = 'ROLES',
SECURITY = 'SECURITY',
WORKFLOWS = 'WORKFLOWS',
WORKSPACE = 'WORKSPACE',
WORKSPACE_MEMBERS = 'WORKSPACE_MEMBERS'
}
export type SetupOidcSsoInput = {
clientID: Scalars['String'];
clientSecret: Scalars['String'];
@ -2686,6 +2689,7 @@ export type UpdateRoleInput = {
};
export type UpdateRolePayload = {
canAccessAllTools?: InputMaybe<Scalars['Boolean']>;
canDestroyAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canReadAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canSoftDeleteAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
@ -2752,9 +2756,9 @@ export type UpsertObjectPermissionsInput = {
roleId: Scalars['String'];
};
export type UpsertSettingPermissionsInput = {
export type UpsertPermissionFlagsInput = {
permissionFlagKeys: Array<PermissionFlagType>;
roleId: Scalars['String'];
settingPermissionKeys: Array<SettingPermissionType>;
};
export type User = {
@ -2832,7 +2836,7 @@ export type UserWorkspace = {
objectPermissions?: Maybe<Array<ObjectPermission>>;
/** @deprecated Use objectPermissions instead */
objectRecordsPermissions?: Maybe<Array<PermissionsOnAllObjectRecords>>;
settingsPermissions?: Maybe<Array<SettingPermissionType>>;
settingsPermissions?: Maybe<Array<PermissionFlagType>>;
twoFactorAuthenticationMethodSummary?: Maybe<Array<TwoFactorAuthenticationMethodDto>>;
updatedAt: Scalars['DateTime'];
user: User;
@ -3654,16 +3658,16 @@ export type UpdateLabPublicFeatureFlagMutation = { __typename?: 'Mutation', upda
export type ObjectPermissionFragmentFragment = { __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null };
export type RoleFragmentFragment = { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean };
export type PermissionFlagFragmentFragment = { __typename?: 'PermissionFlag', id: string, flag: PermissionFlagType, roleId: string };
export type SettingPermissionFragmentFragment = { __typename?: 'SettingPermission', id: string, setting: SettingPermissionType, roleId: string };
export type RoleFragmentFragment = { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean };
export type CreateOneRoleMutationVariables = Exact<{
createRoleInput: CreateRoleInput;
}>;
export type CreateOneRoleMutation = { __typename?: 'Mutation', createOneRole: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } };
export type CreateOneRoleMutation = { __typename?: 'Mutation', createOneRole: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } };
export type DeleteOneRoleMutationVariables = Exact<{
roleId: Scalars['String'];
@ -3677,7 +3681,7 @@ export type UpdateOneRoleMutationVariables = Exact<{
}>;
export type UpdateOneRoleMutation = { __typename?: 'Mutation', updateOneRole: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } };
export type UpdateOneRoleMutation = { __typename?: 'Mutation', updateOneRole: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } };
export type UpdateWorkspaceMemberRoleMutationVariables = Exact<{
workspaceMemberId: Scalars['String'];
@ -3685,7 +3689,7 @@ export type UpdateWorkspaceMemberRoleMutationVariables = Exact<{
}>;
export type UpdateWorkspaceMemberRoleMutation = { __typename?: 'Mutation', updateWorkspaceMemberRole: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, roles?: Array<{ __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean }> | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } };
export type UpdateWorkspaceMemberRoleMutation = { __typename?: 'Mutation', updateWorkspaceMemberRole: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, roles?: Array<{ __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean }> | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } };
export type UpsertObjectPermissionsMutationVariables = Exact<{
upsertObjectPermissionsInput: UpsertObjectPermissionsInput;
@ -3694,17 +3698,17 @@ export type UpsertObjectPermissionsMutationVariables = Exact<{
export type UpsertObjectPermissionsMutation = { __typename?: 'Mutation', upsertObjectPermissions: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> };
export type UpsertSettingPermissionsMutationVariables = Exact<{
upsertSettingPermissionsInput: UpsertSettingPermissionsInput;
export type UpsertPermissionFlagsMutationVariables = Exact<{
upsertPermissionFlagsInput: UpsertPermissionFlagsInput;
}>;
export type UpsertSettingPermissionsMutation = { __typename?: 'Mutation', upsertSettingPermissions: Array<{ __typename?: 'SettingPermission', id: string, setting: SettingPermissionType, roleId: string }> };
export type UpsertPermissionFlagsMutation = { __typename?: 'Mutation', upsertPermissionFlags: Array<{ __typename?: 'PermissionFlag', id: string, flag: PermissionFlagType, roleId: string }> };
export type GetRolesQueryVariables = Exact<{ [key: string]: never; }>;
export type GetRolesQuery = { __typename?: 'Query', getRoles: Array<{ __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, workspaceMembers: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }>, settingPermissions?: Array<{ __typename?: 'SettingPermission', id: string, setting: SettingPermissionType, roleId: string }> | null, objectPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> | null }> };
export type GetRolesQuery = { __typename?: 'Query', getRoles: Array<{ __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, workspaceMembers: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }>, permissionFlags?: Array<{ __typename?: 'PermissionFlag', id: string, flag: PermissionFlagType, roleId: string }> | null, objectPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> | null }> };
export type CreateApprovedAccessDomainMutationVariables = Exact<{
input: CreateApprovedAccessDomainInput;
@ -3835,7 +3839,7 @@ export type VerifyTwoFactorAuthenticationMethodForAuthenticatedUserMutationVaria
export type VerifyTwoFactorAuthenticationMethodForAuthenticatedUserMutation = { __typename?: 'Mutation', verifyTwoFactorAuthenticationMethodForAuthenticatedUser: { __typename?: 'VerifyTwoFactorAuthenticationMethodOutput', success: boolean } };
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: any, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingPermissionType> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | null, objectPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodDTO', twoFactorAuthenticationMethodId: any, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEnterpriseKey: boolean, customDomain?: string | null, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, isTwoFactorAuthenticationEnforced: boolean, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: any, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, billingProduct?: { __typename?: 'BillingProduct', name: string, description: string, metadata: { __typename?: 'BillingProductMetadata', planKey: BillingPlanKey, priceUsageBased: BillingUsageType, productKey: BillingProductKey } } | null }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, metadata: any }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } | null, defaultAgent?: { __typename?: 'Agent', id: any } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } };
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: any, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<PermissionFlagType> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | null, objectPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodDTO', twoFactorAuthenticationMethodId: any, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEnterpriseKey: boolean, customDomain?: string | null, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, isTwoFactorAuthenticationEnforced: boolean, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: any, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, billingProduct?: { __typename?: 'BillingProduct', name: string, description: string, metadata: { __typename?: 'BillingProductMetadata', planKey: BillingPlanKey, priceUsageBased: BillingUsageType, productKey: BillingProductKey } } | null }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, metadata: any }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } | null, defaultAgent?: { __typename?: 'Agent', id: any } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } };
export type WorkspaceUrlsFragmentFragment = { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null };
@ -3854,7 +3858,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: any, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingPermissionType> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | null, objectPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodDTO', twoFactorAuthenticationMethodId: any, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEnterpriseKey: boolean, customDomain?: string | null, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, isTwoFactorAuthenticationEnforced: boolean, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: any, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, billingProduct?: { __typename?: 'BillingProduct', name: string, description: string, metadata: { __typename?: 'BillingProductMetadata', planKey: BillingPlanKey, priceUsageBased: BillingUsageType, productKey: BillingProductKey } } | null }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, metadata: any }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } | null, defaultAgent?: { __typename?: 'Agent', id: any } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } } };
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: any, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<PermissionFlagType> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | null, objectPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodDTO', twoFactorAuthenticationMethodId: any, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEnterpriseKey: boolean, customDomain?: string | null, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, isTwoFactorAuthenticationEnforced: boolean, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: any, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, billingProduct?: { __typename?: 'BillingProduct', name: string, description: string, metadata: { __typename?: 'BillingProductMetadata', planKey: BillingPlanKey, priceUsageBased: BillingUsageType, productKey: BillingProductKey } } | null }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, metadata: any }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } | null, defaultAgent?: { __typename?: 'Agent', id: any } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } } };
export type ActivateWorkflowVersionMutationVariables = Exact<{
workflowVersionId: Scalars['String'];
@ -3973,7 +3977,7 @@ export type UpdateWorkspaceMutationVariables = Exact<{
}>;
export type UpdateWorkspaceMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: any, customDomain?: string | null, subdomain: string, displayName?: string | null, logo?: string | null, allowImpersonation: boolean, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, isTwoFactorAuthenticationEnforced: boolean, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } | null } };
export type UpdateWorkspaceMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: any, customDomain?: string | null, subdomain: string, displayName?: string | null, logo?: string | null, allowImpersonation: boolean, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, isTwoFactorAuthenticationEnforced: boolean, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean } | null } };
export type UploadWorkspaceLogoMutationVariables = Exact<{
file: Scalars['Upload'];
@ -4063,10 +4067,10 @@ export const WebhookFragmentFragmentDoc = gql`
secret
}
`;
export const SettingPermissionFragmentFragmentDoc = gql`
fragment SettingPermissionFragment on SettingPermission {
export const PermissionFlagFragmentFragmentDoc = gql`
fragment PermissionFlagFragment on PermissionFlag {
id
setting
flag
roleId
}
`;
@ -4133,6 +4137,7 @@ export const RoleFragmentFragmentDoc = gql`
description
icon
canUpdateAllSettings
canAccessAllTools
isEditable
canReadAllObjectRecords
canUpdateAllObjectRecords
@ -7732,41 +7737,39 @@ export function useUpsertObjectPermissionsMutation(baseOptions?: Apollo.Mutation
export type UpsertObjectPermissionsMutationHookResult = ReturnType<typeof useUpsertObjectPermissionsMutation>;
export type UpsertObjectPermissionsMutationResult = Apollo.MutationResult<UpsertObjectPermissionsMutation>;
export type UpsertObjectPermissionsMutationOptions = Apollo.BaseMutationOptions<UpsertObjectPermissionsMutation, UpsertObjectPermissionsMutationVariables>;
export const UpsertSettingPermissionsDocument = gql`
mutation UpsertSettingPermissions($upsertSettingPermissionsInput: UpsertSettingPermissionsInput!) {
upsertSettingPermissions(
upsertSettingPermissionsInput: $upsertSettingPermissionsInput
) {
...SettingPermissionFragment
export const UpsertPermissionFlagsDocument = gql`
mutation UpsertPermissionFlags($upsertPermissionFlagsInput: UpsertPermissionFlagsInput!) {
upsertPermissionFlags(upsertPermissionFlagsInput: $upsertPermissionFlagsInput) {
...PermissionFlagFragment
}
}
${SettingPermissionFragmentFragmentDoc}`;
export type UpsertSettingPermissionsMutationFn = Apollo.MutationFunction<UpsertSettingPermissionsMutation, UpsertSettingPermissionsMutationVariables>;
${PermissionFlagFragmentFragmentDoc}`;
export type UpsertPermissionFlagsMutationFn = Apollo.MutationFunction<UpsertPermissionFlagsMutation, UpsertPermissionFlagsMutationVariables>;
/**
* __useUpsertSettingPermissionsMutation__
* __useUpsertPermissionFlagsMutation__
*
* To run a mutation, you first call `useUpsertSettingPermissionsMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpsertSettingPermissionsMutation` returns a tuple that includes:
* To run a mutation, you first call `useUpsertPermissionFlagsMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpsertPermissionFlagsMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [upsertSettingPermissionsMutation, { data, loading, error }] = useUpsertSettingPermissionsMutation({
* const [upsertPermissionFlagsMutation, { data, loading, error }] = useUpsertPermissionFlagsMutation({
* variables: {
* upsertSettingPermissionsInput: // value for 'upsertSettingPermissionsInput'
* upsertPermissionFlagsInput: // value for 'upsertPermissionFlagsInput'
* },
* });
*/
export function useUpsertSettingPermissionsMutation(baseOptions?: Apollo.MutationHookOptions<UpsertSettingPermissionsMutation, UpsertSettingPermissionsMutationVariables>) {
export function useUpsertPermissionFlagsMutation(baseOptions?: Apollo.MutationHookOptions<UpsertPermissionFlagsMutation, UpsertPermissionFlagsMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpsertSettingPermissionsMutation, UpsertSettingPermissionsMutationVariables>(UpsertSettingPermissionsDocument, options);
return Apollo.useMutation<UpsertPermissionFlagsMutation, UpsertPermissionFlagsMutationVariables>(UpsertPermissionFlagsDocument, options);
}
export type UpsertSettingPermissionsMutationHookResult = ReturnType<typeof useUpsertSettingPermissionsMutation>;
export type UpsertSettingPermissionsMutationResult = Apollo.MutationResult<UpsertSettingPermissionsMutation>;
export type UpsertSettingPermissionsMutationOptions = Apollo.BaseMutationOptions<UpsertSettingPermissionsMutation, UpsertSettingPermissionsMutationVariables>;
export type UpsertPermissionFlagsMutationHookResult = ReturnType<typeof useUpsertPermissionFlagsMutation>;
export type UpsertPermissionFlagsMutationResult = Apollo.MutationResult<UpsertPermissionFlagsMutation>;
export type UpsertPermissionFlagsMutationOptions = Apollo.BaseMutationOptions<UpsertPermissionFlagsMutation, UpsertPermissionFlagsMutationVariables>;
export const GetRolesDocument = gql`
query GetRoles {
getRoles {
@ -7774,8 +7777,8 @@ export const GetRolesDocument = gql`
workspaceMembers {
...WorkspaceMemberQueryFragment
}
settingPermissions {
...SettingPermissionFragment
permissionFlags {
...PermissionFlagFragment
}
objectPermissions {
...ObjectPermissionFragment
@ -7784,7 +7787,7 @@ export const GetRolesDocument = gql`
}
${RoleFragmentFragmentDoc}
${WorkspaceMemberQueryFragmentFragmentDoc}
${SettingPermissionFragmentFragmentDoc}
${PermissionFlagFragmentFragmentDoc}
${ObjectPermissionFragmentFragmentDoc}`;
/**

View File

@ -512,6 +512,7 @@ export type CreateOneFieldMetadataInput = {
};
export type CreateRoleInput = {
canAccessAllTools?: InputMaybe<Scalars['Boolean']>;
canDestroyAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canReadAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canSoftDeleteAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
@ -1153,7 +1154,7 @@ export type Mutation = {
uploadWorkspaceLogo: SignedFileDto;
upsertFieldPermissions: Array<FieldPermission>;
upsertObjectPermissions: Array<ObjectPermission>;
upsertSettingPermissions: Array<SettingPermission>;
upsertPermissionFlags: Array<PermissionFlag>;
userLookupAdminPanel: UserLookup;
validateApprovedAccessDomain: ApprovedAccessDomain;
verifyTwoFactorAuthenticationMethodForAuthenticatedUser: VerifyTwoFactorAuthenticationMethodOutput;
@ -1604,8 +1605,8 @@ export type MutationUpsertObjectPermissionsArgs = {
};
export type MutationUpsertSettingPermissionsArgs = {
upsertSettingPermissionsInput: UpsertSettingPermissionsInput;
export type MutationUpsertPermissionFlagsArgs = {
upsertPermissionFlagsInput: UpsertPermissionFlagsInput;
};
@ -1787,6 +1788,25 @@ export type PageInfo = {
startCursor?: Maybe<Scalars['ConnectionCursor']>;
};
export type PermissionFlag = {
__typename?: 'PermissionFlag';
flag: PermissionFlagType;
id: Scalars['String'];
roleId: Scalars['String'];
};
export enum PermissionFlagType {
ADMIN_PANEL = 'ADMIN_PANEL',
API_KEYS_AND_WEBHOOKS = 'API_KEYS_AND_WEBHOOKS',
DATA_MODEL = 'DATA_MODEL',
ROLES = 'ROLES',
SECURITY = 'SECURITY',
SEND_EMAIL_TOOL = 'SEND_EMAIL_TOOL',
WORKFLOWS = 'WORKFLOWS',
WORKSPACE = 'WORKSPACE',
WORKSPACE_MEMBERS = 'WORKSPACE_MEMBERS'
}
export enum PermissionsOnAllObjectRecords {
DESTROY_ALL_OBJECT_RECORDS = 'DESTROY_ALL_OBJECT_RECORDS',
READ_ALL_OBJECT_RECORDS = 'READ_ALL_OBJECT_RECORDS',
@ -2096,6 +2116,7 @@ export type RevokeApiKeyDto = {
export type Role = {
__typename?: 'Role';
canAccessAllTools: Scalars['Boolean'];
canDestroyAllObjectRecords: Scalars['Boolean'];
canReadAllObjectRecords: Scalars['Boolean'];
canSoftDeleteAllObjectRecords: Scalars['Boolean'];
@ -2107,7 +2128,7 @@ export type Role = {
isEditable: Scalars['Boolean'];
label: Scalars['String'];
objectPermissions?: Maybe<Array<ObjectPermission>>;
settingPermissions?: Maybe<Array<SettingPermission>>;
permissionFlags?: Maybe<Array<PermissionFlag>>;
workspaceMembers: Array<WorkspaceMember>;
};
@ -2227,24 +2248,6 @@ export type ServerlessFunctionIdInput = {
id: Scalars['ID'];
};
export type SettingPermission = {
__typename?: 'SettingPermission';
id: Scalars['String'];
roleId: Scalars['String'];
setting: SettingPermissionType;
};
export enum SettingPermissionType {
ADMIN_PANEL = 'ADMIN_PANEL',
API_KEYS_AND_WEBHOOKS = 'API_KEYS_AND_WEBHOOKS',
DATA_MODEL = 'DATA_MODEL',
ROLES = 'ROLES',
SECURITY = 'SECURITY',
WORKFLOWS = 'WORKFLOWS',
WORKSPACE = 'WORKSPACE',
WORKSPACE_MEMBERS = 'WORKSPACE_MEMBERS'
}
export type SetupOidcSsoInput = {
clientID: Scalars['String'];
clientSecret: Scalars['String'];
@ -2524,6 +2527,7 @@ export type UpdateRoleInput = {
};
export type UpdateRolePayload = {
canAccessAllTools?: InputMaybe<Scalars['Boolean']>;
canDestroyAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canReadAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
canSoftDeleteAllObjectRecords?: InputMaybe<Scalars['Boolean']>;
@ -2590,9 +2594,9 @@ export type UpsertObjectPermissionsInput = {
roleId: Scalars['String'];
};
export type UpsertSettingPermissionsInput = {
export type UpsertPermissionFlagsInput = {
permissionFlagKeys: Array<PermissionFlagType>;
roleId: Scalars['String'];
settingPermissionKeys: Array<SettingPermissionType>;
};
export type User = {
@ -2660,7 +2664,7 @@ export type UserWorkspace = {
objectPermissions?: Maybe<Array<ObjectPermission>>;
/** @deprecated Use objectPermissions instead */
objectRecordsPermissions?: Maybe<Array<PermissionsOnAllObjectRecords>>;
settingsPermissions?: Maybe<Array<SettingPermissionType>>;
settingsPermissions?: Maybe<Array<PermissionFlagType>>;
twoFactorAuthenticationMethodSummary?: Maybe<Array<TwoFactorAuthenticationMethodDto>>;
updatedAt: Scalars['DateTime'];
user: User;

View File

@ -4,7 +4,7 @@ import { Route, Routes } from 'react-router-dom';
import { SettingsProtectedRouteWrapper } from '@/settings/components/SettingsProtectedRouteWrapper';
import { SettingsSkeletonLoader } from '@/settings/components/SettingsSkeletonLoader';
import { SettingsPath } from '@/types/SettingsPath';
import { SettingPermissionType } from '~/generated/graphql';
import { PermissionFlagType } from '~/generated/graphql';
const SettingsApiKeys = lazy(() =>
import('~/pages/settings/developers/api-keys/SettingsApiKeys').then(
@ -405,7 +405,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.WORKSPACE}
settingsPermission={PermissionFlagType.WORKSPACE}
/>
}
>
@ -416,7 +416,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.WORKSPACE_MEMBERS}
settingsPermission={PermissionFlagType.WORKSPACE_MEMBERS}
/>
}
>
@ -428,7 +428,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.DATA_MODEL}
settingsPermission={PermissionFlagType.DATA_MODEL}
/>
}
>
@ -458,7 +458,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.ROLES}
settingsPermission={PermissionFlagType.ROLES}
/>
}
>
@ -480,7 +480,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.API_KEYS_AND_WEBHOOKS}
settingsPermission={PermissionFlagType.API_KEYS_AND_WEBHOOKS}
/>
}
>
@ -555,7 +555,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.SECURITY}
settingsPermission={PermissionFlagType.SECURITY}
/>
}
>
@ -587,7 +587,7 @@ export const SettingsRoutes = ({
<Route
element={
<SettingsProtectedRouteWrapper
settingsPermission={SettingPermissionType.WORKSPACE}
settingsPermission={PermissionFlagType.WORKSPACE}
/>
}
>

View File

@ -5,7 +5,7 @@ import { SettingsPath } from '@/types/SettingsPath';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import {
SettingPermissionType,
PermissionFlagType,
useBillingPortalSessionQuery,
} from '~/generated-metadata/graphql';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
@ -20,7 +20,7 @@ export const InformationBannerBillingSubscriptionPaused = () => {
});
const {
[SettingPermissionType.WORKSPACE]: hasPermissionToUpdateBillingDetails,
[PermissionFlagType.WORKSPACE]: hasPermissionToUpdateBillingDetails,
} = useSettingsPermissionMap();
const openBillingPortal = () => {

View File

@ -2,13 +2,13 @@ import { useEndSubscriptionTrialPeriod } from '@/billing/hooks/useEndSubscriptio
import { InformationBanner } from '@/information-banner/components/InformationBanner';
import { useSettingsPermissionMap } from '@/settings/roles/hooks/useSettingsPermissionMap';
import { useLingui } from '@lingui/react/macro';
import { SettingPermissionType } from '~/generated-metadata/graphql';
import { PermissionFlagType } from '~/generated-metadata/graphql';
export const InformationBannerEndTrialPeriod = () => {
const { endTrialPeriod, isLoading } = useEndSubscriptionTrialPeriod();
const { t } = useLingui();
const { [SettingPermissionType.WORKSPACE]: hasPermissionToEndTrialPeriod } =
const { [PermissionFlagType.WORKSPACE]: hasPermissionToEndTrialPeriod } =
useSettingsPermissionMap();
return (

View File

@ -5,7 +5,7 @@ import { SettingsPath } from '@/types/SettingsPath';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import {
SettingPermissionType,
PermissionFlagType,
useBillingPortalSessionQuery,
} from '~/generated-metadata/graphql';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
@ -20,7 +20,7 @@ export const InformationBannerFailPaymentInfo = () => {
});
const {
[SettingPermissionType.WORKSPACE]: hasPermissionToUpdateBillingDetails,
[PermissionFlagType.WORKSPACE]: hasPermissionToUpdateBillingDetails,
} = useSettingsPermissionMap();
const openBillingPortal = () => {

View File

@ -4,7 +4,7 @@ import { InformationBanner } from '@/information-banner/components/InformationBa
import { useSettingsPermissionMap } from '@/settings/roles/hooks/useSettingsPermissionMap';
import { SettingsPath } from '@/types/SettingsPath';
import { t } from '@lingui/core/macro';
import { SettingPermissionType } from '~/generated-metadata/graphql';
import { PermissionFlagType } from '~/generated-metadata/graphql';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const InformationBannerNoBillingSubscription = () => {
@ -15,7 +15,7 @@ export const InformationBannerNoBillingSubscription = () => {
successUrlPath: getSettingsPath(SettingsPath.Billing),
});
const { [SettingPermissionType.WORKSPACE]: hasPermissionToSubscribe } =
const { [PermissionFlagType.WORKSPACE]: hasPermissionToSubscribe } =
useSettingsPermissionMap();
return (

View File

@ -24,7 +24,7 @@ import {
IconEyeOff,
IconSettings,
} from 'twenty-ui/display';
import { SettingPermissionType } from '~/generated/graphql';
import { PermissionFlagType } from '~/generated/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
type UseRecordGroupActionsParams = {
@ -91,7 +91,7 @@ export const useRecordGroupActions = ({
]);
const hasAccessToDataModelSettings = useHasSettingsPermission(
SettingPermissionType.DATA_MODEL,
PermissionFlagType.DATA_MODEL,
);
const currentIndex = visibleRecordGroupIds.findIndex(
(id) => id === recordGroupDefinition.id,

View File

@ -3,12 +3,12 @@ import { SettingsPath } from '@/types/SettingsPath';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { ReactNode } from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { FeatureFlagKey, SettingPermissionType } from '~/generated/graphql';
import { FeatureFlagKey, PermissionFlagType } from '~/generated/graphql';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
type SettingsProtectedRouteWrapperProps = {
children?: ReactNode;
settingsPermission?: SettingPermissionType;
settingsPermission?: PermissionFlagType;
requiredFeatureFlag?: FeatureFlagKey;
};

View File

@ -7,7 +7,7 @@ import { MutableSnapshot, RecoilRoot } from 'recoil';
import {
Billing,
OnboardingStatus,
SettingPermissionType,
PermissionFlagType,
} from '~/generated/graphql';
import { currentUserState } from '@/auth/states/currentUserState';
@ -60,12 +60,12 @@ jest.mock('@/settings/roles/hooks/useSettingsPermissionMap', () => ({
describe('useSettingsNavigationItems', () => {
it('should hide workspace settings when no permissions', () => {
(useSettingsPermissionMap as jest.Mock).mockImplementation(() => ({
[SettingPermissionType.WORKSPACE]: false,
[SettingPermissionType.WORKSPACE_MEMBERS]: false,
[SettingPermissionType.DATA_MODEL]: false,
[SettingPermissionType.API_KEYS_AND_WEBHOOKS]: false,
[SettingPermissionType.ROLES]: false,
[SettingPermissionType.SECURITY]: false,
[PermissionFlagType.WORKSPACE]: false,
[PermissionFlagType.WORKSPACE_MEMBERS]: false,
[PermissionFlagType.DATA_MODEL]: false,
[PermissionFlagType.API_KEYS_AND_WEBHOOKS]: false,
[PermissionFlagType.ROLES]: false,
[PermissionFlagType.SECURITY]: false,
}));
const { result } = renderHook(() => useSettingsNavigationItems(), {
@ -81,12 +81,12 @@ describe('useSettingsNavigationItems', () => {
it('should show workspace settings when has permissions', () => {
(useSettingsPermissionMap as jest.Mock).mockImplementation(() => ({
[SettingPermissionType.WORKSPACE]: true,
[SettingPermissionType.WORKSPACE_MEMBERS]: true,
[SettingPermissionType.DATA_MODEL]: true,
[SettingPermissionType.API_KEYS_AND_WEBHOOKS]: true,
[SettingPermissionType.ROLES]: true,
[SettingPermissionType.SECURITY]: true,
[PermissionFlagType.WORKSPACE]: true,
[PermissionFlagType.WORKSPACE_MEMBERS]: true,
[PermissionFlagType.DATA_MODEL]: true,
[PermissionFlagType.API_KEYS_AND_WEBHOOKS]: true,
[PermissionFlagType.ROLES]: true,
[PermissionFlagType.SECURITY]: true,
}));
const { result } = renderHook(() => useSettingsNavigationItems(), {

View File

@ -30,7 +30,7 @@ import {
IconUsers,
IconWebhook,
} from 'twenty-ui/display';
import { SettingPermissionType } from '~/generated/graphql';
import { PermissionFlagType } from '~/generated/graphql';
export type SettingsNavigationSection = {
label: string;
@ -107,46 +107,45 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
label: t`General`,
path: SettingsPath.Workspace,
Icon: IconSettings,
isHidden: !permissionMap[SettingPermissionType.WORKSPACE],
isHidden: !permissionMap[PermissionFlagType.WORKSPACE],
},
{
label: t`Members`,
path: SettingsPath.WorkspaceMembersPage,
Icon: IconUsers,
isHidden: !permissionMap[SettingPermissionType.WORKSPACE_MEMBERS],
isHidden: !permissionMap[PermissionFlagType.WORKSPACE_MEMBERS],
},
{
label: t`Roles`,
path: SettingsPath.Roles,
Icon: IconLock,
isHidden: !permissionMap[SettingPermissionType.ROLES],
isHidden: !permissionMap[PermissionFlagType.ROLES],
},
{
label: t`Billing`,
path: SettingsPath.Billing,
Icon: IconCurrencyDollar,
isHidden:
!isBillingEnabled ||
!permissionMap[SettingPermissionType.WORKSPACE],
!isBillingEnabled || !permissionMap[PermissionFlagType.WORKSPACE],
},
{
label: t`Data model`,
path: SettingsPath.Objects,
Icon: IconHierarchy2,
isHidden: !permissionMap[SettingPermissionType.DATA_MODEL],
isHidden: !permissionMap[PermissionFlagType.DATA_MODEL],
},
{
label: t`Integrations`,
path: SettingsPath.Integrations,
Icon: IconApps,
isHidden: !permissionMap[SettingPermissionType.API_KEYS_AND_WEBHOOKS],
isHidden: !permissionMap[PermissionFlagType.API_KEYS_AND_WEBHOOKS],
},
{
label: t`Security`,
path: SettingsPath.Security,
Icon: IconKey,
isAdvanced: true,
isHidden: !permissionMap[SettingPermissionType.SECURITY],
isHidden: !permissionMap[PermissionFlagType.SECURITY],
},
],
},
@ -159,14 +158,14 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
path: SettingsPath.APIs,
Icon: IconApi,
isAdvanced: true,
isHidden: !permissionMap[SettingPermissionType.API_KEYS_AND_WEBHOOKS],
isHidden: !permissionMap[PermissionFlagType.API_KEYS_AND_WEBHOOKS],
},
{
label: t`Webhooks`,
path: SettingsPath.Webhooks,
Icon: IconWebhook,
isAdvanced: true,
isHidden: !permissionMap[SettingPermissionType.API_KEYS_AND_WEBHOOKS],
isHidden: !permissionMap[PermissionFlagType.API_KEYS_AND_WEBHOOKS],
},
{
label: t`Functions`,
@ -192,7 +191,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
Icon: IconFlask,
isHidden:
!labPublicFeatureFlags.length ||
!permissionMap[SettingPermissionType.WORKSPACE],
!permissionMap[PermissionFlagType.WORKSPACE],
},
{
label: t`Releases`,

View File

@ -0,0 +1,9 @@
import { gql } from '@apollo/client';
export const PERMISSION_FLAG_FRAGMENT = gql`
fragment PermissionFlagFragment on PermissionFlag {
id
flag
roleId
}
`;

View File

@ -7,6 +7,7 @@ export const ROLE_FRAGMENT = gql`
description
icon
canUpdateAllSettings
canAccessAllTools
isEditable
canReadAllObjectRecords
canUpdateAllObjectRecords

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const SETTING_PERMISSION_FRAGMENT = gql`
fragment SettingPermissionFragment on SettingPermission {
id
setting
roleId
}
`;

View File

@ -0,0 +1,15 @@
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
}
}
`;

View File

@ -1,15 +0,0 @@
import { SETTING_PERMISSION_FRAGMENT } from '@/settings/roles/graphql/fragments/settingPermissionFragment';
import { gql } from '@apollo/client';
export const UPSERT_SETTING_PERMISSIONS = gql`
${SETTING_PERMISSION_FRAGMENT}
mutation UpsertSettingPermissions(
$upsertSettingPermissionsInput: UpsertSettingPermissionsInput!
) {
upsertSettingPermissions(
upsertSettingPermissionsInput: $upsertSettingPermissionsInput
) {
...SettingPermissionFragment
}
}
`;

View File

@ -1,13 +1,13 @@
import { OBJECT_PERMISSION_FRAGMENT } from '@/settings/roles/graphql/fragments/objectPermissionFragment';
import { PERMISSION_FLAG_FRAGMENT } from '@/settings/roles/graphql/fragments/permissionFlagFragment';
import { ROLE_FRAGMENT } from '@/settings/roles/graphql/fragments/roleFragment';
import { SETTING_PERMISSION_FRAGMENT } from '@/settings/roles/graphql/fragments/settingPermissionFragment';
import { WORKSPACE_MEMBER_QUERY_FRAGMENT } from '@/workspace-member/graphql/fragments/workspaceMemberQueryFragment';
import { gql } from '@apollo/client';
export const GET_ROLES = gql`
${WORKSPACE_MEMBER_QUERY_FRAGMENT}
${ROLE_FRAGMENT}
${SETTING_PERMISSION_FRAGMENT}
${PERMISSION_FLAG_FRAGMENT}
${OBJECT_PERMISSION_FRAGMENT}
query GetRoles {
getRoles {
@ -15,8 +15,8 @@ export const GET_ROLES = gql`
workspaceMembers {
...WorkspaceMemberQueryFragment
}
settingPermissions {
...SettingPermissionFragment
permissionFlags {
...PermissionFlagFragment
}
objectPermissions {
...ObjectPermissionFragment

View File

@ -2,20 +2,20 @@ import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceSta
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useRecoilValue } from 'recoil';
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { SettingPermissionType } from '~/generated/graphql';
import { PermissionFlagType } from '~/generated/graphql';
export const useHasSettingsPermission = (
settingsPermission?: SettingPermissionType,
permissionFlag?: PermissionFlagType,
) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const currentUserWorkspace = useRecoilValue(currentUserWorkspaceState);
if (!settingsPermission) {
if (!permissionFlag) {
return true;
}
if (
settingsPermission === SettingPermissionType.WORKSPACE &&
permissionFlag === PermissionFlagType.WORKSPACE &&
currentWorkspace?.activationStatus ===
WorkspaceActivationStatus.PENDING_CREATION
) {
@ -28,5 +28,5 @@ export const useHasSettingsPermission = (
return false;
}
return currentUserWorkspaceSetting.includes(settingsPermission);
return currentUserWorkspaceSetting.includes(permissionFlag);
};

View File

@ -1,10 +1,10 @@
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
import { useRecoilValue } from 'recoil';
import { SettingPermissionType } from '~/generated/graphql';
import { PermissionFlagType } from '~/generated/graphql';
import { buildRecordFromKeysWithSameValue } from '~/utils/array/buildRecordFromKeysWithSameValue';
export const useSettingsPermissionMap = (): Record<
SettingPermissionType,
PermissionFlagType,
boolean
> => {
const currentUserWorkspace = useRecoilValue(currentUserWorkspaceState);
@ -13,7 +13,7 @@ export const useSettingsPermissionMap = (): Record<
currentUserWorkspace?.settingsPermissions;
const initialPermissions = buildRecordFromKeysWithSameValue(
Object.values(SettingPermissionType),
Object.values(PermissionFlagType),
false,
);

View File

@ -1,6 +1,7 @@
import { SettingsRolePermissionsObjectLevelSection } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelSection';
import { SettingsRolePermissionsObjectsSection } from '@/settings/roles/role-permissions/objects-permissions/components/SettingsRolePermissionsObjectsSection';
import { SettingsRolePermissionsSettingsSection } from '@/settings/roles/role-permissions/settings-permissions/components/SettingsRolePermissionsSettingsSection';
import { SettingsRolePermissionsSettingsSection } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsSection';
import { SettingsRolePermissionsToolSection } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsToolSection';
import styled from '@emotion/styled';
const StyledRolePermissionsContainer = styled.div`
@ -32,6 +33,10 @@ export const SettingsRolePermissions = ({
roleId={roleId}
isEditable={isEditable}
/>
<SettingsRolePermissionsToolSection
roleId={roleId}
isEditable={isEditable}
/>
</StyledRolePermissionsContainer>
);
};

View File

@ -1,7 +1,7 @@
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
import { SettingsRolePermissionsSettingsTableHeader } from '@/settings/roles/role-permissions/settings-permissions/components/SettingsRolePermissionsSettingsTableHeader';
import { SettingsRolePermissionsSettingsTableRow } from '@/settings/roles/role-permissions/settings-permissions/components/SettingsRolePermissionsSettingsTableRow';
import { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/settings-permissions/types/SettingsRolePermissionsSettingPermission';
import { SettingsRolePermissionsSettingsTableHeader } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsTableHeader';
import { SettingsRolePermissionsSettingsTableRow } from '@/settings/roles/role-permissions/permission-flags/components/SettingsRolePermissionsSettingsTableRow';
import { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/permission-flags/types/SettingsRolePermissionsSettingPermission';
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
@ -17,7 +17,7 @@ import {
IconUsers,
} from 'twenty-ui/display';
import { AnimatedExpandableContainer, Card, Section } from 'twenty-ui/layout';
import { SettingPermissionType } from '~/generated-metadata/graphql';
import { PermissionFlagType } from '~/generated-metadata/graphql';
const StyledTable = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
@ -48,43 +48,43 @@ export const SettingsRolePermissionsSettingsSection = ({
const settingsPermissionsConfig: SettingsRolePermissionsSettingPermission[] =
[
{
key: SettingPermissionType.API_KEYS_AND_WEBHOOKS,
key: PermissionFlagType.API_KEYS_AND_WEBHOOKS,
name: t`API Keys & Webhooks`,
description: t`Manage API keys and webhooks`,
Icon: IconCode,
},
{
key: SettingPermissionType.WORKSPACE,
key: PermissionFlagType.WORKSPACE,
name: t`Workspace`,
description: t`Set global workspace preferences`,
Icon: IconSettings,
},
{
key: SettingPermissionType.WORKSPACE_MEMBERS,
key: PermissionFlagType.WORKSPACE_MEMBERS,
name: t`Users`,
description: t`Add or remove users`,
Icon: IconUsers,
},
{
key: SettingPermissionType.ROLES,
key: PermissionFlagType.ROLES,
name: t`Roles`,
description: t`Define user roles and access levels`,
Icon: IconLockOpen,
},
{
key: SettingPermissionType.DATA_MODEL,
key: PermissionFlagType.DATA_MODEL,
name: t`Data Model`,
description: t`Edit CRM data structure and fields`,
Icon: IconHierarchy,
},
{
key: SettingPermissionType.SECURITY,
key: PermissionFlagType.SECURITY,
name: t`Security`,
description: t`Manage security policies`,
Icon: IconKey,
},
{
key: SettingPermissionType.WORKFLOWS,
key: PermissionFlagType.WORKFLOWS,
name: t`Workflows`,
description: t`Manage workflows`,
Icon: IconSettingsAutomation,

View File

@ -4,7 +4,7 @@ import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { Checkbox } from 'twenty-ui/input';
import { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/settings-permissions/types/SettingsRolePermissionsSettingPermission';
import { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/permission-flags/types/SettingsRolePermissionsSettingPermission';
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
import { useRecoilState } from 'recoil';
import { v4 } from 'uuid';
@ -32,15 +32,15 @@ export const SettingsRolePermissionsSettingsTableHeader = ({
);
const allSettingsPermissionsEnabled = settingsPermissionsConfig.every(
(permission) =>
settingsDraftRole.settingPermissions?.some(
(settingPermission) => settingPermission.setting === permission.key,
settingsDraftRole.permissionFlags?.some(
(permissionFlag) => permissionFlag.flag === permission.key,
),
);
const someSettingsPermissionsEnabled = settingsPermissionsConfig.some(
(permission) =>
settingsDraftRole.settingPermissions?.some(
(settingPermission) => settingPermission.setting === permission.key,
settingsDraftRole.permissionFlags?.some(
(permissionFlag) => permissionFlag.flag === permission.key,
),
);
@ -61,10 +61,10 @@ export const SettingsRolePermissionsSettingsTableHeader = ({
setSettingsDraftRole({
...settingsDraftRole,
settingPermissions: newValue
permissionFlags: newValue
? settingsPermissionsConfig.map((permission) => ({
id: v4(),
setting: permission.key,
flag: permission.key,
roleId,
}))
: [],

View File

@ -1,4 +1,4 @@
import { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/settings-permissions/types/SettingsRolePermissionsSettingPermission';
import { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/permission-flags/types/SettingsRolePermissionsSettingPermission';
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
@ -44,6 +44,7 @@ type SettingsRolePermissionsSettingsTableRowProps = {
roleId: string;
permission: SettingsRolePermissionsSettingPermission;
isEditable: boolean;
isToolPermission?: boolean;
};
export const SettingsRolePermissionsSettingsTableRow = ({
@ -55,27 +56,35 @@ export const SettingsRolePermissionsSettingsTableRow = ({
const [settingsDraftRole, setSettingsDraftRole] = useRecoilState(
settingsDraftRoleFamilyState(roleId),
);
const canUpdateAllSettings = settingsDraftRole.canUpdateAllSettings;
const isSettingPermissionEnabled =
settingsDraftRole.settingPermissions?.some(
(settingPermission) => settingPermission.setting === permission.key,
const isPermissionEnabled =
settingsDraftRole.permissionFlags?.some(
(permissionFlag) => permissionFlag.flag === permission.key,
) ?? false;
const isChecked = isSettingPermissionEnabled || canUpdateAllSettings;
const isDisabled = !isEditable || canUpdateAllSettings;
const isAllSettingsOverride =
!permission.isToolPermission &&
settingsDraftRole.canUpdateAllSettings === true;
const isAllToolsOverride =
permission.isToolPermission && settingsDraftRole.canAccessAllTools === true;
const isChecked = Boolean(
isPermissionEnabled || isAllSettingsOverride || isAllToolsOverride,
);
const isDisabled = Boolean(
!isEditable || isAllSettingsOverride || isAllToolsOverride,
);
const handleChange = (value: boolean) => {
const currentPermissions = settingsDraftRole.settingPermissions ?? [];
const currentPermissions = settingsDraftRole.permissionFlags ?? [];
if (value === true) {
setSettingsDraftRole({
...settingsDraftRole,
settingPermissions: [
permissionFlags: [
...currentPermissions,
{
id: v4(),
setting: permission.key,
flag: permission.key,
roleId,
},
],
@ -83,8 +92,8 @@ export const SettingsRolePermissionsSettingsTableRow = ({
} else {
setSettingsDraftRole({
...settingsDraftRole,
settingPermissions: currentPermissions.filter(
(p) => p.setting !== permission.key,
permissionFlags: currentPermissions.filter(
(p) => p.flag !== permission.key,
),
});
}

View File

@ -0,0 +1,101 @@
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 { SettingsRolePermissionsSettingPermission } from '@/settings/roles/role-permissions/permission-flags/types/SettingsRolePermissionsSettingPermission';
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { useRecoilState } from 'recoil';
import { H2Title, IconMail, IconTool } from 'twenty-ui/display';
import { AnimatedExpandableContainer, Card, Section } from 'twenty-ui/layout';
import { PermissionFlagType } from '~/generated-metadata/graphql';
const StyledTable = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
`;
const StyledTableRows = styled.div`
padding-bottom: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(2)};
`;
const StyledCard = styled(Card)`
margin-bottom: ${({ theme }) => theme.spacing(4)};
`;
type SettingsRolePermissionsToolSectionProps = {
roleId: string;
isEditable: boolean;
};
export const SettingsRolePermissionsToolSection = ({
roleId,
isEditable,
}: SettingsRolePermissionsToolSectionProps) => {
const [settingsDraftRole, setSettingsDraftRole] = useRecoilState(
settingsDraftRoleFamilyState(roleId),
);
const toolPermissionsConfig: SettingsRolePermissionsSettingPermission[] = [
{
key: PermissionFlagType.SEND_EMAIL_TOOL,
name: t`Send Email`,
description: t`Allow sending emails using connected accounts`,
Icon: IconMail,
isToolPermission: true,
},
];
return (
<Section>
<H2Title
title={t`Action Permissions`}
description={t`Permissions for performing automated actions.`}
/>
<StyledCard rounded>
<SettingsOptionCardContentToggle
Icon={IconTool}
title={t`All Actions Access`}
description={t`Grants permission to perform all available actions without restriction.`}
checked={settingsDraftRole.canAccessAllTools}
disabled={!isEditable}
onChange={() => {
setSettingsDraftRole({
...settingsDraftRole,
canAccessAllTools: !settingsDraftRole.canAccessAllTools,
});
}}
/>
</StyledCard>
<AnimatedExpandableContainer
isExpanded={!settingsDraftRole.canAccessAllTools}
dimension="height"
animationDurations={{
opacity: 0.2,
size: 0.4,
}}
mode="scroll-height"
containAnimation={false}
>
<StyledTable>
<SettingsRolePermissionsSettingsTableHeader
roleId={roleId}
settingsPermissionsConfig={toolPermissionsConfig}
isEditable={isEditable}
/>
<StyledTableRows>
{toolPermissionsConfig.map((permission) => (
<SettingsRolePermissionsSettingsTableRow
key={permission.key}
roleId={roleId}
permission={permission}
isEditable={isEditable}
/>
))}
</StyledTableRows>
</StyledTable>
</AnimatedExpandableContainer>
</Section>
);
};

View File

@ -1,9 +1,10 @@
import { IconComponent } from 'twenty-ui/display';
import { SettingPermissionType } from '~/generated-metadata/graphql';
import { PermissionFlagType } from '~/generated-metadata/graphql';
export type SettingsRolePermissionsSettingPermission = {
key: SettingPermissionType;
key: PermissionFlagType;
name: string;
description: string;
Icon: IconComponent;
isToolPermission?: boolean;
};

View File

@ -28,7 +28,7 @@ import {
useCreateOneRoleMutation,
useUpdateOneRoleMutation,
useUpsertObjectPermissionsMutation,
useUpsertSettingPermissionsMutation,
useUpsertPermissionFlagsMutation,
} from '~/generated-metadata/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getDirtyFields } from '~/utils/getDirtyFields';
@ -45,6 +45,7 @@ const ROLE_BASIC_KEYS: Array<keyof Role> = [
'description',
'icon',
'canUpdateAllSettings',
'canAccessAllTools',
'canReadAllObjectRecords',
'canUpdateAllObjectRecords',
'canSoftDeleteAllObjectRecords',
@ -61,7 +62,7 @@ export const SettingsRole = ({ roleId, isCreateMode }: SettingsRoleProps) => {
const [createRole] = useCreateOneRoleMutation();
const [updateRole] = useUpdateOneRoleMutation();
const [upsertSettingPermissions] = useUpsertSettingPermissionsMutation();
const [upsertPermissionFlags] = useUpsertPermissionFlagsMutation();
const [upsertObjectPermissions] = useUpsertObjectPermissionsMutation();
const [isSaving, setIsSaving] = useState(false);
@ -144,6 +145,7 @@ export const SettingsRole = ({ roleId, isCreateMode }: SettingsRoleProps) => {
description: settingsDraftRole.description,
icon: settingsDraftRole.icon,
canUpdateAllSettings: settingsDraftRole.canUpdateAllSettings,
canAccessAllTools: settingsDraftRole.canAccessAllTools,
canReadAllObjectRecords:
settingsDraftRole.canReadAllObjectRecords,
canUpdateAllObjectRecords:
@ -161,14 +163,14 @@ export const SettingsRole = ({ roleId, isCreateMode }: SettingsRoleProps) => {
return;
}
if (isDefined(dirtyFields.settingPermissions)) {
await upsertSettingPermissions({
if (isDefined(dirtyFields.permissionFlags)) {
await upsertPermissionFlags({
variables: {
upsertSettingPermissionsInput: {
upsertPermissionFlagsInput: {
roleId: data.createOneRole.id,
settingPermissionKeys:
settingsDraftRole.settingPermissions?.map(
(settingPermission) => settingPermission.setting,
permissionFlagKeys:
settingsDraftRole.permissionFlags?.map(
(permissionFlag) => permissionFlag.flag,
) ?? [],
},
},
@ -214,14 +216,14 @@ export const SettingsRole = ({ roleId, isCreateMode }: SettingsRoleProps) => {
roleId: data.createOneRole.id,
});
} else {
if (isDefined(dirtyFields.settingPermissions)) {
await upsertSettingPermissions({
if (isDefined(dirtyFields.permissionFlags)) {
await upsertPermissionFlags({
variables: {
upsertSettingPermissionsInput: {
upsertPermissionFlagsInput: {
roleId: roleId,
settingPermissionKeys:
settingsDraftRole.settingPermissions?.map(
(settingPermission) => settingPermission.setting,
permissionFlagKeys:
settingsDraftRole.permissionFlags?.map(
(permissionFlag) => permissionFlag.flag,
) ?? [],
},
},
@ -239,6 +241,7 @@ export const SettingsRole = ({ roleId, isCreateMode }: SettingsRoleProps) => {
description: settingsDraftRole.description,
icon: settingsDraftRole.icon,
canUpdateAllSettings: settingsDraftRole.canUpdateAllSettings,
canAccessAllTools: settingsDraftRole.canAccessAllTools,
canReadAllObjectRecords:
settingsDraftRole.canReadAllObjectRecords,
canUpdateAllObjectRecords:

View File

@ -42,6 +42,7 @@ export const SettingsRoleCreateEffect = ({
description: '',
icon: 'IconUser',
canUpdateAllSettings: true,
canAccessAllTools: true,
canReadAllObjectRecords: true,
canUpdateAllObjectRecords: true,
canSoftDeleteAllObjectRecords: true,

View File

@ -13,9 +13,10 @@ export const settingsDraftRoleFamilyState = createFamilyState<Role, string>({
canSoftDeleteAllObjectRecords: false,
canUpdateAllObjectRecords: false,
canUpdateAllSettings: false,
canAccessAllTools: false,
isEditable: false,
workspaceMembers: [],
settingPermissions: [],
permissionFlags: [],
objectPermissions: [],
},
});

View File

@ -11,6 +11,7 @@ const rolesMock: Role[] = [
canSoftDeleteAllObjectRecords: true,
canUpdateAllObjectRecords: true,
canUpdateAllSettings: true,
canAccessAllTools: true,
isEditable: false,
workspaceMembers: [mockWorkspaceMembers[0]],
},
@ -23,6 +24,7 @@ const rolesMock: Role[] = [
canSoftDeleteAllObjectRecords: false,
canUpdateAllObjectRecords: false,
canUpdateAllSettings: false,
canAccessAllTools: false,
isEditable: true,
workspaceMembers: [mockWorkspaceMembers[1]],
},

View File

@ -3,7 +3,7 @@ import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import {
FeatureFlagKey,
OnboardingStatus,
SettingPermissionType,
PermissionFlagType,
SubscriptionInterval,
SubscriptionStatus,
User,
@ -125,7 +125,7 @@ export const mockedUserData: MockedUser = {
workspaceMember: mockedWorkspaceMemberData,
currentWorkspace: mockCurrentWorkspace,
currentUserWorkspace: {
settingsPermissions: [SettingPermissionType.WORKSPACE_MEMBERS],
settingsPermissions: [PermissionFlagType.WORKSPACE_MEMBERS],
objectPermissions: generatedMockObjectMetadataItems.map((item) => ({
objectMetadataId: item.id,
canReadObjectRecords: true,