[permissions] Add object records permissions to role entity (#10255)
Closes https://github.com/twentyhq/core-team-issues/issues/388 - Add object records-related permissions to role entity - Add it to queriable `currentUserWorkspace` (used in FE)
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
||||||
|
import { PermissionsOnAllObjectRecords } from 'twenty-shared';
|
||||||
export type Maybe<T> = T | null;
|
export type Maybe<T> = T | null;
|
||||||
export type InputMaybe<T> = Maybe<T>;
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
@ -2050,6 +2051,7 @@ export type UserWorkspace = {
|
|||||||
deletedAt?: Maybe<Scalars['DateTime']['output']>;
|
deletedAt?: Maybe<Scalars['DateTime']['output']>;
|
||||||
id: Scalars['UUID']['output'];
|
id: Scalars['UUID']['output'];
|
||||||
settingsPermissions?: Maybe<Array<SettingsFeatures>>;
|
settingsPermissions?: Maybe<Array<SettingsFeatures>>;
|
||||||
|
objectRecordsPermissions?: Maybe<Array<PermissionsOnAllObjectRecords>>;
|
||||||
updatedAt: Scalars['DateTime']['output'];
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
user: User;
|
user: User;
|
||||||
userId: Scalars['String']['output'];
|
userId: Scalars['String']['output'];
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import * as Apollo from '@apollo/client';
|
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
import * as Apollo from '@apollo/client';
|
||||||
export type Maybe<T> = T | null;
|
export type Maybe<T> = T | null;
|
||||||
export type InputMaybe<T> = Maybe<T>;
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
@ -1172,6 +1172,13 @@ export type PageInfo = {
|
|||||||
startCursor?: Maybe<Scalars['ConnectionCursor']>;
|
startCursor?: Maybe<Scalars['ConnectionCursor']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum PermissionsOnAllObjectRecords {
|
||||||
|
DESTROY_ALL_OBJECT_RECORDS = 'DESTROY_ALL_OBJECT_RECORDS',
|
||||||
|
READ_ALL_OBJECT_RECORDS = 'READ_ALL_OBJECT_RECORDS',
|
||||||
|
SOFT_DELETE_ALL_OBJECT_RECORDS = 'SOFT_DELETE_ALL_OBJECT_RECORDS',
|
||||||
|
UPDATE_ALL_OBJECT_RECORDS = 'UPDATE_ALL_OBJECT_RECORDS'
|
||||||
|
}
|
||||||
|
|
||||||
export type PostgresCredentials = {
|
export type PostgresCredentials = {
|
||||||
__typename?: 'PostgresCredentials';
|
__typename?: 'PostgresCredentials';
|
||||||
id: Scalars['UUID'];
|
id: Scalars['UUID'];
|
||||||
@ -1428,6 +1435,10 @@ export type ResendEmailVerificationTokenOutput = {
|
|||||||
|
|
||||||
export type Role = {
|
export type Role = {
|
||||||
__typename?: 'Role';
|
__typename?: 'Role';
|
||||||
|
canDestroyAllObjectRecords: Scalars['Boolean'];
|
||||||
|
canReadAllObjectRecords: Scalars['Boolean'];
|
||||||
|
canSoftDeleteAllObjectRecords: Scalars['Boolean'];
|
||||||
|
canUpdateAllObjectRecords: Scalars['Boolean'];
|
||||||
canUpdateAllSettings: Scalars['Boolean'];
|
canUpdateAllSettings: Scalars['Boolean'];
|
||||||
description?: Maybe<Scalars['String']>;
|
description?: Maybe<Scalars['String']>;
|
||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
@ -1827,6 +1838,7 @@ export type UserWorkspace = {
|
|||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
deletedAt?: Maybe<Scalars['DateTime']>;
|
deletedAt?: Maybe<Scalars['DateTime']>;
|
||||||
id: Scalars['UUID'];
|
id: Scalars['UUID'];
|
||||||
|
objectRecordsPermissions?: Maybe<Array<PermissionsOnAllObjectRecords>>;
|
||||||
settingsPermissions?: Maybe<Array<SettingsFeatures>>;
|
settingsPermissions?: Maybe<Array<SettingsFeatures>>;
|
||||||
updatedAt: Scalars['DateTime'];
|
updatedAt: Scalars['DateTime'];
|
||||||
user: User;
|
user: User;
|
||||||
@ -2292,7 +2304,7 @@ export type ListSsoIdentityProvidersByWorkspaceIdQueryVariables = Exact<{ [key:
|
|||||||
|
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdQuery = { __typename?: 'Query', listSSOIdentityProvidersByWorkspaceId: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> };
|
export type ListSsoIdentityProvidersByWorkspaceIdQuery = { __typename?: 'Query', listSSOIdentityProvidersByWorkspaceId: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> };
|
||||||
|
|
||||||
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | 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, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingsFeatures> | 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, metadataVersion: number, workspaceMembersCount?: number | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, subdomain: string, customDomain?: string | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null } } | null }> };
|
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | 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, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingsFeatures> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | 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, metadataVersion: number, workspaceMembersCount?: number | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, subdomain: string, customDomain?: string | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null } } | null }> };
|
||||||
|
|
||||||
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
|
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
@ -2309,7 +2321,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf
|
|||||||
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | 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, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingsFeatures> | 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, metadataVersion: number, workspaceMembersCount?: number | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, subdomain: string, customDomain?: string | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null } } | null }> } };
|
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | 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, currentUserWorkspace?: { __typename?: 'UserWorkspace', settingsPermissions?: Array<SettingsFeatures> | null, objectRecordsPermissions?: Array<PermissionsOnAllObjectRecords> | 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, metadataVersion: number, workspaceMembersCount?: number | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, subdomain: string, customDomain?: string | null, workspaceUrls: { __typename?: 'workspaceUrls', subdomainUrl: string, customUrl?: string | null } } | null }> } };
|
||||||
|
|
||||||
export type ActivateWorkflowVersionMutationVariables = Exact<{
|
export type ActivateWorkflowVersionMutationVariables = Exact<{
|
||||||
workflowVersionId: Scalars['String'];
|
workflowVersionId: Scalars['String'];
|
||||||
@ -2582,6 +2594,7 @@ export const UserQueryFragmentFragmentDoc = gql`
|
|||||||
}
|
}
|
||||||
currentUserWorkspace {
|
currentUserWorkspace {
|
||||||
settingsPermissions
|
settingsPermissions
|
||||||
|
objectRecordsPermissions
|
||||||
}
|
}
|
||||||
currentWorkspace {
|
currentWorkspace {
|
||||||
id
|
id
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType, PermissionsOnAllObjectRecords } from '~/generated/graphql';
|
||||||
|
|
||||||
export const FIELD_METADATA_ID = '2c43466a-fe9e-4005-8d08-c5836067aa6c';
|
export const FIELD_METADATA_ID = '2c43466a-fe9e-4005-8d08-c5836067aa6c';
|
||||||
export const FIELD_RELATION_METADATA_ID =
|
export const FIELD_RELATION_METADATA_ID =
|
||||||
@ -147,6 +147,7 @@ export const queries = {
|
|||||||
}
|
}
|
||||||
currentUserWorkspace {
|
currentUserWorkspace {
|
||||||
settingsPermissions
|
settingsPermissions
|
||||||
|
objectRecordsPermissions
|
||||||
}
|
}
|
||||||
currentWorkspace {
|
currentWorkspace {
|
||||||
id
|
id
|
||||||
@ -310,6 +311,12 @@ export const responseData = {
|
|||||||
workspaceMembers: [],
|
workspaceMembers: [],
|
||||||
currentUserWorkspace: {
|
currentUserWorkspace: {
|
||||||
settingsPermissions: ['DATA_MODEL'],
|
settingsPermissions: ['DATA_MODEL'],
|
||||||
|
objectRecordsPermissions: [
|
||||||
|
PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS,
|
||||||
|
PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS,
|
||||||
|
PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS,
|
||||||
|
PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
currentWorkspace: {
|
currentWorkspace: {
|
||||||
id: 'test-workspace-id',
|
id: 'test-workspace-id',
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export const USER_QUERY_FRAGMENT = gql`
|
|||||||
}
|
}
|
||||||
currentUserWorkspace {
|
currentUserWorkspace {
|
||||||
settingsPermissions
|
settingsPermissions
|
||||||
|
objectRecordsPermissions
|
||||||
}
|
}
|
||||||
currentWorkspace {
|
currentWorkspace {
|
||||||
id
|
id
|
||||||
|
|||||||
@ -2,20 +2,6 @@ import { DataSource } from 'typeorm';
|
|||||||
|
|
||||||
const tableName = 'featureFlag';
|
const tableName = 'featureFlag';
|
||||||
|
|
||||||
// export const seedFeatureFlags = async (
|
|
||||||
// workspaceDataSource: DataSource,
|
|
||||||
// schemaName: string,
|
|
||||||
// workspaceId: string,
|
|
||||||
// ) => {
|
|
||||||
// await workspaceDataSource
|
|
||||||
// .createQueryBuilder()
|
|
||||||
// .insert()
|
|
||||||
// .into(`${schemaName}.${tableName}`, ['key', 'workspaceId', 'value'])
|
|
||||||
// .orIgnore()
|
|
||||||
// .values([])
|
|
||||||
// .execute();
|
|
||||||
// };
|
|
||||||
|
|
||||||
export const deleteFeatureFlags = async (
|
export const deleteFeatureFlags = async (
|
||||||
workspaceDataSource: DataSource,
|
workspaceDataSource: DataSource,
|
||||||
schemaName: string,
|
schemaName: string,
|
||||||
|
|||||||
@ -80,6 +80,11 @@ export const seedFeatureFlags = async (
|
|||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: FeatureFlagKey.IsPermissionsEnabled,
|
||||||
|
workspaceId: workspaceId,
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
])
|
])
|
||||||
.execute();
|
.execute();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const DEV_SEED_USER_WORKSPACE_IDS = {
|
|||||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b035',
|
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b035',
|
||||||
JONY: '20202020-3957-4908-9c36-2929a23f8353',
|
JONY: '20202020-3957-4908-9c36-2929a23f8353',
|
||||||
PHIL: '20202020-7169-42cf-bc47-1cfef15264b1',
|
PHIL: '20202020-7169-42cf-bc47-1cfef15264b1',
|
||||||
TIM_ACME: '20202020-9e3b-46d4-a556-88b9ddc2b436',
|
TIM_ACME: '20202020-e10a-4c27-a90b-b08c57b02d44',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const seedUserWorkspaces = async (
|
export const seedUserWorkspaces = async (
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateRoleTable1739795699972 implements MigrationInterface {
|
||||||
|
name = 'UpdateRoleTable1739795699972';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" ADD "canReadAllObjectRecords" boolean NOT NULL DEFAULT false`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" ADD "canUpdateAllObjectRecords" boolean NOT NULL DEFAULT false`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" ADD "canSoftDeleteAllObjectRecords" boolean NOT NULL DEFAULT false`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" ADD "canDestroyAllObjectRecords" boolean NOT NULL DEFAULT false`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" DROP COLUMN "canDestroyAllObjectRecords"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" DROP COLUMN "canSoftDeleteAllObjectRecords"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" DROP COLUMN "canUpdateAllObjectRecords"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "metadata"."role" DROP COLUMN "canReadAllObjectRecords"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -199,6 +199,7 @@ export abstract class GraphqlQueryBaseResolverService<
|
|||||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||||
userWorkspaceId: authContext.userWorkspaceId,
|
userWorkspaceId: authContext.userWorkspaceId,
|
||||||
_setting: permissionRequired,
|
_setting: permissionRequired,
|
||||||
|
workspaceId: authContext.workspace.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!userHasPermission) {
|
if (!userHasPermission) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||||
|
|
||||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||||
import { SettingsFeatures } from 'twenty-shared';
|
import { PermissionsOnAllObjectRecords, SettingsFeatures } from 'twenty-shared';
|
||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
@ -25,6 +25,10 @@ registerEnumType(SettingsFeatures, {
|
|||||||
name: 'SettingsFeatures',
|
name: 'SettingsFeatures',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerEnumType(PermissionsOnAllObjectRecords, {
|
||||||
|
name: 'PermissionsOnAllObjectRecords',
|
||||||
|
});
|
||||||
|
|
||||||
@Entity({ name: 'userWorkspace', schema: 'core' })
|
@Entity({ name: 'userWorkspace', schema: 'core' })
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
@Unique('IndexOnUserIdAndWorkspaceIdUnique', ['userId', 'workspaceId'])
|
@Unique('IndexOnUserIdAndWorkspaceIdUnique', ['userId', 'workspaceId'])
|
||||||
@ -75,4 +79,7 @@ export class UserWorkspace {
|
|||||||
|
|
||||||
@Field(() => [SettingsFeatures], { nullable: true })
|
@Field(() => [SettingsFeatures], { nullable: true })
|
||||||
settingsPermissions?: SettingsFeatures[];
|
settingsPermissions?: SettingsFeatures[];
|
||||||
|
|
||||||
|
@Field(() => [PermissionsOnAllObjectRecords], { nullable: true })
|
||||||
|
objectRecordsPermissions?: PermissionsOnAllObjectRecords[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import crypto from 'crypto';
|
|||||||
|
|
||||||
import { GraphQLJSONObject } from 'graphql-type-json';
|
import { GraphQLJSONObject } from 'graphql-type-json';
|
||||||
import { FileUpload, GraphQLUpload } from 'graphql-upload';
|
import { FileUpload, GraphQLUpload } from 'graphql-upload';
|
||||||
import { SettingsFeatures } from 'twenty-shared';
|
import { PermissionsOnAllObjectRecords, SettingsFeatures } from 'twenty-shared';
|
||||||
import { In, Repository } from 'typeorm';
|
import { In, Repository } from 'typeorm';
|
||||||
|
|
||||||
import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface';
|
import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface';
|
||||||
@ -113,16 +113,23 @@ export class UserResolver {
|
|||||||
if (!currentUserWorkspace) {
|
if (!currentUserWorkspace) {
|
||||||
throw new Error('Current user workspace not found');
|
throw new Error('Current user workspace not found');
|
||||||
}
|
}
|
||||||
const permissions =
|
const { settingsPermissions, objectRecordsPermissions } =
|
||||||
await this.permissionsService.getUserWorkspaceSettingsPermissions({
|
await this.permissionsService.getUserWorkspacePermissions({
|
||||||
userWorkspaceId: currentUserWorkspace.id,
|
userWorkspaceId: currentUserWorkspace.id,
|
||||||
|
workspaceId: workspace.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const permittedFeatures: SettingsFeatures[] = (
|
const permittedFeatures: SettingsFeatures[] = (
|
||||||
Object.keys(permissions) as SettingsFeatures[]
|
Object.keys(settingsPermissions) as SettingsFeatures[]
|
||||||
).filter((feature) => permissions[feature] === true);
|
).filter((feature) => settingsPermissions[feature] === true);
|
||||||
|
|
||||||
|
const permittedObjectRecordsPermissions = (
|
||||||
|
Object.keys(objectRecordsPermissions) as PermissionsOnAllObjectRecords[]
|
||||||
|
).filter((permission) => objectRecordsPermissions[permission] === true);
|
||||||
|
|
||||||
currentUserWorkspace.settingsPermissions = permittedFeatures;
|
currentUserWorkspace.settingsPermissions = permittedFeatures;
|
||||||
|
currentUserWorkspace.objectRecordsPermissions =
|
||||||
|
permittedObjectRecordsPermissions;
|
||||||
user.currentUserWorkspace = currentUserWorkspace;
|
user.currentUserWorkspace = currentUserWorkspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,9 +223,12 @@ export class UserResolver {
|
|||||||
);
|
);
|
||||||
|
|
||||||
rolesByUserWorkspaces =
|
rolesByUserWorkspaces =
|
||||||
await this.userRoleService.getRolesByUserWorkspaces(
|
await this.userRoleService.getRolesByUserWorkspaces({
|
||||||
userWorkspaces.map((userWorkspace) => userWorkspace.id),
|
userWorkspaceIds: userWorkspaces.map(
|
||||||
);
|
(userWorkspace) => userWorkspace.id,
|
||||||
|
),
|
||||||
|
workspaceId: workspace.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const workspaceMemberEntity of workspaceMemberEntities) {
|
for (const workspaceMemberEntity of workspaceMemberEntities) {
|
||||||
@ -254,6 +264,11 @@ export class UserResolver {
|
|||||||
description: roleEntity.description,
|
description: roleEntity.description,
|
||||||
isEditable: roleEntity.isEditable,
|
isEditable: roleEntity.isEditable,
|
||||||
userWorkspaceRoles: roleEntity.userWorkspaceRoles,
|
userWorkspaceRoles: roleEntity.userWorkspaceRoles,
|
||||||
|
canReadAllObjectRecords: roleEntity.canReadAllObjectRecords,
|
||||||
|
canUpdateAllObjectRecords: roleEntity.canUpdateAllObjectRecords,
|
||||||
|
canSoftDeleteAllObjectRecords:
|
||||||
|
roleEntity.canSoftDeleteAllObjectRecords,
|
||||||
|
canDestroyAllObjectRecords: roleEntity.canDestroyAllObjectRecords,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -152,11 +152,13 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
|||||||
await this.validateSecurityPermissions({
|
await this.validateSecurityPermissions({
|
||||||
payload,
|
payload,
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId: workspace.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.validateWorkspacePermissions({
|
await this.validateWorkspacePermissions({
|
||||||
payload,
|
payload,
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId: workspace.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,9 +380,11 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
|||||||
private async validateSecurityPermissions({
|
private async validateSecurityPermissions({
|
||||||
payload,
|
payload,
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId,
|
||||||
}: {
|
}: {
|
||||||
payload: Partial<Workspace>;
|
payload: Partial<Workspace>;
|
||||||
userWorkspaceId?: string;
|
userWorkspaceId?: string;
|
||||||
|
workspaceId: string;
|
||||||
}) {
|
}) {
|
||||||
if (
|
if (
|
||||||
'isGoogleAuthEnabled' in payload ||
|
'isGoogleAuthEnabled' in payload ||
|
||||||
@ -396,6 +400,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
|||||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
_setting: SettingsFeatures.SECURITY,
|
_setting: SettingsFeatures.SECURITY,
|
||||||
|
workspaceId: workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!userHasPermission) {
|
if (!userHasPermission) {
|
||||||
@ -410,9 +415,11 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
|||||||
private async validateWorkspacePermissions({
|
private async validateWorkspacePermissions({
|
||||||
payload,
|
payload,
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId,
|
||||||
}: {
|
}: {
|
||||||
payload: Partial<Workspace>;
|
payload: Partial<Workspace>;
|
||||||
userWorkspaceId?: string;
|
userWorkspaceId?: string;
|
||||||
|
workspaceId: string;
|
||||||
}) {
|
}) {
|
||||||
if (
|
if (
|
||||||
'displayName' in payload ||
|
'displayName' in payload ||
|
||||||
@ -427,6 +434,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
|||||||
const userHasPermission =
|
const userHasPermission =
|
||||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId,
|
||||||
_setting: SettingsFeatures.WORKSPACE,
|
_setting: SettingsFeatures.WORKSPACE,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,7 @@ export const SettingsPermissionsGuard = (
|
|||||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
_setting: requiredPermission,
|
_setting: requiredPermission,
|
||||||
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hasPermission === true) {
|
if (hasPermission === true) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { SettingsFeatures } from 'twenty-shared';
|
import { PermissionsOnAllObjectRecords, SettingsFeatures } from 'twenty-shared';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||||
@ -12,13 +12,21 @@ export class PermissionsService {
|
|||||||
private readonly userRoleService: UserRoleService,
|
private readonly userRoleService: UserRoleService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async getUserWorkspaceSettingsPermissions({
|
public async getUserWorkspacePermissions({
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId,
|
||||||
}: {
|
}: {
|
||||||
userWorkspaceId: string;
|
userWorkspaceId: string;
|
||||||
}): Promise<Record<SettingsFeatures, boolean>> {
|
workspaceId: string;
|
||||||
|
}): Promise<{
|
||||||
|
settingsPermissions: Record<SettingsFeatures, boolean>;
|
||||||
|
objectRecordsPermissions: Record<PermissionsOnAllObjectRecords, boolean>;
|
||||||
|
}> {
|
||||||
const [roleOfUserWorkspace] = await this.userRoleService
|
const [roleOfUserWorkspace] = await this.userRoleService
|
||||||
.getRolesByUserWorkspaces([userWorkspaceId])
|
.getRolesByUserWorkspaces({
|
||||||
|
userWorkspaceIds: [userWorkspaceId],
|
||||||
|
workspaceId,
|
||||||
|
})
|
||||||
.then((roles) => roles?.get(userWorkspaceId) ?? []);
|
.then((roles) => roles?.get(userWorkspaceId) ?? []);
|
||||||
|
|
||||||
let hasPermissionOnSettingFeature = false;
|
let hasPermissionOnSettingFeature = false;
|
||||||
@ -27,24 +35,48 @@ export class PermissionsService {
|
|||||||
hasPermissionOnSettingFeature = true;
|
hasPermissionOnSettingFeature = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(SettingsFeatures).reduce(
|
const settingsPermissionsMap = Object.keys(SettingsFeatures).reduce(
|
||||||
(acc, feature) => ({
|
(acc, feature) => ({
|
||||||
...acc,
|
...acc,
|
||||||
[feature]: hasPermissionOnSettingFeature,
|
[feature]: hasPermissionOnSettingFeature,
|
||||||
}),
|
}),
|
||||||
{} as Record<SettingsFeatures, boolean>,
|
{} as Record<SettingsFeatures, boolean>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const objectRecordsPermissionsMap: Record<
|
||||||
|
PermissionsOnAllObjectRecords,
|
||||||
|
boolean
|
||||||
|
> = {
|
||||||
|
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]:
|
||||||
|
roleOfUserWorkspace?.canReadAllObjectRecords ?? false,
|
||||||
|
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]:
|
||||||
|
roleOfUserWorkspace?.canUpdateAllObjectRecords ?? false,
|
||||||
|
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]:
|
||||||
|
roleOfUserWorkspace?.canSoftDeleteAllObjectRecords ?? false,
|
||||||
|
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]:
|
||||||
|
roleOfUserWorkspace?.canDestroyAllObjectRecords ?? false,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
settingsPermissions: settingsPermissionsMap,
|
||||||
|
objectRecordsPermissions: objectRecordsPermissionsMap,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async userHasWorkspaceSettingPermission({
|
public async userHasWorkspaceSettingPermission({
|
||||||
userWorkspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId,
|
||||||
_setting,
|
_setting,
|
||||||
}: {
|
}: {
|
||||||
userWorkspaceId: string;
|
userWorkspaceId: string;
|
||||||
|
workspaceId: string;
|
||||||
_setting: SettingsFeatures;
|
_setting: SettingsFeatures;
|
||||||
}): Promise<boolean> {
|
}): Promise<boolean> {
|
||||||
const [roleOfUserWorkspace] = await this.userRoleService
|
const [roleOfUserWorkspace] = await this.userRoleService
|
||||||
.getRolesByUserWorkspaces([userWorkspaceId])
|
.getRolesByUserWorkspaces({
|
||||||
|
userWorkspaceIds: [userWorkspaceId],
|
||||||
|
workspaceId,
|
||||||
|
})
|
||||||
.then((roles) => roles?.get(userWorkspaceId) ?? []);
|
.then((roles) => roles?.get(userWorkspaceId) ?? []);
|
||||||
|
|
||||||
if (roleOfUserWorkspace?.canUpdateAllSettings === true) {
|
if (roleOfUserWorkspace?.canUpdateAllSettings === true) {
|
||||||
|
|||||||
@ -13,9 +13,6 @@ export class RoleDTO {
|
|||||||
@Field({ nullable: false })
|
@Field({ nullable: false })
|
||||||
label: string;
|
label: string;
|
||||||
|
|
||||||
@Field({ nullable: false })
|
|
||||||
canUpdateAllSettings: boolean;
|
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
@ -27,4 +24,19 @@ export class RoleDTO {
|
|||||||
|
|
||||||
@Field(() => [WorkspaceMember], { nullable: true })
|
@Field(() => [WorkspaceMember], { nullable: true })
|
||||||
workspaceMembers?: WorkspaceMember[];
|
workspaceMembers?: WorkspaceMember[];
|
||||||
|
|
||||||
|
@Field({ nullable: false })
|
||||||
|
canUpdateAllSettings: boolean;
|
||||||
|
|
||||||
|
@Field({ nullable: false })
|
||||||
|
canReadAllObjectRecords: boolean;
|
||||||
|
|
||||||
|
@Field({ nullable: false })
|
||||||
|
canUpdateAllObjectRecords: boolean;
|
||||||
|
|
||||||
|
@Field({ nullable: false })
|
||||||
|
canSoftDeleteAllObjectRecords: boolean;
|
||||||
|
|
||||||
|
@Field({ nullable: false })
|
||||||
|
canDestroyAllObjectRecords: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,18 @@ export class RoleEntity {
|
|||||||
@Column({ nullable: false, default: false })
|
@Column({ nullable: false, default: false })
|
||||||
canUpdateAllSettings: boolean;
|
canUpdateAllSettings: boolean;
|
||||||
|
|
||||||
|
@Column({ nullable: false, default: false })
|
||||||
|
canReadAllObjectRecords: boolean;
|
||||||
|
|
||||||
|
@Column({ nullable: false, default: false })
|
||||||
|
canUpdateAllObjectRecords: boolean;
|
||||||
|
|
||||||
|
@Column({ nullable: false, default: false })
|
||||||
|
canSoftDeleteAllObjectRecords: boolean;
|
||||||
|
|
||||||
|
@Column({ nullable: false, default: false })
|
||||||
|
canDestroyAllObjectRecords: boolean;
|
||||||
|
|
||||||
@Column({ nullable: true, type: 'text' })
|
@Column({ nullable: true, type: 'text' })
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
|
|||||||
@ -38,13 +38,17 @@ export class RoleResolver {
|
|||||||
return roles.map((role) => ({
|
return roles.map((role) => ({
|
||||||
id: role.id,
|
id: role.id,
|
||||||
label: role.label,
|
label: role.label,
|
||||||
canUpdateAllSettings: role.canUpdateAllSettings,
|
|
||||||
description: role.description,
|
description: role.description,
|
||||||
workspaceId: role.workspaceId,
|
workspaceId: role.workspaceId,
|
||||||
createdAt: role.createdAt,
|
createdAt: role.createdAt,
|
||||||
updatedAt: role.updatedAt,
|
updatedAt: role.updatedAt,
|
||||||
isEditable: role.isEditable,
|
isEditable: role.isEditable,
|
||||||
userWorkspaceRoles: role.userWorkspaceRoles,
|
userWorkspaceRoles: role.userWorkspaceRoles,
|
||||||
|
canUpdateAllSettings: role.canUpdateAllSettings,
|
||||||
|
canReadAllObjectRecords: role.canReadAllObjectRecords,
|
||||||
|
canUpdateAllObjectRecords: role.canUpdateAllObjectRecords,
|
||||||
|
canSoftDeleteAllObjectRecords: role.canSoftDeleteAllObjectRecords,
|
||||||
|
canDestroyAllObjectRecords: role.canDestroyAllObjectRecords,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +85,10 @@ export class RoleResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const roles = await this.userRoleService
|
const roles = await this.userRoleService
|
||||||
.getRolesByUserWorkspaces([userWorkspace.id])
|
.getRolesByUserWorkspaces({
|
||||||
|
userWorkspaceIds: [userWorkspace.id],
|
||||||
|
workspaceId: workspace.id,
|
||||||
|
})
|
||||||
.then(
|
.then(
|
||||||
(rolesByUserWorkspaces) =>
|
(rolesByUserWorkspaces) =>
|
||||||
rolesByUserWorkspaces?.get(userWorkspace.id) ?? [],
|
rolesByUserWorkspaces?.get(userWorkspace.id) ?? [],
|
||||||
|
|||||||
@ -30,6 +30,10 @@ export class RoleService {
|
|||||||
label: ADMIN_ROLE_LABEL,
|
label: ADMIN_ROLE_LABEL,
|
||||||
description: 'Admin role',
|
description: 'Admin role',
|
||||||
canUpdateAllSettings: true,
|
canUpdateAllSettings: true,
|
||||||
|
canReadAllObjectRecords: true,
|
||||||
|
canUpdateAllObjectRecords: true,
|
||||||
|
canSoftDeleteAllObjectRecords: true,
|
||||||
|
canDestroyAllObjectRecords: true,
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
@ -44,6 +48,10 @@ export class RoleService {
|
|||||||
label: MEMBER_ROLE_LABEL,
|
label: MEMBER_ROLE_LABEL,
|
||||||
description: 'Member role',
|
description: 'Member role',
|
||||||
canUpdateAllSettings: false,
|
canUpdateAllSettings: false,
|
||||||
|
canReadAllObjectRecords: true,
|
||||||
|
canUpdateAllObjectRecords: true,
|
||||||
|
canSoftDeleteAllObjectRecords: true,
|
||||||
|
canDestroyAllObjectRecords: true,
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -60,7 +60,10 @@ export class UserRoleService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const roles = await this.getRolesByUserWorkspaces([userWorkspace.id]);
|
const roles = await this.getRolesByUserWorkspaces({
|
||||||
|
userWorkspaceIds: [userWorkspace.id],
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
|
||||||
const currentRole = roles.get(userWorkspace.id)?.[0];
|
const currentRole = roles.get(userWorkspace.id)?.[0];
|
||||||
|
|
||||||
@ -88,8 +91,10 @@ export class UserRoleService {
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
await this.validatesUserWorkspaceIsNotLastAdminIfUnassigningAdminRoleOrThrow(
|
await this.validatesUserWorkspaceIsNotLastAdminIfUnassigningAdminRoleOrThrow(
|
||||||
userWorkspaceId,
|
{
|
||||||
workspaceId,
|
userWorkspaceId,
|
||||||
|
workspaceId,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.userWorkspaceRoleRepository.delete({
|
await this.userWorkspaceRoleRepository.delete({
|
||||||
@ -98,9 +103,13 @@ export class UserRoleService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getRolesByUserWorkspaces(
|
public async getRolesByUserWorkspaces({
|
||||||
userWorkspaceIds: string[],
|
userWorkspaceIds,
|
||||||
): Promise<Map<string, RoleDTO[]>> {
|
workspaceId,
|
||||||
|
}: {
|
||||||
|
userWorkspaceIds: string[];
|
||||||
|
workspaceId: string;
|
||||||
|
}): Promise<Map<string, RoleDTO[]>> {
|
||||||
if (!userWorkspaceIds.length) {
|
if (!userWorkspaceIds.length) {
|
||||||
return new Map();
|
return new Map();
|
||||||
}
|
}
|
||||||
@ -108,6 +117,7 @@ export class UserRoleService {
|
|||||||
const allUserWorkspaceRoles = await this.userWorkspaceRoleRepository.find({
|
const allUserWorkspaceRoles = await this.userWorkspaceRoleRepository.find({
|
||||||
where: {
|
where: {
|
||||||
userWorkspaceId: In(userWorkspaceIds),
|
userWorkspaceId: In(userWorkspaceIds),
|
||||||
|
workspaceId,
|
||||||
},
|
},
|
||||||
relations: {
|
relations: {
|
||||||
role: true,
|
role: true,
|
||||||
@ -176,11 +186,17 @@ export class UserRoleService {
|
|||||||
return workspaceMembers;
|
return workspaceMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async validatesUserWorkspaceIsNotLastAdminIfUnassigningAdminRoleOrThrow(
|
private async validatesUserWorkspaceIsNotLastAdminIfUnassigningAdminRoleOrThrow({
|
||||||
userWorkspaceId: string,
|
userWorkspaceId,
|
||||||
workspaceId: string,
|
workspaceId,
|
||||||
): Promise<void> {
|
}: {
|
||||||
const roles = await this.getRolesByUserWorkspaces([userWorkspaceId]);
|
userWorkspaceId: string;
|
||||||
|
workspaceId: string;
|
||||||
|
}): Promise<void> {
|
||||||
|
const roles = await this.getRolesByUserWorkspaces({
|
||||||
|
userWorkspaceIds: [userWorkspaceId],
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
|
||||||
const currentRoles = roles.get(userWorkspaceId);
|
const currentRoles = roles.get(userWorkspaceId);
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,11 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { DEV_SEED_USER_WORKSPACE_IDS } from 'src/database/typeorm-seeds/core/user-workspaces';
|
import { DEV_SEED_USER_WORKSPACE_IDS } from 'src/database/typeorm-seeds/core/user-workspaces';
|
||||||
|
import {
|
||||||
|
SEED_ACME_WORKSPACE_ID,
|
||||||
|
SEED_APPLE_WORKSPACE_ID,
|
||||||
|
} from 'src/database/typeorm-seeds/core/workspaces';
|
||||||
|
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
@ -42,6 +47,7 @@ export class WorkspaceManagerService {
|
|||||||
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
||||||
private readonly roleService: RoleService,
|
private readonly roleService: RoleService,
|
||||||
private readonly userRoleService: UserRoleService,
|
private readonly userRoleService: UserRoleService,
|
||||||
|
private readonly featureFlagService: FeatureFlagService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,20 +267,34 @@ export class WorkspaceManagerService {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.userRoleService.assignRoleToUserWorkspace({
|
let adminUserWorkspaceId: string | undefined;
|
||||||
workspaceId,
|
let memberUserWorkspaceId: string | undefined;
|
||||||
userWorkspaceId: DEV_SEED_USER_WORKSPACE_IDS.TIM,
|
|
||||||
roleId: adminRole.id,
|
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||||
});
|
adminUserWorkspaceId = DEV_SEED_USER_WORKSPACE_IDS.TIM;
|
||||||
|
memberUserWorkspaceId = DEV_SEED_USER_WORKSPACE_IDS.JONY;
|
||||||
|
} else if (workspaceId === SEED_ACME_WORKSPACE_ID) {
|
||||||
|
adminUserWorkspaceId = DEV_SEED_USER_WORKSPACE_IDS.TIM_ACME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adminUserWorkspaceId) {
|
||||||
|
await this.userRoleService.assignRoleToUserWorkspace({
|
||||||
|
workspaceId,
|
||||||
|
userWorkspaceId: adminUserWorkspaceId,
|
||||||
|
roleId: adminRole.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const memberRole = await this.roleService.createMemberRole({
|
const memberRole = await this.roleService.createMemberRole({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.userRoleService.assignRoleToUserWorkspace({
|
if (memberUserWorkspaceId) {
|
||||||
workspaceId,
|
await this.userRoleService.assignRoleToUserWorkspace({
|
||||||
userWorkspaceId: DEV_SEED_USER_WORKSPACE_IDS.JONY,
|
workspaceId,
|
||||||
roleId: memberRole.id,
|
userWorkspaceId: memberUserWorkspaceId,
|
||||||
});
|
roleId: memberRole.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
export enum PermissionsOnAllObjectRecords {
|
||||||
|
READ_ALL_OBJECT_RECORDS = 'READ_ALL_OBJECT_RECORDS',
|
||||||
|
UPDATE_ALL_OBJECT_RECORDS = 'UPDATE_ALL_OBJECT_RECORDS',
|
||||||
|
SOFT_DELETE_ALL_OBJECT_RECORDS = 'SOFT_DELETE_ALL_OBJECT_RECORDS',
|
||||||
|
DESTROY_ALL_OBJECT_RECORDS = 'DESTROY_ALL_OBJECT_RECORDS',
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
export * from './FieldForTotalCountAggregateOperation';
|
export * from './FieldForTotalCountAggregateOperation';
|
||||||
|
export * from './PermissionsOnAllObjectRecords';
|
||||||
export * from './SettingsFeatures';
|
export * from './SettingsFeatures';
|
||||||
export * from './TwentyCompaniesBaseUrl';
|
export * from './TwentyCompaniesBaseUrl';
|
||||||
export * from './TwentyIconsBaseUrl';
|
export * from './TwentyIconsBaseUrl';
|
||||||
|
|||||||
Reference in New Issue
Block a user