refactor(core): Extract all Auth-related User columns into a separate entity (#9557)

Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2024-05-31 09:40:19 +02:00
committed by GitHub
parent 08902bf941
commit 5887ed6498
23 changed files with 182 additions and 282 deletions

View File

@@ -79,16 +79,11 @@ export class AuthController {
throw new AuthError('MFA Error', 998);
}
const { decryptedRecoveryCodes, decryptedSecret } =
await this.mfaService.getSecretAndRecoveryCodes(user.id);
user.mfaSecret = decryptedSecret;
user.mfaRecoveryCodes = decryptedRecoveryCodes;
const isMFATokenValid =
(await this.validateMfaToken(user, mfaToken)) ||
(await this.validateMfaRecoveryCode(user, mfaRecoveryCode));
const isMFATokenValid = await this.mfaService.validateMfa(
user.id,
mfaToken,
mfaRecoveryCode,
);
if (!isMFATokenValid) {
throw new AuthError('Invalid mfa token or recovery code');
}
@@ -193,27 +188,4 @@ export class AuthController {
this.authService.clearCookie(res);
return { loggedOut: true };
}
private async validateMfaToken(user: User, token?: string) {
if (!!!token) return false;
return this.mfaService.totp.verifySecret({
secret: user.mfaSecret ?? '',
token,
});
}
private async validateMfaRecoveryCode(user: User, mfaRecoveryCode?: string) {
if (!!!mfaRecoveryCode) return false;
const index = user.mfaRecoveryCodes.indexOf(mfaRecoveryCode);
if (index === -1) return false;
// remove used recovery code
user.mfaRecoveryCodes.splice(index, 1);
await this.userService.update(user.id, {
mfaRecoveryCodes: this.mfaService.encryptRecoveryCodes(user.mfaRecoveryCodes),
});
return true;
}
}

View File

@@ -16,6 +16,7 @@ import { CacheService } from '@/services/cache/cache.service';
import { PasswordUtility } from '@/services/password.utility';
import Container from 'typedi';
import { Logger } from '@/Logger';
import { AuthUserRepository } from '@/databases/repositories/authUser.repository';
if (!inE2ETests) {
Container.get(Logger).error('E2E endpoints only allowed during E2E tests');
@@ -106,6 +107,7 @@ export class E2EController {
private readonly passwordUtility: PasswordUtility,
private readonly eventBus: MessageEventBus,
private readonly userRepository: UserRepository,
private readonly authUserRepository: AuthUserRepository,
) {
license.isFeatureEnabled = (feature: BooleanLicenseFeature) =>
this.enabledFeatures[feature] ?? false;
@@ -185,13 +187,6 @@ export class E2EController {
members: UserSetupPayload[],
admin: UserSetupPayload,
) {
if (owner?.mfaSecret && owner.mfaRecoveryCodes?.length) {
const { encryptedRecoveryCodes, encryptedSecret } =
this.mfaService.encryptSecretAndRecoveryCodes(owner.mfaSecret, owner.mfaRecoveryCodes);
owner.mfaSecret = encryptedSecret;
owner.mfaRecoveryCodes = encryptedRecoveryCodes;
}
const userCreatePromises = [
this.userRepository.createUserWithProject({
id: uuid(),
@@ -221,7 +216,17 @@ export class E2EController {
);
}
await Promise.all(userCreatePromises);
const [newOwner] = await Promise.all(userCreatePromises);
if (owner?.mfaSecret && owner.mfaRecoveryCodes?.length) {
const { encryptedRecoveryCodes, encryptedSecret } =
this.mfaService.encryptSecretAndRecoveryCodes(owner.mfaSecret, owner.mfaRecoveryCodes);
await this.authUserRepository.update(newOwner.user.id, {
mfaSecret: encryptedSecret,
mfaRecoveryCodes: encryptedRecoveryCodes,
});
}
await this.settingsRepo.update(
{ key: 'userManagement.isInstanceOwnerSetUp' },

View File

@@ -77,7 +77,6 @@ export class UsersController {
delete user.isOwner;
delete user.isPending;
delete user.signInType;
delete user.hasRecoveryCodesLeft;
}
}