From 582e5c4a4f130fd033a4f5df31f123ec15a15518 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 22 Oct 2021 02:43:44 +0200 Subject: [PATCH 1/6] LoginUser Database Model --- .../0003-login_server_tables/LoginUser.ts | 56 +++++++++++++++++++ database/entity/LoginUser.ts | 1 + database/entity/index.ts | 2 + 3 files changed, 59 insertions(+) create mode 100644 database/entity/0003-login_server_tables/LoginUser.ts create mode 100644 database/entity/LoginUser.ts diff --git a/database/entity/0003-login_server_tables/LoginUser.ts b/database/entity/0003-login_server_tables/LoginUser.ts new file mode 100644 index 000000000..26614b4db --- /dev/null +++ b/database/entity/0003-login_server_tables/LoginUser.ts @@ -0,0 +1,56 @@ +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' + +// Moriz: I do not like the idea of having two user tables +@Entity('login_users') +export class LoginUser extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ length: 191, unique: true }) + email: string + + @Column({ name: 'first_name', length: 150 }) + firstName: string + + @Column({ name: 'last_name', length: 255, default: '' }) + lastName: string + + @Column({ length: 255, default: '' }) + username: string + + @Column({ default: '' }) + description: string + + @Column({ type: 'bigint', default: 0, unsigned: true }) + password: string + + @Column({ name: 'pubkey', type: 'binary', length: 32, default: null, nullable: true }) + pubKey: Buffer + + @Column({ name: 'privkey', type: 'binary', length: 80, default: null, nullable: true }) + privKey: Buffer + + @Column({ name: 'email_hash', type: 'binary', length: 32, default: null, nullable: true }) + emailHash: Buffer + + @Column({ name: 'created', default: () => 'CURRENT_TIMESTAMP' }) + createdAt: Date + + @Column({ name: 'email_checked', default: 0 }) + emailChecked: boolean + + @Column({ name: 'passphrase_shown', default: 0 }) + passphraseShown: boolean + + @Column({ length: 4, default: 'de' }) + language: string + + @Column({ default: 0 }) + disabled: boolean + + @Column({ name: 'group_id', default: 0, unsigned: true }) + groupId: number + + @Column({ name: 'publisher_id', default: 0 }) + publisherId: number +} diff --git a/database/entity/LoginUser.ts b/database/entity/LoginUser.ts new file mode 100644 index 000000000..034f791cb --- /dev/null +++ b/database/entity/LoginUser.ts @@ -0,0 +1 @@ +export { LoginUser } from './0003-login_server_tables/LoginUser' diff --git a/database/entity/index.ts b/database/entity/index.ts index e18757ab8..1881b2932 100644 --- a/database/entity/index.ts +++ b/database/entity/index.ts @@ -1,4 +1,5 @@ import { Balance } from './Balance' +import { LoginUser } from './LoginUser' import { Migration } from './Migration' import { Transaction } from './Transaction' import { TransactionCreation } from './TransactionCreation' @@ -9,6 +10,7 @@ import { UserTransaction } from './UserTransaction' export const entities = [ Balance, + LoginUser, Migration, Transaction, TransactionCreation, From af2a77c30f34e905dda579c8f8b52ba9885bdc47 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 22 Oct 2021 02:44:22 +0200 Subject: [PATCH 2/6] implemented checkUsername resolver --- backend/src/graphql/resolver/UserResolver.ts | 29 ++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 33949197c..d4746589b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -26,6 +26,7 @@ import { getCustomRepository } from 'typeorm' import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository' import { Setting } from '../enum/Setting' import { UserRepository } from '../../typeorm/repository/User' +import { LoginUser } from '@entity/LoginUser' @Resolver() export class UserResolver { @@ -276,14 +277,26 @@ export class UserResolver { } @Query(() => CheckUsernameResponse) - async checkUsername( - @Args() { username, groupId = 1 }: CheckUsernameArgs, - ): Promise { - const response = await apiGet( - CONFIG.LOGIN_API_URL + `checkUsername?username=${username}&group_id=${groupId}`, - ) - if (!response.success) throw new Error(response.data) - return new CheckUsernameResponse(response.data) + async checkUsername(@Args() { username }: CheckUsernameArgs): Promise { + // Username empty? + if (username === '') { + throw new Error('Username must be set.') + } + + // Do we fullfil the minimum character length? + const MIN_CHARACTERS_USERNAME = 2 + if (username.length < MIN_CHARACTERS_USERNAME) { + throw new Error(`Username must be at minimum ${MIN_CHARACTERS_USERNAME} characters long.`) + } + + const usersFound = await LoginUser.count({ username }) + + // Username already present? + if (usersFound !== 0) { + throw new Error(`Username "${username}" already taken.`) + } + + return new CheckUsernameResponse({ state: 'success' }) } @Query(() => CheckEmailResponse) From d1ae8a95378ed737e5703a8f55747ea03182d0c4 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 22 Oct 2021 02:44:40 +0200 Subject: [PATCH 3/6] cleaned graphql checkUsername Args --- backend/src/graphql/arg/CheckUsernameArgs.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/graphql/arg/CheckUsernameArgs.ts b/backend/src/graphql/arg/CheckUsernameArgs.ts index 6aaed6d0b..64265b64e 100644 --- a/backend/src/graphql/arg/CheckUsernameArgs.ts +++ b/backend/src/graphql/arg/CheckUsernameArgs.ts @@ -4,7 +4,4 @@ import { ArgsType, Field } from 'type-graphql' export default class CheckUsernameArgs { @Field(() => String) username: string - - @Field(() => Number, { nullable: true }) - groupId?: number } From 973fad7ea96054a27e92d9ccb0b3d5cef64a199a Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 22 Oct 2021 02:44:54 +0200 Subject: [PATCH 4/6] cleaned graphql checkUsername Response --- backend/src/graphql/model/CheckUsernameResponse.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/backend/src/graphql/model/CheckUsernameResponse.ts b/backend/src/graphql/model/CheckUsernameResponse.ts index b3186ffcf..fe93511bc 100644 --- a/backend/src/graphql/model/CheckUsernameResponse.ts +++ b/backend/src/graphql/model/CheckUsernameResponse.ts @@ -6,16 +6,8 @@ import { ObjectType, Field } from 'type-graphql' export class CheckUsernameResponse { constructor(json: any) { this.state = json.state - this.msg = json.msg - this.groupId = json.group_id } @Field(() => String) state: string - - @Field(() => String) - msg?: string - - @Field(() => Number) - groupId?: number } From 9540ab32086e4986da390c3bec90a9a44c8cd667 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 30 Oct 2021 04:52:01 +0200 Subject: [PATCH 5/6] reduced checkUsername response to a boolean --- backend/src/graphql/model/CheckUsernameResponse.ts | 13 ------------- backend/src/graphql/resolver/UserResolver.ts | 9 ++++----- frontend/src/graphql/queries.js | 4 +--- frontend/src/validation-rules.js | 2 +- 4 files changed, 6 insertions(+), 22 deletions(-) delete mode 100644 backend/src/graphql/model/CheckUsernameResponse.ts diff --git a/backend/src/graphql/model/CheckUsernameResponse.ts b/backend/src/graphql/model/CheckUsernameResponse.ts deleted file mode 100644 index fe93511bc..000000000 --- a/backend/src/graphql/model/CheckUsernameResponse.ts +++ /dev/null @@ -1,13 +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 CheckUsernameResponse { - constructor(json: any) { - this.state = json.state - } - - @Field(() => String) - state: string -} diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index d4746589b..ab49ee6bf 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -3,8 +3,8 @@ import { Resolver, Query, Args, Arg, Authorized, Ctx, UseMiddleware, Mutation } from 'type-graphql' import { from_hex as fromHex } from 'libsodium-wrappers' +import { getCustomRepository } from 'typeorm' import CONFIG from '../../config' -import { CheckUsernameResponse } from '../model/CheckUsernameResponse' import { LoginViaVerificationCode } from '../model/LoginViaVerificationCode' import { SendPasswordResetEmailResponse } from '../model/SendPasswordResetEmailResponse' import { UpdateUserInfosResponse } from '../model/UpdateUserInfosResponse' @@ -22,7 +22,6 @@ import { klicktippNewsletterStateMiddleware, } from '../../middleware/klicktippMiddleware' import { CheckEmailResponse } from '../model/CheckEmailResponse' -import { getCustomRepository } from 'typeorm' import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository' import { Setting } from '../enum/Setting' import { UserRepository } from '../../typeorm/repository/User' @@ -276,8 +275,8 @@ export class UserResolver { return response } - @Query(() => CheckUsernameResponse) - async checkUsername(@Args() { username }: CheckUsernameArgs): Promise { + @Query(() => Boolean) + async checkUsername(@Args() { username }: CheckUsernameArgs): Promise { // Username empty? if (username === '') { throw new Error('Username must be set.') @@ -296,7 +295,7 @@ export class UserResolver { throw new Error(`Username "${username}" already taken.`) } - return new CheckUsernameResponse({ state: 'success' }) + return true } @Query(() => CheckEmailResponse) diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 2ee381dd8..01021f601 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -75,9 +75,7 @@ export const sendResetPasswordEmail = gql` export const checkUsername = gql` query($username: String!) { - checkUsername(username: $username) { - state - } + checkUsername(username: $username) } ` diff --git a/frontend/src/validation-rules.js b/frontend/src/validation-rules.js index 5552794d1..54f4c3090 100644 --- a/frontend/src/validation-rules.js +++ b/frontend/src/validation-rules.js @@ -59,7 +59,7 @@ export const loadAllRules = (i18nCallback) => { }, }) .then((result) => { - return result.data.checkUsername.state === 'success' + return result.data.checkUsername }) .catch(() => { return false From 472391a8d2eb2a9cdb877f9b333e806e79652525 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sun, 31 Oct 2021 02:13:29 +0100 Subject: [PATCH 6/6] corrected typescript type (not graphql) --- backend/src/graphql/resolver/UserResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index ab49ee6bf..f6eccd7e8 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -276,7 +276,7 @@ export class UserResolver { } @Query(() => Boolean) - async checkUsername(@Args() { username }: CheckUsernameArgs): Promise { + async checkUsername(@Args() { username }: CheckUsernameArgs): Promise { // Username empty? if (username === '') { throw new Error('Username must be set.')