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:
+2
-2
@@ -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(
|
||||
|
||||
+17
@@ -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()
|
||||
{
|
||||
|
||||
+3
-3
@@ -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
-2
@@ -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;
|
||||
|
||||
+15
-1
@@ -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();
|
||||
|
||||
|
||||
+9
-1
@@ -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 ||
|
||||
|
||||
+5
-5
@@ -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({
|
||||
|
||||
+4
-4
@@ -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,
|
||||
|
||||
+3
-2
@@ -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 || [];
|
||||
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
+2
-1
@@ -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);
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+4
-4
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user