diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index f21082d1d..7a55de8e8 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -51,7 +51,6 @@ const email = { EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'xxx', EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'gmail.com', EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '587', - EMAIL_LINK_VERIFICATION: process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/vue/checkEmail/$1', } diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts index d72f19456..6245ef8ba 100644 --- a/backend/src/graphql/directive/isAuthorized.ts +++ b/backend/src/graphql/directive/isAuthorized.ts @@ -2,9 +2,6 @@ import { AuthChecker } from 'type-graphql' -import CONFIG from '../../config' -import { apiGet } from '../../apis/HttpRequest' - import decode from '../../jwt/decode' import encode from '../../jwt/encode' @@ -13,7 +10,7 @@ const isAuthorized: AuthChecker = async ( ) => { if (context.token) { const decoded = decode(context.token) - context.pubKey = decoded.pubKey + context.pubKey = Buffer.from(decoded.pubKey).toString('hex') context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) }) return true } diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index 08651ae17..5b7682e01 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -10,15 +10,17 @@ export class User { @PrimaryGeneratedColumn() id: number */ - constructor(json: any) { - this.email = json.email - this.firstName = json.first_name - this.lastName = json.last_name - this.username = json.username - this.description = json.description - this.pubkey = json.public_hex - this.language = json.language - this.publisherId = json.publisher_id + constructor(json?: any) { + if (json) { + this.email = json.email + this.firstName = json.first_name + this.lastName = json.last_name + this.username = json.username + this.description = json.description + this.pubkey = json.public_hex + this.language = json.language + this.publisherId = json.publisher_id + } } @Field(() => String) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 5c4625938..ad4566070 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -22,14 +22,14 @@ import { } 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' import { UserRepository } from '../../typeorm/repository/User' import { LoginUser } from '@entity/LoginUser' -import { LoginElopageBuys } from '@entity/LoginElopageBuys' import { LoginUserBackup } from '@entity/LoginUserBackup' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { sendEMail } from '../../util/sendEMail' -import { LoginUserRepository } from '../../typeorm/repository/LoginUser' +import { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys' // eslint-disable-next-line @typescript-eslint/no-var-requires const sodium = require('sodium-native') @@ -201,33 +201,32 @@ export class UserResolver { @Ctx() context: any, ): Promise { email = email.trim().toLowerCase() - const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password }) - - // if there is no user, throw an authentication error - if (!result.success) { - throw new Error(result.data) - } - - context.setHeaders.push({ - key: 'token', - value: encode(result.data.user.public_hex), + // const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password }) + // UnsecureLogin + const loginUserRepository = getCustomRepository(LoginUserRepository) + const loginUser = await loginUserRepository.findByEmail(email).catch(() => { + throw new Error('No user with this credentials') }) - const user = new User(result.data.user) - // Hack: Database Field is not validated properly and not nullable - if (user.publisherId === 0) { - user.publisherId = undefined + const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash + const loginUserPassword = BigInt(loginUser.password.toString()) + if (loginUserPassword !== passwordHash[0].readBigUInt64LE()) { + throw new Error('No user with this credentials') } - user.hasElopage = result.data.hasElopage - // read additional settings from settings table + // TODO: If user has no pubKey Create it again and update user. + const userRepository = getCustomRepository(UserRepository) let userEntity: void | DbUser - userEntity = await userRepository.findByPubkeyHex(user.pubkey).catch(() => { + const loginUserPubKey = loginUser.pubKey + const loginUserPubKeyString = loginUserPubKey.toString('hex') + userEntity = await userRepository.findByPubkeyHex(loginUserPubKeyString).catch(() => { + // User not stored in state_users + // TODO: Check with production data - email is unique which can cause problems userEntity = new DbUser() - userEntity.firstName = user.firstName - userEntity.lastName = user.lastName - userEntity.username = user.username - userEntity.email = user.email - userEntity.pubkey = Buffer.from(user.pubkey, 'hex') + userEntity.firstName = loginUser.firstName + userEntity.lastName = loginUser.lastName + userEntity.username = loginUser.username + userEntity.email = loginUser.email + userEntity.pubkey = loginUser.pubKey userRepository.save(userEntity).catch(() => { throw new Error('error by save userEntity') @@ -237,16 +236,28 @@ export class UserResolver { throw new Error('error with cannot happen') } - // Save publisherId if Elopage is not yet registered + const user = new User() + user.email = email + user.firstName = loginUser.firstName + user.lastName = loginUser.lastName + user.username = loginUser.username + user.description = loginUser.description + user.pubkey = loginUserPubKeyString + user.language = loginUser.language + + // Elopage Status & Stored PublisherId + user.hasElopage = await this.hasElopage({ pubKey: loginUserPubKeyString }) if (!user.hasElopage && publisherId) { user.publisherId = publisherId - + // TODO: Check if we can use updateUserInfos + // await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey }) const loginUserRepository = getCustomRepository(LoginUserRepository) const loginUser = await loginUserRepository.findOneOrFail({ email: userEntity.email }) loginUser.publisherId = publisherId loginUserRepository.save(loginUser) } + // coinAnimation const userSettingRepository = getCustomRepository(UserSettingRepository) const coinanimation = await userSettingRepository .readBoolean(userEntity.id, Setting.COIN_ANIMATION) @@ -254,6 +265,12 @@ export class UserResolver { throw new Error(error) }) user.coinanimation = coinanimation + + context.setHeaders.push({ + key: 'token', + value: encode(loginUser.pubKey), + }) + return user } @@ -609,7 +626,8 @@ export class UserResolver { return false } - const elopageBuyCount = await LoginElopageBuys.count({ payerEmail: userEntity.email }) + const loginElopageBuysRepository = getCustomRepository(LoginElopageBuysRepository) + const elopageBuyCount = await loginElopageBuysRepository.count({ payerEmail: userEntity.email }) return elopageBuyCount > 0 } } diff --git a/backend/src/typeorm/repository/LoginElopageBuys.ts b/backend/src/typeorm/repository/LoginElopageBuys.ts new file mode 100644 index 000000000..15f2a8492 --- /dev/null +++ b/backend/src/typeorm/repository/LoginElopageBuys.ts @@ -0,0 +1,5 @@ +import { EntityRepository, Repository } from 'typeorm' +import { LoginElopageBuys } from '@entity/LoginElopageBuys' + +@EntityRepository(LoginElopageBuys) +export class LoginElopageBuysRepository extends Repository {} diff --git a/backend/src/typeorm/repository/LoginUser.ts b/backend/src/typeorm/repository/LoginUser.ts index d0db007d0..65ac6f67b 100644 --- a/backend/src/typeorm/repository/LoginUser.ts +++ b/backend/src/typeorm/repository/LoginUser.ts @@ -2,4 +2,10 @@ import { EntityRepository, Repository } from 'typeorm' import { LoginUser } from '@entity/LoginUser' @EntityRepository(LoginUser) -export class LoginUserRepository extends Repository {} +export class LoginUserRepository extends Repository { + async findByEmail(email: string): Promise { + return this.createQueryBuilder('loginUser') + .where('loginUser.email = :email', { email }) + .getOneOrFail() + } +} diff --git a/backend/src/typeorm/repository/User.ts b/backend/src/typeorm/repository/User.ts index 441c1b2c8..e127c179c 100644 --- a/backend/src/typeorm/repository/User.ts +++ b/backend/src/typeorm/repository/User.ts @@ -9,6 +9,15 @@ export class UserRepository extends Repository { .getOneOrFail() } + async findByPubkeyHexBuffer(pubkeyHexBuffer: Buffer): Promise { + const pubKeyString = pubkeyHexBuffer.toString('hex') + return await this.findByPubkeyHex(pubKeyString) + } + + async findByEmail(email: string): Promise { + return this.createQueryBuilder('user').where('user.email = :email', { email }).getOneOrFail() + } + async getUsersIndiced(userIds: number[]): Promise { if (!userIds.length) return [] const users = await this.createQueryBuilder('user')