Add WorkspaceAuthContextMiddleware (#17487)

## Context
Introduces a middleware that automatically sets the workspace auth
context in AsyncLocalStorage for HTTP requests, making it available
throughout the request lifecycle without explicit parameter passing.

The motivation behind this change is to reduce boilerplate and simplify
the developer experience when working with workspace data in HTTP
request handlers.

The Problem (Before)
Every HTTP request handler that needed to access workspace data had to:
- Extract auth-related info from decorators (@AuthWorkspace(),
@AuthUserWorkspaceId(), etc.) in controller/resolver and pass down to
services
- Build or pass the authContext explicitly (sometimes with type
assertion which was flaky)
Then call executeInWorkspaceContext(authContext, async () => { ... })

## Changes
- Add WorkspaceAuthContextMiddleware that extracts auth context from the
request and stores it in AsyncLocalStorage
- Register middleware for GraphQL, metadata, and REST routes (runs after
hydration middlewares)
- Simplify executeInWorkspaceContext signature: fn is now the first
parameter, authContext is optional second
- If authContext is not provided, it's automatically retrieved from the
storage (set by middleware)
- Update all callers (~120 files) to use the new parameter order


- Fixes a bug in search where system auth context was used, bypassing
RLS feature.
This commit is contained in:
Weiko
2026-01-27 17:24:51 +00:00
committed by GitHub
parent dd98146c99
commit 2daebc6d0f
151 changed files with 3743 additions and 4002 deletions
@@ -45,7 +45,7 @@ describe('ActorFromAuthContextService', () => {
getRepository: jest.fn().mockResolvedValue(mockWorkspaceMemberRepository),
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
};
beforeEach(async () => {
@@ -165,7 +165,6 @@ export class ActorFromAuthContextService {
if (isDefined(user)) {
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext as WorkspaceAuthContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -187,6 +186,7 @@ export class ActorFromAuthContextService {
workspaceMemberId: workspaceMember.id,
});
},
authContext as WorkspaceAuthContext,
);
}
@@ -47,7 +47,6 @@ export class ApprovedAccessDomainResolver {
const workspaceMember =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -62,6 +61,7 @@ export class ApprovedAccessDomainResolver {
},
});
},
authContext,
);
return this.approvedAccessDomainService.createApprovedAccessDomain(
@@ -0,0 +1,33 @@
import { Injectable, type NestMiddleware } from '@nestjs/common';
import { type NextFunction, type Request, type Response } from 'express';
import { isDefined } from 'twenty-shared/utils';
import { type WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
import { withWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
@Injectable()
export class WorkspaceAuthContextMiddleware implements NestMiddleware {
use(req: Request, _res: Response, next: NextFunction) {
if (!isDefined(req.workspace)) {
next();
return;
}
const authContext: WorkspaceAuthContext = {
user: req.user,
workspace: req.workspace,
workspaceMemberId: req.workspaceMemberId,
workspaceMember: req.workspaceMember,
userWorkspaceId: req.userWorkspaceId,
apiKey: req.apiKey,
application: req.application,
} as WorkspaceAuthContext;
withWorkspaceAuthContext(authContext, () => {
next();
});
}
}
@@ -42,7 +42,6 @@ export class CreateCalendarChannelService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const calendarChannelRepository =
await this.globalWorkspaceOrmManager.getRepository<CalendarChannelWorkspaceEntity>(
@@ -70,6 +69,7 @@ export class CreateCalendarChannelService {
return newCalendarChannel.id;
},
authContext,
);
}
}
@@ -42,29 +42,26 @@ export class CreateConnectedAccountService {
const authContext = buildSystemAuthContext(workspaceId);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
workspaceId,
'connectedAccount',
);
await connectedAccountRepository.save(
{
id: connectedAccountId,
handle,
provider,
accessToken,
refreshToken,
accountOwnerId,
scopes,
},
{},
manager,
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
workspaceId,
'connectedAccount',
);
},
);
await connectedAccountRepository.save(
{
id: connectedAccountId,
handle,
provider,
accessToken,
refreshToken,
accountOwnerId,
scopes,
},
{},
manager,
);
}, authContext);
}
}
@@ -47,7 +47,6 @@ export class CreateMessageChannelService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const messageChannelRepository =
await this.globalWorkspaceOrmManager.getRepository<MessageChannelWorkspaceEntity>(
@@ -93,6 +92,7 @@ export class CreateMessageChannelService {
return newMessageChannelId;
},
authContext,
);
}
}
@@ -98,7 +98,7 @@ describe('GoogleAPIsService', () => {
.mockResolvedValue(mockWorkspaceDataSource),
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
},
},
{
@@ -100,7 +100,6 @@ export class GoogleAPIsService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
@@ -258,6 +257,7 @@ export class GoogleAPIsService {
return newOrExistingConnectedAccountId;
},
authContext,
);
}
}
@@ -97,7 +97,7 @@ describe('MicrosoftAPIsService', () => {
.mockResolvedValue(mockWorkspaceDataSource),
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
},
},
{
@@ -81,7 +81,6 @@ export class MicrosoftAPIsService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
@@ -247,6 +246,7 @@ export class MicrosoftAPIsService {
return newOrExistingConnectedAccountId;
},
authContext,
);
}
}
@@ -35,28 +35,25 @@ export class UpdateConnectedAccountOnReconnectService {
const authContext = buildSystemAuthContext(workspaceId);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
workspaceId,
'connectedAccount',
);
await connectedAccountRepository.update(
{
id: connectedAccountId,
},
{
accessToken,
refreshToken,
scopes,
authFailedAt: null,
},
manager,
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
workspaceId,
'connectedAccount',
);
},
);
await connectedAccountRepository.update(
{
id: connectedAccountId,
},
{
accessToken,
refreshToken,
scopes,
authFailedAt: null,
},
manager,
);
}, authContext);
}
}
@@ -0,0 +1,25 @@
import { AsyncLocalStorage } from 'async_hooks';
import { type WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
export const workspaceAuthContextStorage =
new AsyncLocalStorage<WorkspaceAuthContext>();
export const getWorkspaceAuthContext = (): WorkspaceAuthContext => {
const context = workspaceAuthContextStorage.getStore();
if (!context) {
throw new Error(
'Workspace auth context not set. Operations must be wrapped with withWorkspaceAuthContext()',
);
}
return context;
};
export const withWorkspaceAuthContext = <T>(
context: WorkspaceAuthContext,
fn: () => T | Promise<T>,
): T | Promise<T> => {
return workspaceAuthContextStorage.run(context, fn);
};
@@ -82,7 +82,7 @@ describe('AccessTokenService', () => {
getRepository: jest.fn(),
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
},
},
],
@@ -84,7 +84,6 @@ export class AccessTokenService {
tokenWorkspaceMemberId =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -112,6 +111,7 @@ export class AccessTokenService {
return workspaceMember.id;
},
authContext,
);
}
const userWorkspace = await this.userWorkspaceRepository.findOne({
@@ -29,36 +29,33 @@ export class UpdateSubscriptionQuantityJob {
async handle(data: UpdateSubscriptionQuantityJobData): Promise<void> {
const authContext = buildSystemAuthContext(data.workspaceId);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
data.workspaceId,
'workspaceMember',
);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
data.workspaceId,
'workspaceMember',
);
const workspaceMembersCount = await workspaceMemberRepository.count();
const workspaceMembersCount = await workspaceMemberRepository.count();
if (!workspaceMembersCount || workspaceMembersCount <= 0) {
return;
}
if (!workspaceMembersCount || workspaceMembersCount <= 0) {
return;
}
try {
await this.billingSubscriptionUpdateService.changeSeats(
data.workspaceId,
workspaceMembersCount,
);
try {
await this.billingSubscriptionUpdateService.changeSeats(
data.workspaceId,
workspaceMembersCount,
);
this.logger.log(
`Updating workspace ${data.workspaceId} subscription quantity to ${workspaceMembersCount} members`,
);
} catch (e) {
this.logger.warn(
`Failed to update workspace ${data.workspaceId} subscription quantity to ${workspaceMembersCount} members. Error: ${e}`,
);
}
},
);
this.logger.log(
`Updating workspace ${data.workspaceId} subscription quantity to ${workspaceMembersCount} members`,
);
} catch (e) {
this.logger.warn(
`Failed to update workspace ${data.workspaceId} subscription quantity to ${workspaceMembersCount} members. Error: ${e}`,
);
}
}, authContext);
}
}
@@ -40,7 +40,7 @@ describe('TimelineCalendarEventService', () => {
getRepository: jest.fn().mockResolvedValue(mockCalendarEventRepository),
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
};
const module: TestingModule = await Test.createTestingModule({
@@ -35,7 +35,6 @@ export class TimelineCalendarEventService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const offset = (page - 1) * pageSize;
@@ -166,6 +165,7 @@ export class TimelineCalendarEventService {
timelineCalendarEvents,
};
},
authContext,
);
}
@@ -185,7 +185,6 @@ export class TimelineCalendarEventService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const personRepository =
await this.globalWorkspaceOrmManager.getRepository<PersonWorkspaceEntity>(
@@ -222,6 +221,7 @@ export class TimelineCalendarEventService {
return calendarEvents;
},
authContext,
);
}
@@ -241,7 +241,6 @@ export class TimelineCalendarEventService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const opportunityRepository =
await this.globalWorkspaceOrmManager.getRepository<OpportunityWorkspaceEntity>(
@@ -276,6 +275,7 @@ export class TimelineCalendarEventService {
return calendarEvents;
},
authContext,
);
}
}
@@ -187,7 +187,6 @@ export class ImapSmtpCaldavService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
@@ -204,6 +203,7 @@ export class ImapSmtpCaldavService {
return connectedAccount;
},
authContext,
);
}
}
@@ -77,7 +77,6 @@ export class GetMessagesService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const personRepository =
await this.globalWorkspaceOrmManager.getRepository<PersonWorkspaceEntity>(
@@ -113,6 +112,7 @@ export class GetMessagesService {
return messageThreads;
},
authContext,
);
}
@@ -126,7 +126,6 @@ export class GetMessagesService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const opportunityRepository =
await this.globalWorkspaceOrmManager.getRepository<OpportunityWorkspaceEntity>(
@@ -161,6 +160,7 @@ export class GetMessagesService {
return messageThreads;
},
authContext,
);
}
}
@@ -35,7 +35,6 @@ export class TimelineMessagingService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const messageThreadRepository =
await this.globalWorkspaceOrmManager.getRepository<MessageThreadWorkspaceEntity>(
@@ -99,6 +98,7 @@ export class TimelineMessagingService {
totalNumberOfThreads,
};
},
authContext,
);
}
@@ -111,7 +111,6 @@ export class TimelineMessagingService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const messageParticipantRepository =
await this.globalWorkspaceOrmManager.getRepository<MessageParticipantWorkspaceEntity>(
@@ -198,6 +197,7 @@ export class TimelineMessagingService {
{},
);
},
authContext,
);
}
@@ -211,7 +211,6 @@ export class TimelineMessagingService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const messageThreadRepository =
await this.globalWorkspaceOrmManager.getRepository<MessageThreadWorkspaceEntity>(
@@ -267,6 +266,7 @@ export class TimelineMessagingService {
return threadVisibilityByThreadId;
},
authContext,
);
}
}
@@ -20,7 +20,7 @@ describe('RecordPositionService', () => {
getRepository: jest.fn().mockResolvedValue(mockRepository),
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
} as unknown as jest.Mocked<GlobalWorkspaceOrmManager>;
const module: TestingModule = await Test.createTestingModule({
@@ -163,7 +163,6 @@ export class RecordPositionService {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const repository = await this.globalWorkspaceOrmManager.getRepository(
workspaceId,
@@ -179,6 +178,7 @@ export class RecordPositionService {
return record ? { id: record.id, position: record.position } : null;
},
authContext,
);
}
@@ -190,22 +190,19 @@ export class RecordPositionService {
): Promise<void> {
const authContext = buildSystemAuthContext(workspaceId);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const repository = await this.globalWorkspaceOrmManager.getRepository(
workspaceId,
objectMetadata.nameSingular,
{
shouldBypassPermissionChecks: true,
},
);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const repository = await this.globalWorkspaceOrmManager.getRepository(
workspaceId,
objectMetadata.nameSingular,
{
shouldBypassPermissionChecks: true,
},
);
await repository.update(recordId, {
position: positionValue,
});
},
);
await repository.update(recordId, {
position: positionValue,
});
}, authContext);
}
private async findMinPosition(
@@ -216,7 +213,6 @@ export class RecordPositionService {
const result =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const repository = await this.globalWorkspaceOrmManager.getRepository(
workspaceId,
@@ -228,6 +224,7 @@ export class RecordPositionService {
return await repository.minimum('position');
},
authContext,
);
return sanitizeNumber(result);
@@ -241,7 +238,6 @@ export class RecordPositionService {
const result =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const repository = await this.globalWorkspaceOrmManager.getRepository(
workspaceId,
@@ -253,6 +249,7 @@ export class RecordPositionService {
return await repository.maximum('position');
},
authContext,
);
return sanitizeNumber(result);
@@ -33,7 +33,6 @@ import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-me
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
type LastRanks = { tsRankCD: number; tsRank: number };
@@ -82,13 +81,10 @@ export class SearchService {
OBJECT_METADATA_ITEMS_CHUNK_SIZE,
);
const authContext = buildSystemAuthContext(workspaceId);
for (const objectMetadataItemChunk of filteredObjectMetadataItemsChunks) {
const recordsWithObjectMetadataItems = await Promise.all(
objectMetadataItemChunk.map(async (flatObjectMetadata) => {
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const repository =
await this.globalWorkspaceOrmManager.getRepository<ObjectRecord>(
@@ -65,7 +65,6 @@ export class SendEmailTool implements Tool {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
@@ -91,6 +90,7 @@ export class SendEmailTool implements Tool {
return connectedAccount;
},
authContext,
);
}
@@ -100,7 +100,6 @@ export class SendEmailTool implements Tool {
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const connectedAccountRepository =
await this.globalWorkspaceOrmManager.getRepository<ConnectedAccountWorkspaceEntity>(
@@ -118,6 +117,7 @@ export class SendEmailTool implements Tool {
return allAccounts[0].id;
},
authContext,
);
}
@@ -106,7 +106,9 @@ describe('UserWorkspaceService', () => {
useValue: {
executeInWorkspaceContext: jest
.fn()
.mockImplementation(async (_authContext, callback) => callback()),
.mockImplementation(
async (callback: () => any, _authContext?: any) => callback(),
),
getRepository: jest.fn(),
},
},
@@ -95,47 +95,44 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
async createWorkspaceMember(workspaceId: string, user: UserEntity) {
const authContext = buildSystemAuthContext(workspaceId);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
workspaceId,
'workspaceMember',
{ shouldBypassPermissionChecks: true },
);
const userWorkspace = await this.userWorkspaceRepository.findOneOrFail({
where: {
userId: user.id,
workspaceId,
},
});
await workspaceMemberRepository.insert({
name: {
firstName: user.firstName,
lastName: user.lastName,
},
colorScheme: 'System',
userId: user.id,
userEmail: user.email,
avatarUrl: userWorkspace.defaultAvatarUrl ?? '',
locale: (user.locale ?? SOURCE_LOCALE) as keyof typeof APP_LOCALES,
});
const workspaceMember = await workspaceMemberRepository.find({
where: {
userId: user.id,
},
});
assert(
workspaceMember?.length === 1,
`Error while creating workspace member ${user.email} on workspace ${workspaceId}`,
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
workspaceId,
'workspaceMember',
{ shouldBypassPermissionChecks: true },
);
},
);
const userWorkspace = await this.userWorkspaceRepository.findOneOrFail({
where: {
userId: user.id,
workspaceId,
},
});
await workspaceMemberRepository.insert({
name: {
firstName: user.firstName,
lastName: user.lastName,
},
colorScheme: 'System',
userId: user.id,
userEmail: user.email,
avatarUrl: userWorkspace.defaultAvatarUrl ?? '',
locale: (user.locale ?? SOURCE_LOCALE) as keyof typeof APP_LOCALES,
});
const workspaceMember = await workspaceMemberRepository.find({
where: {
userId: user.id,
},
});
assert(
workspaceMember?.length === 1,
`Error while creating workspace member ${user.email} on workspace ${workspaceId}`,
);
}, authContext);
}
async addUserToWorkspaceIfUserNotInWorkspace(
@@ -356,7 +353,6 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
const authContext = buildSystemAuthContext(workspaceId);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -377,6 +373,7 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
return workspaceMember;
},
authContext,
);
}
@@ -35,21 +35,15 @@ export class UpdateWorkspaceMemberEmailJob {
const authContext = buildSystemAuthContext(workspace.id);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
workspace.id,
'workspaceMember',
{ shouldBypassPermissionChecks: true },
);
await workspaceMemberRepository.update(
{ userId },
{ userEmail: email },
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
workspace.id,
'workspaceMember',
{ shouldBypassPermissionChecks: true },
);
},
);
await workspaceMemberRepository.update({ userId }, { userEmail: email });
}, authContext);
}
}
@@ -76,7 +76,7 @@ describe('UserService', () => {
executeInWorkspaceContext: jest
.fn()
.mockImplementation((_authContext: any, fn: () => any) => fn()),
.mockImplementation((fn: () => any, _authContext?: any) => fn()),
},
},
{
@@ -66,7 +66,6 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
const authContext = buildSystemAuthContext(workspace.id);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -81,6 +80,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
},
});
},
authContext,
);
}
@@ -92,7 +92,6 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
const authContext = buildSystemAuthContext(workspace.id);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -105,6 +104,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
withDeleted: withDeleted,
});
},
authContext,
);
}
@@ -116,7 +116,6 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
const authContext = buildSystemAuthContext(workspace.id);
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -130,6 +129,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
withDeleted: true,
});
},
authContext,
);
}
@@ -202,7 +202,6 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
const workspaceMembers =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -213,6 +212,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
return workspaceMemberRepository.find();
},
authContext,
);
const userWorkspaceId = userWorkspace.id;
@@ -255,21 +255,18 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
assert(workspaceMember, 'WorkspaceMember not found');
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
workspaceId,
'workspaceMember',
{ shouldBypassPermissionChecks: true },
);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
workspaceId,
'workspaceMember',
{ shouldBypassPermissionChecks: true },
);
await workspaceMemberRepository.delete({
userId: userWorkspace.userId,
});
},
);
await workspaceMemberRepository.delete({
userId: userWorkspace.userId,
});
}, authContext);
await this.userWorkspaceService.deleteUserWorkspace({
userWorkspaceId,
@@ -20,7 +20,6 @@ export class WorkspaceFlatWorkspaceMemberMapCacheService extends WorkspaceCacheP
async computeForCache(workspaceId: string): Promise<FlatWorkspaceMemberMaps> {
const flatWorkspaceMemberMaps =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
buildSystemAuthContext(workspaceId),
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -45,6 +44,7 @@ export class WorkspaceFlatWorkspaceMemberMapCacheService extends WorkspaceCacheP
return flatWorkspaceMemberMaps;
},
buildSystemAuthContext(workspaceId),
);
return flatWorkspaceMemberMaps;
@@ -391,7 +391,6 @@ export class UserResolver {
const workspaceMemberToDelete =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -406,6 +405,7 @@ export class UserResolver {
},
});
},
authContext,
);
if (!isDefined(workspaceMemberToDelete)) {
@@ -93,7 +93,6 @@ export class WorkflowTriggerController {
const { workflow } =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workflowRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkflowWorkspaceEntity>(
@@ -156,6 +155,7 @@ export class WorkflowTriggerController {
return { workflow, workflowVersion };
},
authContext,
);
const { workflowRunId } =
@@ -77,7 +77,6 @@ export class WorkflowTriggerResolver {
const workspaceMember =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -92,6 +91,7 @@ export class WorkflowTriggerResolver {
},
});
},
authContext,
);
return this.workflowTriggerWorkspaceService.runWorkflowVersion({
@@ -60,7 +60,6 @@ export class WorkspaceInvitationResolver {
const workspaceMember =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -75,6 +74,7 @@ export class WorkspaceInvitationResolver {
},
});
},
authContext,
);
return this.workspaceInvitationService.resendWorkspaceInvitation(
@@ -100,7 +100,6 @@ export class WorkspaceInvitationResolver {
const workspaceMember =
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
authContext,
async () => {
const workspaceMemberRepository =
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
@@ -115,6 +114,7 @@ export class WorkspaceInvitationResolver {
},
});
},
authContext,
);
return await this.workspaceInvitationService.sendInvitations(