Improve workspace auth context surface (#18164)
This commit is contained in:
+2
-2
@@ -2,7 +2,7 @@ import { type APP_LOCALES } from 'twenty-shared/translations';
|
||||
|
||||
import { type ApiKey } from 'src/engine/core-modules/api-key/api-key.entity';
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { type User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { type AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
|
||||
@@ -22,6 +22,6 @@ declare module 'express-serve-static-core' {
|
||||
workspaceMember?: WorkspaceMemberWorkspaceEntity;
|
||||
userWorkspaceId?: string;
|
||||
authProvider?: AuthProviderEnum | null;
|
||||
impersonationContext?: AuthContext['impersonationContext'];
|
||||
impersonationContext?: RawAuthContext['impersonationContext'];
|
||||
}
|
||||
}
|
||||
|
||||
+6
-7
@@ -3,8 +3,9 @@ import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { DataArgProcessorService } from 'src/engine/api/common/common-args-processors/data-arg-processor/data-arg-processor.service';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type SystemWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -27,12 +28,10 @@ describe('DataArgProcessorService', () => {
|
||||
|
||||
const mockWorkspaceId = '20202020-1234-1234-1234-123456789012';
|
||||
|
||||
const createMockAuthContext = (): AuthContext =>
|
||||
({
|
||||
workspace: {
|
||||
id: mockWorkspaceId,
|
||||
},
|
||||
}) as AuthContext;
|
||||
const createMockAuthContext = (): SystemWorkspaceAuthContext => ({
|
||||
type: 'system',
|
||||
workspace: { id: mockWorkspaceId } as WorkspaceEntity,
|
||||
});
|
||||
|
||||
const createFlatFieldMetadataMaps = (
|
||||
fieldNames: string[],
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ import {
|
||||
CommonQueryRunnerExceptionCode,
|
||||
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
|
||||
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
import { transformEmailsValue } from 'src/engine/core-modules/record-transformer/utils/transform-emails-value.util';
|
||||
import { transformLinksValue } from 'src/engine/core-modules/record-transformer/utils/transform-links-value.util';
|
||||
@@ -73,7 +73,7 @@ export class DataArgProcessorService {
|
||||
shouldBackfillPositionIfUndefined = true,
|
||||
}: {
|
||||
partialRecordInputs: Partial<ObjectRecord>[] | undefined;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
shouldBackfillPositionIfUndefined?: boolean;
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@ import { ProcessAggregateHelper } from 'src/engine/api/graphql/graphql-query-run
|
||||
import { buildColumnsToSelect } from 'src/engine/api/graphql/graphql-query-runner/utils/build-columns-to-select';
|
||||
import { getTargetObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-target-object-metadata.util';
|
||||
import { type AggregationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -55,7 +55,7 @@ export class ProcessNestedRelationsV2Helper {
|
||||
relations: Record<string, FindOptionsRelations<ObjectLiteral>>;
|
||||
aggregate?: Record<string, AggregationField>;
|
||||
limit: number;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
workspaceDataSource: GlobalWorkspaceDataSource;
|
||||
rolePermissionConfig?: RolePermissionConfig;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -111,7 +111,7 @@ export class ProcessNestedRelationsV2Helper {
|
||||
nestedRelations: FindOptionsRelations<ObjectLiteral>;
|
||||
aggregate: Record<string, AggregationField>;
|
||||
limit: number;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
workspaceDataSource: GlobalWorkspaceDataSource;
|
||||
rolePermissionConfig?: RolePermissionConfig;
|
||||
selectedFields: Record<string, unknown>;
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import { type FindOptionsRelations, type ObjectLiteral } from 'typeorm';
|
||||
|
||||
import { ProcessNestedRelationsV2Helper } from 'src/engine/api/common/common-nested-relations-processor/process-nested-relations-v2.helper';
|
||||
import { type AggregationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -41,7 +41,7 @@ export class ProcessNestedRelationsHelper {
|
||||
relations: Record<string, FindOptionsRelations<ObjectLiteral>>;
|
||||
aggregate?: Record<string, AggregationField>;
|
||||
limit: number;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
workspaceDataSource: GlobalWorkspaceDataSource;
|
||||
rolePermissionConfig?: RolePermissionConfig;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
+18
-24
@@ -31,9 +31,8 @@ import { WorkspacePreQueryHookPayload } from 'src/engine/api/graphql/workspace-q
|
||||
import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service';
|
||||
import { ApiKeyRoleService } from 'src/engine/core-modules/api-key/services/api-key-role.service';
|
||||
import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard';
|
||||
import { isApplicationAuthContext } from 'src/engine/core-modules/auth/guards/is-application-auth-context.guard';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { isWorkspaceAuthContext } from 'src/engine/core-modules/auth/guards/is-workspace-auth-context.guard';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
@@ -105,14 +104,6 @@ export abstract class CommonBaseQueryRunnerService<
|
||||
flatFieldMetadataMaps,
|
||||
} = queryRunnerContext;
|
||||
|
||||
if (!isWorkspaceAuthContext(authContext)) {
|
||||
throw new CommonQueryRunnerException(
|
||||
'Invalid auth context',
|
||||
CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT,
|
||||
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
|
||||
);
|
||||
}
|
||||
|
||||
await this.throttleQueryExecution(authContext);
|
||||
|
||||
await this.validate(args, queryRunnerContext);
|
||||
@@ -312,32 +303,35 @@ export abstract class CommonBaseQueryRunnerService<
|
||||
}
|
||||
|
||||
private async getRoleIdOrThrow(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
workspaceId: string,
|
||||
): Promise<string> {
|
||||
if (isDefined(authContext.apiKey)) {
|
||||
if (isApiKeyAuthContext(authContext)) {
|
||||
return this.apiKeyRoleService.getRoleIdForApiKeyId(
|
||||
authContext.apiKey.id,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(authContext.application?.defaultRoleId)) {
|
||||
return authContext.application?.defaultRoleId;
|
||||
if (
|
||||
isApplicationAuthContext(authContext) &&
|
||||
isDefined(authContext.application.defaultRoleId)
|
||||
) {
|
||||
return authContext.application.defaultRoleId;
|
||||
}
|
||||
|
||||
if (!isDefined(authContext.userWorkspaceId)) {
|
||||
throw new CommonQueryRunnerException(
|
||||
'Invalid auth context',
|
||||
CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT,
|
||||
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
|
||||
);
|
||||
if (isUserAuthContext(authContext)) {
|
||||
return this.userRoleService.getRoleIdForUserWorkspace({
|
||||
userWorkspaceId: authContext.userWorkspaceId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
return this.userRoleService.getRoleIdForUserWorkspace({
|
||||
userWorkspaceId: authContext.userWorkspaceId,
|
||||
workspaceId,
|
||||
});
|
||||
throw new CommonQueryRunnerException(
|
||||
'Invalid auth context',
|
||||
CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT,
|
||||
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
|
||||
);
|
||||
}
|
||||
|
||||
private async prepareExtendedQueryRunnerContextWithGlobalDatasource(
|
||||
|
||||
+1
-2
@@ -29,7 +29,6 @@ import { buildColumnsToReturn } from 'src/engine/api/graphql/graphql-query-runne
|
||||
import { buildColumnsToSelect } from 'src/engine/api/graphql/graphql-query-runner/utils/build-columns-to-select';
|
||||
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
|
||||
import { getAllSelectableColumnNames } from 'src/engine/api/utils/get-all-selectable-column-names.utils';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
@@ -117,7 +116,7 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
workspaceDataSource: GlobalWorkspaceDataSource;
|
||||
rolePermissionConfig?: RolePermissionConfig;
|
||||
}): Promise<void> {
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export type CommonBaseQueryRunnerContext = {
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
import { type QueryResultFieldValue } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-field-value';
|
||||
import { type ResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
export interface WorkspacePreQueryHookInstance {
|
||||
execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
objectName: string,
|
||||
payload: ResolverArgs,
|
||||
): Promise<ResolverArgs>;
|
||||
@@ -13,7 +13,7 @@ export interface WorkspacePreQueryHookInstance {
|
||||
|
||||
export interface WorkspacePostQueryHookInstance {
|
||||
execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
objectName: string,
|
||||
payload: QueryResultFieldValue,
|
||||
): Promise<void>;
|
||||
|
||||
+16
-4
@@ -12,6 +12,8 @@ import {
|
||||
type WorkspacePreQueryHookInstance,
|
||||
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
|
||||
import {
|
||||
GraphqlQueryRunnerException,
|
||||
@@ -171,14 +173,24 @@ export class WorkspaceQueryHookExplorer implements OnModuleInit {
|
||||
const contextId = createContextId();
|
||||
|
||||
if (this.moduleRef.registerRequestByContextId) {
|
||||
const authContext = executeParams[0];
|
||||
|
||||
this.moduleRef.registerRequestByContextId(
|
||||
{
|
||||
req: {
|
||||
workspaceId: workspace.id,
|
||||
userWorkspaceId: executeParams?.[0].userWorkspaceId,
|
||||
apiKey: executeParams?.[0].apiKey,
|
||||
workspaceMemberId: executeParams?.[0].workspaceMemberId,
|
||||
user: executeParams?.[0].user,
|
||||
userWorkspaceId: isUserAuthContext(authContext)
|
||||
? authContext.userWorkspaceId
|
||||
: undefined,
|
||||
apiKey: isApiKeyAuthContext(authContext)
|
||||
? authContext.apiKey
|
||||
: undefined,
|
||||
workspaceMemberId: isUserAuthContext(authContext)
|
||||
? authContext.workspaceMemberId
|
||||
: undefined,
|
||||
user: isUserAuthContext(authContext)
|
||||
? authContext.user
|
||||
: undefined,
|
||||
},
|
||||
},
|
||||
contextId,
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ import { type WorkspaceQueryHookKey } from 'src/engine/api/graphql/workspace-que
|
||||
import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage';
|
||||
import { type WorkspacePreQueryHookPayload } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { WorkspaceQueryHookExplorer } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceQueryHookService {
|
||||
@@ -23,7 +23,7 @@ export class WorkspaceQueryHookService {
|
||||
public async executePreQueryHooks<
|
||||
T extends WorkspaceResolverBuilderMethodNames | CommonQueryNames,
|
||||
>(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
// TODO: We should allow wildcard for object name
|
||||
objectName: string,
|
||||
methodName: T,
|
||||
@@ -56,7 +56,7 @@ export class WorkspaceQueryHookService {
|
||||
public async executePostQueryHooks<
|
||||
T extends WorkspaceResolverBuilderMethodNames,
|
||||
>(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
// TODO: We should allow wildcard for object name
|
||||
objectName: string,
|
||||
methodName: T,
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class CreateManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -35,7 +35,6 @@ export class CreateOneResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class DeleteManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -35,7 +35,6 @@ export class DeleteOneResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class DestroyManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -35,7 +35,6 @@ export class DestroyOneResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class FindDuplicatesResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class FindManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class FindOneResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
const record = await this.commonFindOneQueryRunnerService.execute(
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class GroupByResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
const shouldIncludeRecords =
|
||||
|
||||
-1
@@ -35,7 +35,6 @@ export class MergeManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class RestoreManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -35,7 +35,6 @@ export class RestoreOneResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ export class UpdateManyResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
-1
@@ -35,7 +35,6 @@ export class UpdateOneResolverFactory
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
+2
-28
@@ -1,41 +1,15 @@
|
||||
import { type WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface';
|
||||
|
||||
import { type CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { getWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
|
||||
|
||||
export const createQueryRunnerContext = ({
|
||||
workspaceSchemaBuilderContext,
|
||||
request,
|
||||
}: {
|
||||
workspaceSchemaBuilderContext: WorkspaceSchemaBuilderContext;
|
||||
request: AuthContext;
|
||||
}): CommonBaseQueryRunnerContext => {
|
||||
const {
|
||||
user,
|
||||
workspace,
|
||||
apiKey,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
userWorkspace,
|
||||
authProvider,
|
||||
impersonationContext,
|
||||
workspaceMember,
|
||||
application,
|
||||
} = request;
|
||||
|
||||
return {
|
||||
...workspaceSchemaBuilderContext,
|
||||
authContext: {
|
||||
user,
|
||||
workspace,
|
||||
apiKey,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
userWorkspace,
|
||||
authProvider,
|
||||
impersonationContext,
|
||||
workspaceMember,
|
||||
application,
|
||||
},
|
||||
authContext: getWorkspaceAuthContext(),
|
||||
};
|
||||
};
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import {
|
||||
ActorFromAuthContextService,
|
||||
type RecordInput,
|
||||
} from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
@WorkspaceQueryHook(`*.createMany`)
|
||||
export class CreatedByCreateManyPreQueryHook
|
||||
@@ -24,7 +24,7 @@ export class CreatedByCreateManyPreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
objectName: string,
|
||||
payload: CreateManyResolverArgs<RecordInput>,
|
||||
): Promise<CreateManyResolverArgs<RecordInput>> {
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import {
|
||||
ActorFromAuthContextService,
|
||||
type RecordInput,
|
||||
} from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
@WorkspaceQueryHook(`*.createOne`)
|
||||
export class CreatedByCreateOnePreQueryHook
|
||||
@@ -24,7 +24,7 @@ export class CreatedByCreateOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
objectName: string,
|
||||
payload: CreateOneResolverArgs<RecordInput>,
|
||||
): Promise<CreateOneResolverArgs<RecordInput>> {
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import {
|
||||
ActorFromAuthContextService,
|
||||
type RecordInput,
|
||||
} from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
@WorkspaceQueryHook(`*.updateMany`)
|
||||
export class UpdatedByUpdateManyPreQueryHook
|
||||
@@ -24,7 +24,7 @@ export class UpdatedByUpdateManyPreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
objectName: string,
|
||||
payload: UpdateManyResolverArgs<RecordInput>,
|
||||
): Promise<UpdateManyResolverArgs<RecordInput>> {
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import {
|
||||
ActorFromAuthContextService,
|
||||
type RecordInput,
|
||||
} from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
@WorkspaceQueryHook(`*.updateOne`)
|
||||
export class UpdatedByUpdateOnePreQueryHook
|
||||
@@ -24,7 +24,7 @@ export class UpdatedByUpdateOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
objectName: string,
|
||||
payload: UpdateOneResolverArgs<RecordInput>,
|
||||
): Promise<UpdateOneResolverArgs<RecordInput>> {
|
||||
|
||||
+26
-104
@@ -1,5 +1,4 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import {
|
||||
type ActorMetadata,
|
||||
@@ -8,24 +7,11 @@ import {
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { ActorFromAuthContextService } from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
|
||||
import { type ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
type TestingAuthContext = Omit<AuthContext, 'workspace' | 'apiKey' | 'user'> & {
|
||||
workspace: Partial<WorkspaceEntity>;
|
||||
apiKey?: Partial<ApiKeyEntity>;
|
||||
user?: Partial<UserEntity>;
|
||||
};
|
||||
|
||||
type ExpectedResult = { createdBy: ActorMetadata }[];
|
||||
|
||||
// TODO create util
|
||||
const fromFullNameMetadataToName = ({
|
||||
firstName,
|
||||
lastName,
|
||||
@@ -33,35 +19,11 @@ const fromFullNameMetadataToName = ({
|
||||
|
||||
describe('ActorFromAuthContextService', () => {
|
||||
let service: ActorFromAuthContextService;
|
||||
const mockWorkspaceMemberRepository = {
|
||||
findOneOrFail: jest.fn(),
|
||||
};
|
||||
const globalWorkspaceOrmManager: jest.Mocked<
|
||||
Pick<
|
||||
GlobalWorkspaceOrmManager,
|
||||
'getRepository' | 'executeInWorkspaceContext'
|
||||
>
|
||||
> = {
|
||||
getRepository: jest.fn().mockResolvedValue(mockWorkspaceMemberRepository),
|
||||
executeInWorkspaceContext: jest
|
||||
.fn()
|
||||
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
ActorFromAuthContextService,
|
||||
{
|
||||
provide: GlobalWorkspaceOrmManager,
|
||||
useValue: globalWorkspaceOrmManager,
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(FieldMetadataEntity),
|
||||
useValue: {
|
||||
findOne: jest.fn().mockResolvedValue(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
useValue: {
|
||||
@@ -117,101 +79,60 @@ describe('ActorFromAuthContextService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('injectCreatedBy', () => {
|
||||
it('should build metadata from workspaceMemberId and user when both are present', async () => {
|
||||
it('should build metadata from workspaceMember when user auth context', async () => {
|
||||
const workspaceMemberName = {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
};
|
||||
|
||||
const authContext = {
|
||||
type: 'user',
|
||||
workspaceMemberId: '20202020-0b5c-4178-bed7-d371f6411eaa',
|
||||
userWorkspaceId: '20202020-1234-5678-9012-345678901234',
|
||||
user: {
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
id: '20202020-9aae-49a8-bafc-ac44bae62d6d',
|
||||
},
|
||||
workspace: { id: '20202020-bdec-497f-847a-1bb334fefe58' },
|
||||
} as const satisfies TestingAuthContext;
|
||||
|
||||
const mockedWorkspaceMember = {
|
||||
id: '20202020-0b5c-4178-bed7-d371f6411eaa',
|
||||
name: {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
workspaceMember: {
|
||||
id: '20202020-0b5c-4178-bed7-d371f6411eaa',
|
||||
name: workspaceMemberName,
|
||||
},
|
||||
} as const satisfies Partial<WorkspaceMemberWorkspaceEntity>;
|
||||
|
||||
mockWorkspaceMemberRepository.findOneOrFail.mockResolvedValueOnce(
|
||||
mockedWorkspaceMember,
|
||||
);
|
||||
workspace: { id: '20202020-bdec-497f-847a-1bb334fefe58' },
|
||||
} as unknown as WorkspaceAuthContext;
|
||||
|
||||
const result = await service.injectCreatedBy({
|
||||
records: [{}],
|
||||
objectMetadataNameSingular: 'person',
|
||||
authContext: authContext as AuthContext,
|
||||
authContext,
|
||||
});
|
||||
|
||||
expect(result).toEqual<ExpectedResult>([
|
||||
{
|
||||
createdBy: {
|
||||
context: {},
|
||||
name: fromFullNameMetadataToName(mockedWorkspaceMember.name),
|
||||
workspaceMemberId: authContext.workspaceMemberId,
|
||||
name: fromFullNameMetadataToName(workspaceMemberName),
|
||||
workspaceMemberId: '20202020-0b5c-4178-bed7-d371f6411eaa',
|
||||
source: FieldActorSource.MANUAL,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should build metadata from user when workspaceMemberId is missing', async () => {
|
||||
const authContext = {
|
||||
user: {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
id: '20202020-9aae-49a8-bafc-ac44bae62d6d',
|
||||
},
|
||||
workspace: { id: '20202020-bdec-497f-847a-1bb334fefe58' },
|
||||
} as const satisfies TestingAuthContext;
|
||||
|
||||
const mockedWorkspaceMember = {
|
||||
id: '20202020-78a3-4520-ba74-b0e1b534a501',
|
||||
name: {
|
||||
firstName: 'Pepito',
|
||||
lastName: 'Dubois',
|
||||
},
|
||||
} as const satisfies Partial<WorkspaceMemberWorkspaceEntity>;
|
||||
|
||||
mockWorkspaceMemberRepository.findOneOrFail.mockResolvedValueOnce(
|
||||
mockedWorkspaceMember,
|
||||
);
|
||||
|
||||
const result = await service.injectCreatedBy({
|
||||
records: [{}],
|
||||
objectMetadataNameSingular: 'person',
|
||||
authContext: authContext as AuthContext,
|
||||
});
|
||||
|
||||
expect(result).toEqual<ExpectedResult>([
|
||||
{
|
||||
createdBy: {
|
||||
context: {},
|
||||
name: fromFullNameMetadataToName(mockedWorkspaceMember.name),
|
||||
workspaceMemberId: mockedWorkspaceMember.id,
|
||||
source: FieldActorSource.MANUAL,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should build metadata from apiKey when only apiKey is present', async () => {
|
||||
it('should build metadata from apiKey when apiKey auth context', async () => {
|
||||
const authContext = {
|
||||
type: 'apiKey',
|
||||
apiKey: {
|
||||
id: '20202020-56c2-471b-925d-31ed3ecd0951',
|
||||
name: 'API Key Name',
|
||||
},
|
||||
workspace: { id: '20202020-bdec-497f-847a-1bb334fefe58' },
|
||||
} as const satisfies TestingAuthContext;
|
||||
} as unknown as WorkspaceAuthContext;
|
||||
|
||||
const result = await service.injectCreatedBy({
|
||||
records: [{}],
|
||||
objectMetadataNameSingular: 'person',
|
||||
authContext: authContext as AuthContext,
|
||||
authContext,
|
||||
});
|
||||
|
||||
expect(result).toEqual<ExpectedResult>([
|
||||
@@ -219,7 +140,7 @@ describe('ActorFromAuthContextService', () => {
|
||||
createdBy: {
|
||||
source: FieldActorSource.API,
|
||||
workspaceMemberId: null,
|
||||
name: authContext.apiKey.name,
|
||||
name: 'API Key Name',
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
@@ -228,14 +149,15 @@ describe('ActorFromAuthContextService', () => {
|
||||
|
||||
it('should throw error when no valid actor information is found', async () => {
|
||||
const authContext = {
|
||||
type: 'system',
|
||||
workspace: { id: 'workspace-id' },
|
||||
} as const satisfies TestingAuthContext;
|
||||
} as unknown as WorkspaceAuthContext;
|
||||
|
||||
await expect(
|
||||
service.injectCreatedBy({
|
||||
records: [{}],
|
||||
objectMetadataNameSingular: 'person',
|
||||
authContext: authContext as AuthContext,
|
||||
authContext,
|
||||
}),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unable to build actor metadata - no valid actor information found in auth context"`,
|
||||
|
||||
+20
-50
@@ -1,27 +1,26 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { type ActorMetadata } from 'twenty-shared/types';
|
||||
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { buildCreatedByFromApiKey } from 'src/engine/core-modules/actor/utils/build-created-by-from-api-key.util';
|
||||
import { buildCreatedByFromApplication } from 'src/engine/core-modules/actor/utils/build-created-by-from-application.util';
|
||||
import { buildCreatedByFromFullNameMetadata } from 'src/engine/core-modules/actor/utils/build-created-by-from-full-name-metadata.util';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard';
|
||||
import { isApplicationAuthContext } from 'src/engine/core-modules/auth/guards/is-application-auth-context.guard';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { buildFieldMapsFromFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/build-field-maps-from-flat-object-metadata.util';
|
||||
import { buildObjectIdByNameMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/build-object-id-by-name-maps.util';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
export type RecordInput = Record<string, unknown>;
|
||||
|
||||
export type InjectActorParams = {
|
||||
records: RecordInput[];
|
||||
objectMetadataNameSingular: string;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -29,7 +28,6 @@ export class ActorFromAuthContextService {
|
||||
private readonly logger = new Logger(ActorFromAuthContextService.name);
|
||||
|
||||
constructor(
|
||||
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
) {}
|
||||
|
||||
@@ -89,8 +87,6 @@ export class ActorFromAuthContextService {
|
||||
> {
|
||||
const workspace = authContext.workspace;
|
||||
|
||||
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
|
||||
|
||||
const { flatObjectMetadataMaps, flatFieldMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -131,7 +127,7 @@ export class ActorFromAuthContextService {
|
||||
|
||||
const clonedRecords = structuredClone(records);
|
||||
|
||||
const actorMetadata = await this.buildActorMetadata(authContext);
|
||||
const actorMetadata = this.buildActorMetadata(authContext);
|
||||
|
||||
for (const record of clonedRecords) {
|
||||
this.injectActorToRecord(actorMetadata, record, fieldName);
|
||||
@@ -159,49 +155,23 @@ export class ActorFromAuthContextService {
|
||||
}
|
||||
}
|
||||
|
||||
private async buildActorMetadata(
|
||||
authContext: AuthContext,
|
||||
): Promise<ActorMetadata> {
|
||||
const { workspace, user, apiKey, application } = authContext;
|
||||
|
||||
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
|
||||
|
||||
if (isDefined(user)) {
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
async () => {
|
||||
const workspaceMemberRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail(
|
||||
{
|
||||
where: {
|
||||
userId: user.id,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return buildCreatedByFromFullNameMetadata({
|
||||
fullNameMetadata: workspaceMember.name,
|
||||
workspaceMemberId: workspaceMember.id,
|
||||
});
|
||||
},
|
||||
authContext as WorkspaceAuthContext,
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(apiKey)) {
|
||||
return buildCreatedByFromApiKey({
|
||||
apiKey,
|
||||
private buildActorMetadata(authContext: WorkspaceAuthContext): ActorMetadata {
|
||||
if (isUserAuthContext(authContext)) {
|
||||
return buildCreatedByFromFullNameMetadata({
|
||||
fullNameMetadata: authContext.workspaceMember.name,
|
||||
workspaceMemberId: authContext.workspaceMemberId,
|
||||
});
|
||||
}
|
||||
|
||||
if (isDefined(application)) {
|
||||
if (isApiKeyAuthContext(authContext)) {
|
||||
return buildCreatedByFromApiKey({
|
||||
apiKey: authContext.apiKey,
|
||||
});
|
||||
}
|
||||
|
||||
if (isApplicationAuthContext(authContext)) {
|
||||
return buildCreatedByFromApplication({
|
||||
application,
|
||||
application: authContext.application,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
export const isWorkspaceAuthContext = (
|
||||
context: AuthContext,
|
||||
): context is WorkspaceAuthContext => {
|
||||
return (
|
||||
isDefined(context.workspace) &&
|
||||
(isDefined(context.userWorkspaceId) ||
|
||||
isDefined(context.apiKey) ||
|
||||
isDefined(context.application))
|
||||
);
|
||||
};
|
||||
@@ -9,7 +9,7 @@ import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-membe
|
||||
export { AUTH_CONTEXT_USER_SELECT_FIELDS } from 'src/engine/core-modules/auth/constants/auth-context-user-select-fields.constants';
|
||||
export { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context-user.type';
|
||||
|
||||
export type AuthContext = {
|
||||
export type RawAuthContext = {
|
||||
user?: AuthContextUser | null | undefined;
|
||||
apiKey?: ApiKeyEntity | null | undefined;
|
||||
workspaceMemberId?: string;
|
||||
@@ -25,6 +25,9 @@ export type AuthContext = {
|
||||
};
|
||||
};
|
||||
|
||||
// @deprecated Use WorkspaceAuthContext instead
|
||||
export type AuthContext = RawAuthContext;
|
||||
|
||||
export type SerializableAuthContext = {
|
||||
userId?: string;
|
||||
userWorkspaceId?: string;
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
|
||||
export type WorkspaceAuthContextType =
|
||||
| 'system'
|
||||
@@ -9,27 +9,27 @@ export type WorkspaceAuthContextType =
|
||||
|
||||
interface BaseWorkspaceAuthContext {
|
||||
type: WorkspaceAuthContextType;
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
workspace: NonNullable<RawAuthContext['workspace']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
}
|
||||
|
||||
export interface ApiKeyWorkspaceAuthContext extends BaseWorkspaceAuthContext {
|
||||
type: 'apiKey';
|
||||
apiKey: NonNullable<AuthContext['apiKey']>;
|
||||
apiKey: NonNullable<RawAuthContext['apiKey']>;
|
||||
}
|
||||
|
||||
export interface UserWorkspaceAuthContext extends BaseWorkspaceAuthContext {
|
||||
type: 'user';
|
||||
userWorkspaceId: NonNullable<AuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<AuthContext['user']>;
|
||||
workspaceMemberId: NonNullable<AuthContext['workspaceMemberId']>;
|
||||
workspaceMember: NonNullable<AuthContext['workspaceMember']>;
|
||||
userWorkspaceId: NonNullable<RawAuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<RawAuthContext['user']>;
|
||||
workspaceMemberId: NonNullable<RawAuthContext['workspaceMemberId']>;
|
||||
workspaceMember: NonNullable<RawAuthContext['workspaceMember']>;
|
||||
}
|
||||
|
||||
export interface ApplicationWorkspaceAuthContext
|
||||
extends BaseWorkspaceAuthContext {
|
||||
type: 'application';
|
||||
application: NonNullable<AuthContext['application']>;
|
||||
application: NonNullable<RawAuthContext['application']>;
|
||||
}
|
||||
|
||||
export interface SystemWorkspaceAuthContext extends BaseWorkspaceAuthContext {
|
||||
@@ -39,8 +39,8 @@ export interface SystemWorkspaceAuthContext extends BaseWorkspaceAuthContext {
|
||||
export interface PendingActivationUserWorkspaceAuthContext
|
||||
extends BaseWorkspaceAuthContext {
|
||||
type: 'pendingActivationUser';
|
||||
userWorkspaceId: NonNullable<AuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<AuthContext['user']>;
|
||||
userWorkspaceId: NonNullable<RawAuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<RawAuthContext['user']>;
|
||||
}
|
||||
|
||||
export type WorkspaceAuthContext =
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type ApiKeyWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
type ApiKeyAuthContextInput = {
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
apiKey: NonNullable<AuthContext['apiKey']>;
|
||||
workspace: NonNullable<RawAuthContext['workspace']>;
|
||||
apiKey: NonNullable<RawAuthContext['apiKey']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
};
|
||||
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type ApplicationWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
type ApplicationAuthContextInput = {
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
application: NonNullable<AuthContext['application']>;
|
||||
workspace: NonNullable<RawAuthContext['workspace']>;
|
||||
application: NonNullable<RawAuthContext['application']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
};
|
||||
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type PendingActivationUserWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
type PendingActivationUserAuthContextInput = {
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
userWorkspaceId: NonNullable<AuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<AuthContext['user']>;
|
||||
workspace: NonNullable<RawAuthContext['workspace']>;
|
||||
userWorkspaceId: NonNullable<RawAuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<RawAuthContext['user']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type SystemWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
type SystemAuthContextInput = {
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
workspace: NonNullable<RawAuthContext['workspace']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
};
|
||||
|
||||
|
||||
+6
-6
@@ -1,12 +1,12 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type UserWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
|
||||
type UserAuthContextInput = {
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
userWorkspaceId: NonNullable<AuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<AuthContext['user']>;
|
||||
workspaceMemberId: NonNullable<AuthContext['workspaceMemberId']>;
|
||||
workspaceMember: NonNullable<AuthContext['workspaceMember']>;
|
||||
workspace: NonNullable<RawAuthContext['workspace']>;
|
||||
userWorkspaceId: NonNullable<RawAuthContext['userWorkspaceId']>;
|
||||
user: NonNullable<RawAuthContext['user']>;
|
||||
workspaceMemberId: NonNullable<RawAuthContext['workspaceMemberId']>;
|
||||
workspaceMember: NonNullable<RawAuthContext['workspaceMember']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
};
|
||||
|
||||
|
||||
+3
-4
@@ -37,7 +37,6 @@ import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interf
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { InternalServerError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
@@ -138,7 +137,7 @@ export class WorkspaceEntityManager extends EntityManager {
|
||||
override getRepository<Entity extends ObjectLiteral>(
|
||||
target: EntityTarget<Entity>,
|
||||
rolePermissionConfig?: RolePermissionConfig,
|
||||
authContext?: AuthContext,
|
||||
authContext?: WorkspaceAuthContext,
|
||||
): WorkspaceRepository<Entity> {
|
||||
const dataSource = this.connection;
|
||||
|
||||
@@ -239,7 +238,7 @@ export class WorkspaceEntityManager extends EntityManager {
|
||||
| QueryDeepPartialEntityWithNestedRelationFields<Entity>[],
|
||||
selectedColumns: string[] | '*' = '*',
|
||||
permissionOptions?: PermissionOptions,
|
||||
authContext?: AuthContext,
|
||||
authContext?: WorkspaceAuthContext,
|
||||
): Promise<InsertResult> {
|
||||
const metadata = this.connection.getMetadata(target);
|
||||
|
||||
@@ -250,7 +249,7 @@ export class WorkspaceEntityManager extends EntityManager {
|
||||
permissionOptions,
|
||||
)
|
||||
.insert()
|
||||
.setAuthContext(authContext ?? {})
|
||||
.setWorkspaceAuthContext(authContext ?? ({} as WorkspaceAuthContext))
|
||||
.values(entity)
|
||||
.returning(selectedColumns)
|
||||
.execute();
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@ import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interf
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { computeTwentyORMException } from 'src/engine/twenty-orm/error-handling/compute-twenty-orm-exception';
|
||||
import {
|
||||
TwentyORMException,
|
||||
@@ -38,14 +38,14 @@ export class WorkspaceDeleteQueryBuilder<
|
||||
private objectRecordsPermissions: ObjectsPermissions;
|
||||
private shouldBypassPermissionChecks: boolean;
|
||||
private internalContext: WorkspaceInternalContext;
|
||||
private authContext: AuthContext;
|
||||
private authContext: WorkspaceAuthContext;
|
||||
private featureFlagMap: FeatureFlagMap;
|
||||
constructor(
|
||||
queryBuilder: DeleteQueryBuilder<T>,
|
||||
objectRecordsPermissions: ObjectsPermissions,
|
||||
internalContext: WorkspaceInternalContext,
|
||||
shouldBypassPermissionChecks: boolean,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
featureFlagMap: FeatureFlagMap,
|
||||
) {
|
||||
super(queryBuilder);
|
||||
|
||||
+6
-4
@@ -11,7 +11,7 @@ import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interf
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type QueryDeepPartialEntityWithNestedRelationFields } from 'src/engine/twenty-orm/entity-manager/types/query-deep-partial-entity-with-nested-relation-fields.type';
|
||||
import { type RelationConnectQueryConfig } from 'src/engine/twenty-orm/entity-manager/types/relation-connect-query-config.type';
|
||||
import { type RelationDisconnectQueryFieldsByEntityIndex } from 'src/engine/twenty-orm/entity-manager/types/relation-nested-query-fields-by-entity-index.type';
|
||||
@@ -40,7 +40,7 @@ export class WorkspaceInsertQueryBuilder<
|
||||
private objectRecordsPermissions: ObjectsPermissions;
|
||||
private shouldBypassPermissionChecks: boolean;
|
||||
private internalContext: WorkspaceInternalContext;
|
||||
private authContext: AuthContext;
|
||||
private authContext: WorkspaceAuthContext;
|
||||
private featureFlagMap: FeatureFlagMap;
|
||||
private relationNestedConfig:
|
||||
| [RelationConnectQueryConfig[], RelationDisconnectQueryFieldsByEntityIndex]
|
||||
@@ -64,7 +64,7 @@ export class WorkspaceInsertQueryBuilder<
|
||||
objectRecordsPermissions: ObjectsPermissions,
|
||||
internalContext: WorkspaceInternalContext,
|
||||
shouldBypassPermissionChecks: boolean,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
featureFlagMap: FeatureFlagMap,
|
||||
) {
|
||||
super(queryBuilder);
|
||||
@@ -399,7 +399,9 @@ export class WorkspaceInsertQueryBuilder<
|
||||
);
|
||||
}
|
||||
|
||||
setAuthContext(authContext: AuthContext): WorkspaceInsertQueryBuilder<T> {
|
||||
setWorkspaceAuthContext(
|
||||
authContext: WorkspaceAuthContext,
|
||||
): WorkspaceInsertQueryBuilder<T> {
|
||||
this.authContext = authContext;
|
||||
|
||||
return this;
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialE
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
@@ -34,14 +34,14 @@ export class WorkspaceSelectQueryBuilder<
|
||||
objectRecordsPermissions: ObjectsPermissions;
|
||||
shouldBypassPermissionChecks: boolean;
|
||||
internalContext: WorkspaceInternalContext;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
featureFlagMap: FeatureFlagMap;
|
||||
constructor(
|
||||
queryBuilder: SelectQueryBuilder<T>,
|
||||
objectRecordsPermissions: ObjectsPermissions,
|
||||
internalContext: WorkspaceInternalContext,
|
||||
shouldBypassPermissionChecks: boolean,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
featureFlagMap: FeatureFlagMap,
|
||||
) {
|
||||
super(queryBuilder);
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@ import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interf
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { computeTwentyORMException } from 'src/engine/twenty-orm/error-handling/compute-twenty-orm-exception';
|
||||
import {
|
||||
TwentyORMException,
|
||||
@@ -36,7 +36,7 @@ export class WorkspaceSoftDeleteQueryBuilder<
|
||||
private objectRecordsPermissions: ObjectsPermissions;
|
||||
private shouldBypassPermissionChecks: boolean;
|
||||
private internalContext: WorkspaceInternalContext;
|
||||
private authContext: AuthContext;
|
||||
private authContext: WorkspaceAuthContext;
|
||||
private featureFlagMap: FeatureFlagMap;
|
||||
|
||||
constructor(
|
||||
@@ -44,7 +44,7 @@ export class WorkspaceSoftDeleteQueryBuilder<
|
||||
objectRecordsPermissions: ObjectsPermissions,
|
||||
internalContext: WorkspaceInternalContext,
|
||||
shouldBypassPermissionChecks: boolean,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
featureFlagMap: FeatureFlagMap,
|
||||
) {
|
||||
super(queryBuilder);
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interf
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type QueryDeepPartialEntityWithNestedRelationFields } from 'src/engine/twenty-orm/entity-manager/types/query-deep-partial-entity-with-nested-relation-fields.type';
|
||||
import { type RelationConnectQueryConfig } from 'src/engine/twenty-orm/entity-manager/types/relation-connect-query-config.type';
|
||||
import { type RelationDisconnectQueryFieldsByEntityIndex } from 'src/engine/twenty-orm/entity-manager/types/relation-nested-query-fields-by-entity-index.type';
|
||||
@@ -47,7 +47,7 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
private objectRecordsPermissions: ObjectsPermissions;
|
||||
private shouldBypassPermissionChecks: boolean;
|
||||
private internalContext: WorkspaceInternalContext;
|
||||
private authContext: AuthContext;
|
||||
private authContext: WorkspaceAuthContext;
|
||||
private featureFlagMap: FeatureFlagMap;
|
||||
private relationNestedConfig:
|
||||
| [RelationConnectQueryConfig[], RelationDisconnectQueryFieldsByEntityIndex]
|
||||
@@ -75,7 +75,7 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
objectRecordsPermissions: ObjectsPermissions,
|
||||
internalContext: WorkspaceInternalContext,
|
||||
shouldBypassPermissionChecks: boolean,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
featureFlagMap: FeatureFlagMap,
|
||||
) {
|
||||
super(queryBuilder);
|
||||
|
||||
@@ -22,7 +22,7 @@ import { type UpsertOptions } from 'typeorm/repository/UpsertOptions';
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
@@ -40,7 +40,7 @@ export class WorkspaceRepository<
|
||||
private shouldBypassPermissionChecks: boolean;
|
||||
private featureFlagMap: FeatureFlagMap;
|
||||
public readonly objectRecordsPermissions?: ObjectsPermissions;
|
||||
private authContext?: AuthContext;
|
||||
private authContext?: WorkspaceAuthContext;
|
||||
declare manager: WorkspaceEntityManager;
|
||||
|
||||
get internalContext(): WorkspaceInternalContext {
|
||||
@@ -54,7 +54,7 @@ export class WorkspaceRepository<
|
||||
queryRunner?: QueryRunner,
|
||||
objectRecordsPermissions?: ObjectsPermissions,
|
||||
shouldBypassPermissionChecks = false,
|
||||
authContext?: AuthContext,
|
||||
authContext?: WorkspaceAuthContext,
|
||||
) {
|
||||
super(target, manager, queryRunner);
|
||||
this.featureFlagMap = featureFlagMap;
|
||||
@@ -82,7 +82,7 @@ export class WorkspaceRepository<
|
||||
this.objectRecordsPermissions,
|
||||
this.internalContext,
|
||||
this.shouldBypassPermissionChecks,
|
||||
this.authContext ?? {},
|
||||
this.authContext ?? ({} as WorkspaceAuthContext),
|
||||
this.featureFlagMap,
|
||||
);
|
||||
}
|
||||
|
||||
+12
-6
@@ -1,18 +1,19 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { FeatureFlagKey } from 'twenty-shared/types';
|
||||
import {
|
||||
Brackets,
|
||||
NotBrackets,
|
||||
type ObjectLiteral,
|
||||
type WhereExpressionBuilder,
|
||||
} from 'typeorm';
|
||||
import { FeatureFlagKey } from 'twenty-shared/types';
|
||||
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { GraphqlQueryFilterFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
|
||||
import { buildRowLevelPermissionRecordFilter } from 'src/engine/twenty-orm/utils/build-row-level-permission-record-filter.util';
|
||||
@@ -21,7 +22,7 @@ type ApplyRowLevelPermissionPredicatesArgs<T extends ObjectLiteral> = {
|
||||
queryBuilder: WorkspaceSelectQueryBuilder<T>;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
internalContext: WorkspaceInternalContext;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
featureFlagMap: FeatureFlagMap;
|
||||
};
|
||||
|
||||
@@ -40,8 +41,11 @@ export const applyRowLevelPermissionPredicates = <T extends ObjectLiteral>({
|
||||
return;
|
||||
}
|
||||
|
||||
const roleId = authContext.userWorkspaceId
|
||||
? internalContext.userWorkspaceRoleMap[authContext.userWorkspaceId]
|
||||
const userWorkspaceId = isUserAuthContext(authContext)
|
||||
? authContext.userWorkspaceId
|
||||
: undefined;
|
||||
const roleId = userWorkspaceId
|
||||
? internalContext.userWorkspaceRoleMap[userWorkspaceId]
|
||||
: undefined;
|
||||
|
||||
const recordFilter = buildRowLevelPermissionRecordFilter({
|
||||
@@ -52,7 +56,9 @@ export const applyRowLevelPermissionPredicates = <T extends ObjectLiteral>({
|
||||
flatFieldMetadataMaps: internalContext.flatFieldMetadataMaps,
|
||||
objectMetadata,
|
||||
roleId,
|
||||
authContext,
|
||||
workspaceMember: isUserAuthContext(authContext)
|
||||
? authContext.workspaceMember
|
||||
: undefined,
|
||||
});
|
||||
|
||||
if (!recordFilter || Object.keys(recordFilter).length === 0) {
|
||||
|
||||
+8
-7
@@ -18,7 +18,7 @@ import {
|
||||
type RecordFilterGroup,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type UserWorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
@@ -38,7 +38,7 @@ type BuildRowLevelPermissionRecordFilterArgs = {
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
roleId: string | undefined;
|
||||
authContext: AuthContext;
|
||||
workspaceMember?: UserWorkspaceAuthContext['workspaceMember'];
|
||||
};
|
||||
|
||||
export const buildRowLevelPermissionRecordFilter = ({
|
||||
@@ -47,7 +47,7 @@ export const buildRowLevelPermissionRecordFilter = ({
|
||||
flatFieldMetadataMaps,
|
||||
objectMetadata,
|
||||
roleId,
|
||||
authContext,
|
||||
workspaceMember,
|
||||
}: BuildRowLevelPermissionRecordFilterArgs): RecordGqlOperationFilter | null => {
|
||||
if (!isDefined(roleId)) {
|
||||
return null;
|
||||
@@ -68,8 +68,6 @@ export const buildRowLevelPermissionRecordFilter = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const workspaceMember = authContext.workspaceMember;
|
||||
|
||||
const recordFilters = predicates
|
||||
.map((predicate) => {
|
||||
const fieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
@@ -114,9 +112,12 @@ export const buildRowLevelPermissionRecordFilter = ({
|
||||
const workspaceMemberSubFieldName =
|
||||
predicate.workspaceMemberSubFieldName;
|
||||
|
||||
if (!isDefined(rawWorkspaceMemberValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(workspaceMemberSubFieldName) &&
|
||||
isDefined(rawWorkspaceMemberValue) &&
|
||||
isCompositeFieldMetadataType(workspaceMemberFieldMetadata.type) &&
|
||||
typeof rawWorkspaceMemberValue === 'object'
|
||||
) {
|
||||
@@ -236,7 +237,7 @@ export const buildRowLevelPermissionRecordFilter = ({
|
||||
recordFilterGroups,
|
||||
fields: fieldMetadataItems,
|
||||
filterValueDependencies: {
|
||||
currentWorkspaceMemberId: authContext.workspaceMemberId,
|
||||
currentWorkspaceMemberId: workspaceMember?.id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import { type QueryExpressionMap } from 'typeorm/query-builder/QueryExpressionMa
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type WorkspaceDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-delete-query-builder';
|
||||
import { type WorkspaceInsertQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-insert-query-builder';
|
||||
import { WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
|
||||
@@ -18,7 +18,7 @@ type EventSelectQueryBuilderFactoryArgs<T extends ObjectLiteral> = {
|
||||
| WorkspaceSoftDeleteQueryBuilder<T>
|
||||
| WorkspaceDeleteQueryBuilder<T>
|
||||
| WorkspaceInsertQueryBuilder<T>;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
internalContext: WorkspaceInternalContext;
|
||||
featureFlagMap: FeatureFlagMap;
|
||||
expressionMap: QueryExpressionMap;
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import {
|
||||
import type { ObjectLiteral } from 'typeorm';
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import type { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -43,7 +43,7 @@ export const formatTwentyOrmEventToDatabaseBatchEvent = <
|
||||
objectMetadataItem: FlatObjectMetadata;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
workspaceId: string;
|
||||
authContext?: AuthContext;
|
||||
authContext?: RawAuthContext;
|
||||
recordsAfter?: T[];
|
||||
recordsBefore?: T[];
|
||||
}): DatabaseBatchEventInput<T, DatabaseEventAction> | undefined => {
|
||||
|
||||
+11
-5
@@ -5,7 +5,8 @@ import { type ObjectLiteral } from 'typeorm';
|
||||
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import {
|
||||
TwentyORMException,
|
||||
@@ -18,7 +19,7 @@ type ValidateRLSPredicatesForRecordsArgs<T extends ObjectLiteral> = {
|
||||
records: T[];
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
internalContext: WorkspaceInternalContext;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
shouldBypassPermissionChecks: boolean;
|
||||
errorMessage?: string;
|
||||
};
|
||||
@@ -35,8 +36,11 @@ export const validateRLSPredicatesForRecords = <T extends ObjectLiteral>({
|
||||
return;
|
||||
}
|
||||
|
||||
const roleId = authContext.userWorkspaceId
|
||||
? internalContext.userWorkspaceRoleMap[authContext.userWorkspaceId]
|
||||
const userWorkspaceId = isUserAuthContext(authContext)
|
||||
? authContext.userWorkspaceId
|
||||
: undefined;
|
||||
const roleId = userWorkspaceId
|
||||
? internalContext.userWorkspaceRoleMap[userWorkspaceId]
|
||||
: undefined;
|
||||
|
||||
if (!roleId) {
|
||||
@@ -51,7 +55,9 @@ export const validateRLSPredicatesForRecords = <T extends ObjectLiteral>({
|
||||
flatFieldMetadataMaps: internalContext.flatFieldMetadataMaps,
|
||||
objectMetadata,
|
||||
roleId,
|
||||
authContext,
|
||||
workspaceMember: isUserAuthContext(authContext)
|
||||
? authContext.workspaceMember
|
||||
: undefined,
|
||||
});
|
||||
|
||||
if (!recordFilter || Object.keys(recordFilter).length === 0) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { type Request } from 'express';
|
||||
import { type APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type RawAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
|
||||
export const bindDataToRequestObject = (
|
||||
data: AuthContext,
|
||||
data: RawAuthContext,
|
||||
request: Request,
|
||||
metadataVersion: number | undefined,
|
||||
) => {
|
||||
|
||||
+4
-13
@@ -1074,9 +1074,8 @@ describe('WorkspaceEventEmitterService', () => {
|
||||
|
||||
expect(buildRowLevelPermissionRecordFilter).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
authContext: expect.objectContaining({
|
||||
userWorkspaceId,
|
||||
workspaceMemberId,
|
||||
workspaceMember: expect.objectContaining({
|
||||
id: workspaceMemberId,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
@@ -1157,11 +1156,7 @@ describe('WorkspaceEventEmitterService', () => {
|
||||
|
||||
expect(buildRowLevelPermissionRecordFilter).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
authContext: expect.objectContaining({
|
||||
userWorkspaceId,
|
||||
workspaceMemberId,
|
||||
workspaceMember: customWorkspaceMember,
|
||||
}),
|
||||
workspaceMember: customWorkspaceMember,
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -1214,11 +1209,7 @@ describe('WorkspaceEventEmitterService', () => {
|
||||
|
||||
expect(buildRowLevelPermissionRecordFilter).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
authContext: expect.objectContaining({
|
||||
userWorkspaceId,
|
||||
workspaceMemberId,
|
||||
workspaceMember: undefined,
|
||||
}),
|
||||
workspaceMember: undefined,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
+3
-6
@@ -24,6 +24,7 @@ import { CommonSelectFieldsHelper } from 'src/engine/api/common/common-select-fi
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
|
||||
import { type SerializableAuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type FlatWorkspaceMemberMaps } from 'src/engine/core-modules/user/types/flat-workspace-member-maps.type';
|
||||
import { type MetadataEventBatch } from 'src/engine/metadata-event-emitter/types/metadata-event-batch.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
@@ -463,7 +464,7 @@ export class WorkspaceEventEmitterService {
|
||||
flatFieldMetadataMaps,
|
||||
parentObjectMetadataItem: objectMetadata,
|
||||
parentObjectRecords: allRecords,
|
||||
authContext: streamData.authContext,
|
||||
authContext: streamData.authContext as unknown as WorkspaceAuthContext,
|
||||
limit: QUERY_MAX_RECORDS_FROM_RELATION,
|
||||
rolePermissionConfig,
|
||||
workspaceDataSource: globalWorkspaceDataSource,
|
||||
@@ -498,11 +499,7 @@ export class WorkspaceEventEmitterService {
|
||||
flatFieldMetadataMaps: permissionsContext.flatFieldMetadataMaps,
|
||||
objectMetadata,
|
||||
roleId,
|
||||
authContext: {
|
||||
userWorkspaceId: subscriberAuthContext.userWorkspaceId,
|
||||
workspaceMemberId: subscriberAuthContext.workspaceMemberId,
|
||||
workspaceMember,
|
||||
},
|
||||
workspaceMember,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+6
-12
@@ -1,17 +1,15 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
import { type CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import {
|
||||
type BlocklistItem,
|
||||
BlocklistValidationService,
|
||||
} from 'src/modules/blocklist/blocklist-validation-manager/services/blocklist-validation.service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
|
||||
@WorkspaceQueryHook(`blocklist.createMany`)
|
||||
export class BlocklistCreateManyPreQueryHook
|
||||
@@ -22,22 +20,18 @@ export class BlocklistCreateManyPreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CreateManyResolverArgs<BlocklistItem>,
|
||||
): Promise<CreateManyResolverArgs<BlocklistItem>> {
|
||||
if (!authContext.user?.id) {
|
||||
if (!isUserAuthContext(authContext)) {
|
||||
throw new BadRequestException('User id is required');
|
||||
}
|
||||
|
||||
const workspace = authContext.workspace;
|
||||
|
||||
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
|
||||
|
||||
await this.blocklistValidationService.validateBlocklistForCreateMany(
|
||||
payload,
|
||||
authContext.user?.id,
|
||||
workspace.id,
|
||||
authContext.user.id,
|
||||
authContext.workspace.id,
|
||||
);
|
||||
|
||||
return payload;
|
||||
|
||||
+5
-9
@@ -1,17 +1,15 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
import { type UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import {
|
||||
type BlocklistItem,
|
||||
BlocklistValidationService,
|
||||
} from 'src/modules/blocklist/blocklist-validation-manager/services/blocklist-validation.service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
|
||||
@WorkspaceQueryHook(`blocklist.updateOne`)
|
||||
export class BlocklistUpdateOnePreQueryHook
|
||||
@@ -22,21 +20,19 @@ export class BlocklistUpdateOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: UpdateOneResolverArgs<BlocklistItem>,
|
||||
): Promise<UpdateOneResolverArgs<BlocklistItem>> {
|
||||
if (!authContext.user?.id) {
|
||||
if (!isUserAuthContext(authContext)) {
|
||||
throw new BadRequestException('User id is required');
|
||||
}
|
||||
|
||||
const workspace = authContext.workspace;
|
||||
|
||||
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
|
||||
|
||||
await this.blocklistValidationService.validateBlocklistForUpdateOne(
|
||||
payload,
|
||||
authContext.user?.id,
|
||||
authContext.user.id,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
|
||||
+10
-10
@@ -1,10 +1,9 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
|
||||
@@ -22,20 +21,21 @@ export class CalendarEventFindManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CalendarEventWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
const { user, apiKey, application } = authContext;
|
||||
const isUserContext = isUserAuthContext(authContext);
|
||||
const userId = isUserContext ? authContext.user.id : undefined;
|
||||
|
||||
const isTwentyStandardApplication =
|
||||
isDefined(application) &&
|
||||
application.universalIdentifier ===
|
||||
authContext.type === 'application' &&
|
||||
authContext.application.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier;
|
||||
|
||||
if (
|
||||
!isDefined(user) &&
|
||||
!isDefined(apiKey) &&
|
||||
!isUserContext &&
|
||||
authContext.type !== 'apiKey' &&
|
||||
!isTwentyStandardApplication
|
||||
) {
|
||||
throw new ForbiddenError('Authentication is required');
|
||||
@@ -50,7 +50,7 @@ export class CalendarEventFindManyPostQueryHook
|
||||
await this.applyCalendarEventsVisibilityRestrictionsService.applyCalendarEventsVisibilityRestrictions(
|
||||
payload,
|
||||
workspace.id,
|
||||
user?.id,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,10 +1,9 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
|
||||
@@ -22,20 +21,21 @@ export class CalendarEventFindOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CalendarEventWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
const { user, apiKey, application } = authContext;
|
||||
const isUserContext = isUserAuthContext(authContext);
|
||||
const userId = isUserContext ? authContext.user.id : undefined;
|
||||
|
||||
const isTwentyStandardApplication =
|
||||
isDefined(application) &&
|
||||
application.universalIdentifier ===
|
||||
authContext.type === 'application' &&
|
||||
authContext.application.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier;
|
||||
|
||||
if (
|
||||
!isDefined(user) &&
|
||||
!isDefined(apiKey) &&
|
||||
!isUserContext &&
|
||||
authContext.type !== 'apiKey' &&
|
||||
!isTwentyStandardApplication
|
||||
) {
|
||||
throw new ForbiddenError('Authentication is required');
|
||||
@@ -50,7 +50,7 @@ export class CalendarEventFindOnePostQueryHook
|
||||
await this.applyCalendarEventsVisibilityRestrictionsService.applyCalendarEventsVisibilityRestrictions(
|
||||
payload,
|
||||
workspace.id,
|
||||
user?.id,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -6,7 +6,6 @@ import { type DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-res
|
||||
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
@@ -26,7 +25,7 @@ export class ConnectedAccountDeleteOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: DeleteOneResolverArgs,
|
||||
): Promise<DeleteOneResolverArgs> {
|
||||
@@ -49,7 +48,7 @@ export class ConnectedAccountDeleteOnePreQueryHook
|
||||
connectedAccountId,
|
||||
});
|
||||
},
|
||||
authContext as WorkspaceAuthContext,
|
||||
authContext,
|
||||
);
|
||||
|
||||
const { flatObjectMetadataMaps } =
|
||||
|
||||
+4
-21
@@ -1,21 +1,13 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Query } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
AuthContext,
|
||||
type AuthContextUser,
|
||||
} from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { getWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace-member-id.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { BarChartDataInput } from 'src/modules/dashboard/chart-data/dtos/inputs/bar-chart-data.input';
|
||||
import { BarChartDataDTO } from 'src/modules/dashboard/chart-data/dtos/bar-chart-data.dto';
|
||||
import { BarChartDataInput } from 'src/modules/dashboard/chart-data/dtos/inputs/bar-chart-data.input';
|
||||
import { ChartDataGraphqlApiExceptionFilter } from 'src/modules/dashboard/chart-data/filters/chart-data-graphql-api-exception.filter';
|
||||
import { BarChartDataService } from 'src/modules/dashboard/chart-data/services/bar-chart-data.service';
|
||||
|
||||
@@ -30,22 +22,13 @@ export class BarChartDataResolver {
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async barChartData(
|
||||
@Args('input') input: BarChartDataInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthUser() user: AuthContextUser,
|
||||
@AuthWorkspaceMemberId() workspaceMemberId: string,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string,
|
||||
): Promise<BarChartDataDTO> {
|
||||
const authContext: AuthContext = {
|
||||
user,
|
||||
workspace,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
};
|
||||
const authContext = getWorkspaceAuthContext();
|
||||
|
||||
return this.barChartDataService.getBarChartData({
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
configuration: input.configuration,
|
||||
workspaceId: workspace.id,
|
||||
workspaceId: authContext.workspace.id,
|
||||
authContext,
|
||||
});
|
||||
}
|
||||
|
||||
+3
-20
@@ -1,17 +1,9 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Query } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
AuthContext,
|
||||
type AuthContextUser,
|
||||
} from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { getWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace-member-id.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { LineChartDataInput } from 'src/modules/dashboard/chart-data/dtos/inputs/line-chart-data.input';
|
||||
@@ -30,22 +22,13 @@ export class LineChartDataResolver {
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async lineChartData(
|
||||
@Args('input') input: LineChartDataInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthUser() user: AuthContextUser,
|
||||
@AuthWorkspaceMemberId() workspaceMemberId: string,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string,
|
||||
): Promise<LineChartDataDTO> {
|
||||
const authContext: AuthContext = {
|
||||
user,
|
||||
workspace,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
};
|
||||
const authContext = getWorkspaceAuthContext();
|
||||
|
||||
return this.lineChartDataService.getLineChartData({
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
configuration: input.configuration,
|
||||
workspaceId: workspace.id,
|
||||
workspaceId: authContext.workspace.id,
|
||||
authContext,
|
||||
});
|
||||
}
|
||||
|
||||
+3
-20
@@ -1,17 +1,9 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Query } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
AuthContext,
|
||||
type AuthContextUser,
|
||||
} from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { getWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace-member-id.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { PieChartDataInput } from 'src/modules/dashboard/chart-data/dtos/inputs/pie-chart-data.input';
|
||||
@@ -30,22 +22,13 @@ export class PieChartDataResolver {
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async pieChartData(
|
||||
@Args('input') input: PieChartDataInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthUser() user: AuthContextUser,
|
||||
@AuthWorkspaceMemberId() workspaceMemberId: string,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string,
|
||||
): Promise<PieChartDataDTO> {
|
||||
const authContext: AuthContext = {
|
||||
user,
|
||||
workspace,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
};
|
||||
const authContext = getWorkspaceAuthContext();
|
||||
|
||||
return this.pieChartDataService.getPieChartData({
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
configuration: input.configuration,
|
||||
workspaceId: workspace.id,
|
||||
workspaceId: authContext.workspace.id,
|
||||
authContext,
|
||||
});
|
||||
}
|
||||
|
||||
+5
-4
@@ -2,7 +2,7 @@ import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { AggregateOperations, FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { BarChartGroupMode } from 'src/engine/metadata-modules/page-layout-widget/enums/bar-chart-group-mode.enum';
|
||||
import { BarChartLayout } from 'src/engine/metadata-modules/page-layout-widget/enums/bar-chart-layout.enum';
|
||||
@@ -17,9 +17,10 @@ describe('BarChartDataService', () => {
|
||||
let mockGetOrRecomputeManyOrAllFlatEntityMaps: jest.Mock;
|
||||
|
||||
const workspaceId = 'test-workspace-id';
|
||||
const mockAuthContext: AuthContext = {
|
||||
workspace: { id: workspaceId } as any,
|
||||
};
|
||||
const mockAuthContext = {
|
||||
type: 'system',
|
||||
workspace: { id: workspaceId },
|
||||
} as unknown as WorkspaceAuthContext;
|
||||
const objectMetadataId = 'test-object-id';
|
||||
|
||||
const mockGroupByField = {
|
||||
|
||||
+5
-4
@@ -2,7 +2,7 @@ import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { AggregateOperations, FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS } from 'src/modules/dashboard/chart-data/constants/line-chart-maximum-number-of-data-points.constant';
|
||||
@@ -14,9 +14,10 @@ describe('LineChartDataService', () => {
|
||||
let mockExecuteGroupByQuery: jest.Mock;
|
||||
|
||||
const workspaceId = 'test-workspace-id';
|
||||
const mockAuthContext: AuthContext = {
|
||||
workspace: { id: workspaceId } as any,
|
||||
};
|
||||
const mockAuthContext = {
|
||||
type: 'system',
|
||||
workspace: { id: workspaceId },
|
||||
} as unknown as WorkspaceAuthContext;
|
||||
const objectMetadataId = 'test-object-id';
|
||||
|
||||
const mockGroupByFieldX = {
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@ import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { AggregateOperations, FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PIE_CHART_MAXIMUM_NUMBER_OF_SLICES } from 'src/modules/dashboard/chart-data/constants/pie-chart-maximum-number-of-slices.constant';
|
||||
@@ -15,9 +15,10 @@ describe('PieChartDataService', () => {
|
||||
let mockGetOrRecomputeManyOrAllFlatEntityMaps: jest.Mock;
|
||||
|
||||
const workspaceId = 'test-workspace-id';
|
||||
const mockAuthContext: AuthContext = {
|
||||
const mockAuthContext = {
|
||||
type: 'system',
|
||||
workspace: { id: workspaceId } as any,
|
||||
};
|
||||
} as unknown as WorkspaceAuthContext;
|
||||
const objectMetadataId = 'test-object-id';
|
||||
|
||||
const mockGroupByField = {
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import {
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -44,7 +44,7 @@ type GetBarChartDataParams = {
|
||||
workspaceId: string;
|
||||
objectMetadataId: string;
|
||||
configuration: BarChartConfigurationDTO;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ import {
|
||||
import { ObjectRecordGroupBy } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { CommonGroupByQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-group-by-query-runner.service';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -45,7 +45,7 @@ type ExecuteGroupByQueryParams = {
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
objectIdByNameSingular: Record<string, string>;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
groupByFieldMetadataId: string;
|
||||
groupBySubFieldName?: string | null;
|
||||
aggregateFieldMetadataId: string;
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import {
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -43,7 +43,7 @@ type GetLineChartDataParams = {
|
||||
workspaceId: string;
|
||||
objectMetadataId: string;
|
||||
configuration: LineChartConfigurationDTO;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import {
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -31,7 +31,7 @@ type GetPieChartDataParams = {
|
||||
workspaceId: string;
|
||||
objectMetadataId: string;
|
||||
configuration: PieChartConfigurationDTO;
|
||||
authContext: AuthContext;
|
||||
authContext: WorkspaceAuthContext;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import { Controller, Param, Post, UseFilters, UseGuards } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
AuthContext,
|
||||
type AuthContextUser,
|
||||
} from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace-member-id.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { getWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
|
||||
import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
@@ -25,19 +17,8 @@ export class DashboardController {
|
||||
) {}
|
||||
|
||||
@Post(':id/duplicate')
|
||||
async duplicate(
|
||||
@Param('id') id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthUser() user: AuthContextUser,
|
||||
@AuthWorkspaceMemberId() workspaceMemberId: string,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string,
|
||||
): Promise<DuplicatedDashboardDTO> {
|
||||
const authContext: AuthContext = {
|
||||
user,
|
||||
workspace,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
};
|
||||
async duplicate(@Param('id') id: string): Promise<DuplicatedDashboardDTO> {
|
||||
const authContext = getWorkspaceAuthContext();
|
||||
|
||||
return this.dashboardDuplicationService.duplicateDashboard(id, authContext);
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { DashboardToPageLayoutSyncService } from 'src/modules/dashboard/services/dashboard-to-page-layout-sync.service';
|
||||
import { type DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
|
||||
@@ -21,7 +21,7 @@ export class DashboardCreateManyPreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CreateManyResolverArgs<DashboardWorkspaceEntity>,
|
||||
): Promise<CreateManyResolverArgs<DashboardWorkspaceEntity>> {
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { DashboardToPageLayoutSyncService } from 'src/modules/dashboard/services/dashboard-to-page-layout-sync.service';
|
||||
import { type DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
|
||||
@@ -21,7 +21,7 @@ export class DashboardCreateOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CreateOneResolverArgs<DashboardWorkspaceEntity>,
|
||||
): Promise<CreateOneResolverArgs<DashboardWorkspaceEntity>> {
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type DestroyManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { DashboardToPageLayoutSyncService } from 'src/modules/dashboard/services/dashboard-to-page-layout-sync.service';
|
||||
|
||||
@@ -20,7 +20,7 @@ export class DashboardDestroyManyPreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: DestroyManyResolverArgs<{ id: { in: string[] } }>,
|
||||
): Promise<DestroyManyResolverArgs<{ id: { in: string[] } }>> {
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type DestroyOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { DashboardToPageLayoutSyncService } from 'src/modules/dashboard/services/dashboard-to-page-layout-sync.service';
|
||||
|
||||
@@ -20,7 +20,7 @@ export class DashboardDestroyOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: DestroyOneResolverArgs,
|
||||
): Promise<DestroyOneResolverArgs> {
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Mutation } from '@nestjs/graphql';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import {
|
||||
AuthContext,
|
||||
type AuthContextUser,
|
||||
} from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { getWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace-member-id.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
|
||||
@@ -36,17 +28,8 @@ export class DashboardResolver {
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async duplicateDashboard(
|
||||
@Args('id', { type: () => UUIDScalarType }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthUser() user: AuthContextUser,
|
||||
@AuthWorkspaceMemberId() workspaceMemberId: string,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string,
|
||||
): Promise<DuplicatedDashboardDTO> {
|
||||
const authContext: AuthContext = {
|
||||
user,
|
||||
workspace,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
};
|
||||
const authContext = getWorkspaceAuthContext();
|
||||
|
||||
return this.dashboardDuplicationService.duplicateDashboard(id, authContext);
|
||||
}
|
||||
|
||||
+6
-15
@@ -1,15 +1,9 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
appendCopySuffix,
|
||||
assertIsDefinedOrThrow,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
import { appendCopySuffix, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { ActorFromAuthContextService } from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { PageLayoutDuplicationService } from 'src/engine/metadata-modules/page-layout/services/page-layout-duplication.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
@@ -34,12 +28,9 @@ export class DashboardDuplicationService {
|
||||
|
||||
async duplicateDashboard(
|
||||
dashboardId: string,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
): Promise<DuplicatedDashboardDTO> {
|
||||
const { workspace } = authContext;
|
||||
|
||||
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
|
||||
|
||||
const workspace = authContext.workspace;
|
||||
const workspaceId = workspace.id;
|
||||
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
@@ -106,7 +97,7 @@ export class DashboardDuplicationService {
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
authContext as WorkspaceAuthContext,
|
||||
authContext,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,7 +105,7 @@ export class DashboardDuplicationService {
|
||||
originalDashboard: DashboardWorkspaceEntity,
|
||||
newPageLayoutId: string,
|
||||
dashboardRepository: WorkspaceRepository<DashboardWorkspaceEntity>,
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
): Promise<DashboardWorkspaceEntity> {
|
||||
const newTitle = appendCopySuffix(originalDashboard.title ?? '');
|
||||
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import {
|
||||
WorkspaceQueryRunnerException,
|
||||
WorkspaceQueryRunnerExceptionCode,
|
||||
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
@@ -45,7 +45,7 @@ export class MessageChannelUpdateOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: UpdateOneResolverArgs<MessageChannelWorkspaceEntity>,
|
||||
): Promise<UpdateOneResolverArgs<MessageChannelWorkspaceEntity>> {
|
||||
|
||||
+12
-11
@@ -1,10 +1,9 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service';
|
||||
@@ -22,20 +21,18 @@ export class MessageFindManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: MessageWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
const { user, apiKey, application } = authContext;
|
||||
|
||||
const isTwentyStandardApplication =
|
||||
isDefined(application) &&
|
||||
application.universalIdentifier ===
|
||||
authContext.type === 'application' &&
|
||||
authContext.application.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier;
|
||||
|
||||
if (
|
||||
!isDefined(user) &&
|
||||
!isDefined(apiKey) &&
|
||||
authContext.type !== 'user' &&
|
||||
authContext.type !== 'apiKey' &&
|
||||
!isTwentyStandardApplication
|
||||
) {
|
||||
throw new ForbiddenError('Authentication is required');
|
||||
@@ -47,10 +44,14 @@ export class MessageFindManyPostQueryHook
|
||||
throw new ForbiddenError('Workspace is required');
|
||||
}
|
||||
|
||||
const userId = isUserAuthContext(authContext)
|
||||
? authContext.user.id
|
||||
: undefined;
|
||||
|
||||
await this.applyMessagesVisibilityRestrictionsService.applyMessagesVisibilityRestrictions(
|
||||
payload,
|
||||
workspace.id,
|
||||
user?.id,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-11
@@ -1,10 +1,11 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard';
|
||||
import { isApplicationAuthContext } from 'src/engine/core-modules/auth/guards/is-application-auth-context.guard';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service';
|
||||
@@ -22,20 +23,18 @@ export class MessageFindOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: MessageWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
const { user, apiKey, application } = authContext;
|
||||
|
||||
const isTwentyStandardApplication =
|
||||
isDefined(application) &&
|
||||
application.universalIdentifier ===
|
||||
isApplicationAuthContext(authContext) &&
|
||||
authContext.application.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier;
|
||||
|
||||
if (
|
||||
!isDefined(user) &&
|
||||
!isDefined(apiKey) &&
|
||||
!isUserAuthContext(authContext) &&
|
||||
!isApiKeyAuthContext(authContext) &&
|
||||
!isTwentyStandardApplication
|
||||
) {
|
||||
throw new ForbiddenError('Authentication is required');
|
||||
@@ -47,10 +46,14 @@ export class MessageFindOnePostQueryHook
|
||||
throw new ForbiddenError('Workspace is required');
|
||||
}
|
||||
|
||||
const userId = isUserAuthContext(authContext)
|
||||
? authContext.user.id
|
||||
: undefined;
|
||||
|
||||
await this.applyMessagesVisibilityRestrictionsService.applyMessagesVisibilityRestrictions(
|
||||
payload,
|
||||
workspace.id,
|
||||
user?.id,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { NotePostQueryHookService } from 'src/modules/note/query-hooks/note-post-query-hook.service';
|
||||
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class NoteDeleteManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: NoteWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { NotePostQueryHookService } from 'src/modules/note/query-hooks/note-post-query-hook.service';
|
||||
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class NoteDeleteOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: NoteWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
|
||||
@@ -17,7 +16,7 @@ export class NotePostQueryHookService {
|
||||
) {}
|
||||
|
||||
async handleNoteTargetsDelete(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
payload: NoteWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
if (!payload || payload?.length === 0) {
|
||||
@@ -38,11 +37,11 @@ export class NotePostQueryHookService {
|
||||
await noteTargetRepository.softDelete({
|
||||
noteId: In(payload.map((note) => note.id)),
|
||||
});
|
||||
}, authContext as WorkspaceAuthContext);
|
||||
}, authContext);
|
||||
}
|
||||
|
||||
async handleNoteTargetsRestore(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
payload: NoteWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
if (!payload || payload?.length === 0) {
|
||||
@@ -63,6 +62,6 @@ export class NotePostQueryHookService {
|
||||
await noteTargetRepository.restore({
|
||||
noteId: In(payload.map((note) => note.id)),
|
||||
});
|
||||
}, authContext as WorkspaceAuthContext);
|
||||
}, authContext);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { NotePostQueryHookService } from 'src/modules/note/query-hooks/note-post-query-hook.service';
|
||||
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class NoteRestoreManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: NoteWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { NotePostQueryHookService } from 'src/modules/note/query-hooks/note-post-query-hook.service';
|
||||
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class NoteRestoreOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: NoteWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { TaskPostQueryHookService } from 'src/modules/task/query-hooks/task-post-query-hook.service';
|
||||
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class TaskDeleteManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: TaskWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { TaskPostQueryHookService } from 'src/modules/task/query-hooks/task-post-query-hook.service';
|
||||
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class TaskDeleteOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: TaskWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
|
||||
@@ -17,7 +16,7 @@ export class TaskPostQueryHookService {
|
||||
) {}
|
||||
|
||||
async handleTaskTargetsDelete(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
payload: TaskWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
if (!payload || payload?.length === 0) {
|
||||
@@ -38,11 +37,11 @@ export class TaskPostQueryHookService {
|
||||
await taskTargetRepository.softDelete({
|
||||
taskId: In(payload.map((task) => task.id)),
|
||||
});
|
||||
}, authContext as WorkspaceAuthContext);
|
||||
}, authContext);
|
||||
}
|
||||
|
||||
async handleTaskTargetsRestore(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
payload: TaskWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
if (!payload || payload?.length === 0) {
|
||||
@@ -63,6 +62,6 @@ export class TaskPostQueryHookService {
|
||||
await taskTargetRepository.restore({
|
||||
taskId: In(payload.map((task) => task.id)),
|
||||
});
|
||||
}, authContext as WorkspaceAuthContext);
|
||||
}, authContext);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { TaskPostQueryHookService } from 'src/modules/task/query-hooks/task-post-query-hook.service';
|
||||
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class TaskRestoreManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: TaskWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { TaskPostQueryHookService } from 'src/modules/task/query-hooks/task-post-query-hook.service';
|
||||
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
|
||||
|
||||
@@ -21,7 +21,7 @@ export class TaskRestoreOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: TaskWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+3
-4
@@ -2,10 +2,9 @@ import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
@@ -28,7 +27,7 @@ export class WorkflowCreateManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: WorkflowWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
@@ -64,6 +63,6 @@ export class WorkflowCreateManyPostQueryHook
|
||||
return workflowVersionRepository.insert(workflowVersion);
|
||||
}),
|
||||
);
|
||||
}, authContext as WorkspaceAuthContext);
|
||||
}, authContext);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { assertWorkflowStatusesNotSetOrEmpty } from 'src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty';
|
||||
|
||||
@@ -11,7 +11,7 @@ export class WorkflowCreateManyPreQueryHook
|
||||
implements WorkspacePreQueryHookInstance
|
||||
{
|
||||
async execute(
|
||||
_authContext: AuthContext,
|
||||
_authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CreateManyResolverArgs<WorkflowWorkspaceEntity>,
|
||||
): Promise<CreateManyResolverArgs<WorkflowWorkspaceEntity>> {
|
||||
|
||||
+3
-4
@@ -2,10 +2,9 @@ import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
@@ -28,7 +27,7 @@ export class WorkflowCreateOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: WorkflowWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
@@ -60,6 +59,6 @@ export class WorkflowCreateOnePostQueryHook
|
||||
name: 'v1',
|
||||
position,
|
||||
});
|
||||
}, authContext as WorkspaceAuthContext);
|
||||
}, authContext);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { assertWorkflowStatusesNotSetOrEmpty } from 'src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty';
|
||||
|
||||
@@ -11,7 +11,7 @@ export class WorkflowCreateOnePreQueryHook
|
||||
implements WorkspacePreQueryHookInstance
|
||||
{
|
||||
async execute(
|
||||
_authContext: AuthContext,
|
||||
_authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: CreateOneResolverArgs<WorkflowWorkspaceEntity>,
|
||||
): Promise<CreateOneResolverArgs<WorkflowWorkspaceEntity>> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
@@ -21,7 +21,7 @@ export class WorkflowDeleteManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: WorkflowWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
@@ -21,7 +21,7 @@ export class WorkflowDeleteOnePostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: WorkflowWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type DestroyManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
|
||||
@@ -17,7 +17,7 @@ export class WorkflowDestroyManyPreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: DestroyManyResolverArgs<{ id: { in: string[] } }>,
|
||||
): Promise<DestroyManyResolverArgs<{ id: { in: string[] } }>> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
|
||||
import { type DestroyOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
|
||||
@@ -17,7 +17,7 @@ export class WorkflowDestroyOnePreQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: DestroyOneResolverArgs,
|
||||
): Promise<DestroyOneResolverArgs> {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type WorkspacePostQueryHookInstance } from 'src/engine/api/graphql/work
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
@@ -21,7 +21,7 @@ export class WorkflowRestoreManyPostQueryHook
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
authContext: WorkspaceAuthContext,
|
||||
_objectName: string,
|
||||
payload: WorkflowWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user