From 25e03c35b2a610946c592707ad3b75ce9b4b48c5 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 31 Jan 2023 13:31:10 +0100 Subject: [PATCH] refactor UserResolver to use LogError, clean comments --- backend/src/graphql/resolver/UserResolver.ts | 131 ++++++------------- 1 file changed, 38 insertions(+), 93 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index c630c240a..773e1bac1 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -63,6 +63,7 @@ import { isValidPassword } from '@/password/EncryptorUtils' import { FULL_CREATION_AVAILABLE } from './const/const' import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor' import { PasswordEncryptionType } from '../enum/PasswordEncryptionType' +import LogError from '@/server/LogError' // eslint-disable-next-line @typescript-eslint/no-var-requires const sodium = require('sodium-native') @@ -134,22 +135,18 @@ export class UserResolver { email = email.trim().toLowerCase() const dbUser = await findUserByEmail(email) if (dbUser.deletedAt) { - logger.error('The User was permanently deleted in database.') - throw new Error('This user was permanently deleted. Contact support for questions.') + throw new LogError('This user was permanently deleted. Contact support for questions', dbUser) } if (!dbUser.emailContact.emailChecked) { - logger.error('The Users email is not validate yet.') - throw new Error('User email not validated') + throw new LogError('The Users email is not validate yet', dbUser) } if (dbUser.password === BigInt(0)) { - logger.error('The User has not set a password yet.') // TODO we want to catch this on the frontend and ask the user to check his emails or resend code - throw new Error('User has no password set yet') + throw new LogError('The User has not set a password yet', dbUser) } if (!verifyPassword(dbUser, password)) { - logger.error('The User has no valid credentials.') - throw new Error('No user with this credentials') + throw new LogError('No user with this credentials', dbUser) } if (dbUser.passwordEncryptionType !== PasswordEncryptionType.GRADIDO_ID) { @@ -309,30 +306,19 @@ export class UserResolver { await queryRunner.startTransaction('REPEATABLE READ') try { dbUser = await queryRunner.manager.save(dbUser).catch((error) => { - logger.error('Error while saving dbUser', error) - throw new Error('error saving user') + throw new LogError('Error while saving dbUser', error) }) let emailContact = newEmailContact(email, dbUser.id) emailContact = await queryRunner.manager.save(emailContact).catch((error) => { - logger.error('Error while saving emailContact', error) - throw new Error('error saving email user contact') + throw new LogError('Error while saving user email contact', error) }) dbUser.emailContact = emailContact dbUser.emailId = emailContact.id await queryRunner.manager.save(dbUser).catch((error) => { - logger.error('Error while updating dbUser', error) - throw new Error('error updating user') + throw new LogError('Error while updating dbUser', error) }) - /* - const emailOptIn = newEmailOptIn(dbUser.id) - await queryRunner.manager.save(emailOptIn).catch((error) => { - logger.error('Error while saving emailOptIn', error) - throw new Error('error saving email opt in') - }) - */ - const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( /{optin}/g, emailContact.emailVerificationCode.toString(), @@ -358,9 +344,8 @@ export class UserResolver { await queryRunner.commitTransaction() logger.addContext('user', dbUser.id) } catch (e) { - logger.error(`error during create user with ${e}`) await queryRunner.rollbackTransaction() - throw e + throw new LogError(`Error during create user with error: ${e}`, e) } finally { await queryRunner.release() } @@ -392,13 +377,8 @@ export class UserResolver { } if (!canEmailResend(user.emailContact.updatedAt || user.emailContact.createdAt)) { - logger.error( - `email already sent less than ${printTimeDuration( - CONFIG.EMAIL_CODE_REQUEST_TIME, - )} minutes ago`, - ) - throw new Error( - `email already sent less than ${printTimeDuration( + throw new LogError( + `Email already sent less than ${printTimeDuration( CONFIG.EMAIL_CODE_REQUEST_TIME, )} minutes ago`, ) @@ -409,8 +389,7 @@ export class UserResolver { user.emailContact.emailVerificationCode = random(64) user.emailContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_RESET_PASSWORD await user.emailContact.save().catch(() => { - logger.error('Unable to save email verification code= ' + user.emailContact) - throw new Error('Unable to save email verification code.') + throw new LogError('Unable to save email verification code', user.emailContact) }) logger.info(`optInCode for ${email}=${user.emailContact}`) @@ -445,33 +424,22 @@ export class UserResolver { logger.info(`setPassword(${code}, ***)...`) // Validate Password if (!isValidPassword(password)) { - logger.error('Password entered is lexically invalid') - throw new Error( + throw new LogError( 'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!', ) } - // Load code - /* - const optInCode = await LoginEmailOptIn.findOneOrFail({ verificationCode: code }).catch(() => { - logger.error('Could not login with emailVerificationCode') - throw new Error('Could not login with emailVerificationCode') - }) - */ + // load code const userContact = await DbUserContact.findOneOrFail( { emailVerificationCode: code }, { relations: ['user'] }, ).catch(() => { - logger.error('Could not login with emailVerificationCode') - throw new Error('Could not login with emailVerificationCode') + throw new LogError('Could not login with emailVerificationCode') }) logger.debug('userContact loaded...') // Code is only valid for `CONFIG.EMAIL_CODE_VALID_TIME` minutes if (!isEmailVerificationCodeValid(userContact.updatedAt || userContact.createdAt)) { - logger.error( - `email was sent more than ${printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME)} ago`, - ) - throw new Error( + throw new LogError( `email was sent more than ${printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME)} ago`, ) } @@ -498,13 +466,11 @@ export class UserResolver { try { // Save user await queryRunner.manager.save(user).catch((error) => { - logger.error('error saving user: ' + error) - throw new Error('error saving user: ' + error) + throw new LogError(`Error saving user: ${error}`, error) }) // Save userContact await queryRunner.manager.save(userContact).catch((error) => { - logger.error('error saving userContact: ' + error) - throw new Error('error saving userContact: ' + error) + throw new LogError(`error saving userContact: ${error}`, error) }) await queryRunner.commitTransaction() @@ -515,8 +481,7 @@ export class UserResolver { eventProtocol.writeEvent(event.setEventActivateAccount(eventActivateAccount)) } catch (e) { await queryRunner.rollbackTransaction() - logger.error('Error on writing User and UserContact data:' + e) - throw e + throw new LogError(`Error on writing User and UserContact data: ${e}`, e) } finally { await queryRunner.release() } @@ -530,7 +495,7 @@ export class UserResolver { `klicktippSignIn(${userContact.email}, ${user.language}, ${user.firstName}, ${user.lastName})`, ) } catch (e) { - logger.error('Error subscribe to klicktipp:' + e) + logger.error(`Error subscribe to klicktipp: ${e}`, e) // TODO is this a problem? // eslint-disable-next-line no-console /* uncomment this, when you need the activation link on the console @@ -550,10 +515,7 @@ export class UserResolver { logger.debug(`found optInCode=${userContact}`) // Code is only valid for `CONFIG.EMAIL_CODE_VALID_TIME` minutes if (!isEmailVerificationCodeValid(userContact.updatedAt || userContact.createdAt)) { - logger.error( - `email was sent more than ${printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME)} ago`, - ) - throw new Error( + throw new LogError( `email was sent more than ${printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME)} ago`, ) } @@ -589,8 +551,7 @@ export class UserResolver { if (language) { if (!isLanguage(language)) { - logger.error(`"${language}" isn't a valid language`) - throw new Error(`"${language}" isn't a valid language`) + throw new LogError(`"${language}" isn't a valid language`, language) } userEntity.language = language i18n.setLocale(language) @@ -599,15 +560,13 @@ export class UserResolver { if (password && passwordNew) { // Validate Password if (!isValidPassword(passwordNew)) { - logger.error('newPassword does not fullfil the rules') - throw new Error( + throw new LogError( 'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!', ) } if (!verifyPassword(userEntity, password)) { - logger.error(`Old password is invalid`) - throw new Error(`Old password is invalid`) + throw new LogError(`Old password is invalid`) } // Save new password hash and newly encrypted private key @@ -630,16 +589,14 @@ export class UserResolver { try { await queryRunner.manager.save(userEntity).catch((error) => { - logger.error('error saving user: ' + error) - throw new Error('error saving user: ' + error) + throw new LogError(`error saving user: ${error}`, error) }) await queryRunner.commitTransaction() logger.debug('writing User data successful...') } catch (e) { await queryRunner.rollbackTransaction() - logger.error(`error on writing updated user data: ${e}`) - throw e + throw new LogError(`error on writing updated user data: ${e}`, e) } finally { await queryRunner.release() } @@ -766,14 +723,12 @@ export class UserResolver { const user = await DbUser.findOne({ id: userId }) // user exists ? if (!user) { - logger.error(`Could not find user with userId: ${userId}`) - throw new Error(`Could not find user with userId: ${userId}`) + throw new LogError(`Could not find user with userId: ${userId}`, userId) } // administrator user changes own role? const moderatorUser = getUser(context) if (moderatorUser.id === userId) { - logger.error('Administrator can not change his own role!') - throw new Error('Administrator can not change his own role!') + throw new LogError('Administrator can not change his own role') } // change isAdmin switch (user.isAdmin) { @@ -781,16 +736,14 @@ export class UserResolver { if (isAdmin === true) { user.isAdmin = new Date() } else { - logger.error('User is already a usual user!') - throw new Error('User is already a usual user!') + throw new LogError('User is already an usual user') } break default: if (isAdmin === false) { user.isAdmin = null } else { - logger.error('User is already admin!') - throw new Error('User is already admin!') + throw new LogError('User is already admin') } break } @@ -808,14 +761,12 @@ export class UserResolver { const user = await DbUser.findOne({ id: userId }) // user exists ? if (!user) { - logger.error(`Could not find user with userId: ${userId}`) - throw new Error(`Could not find user with userId: ${userId}`) + throw new LogError(`Could not find user with userId: ${userId}`, userId) } // moderator user disabled own account? const moderatorUser = getUser(context) if (moderatorUser.id === userId) { - logger.error('Moderator can not delete his own account!') - throw new Error('Moderator can not delete his own account!') + throw new LogError('Moderator can not delete his own account') } // soft-delete user await user.softRemove() @@ -828,12 +779,10 @@ export class UserResolver { async unDeleteUser(@Arg('userId', () => Int) userId: number): Promise { const user = await DbUser.findOne({ id: userId }, { withDeleted: true }) if (!user) { - logger.error(`Could not find user with userId: ${userId}`) - throw new Error(`Could not find user with userId: ${userId}`) + throw new LogError(`Could not find user with userId: ${userId}`, userId) } if (!user.deletedAt) { - logger.error('User is not deleted') - throw new Error('User is not deleted') + throw new LogError('User is not deleted') } await user.recover() return null @@ -846,17 +795,14 @@ export class UserResolver { // const user = await dbUser.findOne({ id: emailContact.userId }) const user = await findUserByEmail(email) if (!user) { - logger.error(`Could not find User to emailContact: ${email}`) - throw new Error(`Could not find User to emailContact: ${email}`) + throw new LogError(`Could not find User to emailContact: ${email}`, email) } if (user.deletedAt) { - logger.error(`User with emailContact: ${email} is deleted.`) - throw new Error(`User with emailContact: ${email} is deleted.`) + throw new LogError(`User with emailContact: ${email} is deleted`, email) } const emailContact = user.emailContact if (emailContact.deletedAt) { - logger.error(`The emailContact: ${email} of this User is deleted.`) - throw new Error(`The emailContact: ${email} of this User is deleted.`) + throw new LogError(`The emailContact: ${email} of this User is deleted`, email) } emailContact.emailResendCount++ @@ -893,8 +839,7 @@ export async function findUserByEmail(email: string): Promise { { email: email }, { withDeleted: true, relations: ['user'] }, ).catch(() => { - logger.error(`UserContact with email=${email} does not exists`) - throw new Error('No user with this credentials') + throw new LogError('No user with this credentials', email) }) const dbUser = dbUserContact.user dbUser.emailContact = dbUserContact