Improve workspace auth context surface (#18164)

This commit is contained in:
Weiko
2026-03-05 16:13:59 +01:00
committed by GitHub
parent 5853891b02
commit cfeea43eaf
118 changed files with 453 additions and 677 deletions
@@ -4,7 +4,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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberCreateManyPreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<CreateManyResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<CreateManyResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -4,7 +4,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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberCreateOnePreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<CreateOneResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<CreateOneResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -8,7 +8,7 @@ import {
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
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';
@WorkspaceQueryHook(`workspaceMember.deleteMany`)
export class WorkspaceMemberDeleteManyPreQueryHook
@@ -16,7 +16,9 @@ export class WorkspaceMemberDeleteManyPreQueryHook
{
constructor() {}
async execute(_authContext: AuthContext): Promise<DeleteManyResolverArgs> {
async execute(
_authContext: WorkspaceAuthContext,
): Promise<DeleteManyResolverArgs> {
throw new CommonQueryRunnerException(
'Please use /deleteUserFromWorkspace to remove a workspace member.',
CommonQueryRunnerExceptionCode.BAD_REQUEST,
@@ -5,10 +5,11 @@ import { Repository } from 'typeorm';
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 { 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 { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@@ -36,7 +37,7 @@ export class WorkspaceMemberDeleteOnePostQueryHook
) {}
async execute(
authContext: AuthContext,
authContext: WorkspaceAuthContext,
_objectName: string,
payload: WorkspaceMemberWorkspaceEntity[],
): Promise<void> {
@@ -53,11 +54,17 @@ export class WorkspaceMemberDeleteOnePostQueryHook
await this.workspaceMemberPreQueryHookService.validateWorkspaceMemberUpdatePermissionOrThrow(
{
userWorkspaceId: authContext.userWorkspaceId,
workspaceMemberId: authContext.workspaceMemberId,
userWorkspaceId: isUserAuthContext(authContext)
? authContext.userWorkspaceId
: undefined,
workspaceMemberId: isUserAuthContext(authContext)
? authContext.workspaceMemberId
: undefined,
targettedWorkspaceMemberId,
workspaceId: workspace.id,
apiKey: authContext.apiKey,
apiKey: isApiKeyAuthContext(authContext)
? authContext.apiKey
: undefined,
},
);
@@ -77,7 +84,7 @@ export class WorkspaceMemberDeleteOnePostQueryHook
withDeleted: true,
});
},
authContext as WorkspaceAuthContext,
authContext,
);
if (!isDefined(workspaceMember)) {
@@ -8,7 +8,7 @@ import {
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
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';
@WorkspaceQueryHook(`workspaceMember.deleteOne`)
export class WorkspaceMemberDeleteOnePreQueryHook
@@ -16,7 +16,9 @@ export class WorkspaceMemberDeleteOnePreQueryHook
{
constructor() {}
async execute(_authContext: AuthContext): Promise<RestoreOneResolverArgs> {
async execute(
_authContext: WorkspaceAuthContext,
): Promise<RestoreOneResolverArgs> {
throw new CommonQueryRunnerException(
'Please use /deleteUserFromWorkspace to remove a workspace member.',
CommonQueryRunnerExceptionCode.BAD_REQUEST,
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
import { type DeleteManyResolverArgs } 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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberDestroyManyPreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<DeleteManyResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<DeleteManyResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
import { type DeleteOneResolverArgs } 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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberDestroyOnePreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<DeleteOneResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<DeleteOneResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
import { type RestoreManyResolverArgs } 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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberRestoreManyPreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<RestoreManyResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<RestoreManyResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
import { type RestoreOneResolverArgs } 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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberRestoreOnePreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<RestoreOneResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<RestoreOneResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -4,7 +4,7 @@ import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/works
import { type UpdateManyResolverArgs } 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 {
PermissionsException,
PermissionsExceptionCode,
@@ -18,7 +18,9 @@ export class WorkspaceMemberUpdateManyPreQueryHook
{
constructor() {}
async execute(authContext: AuthContext): Promise<UpdateManyResolverArgs> {
async execute(
authContext: WorkspaceAuthContext,
): Promise<UpdateManyResolverArgs> {
const workspace = authContext.workspace;
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
@@ -12,7 +12,9 @@ import {
AuthException,
AuthExceptionCode,
} from 'src/engine/core-modules/auth/auth.exception';
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 { 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 { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
import { WorkspaceMemberPreQueryHookService } from 'src/modules/workspace-member/query-hooks/workspace-member-pre-query-hook.service';
@@ -28,7 +30,7 @@ export class WorkspaceMemberUpdateOnePreQueryHook
) {}
async execute(
authContext: AuthContext,
authContext: WorkspaceAuthContext,
_objectName: string,
payload: UpdateOneResolverArgs,
): Promise<UpdateOneResolverArgs> {
@@ -38,16 +40,22 @@ export class WorkspaceMemberUpdateOnePreQueryHook
await this.workspaceMemberPreQueryHookService.validateWorkspaceMemberUpdatePermissionOrThrow(
{
userWorkspaceId: authContext.userWorkspaceId,
userWorkspaceId: isUserAuthContext(authContext)
? authContext.userWorkspaceId
: undefined,
targettedWorkspaceMemberId: payload.id,
workspaceId: workspace.id,
apiKey: authContext.apiKey,
workspaceMemberId: authContext.workspaceMemberId,
apiKey: isApiKeyAuthContext(authContext)
? authContext.apiKey
: undefined,
workspaceMemberId: isUserAuthContext(authContext)
? authContext.workspaceMemberId
: undefined,
},
);
// TODO: remove this code once we have migrated locale update to userWorkspace update
if (payload.data.locale) {
if (payload.data.locale && isUserAuthContext(authContext)) {
const userWorkspace = await this.userWorkspaceRepository.findOne({
where: {
id: authContext.userWorkspaceId,
@@ -69,7 +77,9 @@ export class WorkspaceMemberUpdateOnePreQueryHook
await this.workspaceMemberPreQueryHookService.completeOnboardingProfileStepIfNameProvided(
{
userId: authContext.user?.id,
userId: isUserAuthContext(authContext)
? authContext.user.id
: undefined,
workspaceId: workspace.id,
firstName: payload.data.name?.firstName,
lastName: payload.data.name?.lastName,