use auth context guard + move build auth context logic from middleware to shared util

This commit is contained in:
Weiko
2026-05-27 19:19:17 +02:00
parent ebb5758810
commit ddf657669f
3 changed files with 89 additions and 64 deletions
@@ -9,10 +9,7 @@ import {
} from 'src/engine/core-modules/auth/auth.exception';
import { withWorkspaceAuthContext } from 'src/engine/core-modules/auth/storage/workspace-auth-context.storage';
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
import { buildApiKeyAuthContext } from 'src/engine/core-modules/auth/utils/build-api-key-auth-context.util';
import { buildApplicationAuthContext } from 'src/engine/core-modules/auth/utils/build-application-auth-context.util';
import { buildPendingActivationUserAuthContext } from 'src/engine/core-modules/auth/utils/build-pending-activation-user-auth-context.util';
import { buildUserAuthContext } from 'src/engine/core-modules/auth/utils/build-user-auth-context.util';
import { buildWorkspaceAuthContext } from 'src/engine/core-modules/auth/utils/build-workspace-auth-context.util';
import { applyWorkspaceSentryContext } from 'src/engine/core-modules/sentry/utils/apply-workspace-sentry-context.util';
@Injectable()
@@ -34,46 +31,23 @@ export class WorkspaceAuthContextMiddleware implements NestMiddleware {
}
private buildAuthContext(req: Request): WorkspaceAuthContext {
if (isDefined(req.apiKey)) {
return buildApiKeyAuthContext({
workspace: req.workspace!,
apiKey: req.apiKey,
});
const authContext = buildWorkspaceAuthContext({
workspace: req.workspace,
apiKey: req.apiKey,
userWorkspaceId: req.userWorkspaceId,
workspaceMemberId: req.workspaceMemberId,
workspaceMember: req.workspaceMember,
user: req.user,
application: req.application,
});
if (!isDefined(authContext)) {
throw new AuthException(
'No authentication context found',
AuthExceptionCode.UNAUTHENTICATED,
);
}
if (
isDefined(req.userWorkspaceId) &&
isDefined(req.workspaceMemberId) &&
isDefined(req.workspaceMember) &&
isDefined(req.user)
) {
return buildUserAuthContext({
workspace: req.workspace!,
userWorkspaceId: req.userWorkspaceId,
user: req.user,
workspaceMemberId: req.workspaceMemberId,
workspaceMember: req.workspaceMember,
});
}
if (isDefined(req.application)) {
return buildApplicationAuthContext({
workspace: req.workspace!,
application: req.application,
});
}
if (isDefined(req.userWorkspaceId) && isDefined(req.user)) {
return buildPendingActivationUserAuthContext({
workspace: req.workspace!,
userWorkspaceId: req.userWorkspaceId,
user: req.user,
});
}
throw new AuthException(
'No authentication context found',
AuthExceptionCode.UNAUTHENTICATED,
);
return authContext;
}
}
@@ -0,0 +1,55 @@
import { isDefined } from 'twenty-shared/utils';
import { type RawAuthContext } 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 { buildApiKeyAuthContext } from 'src/engine/core-modules/auth/utils/build-api-key-auth-context.util';
import { buildApplicationAuthContext } from 'src/engine/core-modules/auth/utils/build-application-auth-context.util';
import { buildPendingActivationUserAuthContext } from 'src/engine/core-modules/auth/utils/build-pending-activation-user-auth-context.util';
import { buildUserAuthContext } from 'src/engine/core-modules/auth/utils/build-user-auth-context.util';
export const buildWorkspaceAuthContext = (
authContext: RawAuthContext,
): WorkspaceAuthContext | null => {
if (!isDefined(authContext.workspace)) {
return null;
}
if (isDefined(authContext.apiKey)) {
return buildApiKeyAuthContext({
workspace: authContext.workspace,
apiKey: authContext.apiKey,
});
}
if (
isDefined(authContext.userWorkspaceId) &&
isDefined(authContext.workspaceMemberId) &&
isDefined(authContext.workspaceMember) &&
isDefined(authContext.user)
) {
return buildUserAuthContext({
workspace: authContext.workspace,
userWorkspaceId: authContext.userWorkspaceId,
user: authContext.user,
workspaceMemberId: authContext.workspaceMemberId,
workspaceMember: authContext.workspaceMember,
});
}
if (isDefined(authContext.application)) {
return buildApplicationAuthContext({
workspace: authContext.workspace,
application: authContext.application,
});
}
if (isDefined(authContext.userWorkspaceId) && isDefined(authContext.user)) {
return buildPendingActivationUserAuthContext({
workspace: authContext.workspace,
userWorkspaceId: authContext.userWorkspaceId,
user: authContext.user,
});
}
return null;
};
@@ -9,6 +9,7 @@ import { HTTPMethod } from 'twenty-shared/types';
import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { buildWorkspaceAuthContext } from 'src/engine/core-modules/auth/utils/build-workspace-auth-context.util';
import { WorkspaceDomainsService } from 'src/engine/core-modules/domain/workspace-domains/services/workspace-domains.service';
import {
RouteTriggerException,
@@ -25,6 +26,8 @@ import {
LogicFunctionExecutionExceptionCode,
LogicFunctionExecutorService,
} from 'src/engine/core-modules/logic-function/logic-function-executor/logic-function-executor.service';
import { getRoleIdFromRolePermissionConfig } from 'src/engine/twenty-orm/utils/get-role-id-from-role-permission-config.util';
import { resolveRolePermissionConfig } from 'src/engine/twenty-orm/utils/resolve-role-permission-config.util';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { CustomException } from 'src/utils/custom-exception';
@@ -48,32 +51,25 @@ export class RouteTriggerService {
authContext: AuthContext;
workspaceId: string;
}): Promise<string | undefined> {
if (isDefined(authContext.apiKey)) {
const { apiKeyRoleMap } = await this.workspaceCacheService.getOrRecompute(
workspaceId,
['apiKeyRoleMap'],
);
const workspaceAuthContext = buildWorkspaceAuthContext(authContext);
return apiKeyRoleMap[authContext.apiKey.id];
if (!isDefined(workspaceAuthContext)) {
return undefined;
}
if (
isDefined(authContext.application) &&
isDefined(authContext.application.defaultRoleId)
) {
return authContext.application.defaultRoleId;
}
const { userWorkspaceRoleMap, apiKeyRoleMap } =
await this.workspaceCacheService.getOrRecompute(workspaceId, [
'userWorkspaceRoleMap',
'apiKeyRoleMap',
]);
if (isDefined(authContext.userWorkspaceId)) {
const { userWorkspaceRoleMap } =
await this.workspaceCacheService.getOrRecompute(workspaceId, [
'userWorkspaceRoleMap',
]);
const rolePermissionConfig = resolveRolePermissionConfig({
authContext: workspaceAuthContext,
userWorkspaceRoleMap,
apiKeyRoleMap,
});
return userWorkspaceRoleMap[authContext.userWorkspaceId];
}
return undefined;
return getRoleIdFromRolePermissionConfig(rolePermissionConfig);
}
private async getLogicFunctionWithPathParamsOrFail({