Fix server logs leak (#18423)

# Introduction

Previously the auth jwt stragegy would lod the whole user entity in the
auth user context
On an exception it would completely get logged on the pods


## Security layer
- 0/ Updating the type system ( devxp only though )
- 1/ The jwt auth stragegy only load a specific sub set of the user
entity
- 2/ Sanitizing at the exception log level directly in case of a user
context
- 3/ Sanitizing at the console driver

The last two sanitization could sound a bit redundant though they're
still good fallback to keep in case new path occurs in the cb
This commit is contained in:
Paul Rastoin
2026-03-05 14:40:23 +01:00
committed by GitHub
parent 647c32ff3e
commit 38ad0820c0
31 changed files with 147 additions and 75 deletions
@@ -11,7 +11,7 @@ import { ValidateApprovedAccessDomainInput } from 'src/engine/core-modules/appro
import { ApprovedAccessDomainService } from 'src/engine/core-modules/approved-access-domain/services/approved-access-domain.service';
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -42,7 +42,7 @@ export class ApprovedAccessDomainResolver {
async createApprovedAccessDomain(
@Args('input') { domain, email }: CreateApprovedAccessDomainInput,
@AuthWorkspace() currentWorkspace: WorkspaceEntity,
@AuthUser() currentUser: UserEntity,
@AuthUser() currentUser: AuthContextUser,
): Promise<ApprovedAccessDomainDTO> {
const authContext = buildSystemAuthContext(currentWorkspace.id);
@@ -45,6 +45,7 @@ import { RenewTokenService } from 'src/engine/core-modules/auth/token/services/r
import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service';
import { WorkspaceAgnosticTokenService } from 'src/engine/core-modules/auth/token/services/workspace-agnostic-token.service';
import {
AuthContextUser,
JwtTokenTypeEnum,
LoginTokenJwtPayload,
} from 'src/engine/core-modules/auth/types/auth-context.type';
@@ -508,7 +509,7 @@ export class AuthResolver {
@Mutation(() => SignUpDTO)
@UseGuards(UserAuthGuard, NoPermissionGuard)
async signUpInNewWorkspace(
@AuthUser() currentUser: UserEntity,
@AuthUser() currentUser: AuthContextUser,
@AuthProvider() authProvider: AuthProviderEnum,
): Promise<SignUpDTO> {
const { user, workspace } = await this.signInUpService.signUpOnNewWorkspace(
@@ -533,7 +534,7 @@ export class AuthResolver {
@Mutation(() => TransientTokenDTO)
@UseGuards(UserAuthGuard, NoPermissionGuard)
async generateTransientToken(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<TransientTokenDTO | void> {
const workspaceMember = await this.userService.loadWorkspaceMember(
@@ -780,7 +781,7 @@ export class AuthResolver {
@UseGuards(UserAuthGuard, NoPermissionGuard)
async authorizeApp(
@Args() authorizeAppInput: AuthorizeAppInput,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<AuthorizeAppDTO> {
return await this.authService.generateAuthorizationCode(
@@ -0,0 +1,17 @@
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
export const AUTH_CONTEXT_USER_SELECT_FIELDS = [
'id',
'firstName',
'lastName',
'email',
'defaultAvatarUrl',
'isEmailVerified',
'disabled',
'canImpersonate',
'canAccessFullAdminPanel',
'createdAt',
'updatedAt',
'deletedAt',
'locale',
] as const satisfies ReadonlyArray<keyof UserEntity>;
@@ -13,11 +13,11 @@ import { AppPath } from 'twenty-shared/types';
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
import { IsNull, Repository } from 'typeorm';
import { ApplicationRegistrationService } from 'src/engine/core-modules/application/application-registration/application-registration.service';
import {
AppTokenEntity,
AppTokenType,
} from 'src/engine/core-modules/app-token/app-token.entity';
import { ApplicationRegistrationService } from 'src/engine/core-modules/application/application-registration/application-registration.service';
import { AuditService } from 'src/engine/core-modules/audit/services/audit.service';
import {
AuthException,
@@ -29,7 +29,6 @@ import {
hashPassword,
} from 'src/engine/core-modules/auth/auth.util';
import { type AuthTokens } from 'src/engine/core-modules/auth/dto/auth-tokens.dto';
import { validateRedirectUri } from 'src/engine/core-modules/auth/utils/validate-redirect-uri.util';
import { type AuthorizeAppDTO } from 'src/engine/core-modules/auth/dto/authorize-app.dto';
import { type AuthorizeAppInput } from 'src/engine/core-modules/auth/dto/authorize-app.input';
import { type UpdatePasswordDTO } from 'src/engine/core-modules/auth/dto/update-password.dto';
@@ -44,13 +43,17 @@ import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
import { RefreshTokenService } from 'src/engine/core-modules/auth/token/services/refresh-token.service';
import { WorkspaceAgnosticTokenService } from 'src/engine/core-modules/auth/token/services/workspace-agnostic-token.service';
import { JwtTokenTypeEnum } from 'src/engine/core-modules/auth/types/auth-context.type';
import {
AuthContextUser,
JwtTokenTypeEnum,
} from 'src/engine/core-modules/auth/types/auth-context.type';
import {
type AuthProviderWithPasswordType,
type ExistingUserOrNewUser,
type SignInUpBaseParams,
type SignInUpNewUserPayload,
} from 'src/engine/core-modules/auth/types/signInUp.type';
import { validateRedirectUri } from 'src/engine/core-modules/auth/utils/validate-redirect-uri.util';
import { DomainServerConfigService } from 'src/engine/core-modules/domain/domain-server-config/services/domain-server-config.service';
import { WorkspaceDomainsService } from 'src/engine/core-modules/domain/workspace-domains/services/workspace-domains.service';
import { WorkspaceDomainConfig } from 'src/engine/core-modules/domain/workspace-domains/types/workspace-domain-config.type';
@@ -494,7 +497,7 @@ export class AuthService {
async generateAuthorizationCode(
authorizeAppInput: AuthorizeAppInput,
user: UserEntity,
user: AuthContextUser,
workspace: WorkspaceEntity,
): Promise<AuthorizeAppDTO> {
const { clientId, codeChallenge } = authorizeAppInput;
@@ -36,6 +36,7 @@ import { SecureHttpClientService } from 'src/engine/core-modules/secure-http-cli
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
import { AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
@@ -312,7 +313,7 @@ export class SignInUpService {
workspace,
shouldShowConnectAccountStep,
}: {
user: UserEntity;
user: AuthContextUser;
workspace: WorkspaceEntity;
shouldShowConnectAccountStep: boolean;
},
@@ -19,7 +19,9 @@ import {
type AccessTokenJwtPayload,
type ApiKeyTokenJwtPayload,
ApplicationAccessTokenJwtPayload,
AUTH_CONTEXT_USER_SELECT_FIELDS,
type AuthContext,
type AuthContextUser,
FileTokenJwtPayloadLegacy,
type JwtPayload,
JwtTokenTypeEnum,
@@ -118,7 +120,7 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
private async validateAccessToken(
payload: AccessTokenJwtPayload,
): Promise<AuthContext> {
let user: UserEntity | null = null;
let user: AuthContextUser | null = null;
let context: AuthContext = {};
const workspace = await this.workspaceRepository.findOneBy({
@@ -221,11 +223,12 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
userWorkspaceId: string;
expectedWorkspaceId?: string;
}): Promise<{
user: UserEntity;
user: AuthContextUser;
userWorkspace: UserWorkspaceEntity;
} | null> {
const user = await this.userRepository.findOne({
where: { id: params.userId },
select: [...AUTH_CONTEXT_USER_SELECT_FIELDS],
});
if (!isDefined(user)) {
@@ -234,7 +237,6 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
const userWorkspace = await this.userWorkspaceRepository.findOne({
where: { id: params.userWorkspaceId },
relations: ['user', 'workspace'],
});
if (!isDefined(userWorkspace)) {
@@ -243,7 +245,7 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
if (
isDefined(params.expectedWorkspaceId) &&
userWorkspace.workspace.id !== params.expectedWorkspaceId
userWorkspace.workspaceId !== params.expectedWorkspaceId
) {
return null;
}
@@ -348,6 +350,7 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
): Promise<AuthContext> {
const user = await this.userRepository.findOne({
where: { id: payload.sub },
select: [...AUTH_CONTEXT_USER_SELECT_FIELDS],
});
userValidator.assertIsDefinedOrThrow(
@@ -0,0 +1,7 @@
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AUTH_CONTEXT_USER_SELECT_FIELDS } from 'src/engine/core-modules/auth/constants/auth-context-user-select-fields.constants';
export type AuthContextUser = Pick<
UserEntity,
(typeof AUTH_CONTEXT_USER_SELECT_FIELDS)[number]
>;
@@ -1,13 +1,16 @@
import { type ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context-user.type';
import { type UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
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 = {
user?: UserEntity | null | undefined;
user?: AuthContextUser | null | undefined;
apiKey?: ApiKeyEntity | null | undefined;
workspaceMemberId?: string;
workspaceMember?: WorkspaceMemberWorkspaceEntity;
@@ -1,6 +1,7 @@
import { type APP_LOCALES } from 'twenty-shared/translations';
import { type AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
@@ -41,7 +42,7 @@ export type ExistingUserOrNewUser = {
export type ExistingUserOrPartialUserWithPicture = {
userData:
| { type: 'existingUser'; existingUser: UserEntity }
| { type: 'existingUser'; existingUser: AuthContextUser }
| {
type: 'newUserWithPicture';
newUserWithPicture: PartialUserWithPicture;
@@ -29,7 +29,7 @@ import {
} from 'src/engine/core-modules/billing/utils/to-display-credits.util';
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthApiKey } from 'src/engine/decorators/auth/auth-api-key.decorator';
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
@@ -86,7 +86,7 @@ export class BillingResolver {
@UseGuards(WorkspaceAuthGuard, UserAuthGuard, NoPermissionGuard)
async checkoutSession(
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthUserWorkspaceId() userWorkspaceId: string,
@Args()
{
@@ -10,7 +10,7 @@ import { BillingPlanKey } from 'src/engine/core-modules/billing/enums/billing-pl
import { StripeCustomerService } from 'src/engine/core-modules/billing/stripe/services/stripe-customer.service';
import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
@Injectable()
@@ -42,7 +42,7 @@ export class StripeCheckoutService {
requirePaymentMethod = true,
withTrialPeriod,
}: {
user: UserEntity;
user: AuthContextUser;
workspace: Pick<WorkspaceEntity, 'id' | 'displayName'>;
stripeSubscriptionLineItems: Stripe.Checkout.SessionCreateParams.LineItem[];
successUrl?: string;
@@ -97,7 +97,7 @@ export class StripeCheckoutService {
requirePaymentMethod = false,
withTrialPeriod,
}: {
user: UserEntity;
user: AuthContextUser;
workspace: Pick<WorkspaceEntity, 'id' | 'displayName'>;
stripeSubscriptionLineItems: Stripe.Checkout.SessionCreateParams.LineItem[];
stripeCustomerId?: string;
@@ -2,11 +2,11 @@
import { type BillingPlanKey } from 'src/engine/core-modules/billing/enums/billing-plan-key.enum';
import { type BillingGetPricesPerPlanResult } from 'src/engine/core-modules/billing/types/billing-get-prices-per-plan-result.type';
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
export type BillingPortalCheckoutSessionParameters = {
user: UserEntity;
user: AuthContextUser;
workspace: WorkspaceEntity;
billingPricesPerPlan: BillingGetPricesPerPlanResult;
successUrlPath?: string;
@@ -11,8 +11,22 @@ export class ExceptionHandlerConsoleDriver
exceptions: ReadonlyArray<any>,
options?: ExceptionHandlerOptions,
) {
const sanitizedOptions = options
? {
...options,
user: options.user
? {
id: options.user.id,
email: options.user.email,
firstName: options.user.firstName,
lastName: options.user.lastName,
}
: undefined,
}
: undefined;
console.group('Exception Captured');
console.info(options);
console.info(sanitizedOptions);
console.error(exceptions);
console.groupEnd();
@@ -92,7 +92,15 @@ export const useGraphQLErrorHandlerHook = <
}
const operationType = rootOperation.operation;
const user = args.contextValue.req.user;
const rawUser = args.contextValue.req.user;
const user = rawUser
? {
id: rawUser.id,
email: rawUser.email,
firstName: rawUser.firstName,
lastName: rawUser.lastName,
}
: undefined;
const document = getDocumentString(args.document, print);
const opName =
args.operationName ||
@@ -11,7 +11,7 @@ import { DismissReconnectAccountBannerInput } from 'src/engine/core-modules/mess
import { TimelineThreadsWithTotalDTO } from 'src/engine/core-modules/messaging/dtos/timeline-threads-with-total.dto';
import { GetMessagesService } from 'src/engine/core-modules/messaging/services/get-messages.service';
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -71,7 +71,7 @@ export class TimelineMessagingResolver {
@Query(() => TimelineThreadsWithTotalDTO)
async getTimelineThreadsFromPersonId(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
@Args() { personId, page, pageSize }: GetTimelineThreadsFromPersonIdArgs,
) {
@@ -98,7 +98,7 @@ export class TimelineMessagingResolver {
@Query(() => TimelineThreadsWithTotalDTO)
async getTimelineThreadsFromCompanyId(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
@Args() { companyId, page, pageSize }: GetTimelineThreadsFromCompanyIdArgs,
) {
@@ -125,7 +125,7 @@ export class TimelineMessagingResolver {
@Query(() => TimelineThreadsWithTotalDTO)
async getTimelineThreadsFromOpportunityId(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
@Args()
{ opportunityId, page, pageSize }: GetTimelineThreadsFromOpportunityIdArgs,
@@ -154,7 +154,7 @@ export class TimelineMessagingResolver {
@UseGuards(SettingsPermissionGuard(PermissionFlagType.CONNECTED_ACCOUNTS))
@Mutation(() => Boolean)
async dismissReconnectAccountBanner(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
@Args() { connectedAccountId }: DismissReconnectAccountBannerInput,
): Promise<boolean> {
@@ -6,7 +6,7 @@ import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { OnboardingStepSuccessDTO } from 'src/engine/core-modules/onboarding/dtos/onboarding-step-success.dto';
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -24,7 +24,7 @@ export class OnboardingResolver {
@Mutation(() => OnboardingStepSuccessDTO)
@UseGuards(NoPermissionGuard)
async skipSyncEmailOnboardingStep(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<OnboardingStepSuccessDTO> {
await this.onboardingService.setOnboardingConnectAccountPending({
@@ -14,7 +14,7 @@ import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filt
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
import { WorkspaceDomainsService } from 'src/engine/core-modules/domain/workspace-domains/services/workspace-domains.service';
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -102,7 +102,7 @@ export class TwoFactorAuthenticationResolver {
@Mutation(() => InitiateTwoFactorAuthenticationProvisioningDTO)
@UseGuards(UserAuthGuard, NoPermissionGuard)
async initiateOTPProvisioningForAuthenticatedUser(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<InitiateTwoFactorAuthenticationProvisioningDTO> {
const uri =
@@ -129,7 +129,7 @@ export class TwoFactorAuthenticationResolver {
@Args()
deleteTwoFactorAuthenticationMethodInput: DeleteTwoFactorAuthenticationMethodInput,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
): Promise<DeleteTwoFactorAuthenticationMethodDTO> {
const twoFactorMethod =
await this.twoFactorAuthenticationMethodRepository.findOne({
@@ -169,7 +169,7 @@ export class TwoFactorAuthenticationResolver {
@Args()
verifyTwoFactorAuthenticationMethodInput: VerifyTwoFactorAuthenticationMethodInput,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
): Promise<VerifyTwoFactorAuthenticationMethodDTO> {
return await this.twoFactorAuthenticationService.verifyTwoFactorAuthenticationMethodForAuthenticatedUser(
user.id,
@@ -23,6 +23,7 @@ import { extractFileIdFromUrl } from 'src/engine/core-modules/file/files-field/u
import { FileService } from 'src/engine/core-modules/file/services/file.service';
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
import { AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
@@ -102,7 +103,7 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
: this.userWorkspaceRepository.save(userWorkspace);
}
async createWorkspaceMember(workspaceId: string, user: UserEntity) {
async createWorkspaceMember(workspaceId: string, user: AuthContextUser) {
const authContext = buildSystemAuthContext(workspaceId);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => {
@@ -535,7 +536,7 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
appToken?: AppTokenEntity;
}>;
},
user: UserEntity,
user: AuthContextUser,
authProvider: AuthProviderEnum,
) {
return {
@@ -26,6 +26,7 @@ import {
UpdateWorkspaceMemberEmailJob,
UpdateWorkspaceMemberEmailJobData,
} from 'src/engine/core-modules/user/jobs/update-workspace-member-email.job';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { UserExceptionCode } from 'src/engine/core-modules/user/user.exception';
import { userValidator } from 'src/engine/core-modules/user/user.validate';
@@ -58,7 +59,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
super(userRepository);
}
async loadWorkspaceMember(user: UserEntity, workspace: WorkspaceEntity) {
async loadWorkspaceMember(user: AuthContextUser, workspace: WorkspaceEntity) {
if (!isWorkspaceActiveOrSuspended(workspace)) {
return null;
}
@@ -365,7 +366,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
newEmail,
verifyEmailRedirectPath,
}: {
user: UserEntity;
user: AuthContextUser;
workspace: WorkspaceEntity;
newEmail: string;
verifyEmailRedirectPath?: string;
@@ -38,6 +38,7 @@ import {
WorkspaceMemberTranspiler,
} from 'src/engine/core-modules/user/services/workspace-member-transpiler.service';
import { UserVarsService } from 'src/engine/core-modules/user/user-vars/services/user-vars.service';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { userValidator } from 'src/engine/core-modules/user/user.validate';
import { AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
@@ -119,7 +120,7 @@ export class UserResolver {
@Query(() => UserEntity)
@UseGuards(UserAuthGuard, NoPermissionGuard)
async currentUser(
@AuthUser() { id: userId }: UserEntity,
@AuthUser() { id: userId }: AuthContextUser,
@AuthWorkspace({ allowUndefined: true }) workspace: WorkspaceEntity,
): Promise<UserEntity> {
const user = await this.userRepository.findOne({
@@ -360,7 +361,7 @@ export class UserResolver {
@Mutation(() => UserEntity)
@UseGuards(UserAuthGuard, NoPermissionGuard)
async deleteUser(@AuthUser() { id: userId }: UserEntity) {
async deleteUser(@AuthUser() { id: userId }: AuthContextUser) {
return this.userService.deleteUser(userId);
}
@@ -368,7 +369,7 @@ export class UserResolver {
@UseGuards(UserAuthGuard, CustomPermissionGuard)
async deleteUserFromWorkspace(
@Args('workspaceMemberIdToDelete') workspaceMemberIdToDelete: string,
@AuthUser() { id: userId }: UserEntity,
@AuthUser() { id: userId }: AuthContextUser,
@AuthUserWorkspaceId() userWorkspaceId: string,
@AuthWorkspace()
workspace: WorkspaceEntity,
@@ -468,7 +469,7 @@ export class UserResolver {
@ResolveField(() => AvailableWorkspaces)
async availableWorkspaces(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthProvider() authProvider: AuthProviderEnum,
): Promise<AvailableWorkspaces> {
return this.userWorkspaceService.setLoginTokenToAvailableWorkspacesWhenAuthProviderMatch(
@@ -488,7 +489,7 @@ export class UserResolver {
)
async updateUserEmail(
@Args() { newEmail, verifyEmailRedirectPath }: UpdateUserEmailInput,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
) {
const editableFields = workspace.editableProfileFields || [];
@@ -8,7 +8,7 @@ import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/
import { buildCreatedByFromFullNameMetadata } from 'src/engine/core-modules/actor/utils/build-created-by-from-full-name-metadata.util';
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { RunWorkflowVersionInput } from 'src/engine/core-modules/workflow/dtos/run-workflow-version.input';
import { RunWorkflowVersionDTO } from 'src/engine/core-modules/workflow/dtos/run-workflow-version.dto';
import { WorkflowRunDTO } from 'src/engine/core-modules/workflow/dtos/workflow-run.dto';
@@ -69,7 +69,7 @@ export class WorkflowTriggerResolver {
@Mutation(() => RunWorkflowVersionDTO)
async runWorkflowVersion(
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
@Args('input')
{ workflowVersionId, workflowRunId, payload }: RunWorkflowVersionInput,
@@ -6,7 +6,7 @@ import { PermissionFlagType } from 'twenty-shared/constants';
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { SendInvitationsDTO } from 'src/engine/core-modules/workspace-invitation/dtos/send-invitations.dto';
import { WorkspaceInvitation } from 'src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto';
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
@@ -55,7 +55,7 @@ export class WorkspaceInvitationResolver {
async resendWorkspaceInvitation(
@Args('appTokenId') appTokenId: string,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
) {
const authContext = buildSystemAuthContext(workspace.id);
@@ -94,7 +94,7 @@ export class WorkspaceInvitationResolver {
@UseGuards(UserAuthGuard)
async sendInvitations(
@Args() sendInviteLinkInput: SendInvitationsInput,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<SendInvitationsDTO> {
const authContext = buildSystemAuthContext(workspace.id);
@@ -29,6 +29,7 @@ import { MessageQueueService } from 'src/engine/core-modules/message-queue/servi
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
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 { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
@@ -295,7 +296,7 @@ export class WorkspaceService extends TypeOrmQueryService<WorkspaceEntity> {
}
async activateWorkspace(
user: UserEntity,
user: AuthContextUser,
workspace: WorkspaceEntity,
data: ActivateWorkspaceInput,
) {
@@ -33,7 +33,7 @@ import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input';
import {
type AuthProvidersDTO,
@@ -113,7 +113,7 @@ export class WorkspaceResolver {
@UseGuards(UserAuthGuard, WorkspaceAuthGuard, NoPermissionGuard)
async activateWorkspace(
@Args('data') data: ActivateWorkspaceInput,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthWorkspace() workspace: WorkspaceEntity,
) {
return await this.workspaceService.activateWorkspace(user, workspace, data);
@@ -6,7 +6,7 @@ import { PermissionFlagType } from 'twenty-shared/constants';
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { ApplicationTokenService } from 'src/engine/core-modules/auth/token/services/application-token.service';
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { type 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';
@@ -50,7 +50,7 @@ export class FrontComponentResolver {
async frontComponent(
@Args('id', { type: () => UUIDScalarType }) id: string,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser() user: UserEntity,
@AuthUser() user: AuthContextUser,
@AuthUserWorkspaceId() userWorkspaceId: string,
): Promise<FrontComponentDTO | null> {
const dto = await this.frontComponentService.findById(id, workspace.id);
@@ -7,7 +7,7 @@ import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorato
import { type ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
import { type AuthContextUser } from 'src/engine/core-modules/auth/types/auth-context.type';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthApiKey } from 'src/engine/decorators/auth/auth-api-key.decorator';
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
@@ -97,7 +97,7 @@ export class WorkspaceEventEmitterResolver {
async onEventSubscription(
@Args('eventStreamId') eventStreamId: string,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser({ allowUndefined: true }) user: UserEntity | undefined,
@AuthUser({ allowUndefined: true }) user: AuthContextUser | undefined,
@AuthUserWorkspaceId() userWorkspaceId: string | undefined,
@AuthApiKey() apiKey: ApiKeyEntity | undefined,
) {
@@ -163,7 +163,7 @@ export class WorkspaceEventEmitterResolver {
async addQueryToEventStream(
@Args('input') input: AddQuerySubscriptionInput,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser({ allowUndefined: true }) user: UserEntity | undefined,
@AuthUser({ allowUndefined: true }) user: AuthContextUser | undefined,
@AuthUserWorkspaceId() userWorkspaceId: string | undefined,
@AuthApiKey() apiKey: ApiKeyEntity | undefined,
): Promise<boolean> {
@@ -207,7 +207,7 @@ export class WorkspaceEventEmitterResolver {
async removeQueryFromEventStream(
@Args('input') input: RemoveQueryFromEventStreamInput,
@AuthWorkspace() workspace: WorkspaceEntity,
@AuthUser({ allowUndefined: true }) user: UserEntity | undefined,
@AuthUser({ allowUndefined: true }) user: AuthContextUser | undefined,
@AuthUserWorkspaceId() userWorkspaceId: string | undefined,
@AuthApiKey() apiKey: ApiKeyEntity | undefined,
): Promise<boolean> {