From d1dfda81ce503578a4aee79534eb2455c6444a97 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 23 Nov 2021 12:00:14 +0100 Subject: [PATCH] removed password from createUser & implement setPassword --- backend/src/graphql/arg/CreateUserArgs.ts | 3 - .../src/graphql/model/CheckEmailResponse.ts | 29 -------- backend/src/graphql/resolver/UserResolver.ts | 69 ++++++++++--------- frontend/src/graphql/queries.js | 9 --- 4 files changed, 37 insertions(+), 73 deletions(-) delete mode 100644 backend/src/graphql/model/CheckEmailResponse.ts diff --git a/backend/src/graphql/arg/CreateUserArgs.ts b/backend/src/graphql/arg/CreateUserArgs.ts index 3d09e56eb..75897e3fc 100644 --- a/backend/src/graphql/arg/CreateUserArgs.ts +++ b/backend/src/graphql/arg/CreateUserArgs.ts @@ -11,9 +11,6 @@ export default class CreateUserArgs { @Field(() => String) lastName: string - @Field(() => String) - password: string - @Field(() => String) language: string diff --git a/backend/src/graphql/model/CheckEmailResponse.ts b/backend/src/graphql/model/CheckEmailResponse.ts deleted file mode 100644 index 948739722..000000000 --- a/backend/src/graphql/model/CheckEmailResponse.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { ObjectType, Field } from 'type-graphql' - -@ObjectType() -export class CheckEmailResponse { - constructor(json: any) { - this.sessionId = json.session_id - this.email = json.user.email - this.language = json.user.language - this.firstName = json.user.first_name - this.lastName = json.user.last_name - } - - @Field(() => Number) - sessionId: number - - @Field(() => String) - email: string - - @Field(() => String) - firstName: string - - @Field(() => String) - lastName: string - - @Field(() => String) - language: string -} diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 82de72c0a..1c4bc2b50 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -19,7 +19,6 @@ import { klicktippRegistrationMiddleware, klicktippNewsletterStateMiddleware, } from '../../middleware/klicktippMiddleware' -import { CheckEmailResponse } from '../model/CheckEmailResponse' import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository' import { LoginUserRepository } from '../../typeorm/repository/LoginUser' import { Setting } from '../enum/Setting' @@ -288,7 +287,7 @@ export class UserResolver { @Mutation(() => String) async createUser( - @Args() { email, firstName, lastName, password, language, publisherId }: CreateUserArgs, + @Args() { email, firstName, lastName, language, publisherId }: CreateUserArgs, ): Promise { // TODO: wrong default value (should be null), how does graphql work here? Is it an required field? // default int publisher_id = 0; @@ -298,13 +297,6 @@ export class UserResolver { language = DEFAULT_LANGUAGE } - // Validate Password - if (!isPassword(password)) { - throw new Error( - 'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!', - ) - } - // Validate username // TODO: never true const username = '' @@ -322,10 +314,7 @@ export class UserResolver { } const passphrase = PassphraseGenerate() - const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key - const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash const emailHash = getEmailHash(email) - const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) // Table: login_users const loginUser = new LoginUser() @@ -334,13 +323,13 @@ export class UserResolver { loginUser.lastName = lastName loginUser.username = username loginUser.description = '' - loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash + // loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash loginUser.emailHash = emailHash loginUser.language = language loginUser.groupId = 1 loginUser.publisherId = publisherId - loginUser.pubKey = keyPair[0] - loginUser.privKey = encryptedPrivkey + // loginUser.pubKey = keyPair[0] + // loginUser.privKey = encryptedPrivkey const queryRunner = getConnection().createQueryRunner() await queryRunner.connect() @@ -498,25 +487,12 @@ export class UserResolver { return 'success' } - @Query(() => CheckEmailResponse) - @UseMiddleware(klicktippRegistrationMiddleware) - async checkEmail(@Arg('optin') optin: string): Promise { - const result = await apiGet( - CONFIG.LOGIN_API_URL + 'loginViaEmailVerificationCode?emailVerificationCode=' + optin, - ) - if (!result.success) { - throw new Error(result.data) - } - return new CheckEmailResponse(result.data) - } - @Query(() => Boolean) async setPassword( @Arg('code') code: string, @Arg('password') password: string, ): Promise { - - const optInCode = await LoginEmailOptIn.findOneOrFail({verificationCode: code}).catch(()=>{ + const optInCode = await LoginEmailOptIn.findOneOrFail({ verificationCode: code }).catch(() => { throw new Error('Could not login with emailVerificationCode') }) @@ -527,25 +503,54 @@ export class UserResolver { } // load user - const loginUser = await LoginUser.findOneOrFail({id: optInCode.userId}).catch(()=> { + const loginUser = await LoginUser.findOneOrFail({ id: optInCode.userId }).catch(() => { throw new Error('Could not find corresponding User') }) + const loginUserBackup = await LoginUserBackup.findOneOrFail({ userId: loginUser.id }).catch( + () => { + throw new Error('Could not find corresponding BackupUser') + }, + ) + + const passphrase = loginUserBackup.passphrase.slice(0, -1).split(' ') + if (passphrase.length < PHRASE_WORD_COUNT) { + // TODO if this can happen we cannot recover from that + throw new Error('Could not load a correct passphrase') + } + // Activate EMail loginUser.emailChecked = true + // Validate Password + if (!isPassword(password)) { + throw new Error( + 'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!', + ) + } + // Update Password + const passwordHash = SecretKeyCryptographyCreateKey(loginUser.email, password) // return short and long hash + const keyPair = KeyPairEd25519Create(passphrase) // return pub, priv Key + const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) + loginUser.password = passwordHash[0].readBigUInt64LE() // using the shorthash + loginUser.pubKey = keyPair[0] + loginUser.privKey = encryptedPrivkey // Save loginUser + // TODO transaction await loginUser.save() // Sign into Klicktipp - if(optInCode.emailOptInTypeId === EMAIL_OPT_IN_REGISTER){ - // TODO + if (optInCode.emailOptInTypeId === EMAIL_OPT_IN_REGISTER) { + // TODO klicktippRegistrationMiddleware } // Delete Code + // TODO transaction await optInCode.remove() + + return true } @Authorized() diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index bf4d07253..f1b1ac768 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -95,15 +95,6 @@ export const listGDTEntriesQuery = gql` } ` -export const checkEmailQuery = gql` - query($optin: String!) { - checkEmail(optin: $optin) { - email - sessionId - } - } -` - export const communityInfo = gql` query { getCommunityInfo {