From 9d17e31d8fd8e0e90e366b1c8993222980a585fc Mon Sep 17 00:00:00 2001 From: elweyn Date: Tue, 26 Oct 2021 11:35:25 +0200 Subject: [PATCH 01/44] Change the dropbox functionality so that the language is set when changing the language in the register form. --- frontend/src/views/Pages/Register.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/views/Pages/Register.vue b/frontend/src/views/Pages/Register.vue index ff83f84fc..e4e9650fc 100755 --- a/frontend/src/views/Pages/Register.vue +++ b/frontend/src/views/Pages/Register.vue @@ -161,6 +161,7 @@ import InputEmail from '../../components/Inputs/InputEmail.vue' import InputPasswordConfirmation from '../../components/Inputs/InputPasswordConfirmation.vue' import LanguageSwitchSelect from '../../components/LanguageSwitchSelect.vue' import { registerUser } from '../../graphql/mutations' +import { localeChanged } from 'vee-validate' export default { components: { InputPasswordConfirmation, InputEmail, LanguageSwitchSelect }, @@ -187,6 +188,10 @@ export default { methods: { updateLanguage(e) { this.language = e + console.log('language', this.language) + this.$store.commit('language', this.language) + this.$i18n.locale = this.language + localeChanged(this.language) }, getValidationState({ dirty, validated, valid = null }) { return dirty || validated ? valid : null From 9b5d88a53321e98eda06b8f5c6198b5d9b4ace06 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 27 Oct 2021 15:54:20 +0200 Subject: [PATCH 02/44] async calls are working, token is tested on app created (to do: add server call to verify token and role) --- admin/package.json | 1 + admin/src/App.vue | 10 ++++++++++ admin/src/main.js | 3 +++ admin/src/store/store.js | 9 ++++++++- admin/yarn.lock | 2 +- 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/admin/package.json b/admin/package.json index 2b4e33c91..4aebfd131 100644 --- a/admin/package.json +++ b/admin/package.json @@ -33,6 +33,7 @@ "dotenv-webpack": "^7.0.3", "graphql": "^15.6.1", "jest": "26.6.3", + "regenerator-runtime": "^0.13.9", "stats-webpack-plugin": "^0.7.0", "vue": "^2.6.11", "vue-apollo": "^3.0.8", diff --git a/admin/src/App.vue b/admin/src/App.vue index 9267cc82b..8db46b135 100644 --- a/admin/src/App.vue +++ b/admin/src/App.vue @@ -5,5 +5,15 @@ diff --git a/admin/src/main.js b/admin/src/main.js index 61f65129e..f5ec929f2 100644 --- a/admin/src/main.js +++ b/admin/src/main.js @@ -1,6 +1,9 @@ import Vue from 'vue' import App from './App.vue' +// without this async calls are not working +import 'regenerator-runtime' + import store from './store/store' import router from './router/router' diff --git a/admin/src/store/store.js b/admin/src/store/store.js index 0b1a6350e..92fb37835 100644 --- a/admin/src/store/store.js +++ b/admin/src/store/store.js @@ -3,9 +3,16 @@ import Vue from 'vue' Vue.use(Vuex) +export const mutations = { + token: (state, token) => { + state.token = token + }, +} + const store = new Vuex.Store({ + mutations, state: { - token: 'some-valid-token', + token: null, }, }) diff --git a/admin/yarn.lock b/admin/yarn.lock index 59a49674d..fbc12c105 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -10606,7 +10606,7 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.4: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== From d889df51fef03429afbcde935dff36dd095b9cc8 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 27 Oct 2021 15:57:46 +0200 Subject: [PATCH 03/44] test store --- admin/src/store/store.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 admin/src/store/store.test.js diff --git a/admin/src/store/store.test.js b/admin/src/store/store.test.js new file mode 100644 index 000000000..9ab9d980b --- /dev/null +++ b/admin/src/store/store.test.js @@ -0,0 +1,15 @@ +import { mutations } from './store' + +const { token } = mutations + +describe('Vuex store', () => { + describe('mutations', () => { + describe('token', () => { + it('sets the state of token', () => { + const state = { token: null } + token(state, '1234') + expect(state.token).toEqual('1234') + }) + }) + }) +}) From b15b509e5e0adf3cd89350742744109953532190 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 28 Oct 2021 10:55:46 +0200 Subject: [PATCH 04/44] try to test App --- admin/src/App.spec.js | 67 +++++++++++++++++++++++++++++++++++++++++ admin/src/App.vue | 27 +++++++++-------- admin/test/testSetup.js | 3 ++ 3 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 admin/src/App.spec.js diff --git a/admin/src/App.spec.js b/admin/src/App.spec.js new file mode 100644 index 000000000..048493a4d --- /dev/null +++ b/admin/src/App.spec.js @@ -0,0 +1,67 @@ +import { mount } from '@vue/test-utils' +import App from './App' + +const localVue = global.localVue + +const storeCommitMock = jest.fn() + +const mocks = { + $store: { + commit: storeCommitMock, + }, +} + +const storageMock = () => { + let storage = {} + + return { + setItem: function(key, value) { + console.log('SET CALLED') + storage[key] = value || '' + }, + getItem: function(key) { + console.log('GET CALLED') + return key in storage ? storage[key] : null + } + } +} + +// window.localStorage = storageMock() + +describe('App', () => { + let wrapper + + const Wrapper = () => { + return mount(App, { localVue, mocks }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('has a div with id "app"', () => { + expect(wrapper.find('div#app').exists()).toBeTruthy() + }) + }) + + describe('window localStorage is undefined', () => { + it('does not commit a token to the store', () => { + expect(storeCommitMock).not.toBeCalled() + }) + }) + + describe('with token in local storage', () => { + beforeEach(() => { + console.log('Test', window.localStorage) + window.localStorage = { 'foo': 'bar' } + console.log('Test', window.localStorage) + //window.localStorage.setItem('vuex', { token: 1234 }) + }) + + it('commits the token to the store', () => { + expect(storeCommitMock).toBeCalledWith('token', 1234) + }) + }) +}) + diff --git a/admin/src/App.vue b/admin/src/App.vue index 8db46b135..4e7248f1b 100644 --- a/admin/src/App.vue +++ b/admin/src/App.vue @@ -3,17 +3,18 @@ diff --git a/admin/test/testSetup.js b/admin/test/testSetup.js index 118c0b1ce..3b6b50218 100644 --- a/admin/test/testSetup.js +++ b/admin/test/testSetup.js @@ -2,6 +2,9 @@ import { createLocalVue } from '@vue/test-utils' import Vue from 'vue' import { BootstrapVue } from 'bootstrap-vue' +// without this async calls are not working +import 'regenerator-runtime' + global.localVue = createLocalVue() global.localVue.use(BootstrapVue) From 3a37b38489328e7acb3c9c73b028996aee74d3ef Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 28 Oct 2021 12:54:34 +0200 Subject: [PATCH 05/44] read token from localStorage --- admin/src/App.spec.js | 41 +++++++++++++++++++++-------------------- admin/src/App.vue | 27 +++++++++++++-------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/admin/src/App.spec.js b/admin/src/App.spec.js index 048493a4d..b47141972 100644 --- a/admin/src/App.spec.js +++ b/admin/src/App.spec.js @@ -11,22 +11,24 @@ const mocks = { }, } -const storageMock = () => { - let storage = {} +const localStorageMock = (() => { + let store = {} return { - setItem: function(key, value) { - console.log('SET CALLED') - storage[key] = value || '' + getItem: (key) => { + return store[key] || null + }, + setItem: (key, value) => { + store[key] = value.toString() + }, + removeItem: (key) => { + delete store[key] + }, + clear: () => { + store = {} }, - getItem: function(key) { - console.log('GET CALLED') - return key in storage ? storage[key] : null - } } -} - -// window.localStorage = storageMock() +})() describe('App', () => { let wrapper @@ -50,18 +52,17 @@ describe('App', () => { expect(storeCommitMock).not.toBeCalled() }) }) - + describe('with token in local storage', () => { beforeEach(() => { - console.log('Test', window.localStorage) - window.localStorage = { 'foo': 'bar' } - console.log('Test', window.localStorage) - //window.localStorage.setItem('vuex', { token: 1234 }) + Object.defineProperty(window, 'localStorage', { + value: localStorageMock, + }) + window.localStorage.setItem('vuex', JSON.stringify({ token: 1234 })) }) - - it('commits the token to the store', () => { + + it.skip('commits the token to the store', () => { expect(storeCommitMock).toBeCalledWith('token', 1234) }) }) }) - diff --git a/admin/src/App.vue b/admin/src/App.vue index 4e7248f1b..bcc6fadec 100644 --- a/admin/src/App.vue +++ b/admin/src/App.vue @@ -3,18 +3,17 @@ From 01707674d2cc7e765edae5adcab7eb4507b32533 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 8 Nov 2021 13:27:03 +0100 Subject: [PATCH 06/44] Added LoginUserRepository to get login_users. --- backend/src/typeorm/repository/LoginUser.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 backend/src/typeorm/repository/LoginUser.ts diff --git a/backend/src/typeorm/repository/LoginUser.ts b/backend/src/typeorm/repository/LoginUser.ts new file mode 100644 index 000000000..65ac6f67b --- /dev/null +++ b/backend/src/typeorm/repository/LoginUser.ts @@ -0,0 +1,11 @@ +import { EntityRepository, Repository } from 'typeorm' +import { LoginUser } from '@entity/LoginUser' + +@EntityRepository(LoginUser) +export class LoginUserRepository extends Repository { + async findByEmail(email: string): Promise { + return this.createQueryBuilder('loginUser') + .where('loginUser.email = :email', { email }) + .getOneOrFail() + } +} From a375e6ecc9d9982ad7ea569b3f186a562107df30 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 8 Nov 2021 13:27:32 +0100 Subject: [PATCH 07/44] WIP: Change the login so that the unsecureLogin logic is implemented. --- backend/src/graphql/resolver/UserResolver.ts | 41 +++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index d05640e5e..bfb8b41b4 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -26,9 +26,13 @@ import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepos import { Setting } from '../enum/Setting' import { UserRepository } from '../../typeorm/repository/User' import { LoginUser } from '@entity/LoginUser' +import { LoginUserRepository } from '../../typeorm/repository/LoginUser' @Resolver() export class UserResolver { + private userRepository = getCustomRepository(UserRepository) + private userSettingRepository = getCustomRepository(UserSettingRepository) + @Query(() => User) @UseMiddleware(klicktippNewsletterStateMiddleware) async login( @@ -36,27 +40,34 @@ 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) + // const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password }) + // UnsecureLogin + const userCount = await LoginUser.count({ email }) + if (userCount === 0) { + throw new Error('No user with this credentials') } + if (!isPassword(password)) { + throw new Error('No user with this credentials') + } + + const loginUserRepository = getCustomRepository(LoginUserRepository) + const loginUser = await loginUserRepository.findByEmail(email) + if (loginUser.password) context.setHeaders.push({ key: 'token', value: encode(result.data.session_id, result.data.user.public_hex), }) - const user = new User(result.data.user) + // const user = new User(result.data.user) // Hack: Database Field is not validated properly and not nullable if (user.publisherId === 0) { user.publisherId = undefined } user.hasElopage = result.data.hasElopage // read additional settings from settings table - const userRepository = getCustomRepository(UserRepository) + // const userRepository = getCustomRepository(UserRepository) let userEntity: void | DbUser - userEntity = await userRepository.findByPubkeyHex(user.pubkey).catch(() => { + userEntity = await this.userRepository.findByPubkeyHex(user.pubkey).catch(() => { userEntity = new DbUser() userEntity.firstName = user.firstName userEntity.lastName = user.lastName @@ -64,7 +75,7 @@ export class UserResolver { userEntity.email = user.email userEntity.pubkey = Buffer.from(fromHex(user.pubkey)) - userRepository.save(userEntity).catch(() => { + this.userRepository.save(userEntity).catch(() => { throw new Error('error by save userEntity') }) }) @@ -216,7 +227,7 @@ export class UserResolver { }, } let response: UpdateUserInfosResponse | undefined - const userRepository = getCustomRepository(UserRepository) + // const userRepository = getCustomRepository(UserRepository) if ( firstName || @@ -232,7 +243,7 @@ export class UserResolver { if (!result.success) throw new Error(result.data) response = new UpdateUserInfosResponse(result.data) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const userEntity = await this.userRepository.findByPubkeyHex(context.pubKey) let userEntityChanged = false if (firstName) { userEntity.firstName = firstName @@ -247,7 +258,7 @@ export class UserResolver { userEntityChanged = true } if (userEntityChanged) { - userRepository.save(userEntity).catch((error) => { + this.userRepository.save(userEntity).catch((error) => { throw new Error(error) }) } @@ -255,10 +266,10 @@ export class UserResolver { if (coinanimation !== undefined) { // load user and balance - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const userEntity = await this.userRepository.findByPubkeyHex(context.pubKey) - const userSettingRepository = getCustomRepository(UserSettingRepository) - userSettingRepository + // const userSettingRepository = getCustomRepository(UserSettingRepository) + this.userSettingRepository .setOrUpdate(userEntity.id, Setting.COIN_ANIMATION, coinanimation.toString()) .catch((error) => { throw new Error(error) From f2d8d400ac39c48c8534b6a1d5d4702f83920b87 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 8 Nov 2021 14:26:32 +0100 Subject: [PATCH 08/44] Add libsodium. --- backend/package-lock.json | 19 ++++++++++++++++--- backend/package.json | 1 + backend/yarn.lock | 12 ++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index bb0d16316..f18213264 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4903,6 +4903,19 @@ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.34.tgz", "integrity": "sha512-gHTNU9xTtVgSp30IDX/57W4pETMXDIYXFfwEOJVXiYosiY7Hc7ogJwlBjOqlCcU04X0aA8DT57hdwUC1sJBJnA==" }, + "libsodium": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.9.tgz", + "integrity": "sha512-gfeADtR4D/CM0oRUviKBViMGXZDgnFdMKMzHsvBdqLBHd9ySi6EtYnmuhHVDDYgYpAO8eU8hEY+F8vIUAPh08A==" + }, + "libsodium-wrappers": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.9.tgz", + "integrity": "sha512-9HaAeBGk1nKTRFRHkt7nzxqCvnkWTjn1pdjKgcUnZxj0FyOP4CnhgFhMdrFfgNsukijBGyBLpP2m2uKT1vuWhQ==", + "requires": { + "libsodium": "^0.7.0" + } + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -6934,9 +6947,9 @@ } }, "validator": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", - "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==" + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" }, "vary": { "version": "1.1.2", diff --git a/backend/package.json b/backend/package.json index e47939b41..c0d244ecd 100644 --- a/backend/package.json +++ b/backend/package.json @@ -27,6 +27,7 @@ "graphql": "^15.5.1", "jest": "^27.2.4", "jsonwebtoken": "^8.5.1", + "libsodium-wrappers": "^0.7.9", "module-alias": "^2.2.2", "mysql2": "^2.3.0", "nodemailer": "^6.6.5", diff --git a/backend/yarn.lock b/backend/yarn.lock index 915766619..3cb8e9b43 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3918,6 +3918,18 @@ libphonenumber-js@^1.9.7: resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.9.37.tgz#944f59a3618a8f85d9b619767a0b6fb87523f285" integrity sha512-RnUR4XwiVhMLnT7uFSdnmLeprspquuDtaShAgKTA+g/ms9/S4hQU3/QpFdh3iXPHtxD52QscXLm2W2+QBmvYAg== +libsodium-wrappers@^0.7.9: + version "0.7.9" + resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.9.tgz#4ffc2b69b8f7c7c7c5594a93a4803f80f6d0f346" + integrity sha512-9HaAeBGk1nKTRFRHkt7nzxqCvnkWTjn1pdjKgcUnZxj0FyOP4CnhgFhMdrFfgNsukijBGyBLpP2m2uKT1vuWhQ== + dependencies: + libsodium "^0.7.0" + +libsodium@^0.7.0: + version "0.7.9" + resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.9.tgz#4bb7bcbf662ddd920d8795c227ae25bbbfa3821b" + integrity sha512-gfeADtR4D/CM0oRUviKBViMGXZDgnFdMKMzHsvBdqLBHd9ySi6EtYnmuhHVDDYgYpAO8eU8hEY+F8vIUAPh08A== + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" From 5400967142619d975ff74efb0aa802b1f7e6ce1f Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 8 Nov 2021 14:27:07 +0100 Subject: [PATCH 09/44] Get LoginUser from the DB, checkPassword. --- backend/src/graphql/resolver/UserResolver.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index be1e06305..4768b4659 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -196,9 +196,6 @@ const SecretKeyCryptographyEncrypt = (message: Buffer, encryptionKey: Buffer): B @Resolver() export class UserResolver { - - private userSettingRepository = getCustomRepository(UserSettingRepository) - @Query(() => User) @UseMiddleware(klicktippNewsletterStateMiddleware) async login( @@ -208,19 +205,18 @@ export class UserResolver { email = email.trim().toLowerCase() // const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password }) // UnsecureLogin - const userCount = await LoginUser.count({ email }) - if (userCount === 0) { + const loginUserRepository = getCustomRepository(LoginUserRepository) + const loginUser = await loginUserRepository.findByEmail(email) + if (!loginUser) { throw new Error('No user with this credentials') } if (!isPassword(password)) { throw new Error('No user with this credentials') } - const loginUserRepository = getCustomRepository(LoginUserRepository) - const loginUser = await loginUserRepository.findByEmail(email) const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash - // loginUser.password = passwordHash[0].readBigUInt64LE() - if (loginUser.password !== passwordHash[0].readBigUInt64LE()) { + const loginUserPassword = BigInt(loginUser.password.toString()) + if (loginUserPassword !== passwordHash[0].readBigUInt64LE()) { throw new Error('No user with this credentials') } From 8a61f73c56ecf122f74978dc87545841c94f307e Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 06:01:25 +0100 Subject: [PATCH 10/44] Added the load or store of the state_users. --- backend/src/graphql/resolver/UserResolver.ts | 42 +++++++++++--------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 4768b4659..50f2cfe48 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -224,6 +224,29 @@ export class UserResolver { key: 'token', value: encode(loginUser.pubKey), }) + + const userRepository = getCustomRepository(UserRepository) + let userEntity: void | DbUser + userEntity = await userRepository + .findByPubkeyHex(loginUser.pubKey.toString('utf8')) + .catch(() => { + // User not stored in state_users + userEntity = new DbUser() + userEntity.firstName = loginUser.firstName + userEntity.lastName = loginUser.lastName + userEntity.username = loginUser.username + userEntity.email = loginUser.email + userEntity.pubkey = Buffer.from(loginUser.pubKey.toString('utf8'), 'hex') + + userRepository.save(userEntity).catch(() => { + throw new Error('error by save userEntity') + }) + }) + if (!userEntity) { + throw new Error('error with cannot happen') + } + // TODO: Check and/or store hasElopage + // TODO: If user has no pubKey Create it again and update user. throw new Error('WIP') // const user = new User(result.data.user) // Hack: Database Field is not validated properly and not nullable @@ -232,25 +255,8 @@ export class UserResolver { // } // user.hasElopage = result.data.hasElopage // // read additional settings from settings table - // const userRepository = getCustomRepository(UserRepository) - // let userEntity: void | DbUser - // userEntity = await userRepository.findByPubkeyHex(user.pubkey).catch(() => { - // 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') - // userRepository.save(userEntity).catch(() => { - // throw new Error('error by save userEntity') - // }) - // }) - // if (!userEntity) { - // throw new Error('error with cannot happen') - // } - - // // Save publisherId if Elopage is not yet registered + // Save publisherId if Elopage is not yet registered // if (!user.hasElopage && publisherId) { // user.publisherId = publisherId // await this.updateUserInfos( From e8b9765a34c588c909eb4581e4f96c35dec61cf4 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 06:13:29 +0100 Subject: [PATCH 11/44] Withdrew the check on the sessionId when is authorized is called. --- backend/src/graphql/directive/isAuthorized.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts index c553539bc..23971162d 100644 --- a/backend/src/graphql/directive/isAuthorized.ts +++ b/backend/src/graphql/directive/isAuthorized.ts @@ -14,13 +14,13 @@ const isAuthorized: AuthChecker = async ( if (context.token) { const decoded = decode(context.token) // if (decoded.sessionId && decoded.sessionId !== 0) { - // const result = await apiGet( - // `${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`, - // ) - // context.sessionId = decoded.sessionId - context.pubKey = decoded.pubKey - context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) }) - return true + // const result = await apiGet( + // `${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`, + // ) + // context.sessionId = decoded.sessionId + context.pubKey = decoded.pubKey + context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) }) + return true // } } throw new Error('401 Unauthorized') From 8730bc898c86f0300f3a589783e9b1f3b728e864 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 06:14:02 +0100 Subject: [PATCH 12/44] We don't use the login_server to fill this model anymore. --- backend/src/graphql/model/User.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) 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) From 4af3c6ed8c1e422991ad73d7e24b6abc18b46b78 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 06:14:38 +0100 Subject: [PATCH 13/44] Filling the returned model so that we get the same result as before. --- backend/src/graphql/resolver/UserResolver.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 50f2cfe48..b37c568a4 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -219,6 +219,7 @@ export class UserResolver { if (loginUserPassword !== passwordHash[0].readBigUInt64LE()) { throw new Error('No user with this credentials') } + // TODO: If user has no pubKey Create it again and update user. context.setHeaders.push({ key: 'token', @@ -245,8 +246,22 @@ export class UserResolver { if (!userEntity) { throw new Error('error with cannot happen') } - // TODO: Check and/or store hasElopage - // TODO: If user has no pubKey Create it again and update user. + + 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 = loginUser.pubKey.toString('utf8') + user.language = loginUser.language + // TODO: hasElopage + // auto elopage_buy = Poco::AutoPtr(new model::table::ElopageBuy); + // mHasElopage = elopage_buy->isExistInDB("payer_email", mEmail); + // else undefined + + // TODO: coinAnimation + return user throw new Error('WIP') // const user = new User(result.data.user) // Hack: Database Field is not validated properly and not nullable From 75d7ff3905f38b39777ce1934cc8f029255032a1 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 06:15:58 +0100 Subject: [PATCH 14/44] Withdrew the comments. --- backend/src/graphql/directive/isAuthorized.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts index 23971162d..079e8e88c 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,15 +10,9 @@ const isAuthorized: AuthChecker = async ( ) => { if (context.token) { const decoded = decode(context.token) - // if (decoded.sessionId && decoded.sessionId !== 0) { - // const result = await apiGet( - // `${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`, - // ) - // context.sessionId = decoded.sessionId context.pubKey = decoded.pubKey context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) }) return true - // } } throw new Error('401 Unauthorized') } From 30ef78dddea4214c5d65fc11dca19b5ce7d7e4d8 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 10:25:41 +0100 Subject: [PATCH 15/44] Withdrew sessionId from the jwt token. --- backend/src/jwt/decode.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backend/src/jwt/decode.ts b/backend/src/jwt/decode.ts index 34b3ed836..6f09276b0 100644 --- a/backend/src/jwt/decode.ts +++ b/backend/src/jwt/decode.ts @@ -2,27 +2,22 @@ import jwt, { JwtPayload } from 'jsonwebtoken' import CONFIG from '../config/' interface CustomJwtPayload extends JwtPayload { - sessionId: number pubKey: Buffer } type DecodedJwt = { token: string - sessionId: number pubKey: Buffer } export default (token: string): DecodedJwt => { if (!token) throw new Error('401 Unauthorized') - let sessionId = null let pubKey = null try { const decoded = jwt.verify(token, CONFIG.JWT_SECRET) - sessionId = decoded.sessionId pubKey = decoded.pubKey return { token, - sessionId, pubKey, } } catch (err) { From 74cc9522c21e53eb57f2a18347d01247eaedb637 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 10:27:05 +0100 Subject: [PATCH 16/44] Added method to find User with their email & find User with a PubKey Buffer. --- backend/src/typeorm/repository/User.ts | 9 +++++++++ 1 file changed, 9 insertions(+) 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') From a16b7ad47a7ff176760b808a4b3c297f148c486f Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 10:28:31 +0100 Subject: [PATCH 17/44] Changed the decode of context.pubKey so that it is stored in a buffer and transformed after in a Hex string. --- backend/src/graphql/resolver/BalanceResolver.ts | 3 ++- backend/src/graphql/resolver/GdtResolver.ts | 3 ++- backend/src/graphql/resolver/TransactionResolver.ts | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index e067b4d68..902e50b8b 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -18,7 +18,8 @@ export class BalanceResolver { const balanceRepository = getCustomRepository(BalanceRepository) const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const pubKeyString = Buffer.from(context.pubKey).toString('hex') + const userEntity = await userRepository.findByPubkeyHex(pubKeyString) const balanceEntity = await balanceRepository.findByUser(userEntity.id) const now = new Date() diff --git a/backend/src/graphql/resolver/GdtResolver.ts b/backend/src/graphql/resolver/GdtResolver.ts index b4f9a512b..ba10d45bf 100644 --- a/backend/src/graphql/resolver/GdtResolver.ts +++ b/backend/src/graphql/resolver/GdtResolver.ts @@ -22,7 +22,8 @@ export class GdtResolver { ): Promise { // load user const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const pubKeyString = Buffer.from(context.pubKey).toString('hex') + const userEntity = await userRepository.findByPubkeyHex(pubKeyString) const resultGDT = await apiGet( `${CONFIG.GDT_API_URL}/GdtEntries/listPerEmailApi/${userEntity.email}/${currentPage}/${pageSize}/${order}`, diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 70dfdc505..b804c1af9 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -496,7 +496,8 @@ export class TransactionResolver { ): Promise { // load user const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const pubKeyString = Buffer.from(context.pubKey).toString('hex') + const userEntity = await userRepository.findByPubkeyHex(pubKeyString) const transactions = await listTransactions(currentPage, pageSize, order, userEntity) @@ -531,7 +532,8 @@ export class TransactionResolver { // TODO this is subject to replay attacks // validate sender user (logged in) const userRepository = getCustomRepository(UserRepository) - const senderUser = await userRepository.findByPubkeyHex(context.pubKey) + const pubKeyString = Buffer.from(context.pubKey).toString('hex') + const senderUser = await userRepository.findByPubkeyHex(pubKeyString) if (senderUser.pubkey.length !== 32) { throw new Error('invalid sender public key') } From 6a85017406a315c86f8d84215ed5c524c639adfc Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 10:30:35 +0100 Subject: [PATCH 18/44] PubKey decoded has to be cast to buffer and back to hex string, changed the coinanimation. --- backend/src/graphql/resolver/UserResolver.ts | 63 ++++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index b37c568a4..a2d4ee0e8 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -228,21 +228,21 @@ export class UserResolver { const userRepository = getCustomRepository(UserRepository) let userEntity: void | DbUser - userEntity = await userRepository - .findByPubkeyHex(loginUser.pubKey.toString('utf8')) - .catch(() => { - // User not stored in state_users - userEntity = new DbUser() - userEntity.firstName = loginUser.firstName - userEntity.lastName = loginUser.lastName - userEntity.username = loginUser.username - userEntity.email = loginUser.email - userEntity.pubkey = Buffer.from(loginUser.pubKey.toString('utf8'), 'hex') + const loginUserPubKey = loginUser.pubKey + const loginUserPubKeyString = loginUserPubKey.toString('hex') + userEntity = await userRepository.findByPubkeyHex(loginUserPubKeyString).catch(() => { + // User not stored in state_users + userEntity = new DbUser() + 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') - }) + userRepository.save(userEntity).catch(() => { + throw new Error('error by save userEntity') }) + }) if (!userEntity) { throw new Error('error with cannot happen') } @@ -253,24 +253,19 @@ export class UserResolver { user.lastName = loginUser.lastName user.username = loginUser.username user.description = loginUser.description - user.pubkey = loginUser.pubKey.toString('utf8') + user.pubkey = loginUserPubKeyString user.language = loginUser.language - // TODO: hasElopage + // TODO: Get Method from PR (hasElopage) // auto elopage_buy = Poco::AutoPtr(new model::table::ElopageBuy); // mHasElopage = elopage_buy->isExistInDB("payer_email", mEmail); // else undefined + // user.hasElopage = result.data.hasElopage - // TODO: coinAnimation - return user - throw new Error('WIP') - // const user = new User(result.data.user) + // TODO: Get Method from PR (publisherId) // Hack: Database Field is not validated properly and not nullable // if (user.publisherId === 0) { // user.publisherId = undefined // } - // user.hasElopage = result.data.hasElopage - // // read additional settings from settings table - // Save publisherId if Elopage is not yet registered // if (!user.hasElopage && publisherId) { // user.publisherId = publisherId @@ -280,14 +275,15 @@ export class UserResolver { // ) // } - // const userSettingRepository = getCustomRepository(UserSettingRepository) - // const coinanimation = await userSettingRepository - // .readBoolean(userEntity.id, Setting.COIN_ANIMATION) - // .catch((error) => { - // throw new Error(error) - // }) - // user.coinanimation = coinanimation - // return user + // coinAnimation + const userSettingRepository = getCustomRepository(UserSettingRepository) + const coinanimation = await userSettingRepository + .readBoolean(userEntity.id, Setting.COIN_ANIMATION) + .catch((error) => { + throw new Error(error) + }) + user.coinanimation = coinanimation + return user } @Query(() => LoginViaVerificationCode) @@ -521,7 +517,8 @@ export class UserResolver { if (!result.success) throw new Error(result.data) response = new UpdateUserInfosResponse(result.data) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const pubKeyString = Buffer.from(context.pubKey).toString('hex') + const userEntity = await userRepository.findByPubkeyHex(pubKeyString) let userEntityChanged = false if (firstName) { userEntity.firstName = firstName @@ -543,8 +540,8 @@ export class UserResolver { } if (coinanimation !== undefined) { // load user and balance - - const userEntity = await userRepository.findByPubkeyHex(context.pubKey) + const pubKeyString = Buffer.from(context.pubKey).toString('hex') + const userEntity = await userRepository.findByPubkeyHex(pubKeyString) const userSettingRepository = getCustomRepository(UserSettingRepository) userSettingRepository From 5d886a93607a2af03b3c0d4cea51e9daf66e210e Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 10 Nov 2021 11:28:35 +0100 Subject: [PATCH 19/44] LoginUserRepository import has droped out put it in again. --- backend/src/graphql/resolver/UserResolver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index ec28f964e..3aa7e7fd5 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -23,6 +23,7 @@ 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' From 7655a647fe30e3ce7c129cfc1533419e372285ef Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 11 Nov 2021 06:15:21 +0100 Subject: [PATCH 20/44] Implementation of the LoginElopageBuys repository. --- backend/src/typeorm/repository/LoginElopageBuys.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 backend/src/typeorm/repository/LoginElopageBuys.ts 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 {} From 1baf756c08953784111e28cd29e9a72f95e9e42a Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 11 Nov 2021 06:31:00 +0100 Subject: [PATCH 21/44] HasElopage has been called, search loginUser catch instead of if no user, context get's the pubKey at the end of the login call instead of the start. --- backend/src/graphql/resolver/UserResolver.ts | 27 ++++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 437d7072e..bee35d676 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -31,6 +31,7 @@ import { LoginElopageBuys } from '@entity/LoginElopageBuys' import { LoginUserBackup } from '@entity/LoginUserBackup' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { sendEMail } from '../../util/sendEMail' +import { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys' // eslint-disable-next-line @typescript-eslint/no-var-requires const sodium = require('sodium-native') @@ -195,14 +196,9 @@ export class UserResolver { // const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password }) // UnsecureLogin const loginUserRepository = getCustomRepository(LoginUserRepository) - const loginUser = await loginUserRepository.findByEmail(email) - if (!loginUser) { + const loginUser = await loginUserRepository.findByEmail(email).catch(() => { throw new Error('No user with this credentials') - } - if (!isPassword(password)) { - throw new Error('No user with this credentials') - } - + }) const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash const loginUserPassword = BigInt(loginUser.password.toString()) if (loginUserPassword !== passwordHash[0].readBigUInt64LE()) { @@ -210,11 +206,6 @@ export class UserResolver { } // TODO: If user has no pubKey Create it again and update user. - context.setHeaders.push({ - key: 'token', - value: encode(loginUser.pubKey), - }) - const userRepository = getCustomRepository(UserRepository) let userEntity: void | DbUser const loginUserPubKey = loginUser.pubKey @@ -244,11 +235,7 @@ export class UserResolver { user.description = loginUser.description user.pubkey = loginUserPubKeyString user.language = loginUser.language - // TODO: Get Method from PR (hasElopage) - // auto elopage_buy = Poco::AutoPtr(new model::table::ElopageBuy); - // mHasElopage = elopage_buy->isExistInDB("payer_email", mEmail); - // else undefined - // user.hasElopage = result.data.hasElopage + user.hasElopage = await this.hasElopage({ pubkey: loginUser.pubKey }) // TODO: Get Method from PR (publisherId) // Hack: Database Field is not validated properly and not nullable @@ -272,6 +259,12 @@ export class UserResolver { throw new Error(error) }) user.coinanimation = coinanimation + + context.setHeaders.push({ + key: 'token', + value: encode(loginUser.pubKey), + }) + return user } From e976c6854d88d2b4586eb6959c5af77df308cd93 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 11 Nov 2021 06:41:56 +0100 Subject: [PATCH 22/44] Adding hasElopage and publisherId logic, hasElopage is called and checks if in ElopageBuys their is a user with this email, if hasElopage and publisherId is filled store it in the user table. --- backend/src/graphql/resolver/UserResolver.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index bee35d676..8462df819 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -236,7 +236,10 @@ export class UserResolver { user.pubkey = loginUserPubKeyString user.language = loginUser.language user.hasElopage = await this.hasElopage({ pubkey: loginUser.pubKey }) - + if (!user.hasElopage && publisherId) { + user.publisherId = publisherId + await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey }) + } // TODO: Get Method from PR (publisherId) // Hack: Database Field is not validated properly and not nullable // if (user.publisherId === 0) { From e97798d73c780f6a7c16870e1f04b64f20c255e4 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 11 Nov 2021 06:42:27 +0100 Subject: [PATCH 23/44] Withdrew comments. --- backend/src/graphql/resolver/UserResolver.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 8462df819..ee44346e7 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -31,7 +31,6 @@ import { LoginElopageBuys } from '@entity/LoginElopageBuys' import { LoginUserBackup } from '@entity/LoginUserBackup' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { sendEMail } from '../../util/sendEMail' -import { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys' // eslint-disable-next-line @typescript-eslint/no-var-requires const sodium = require('sodium-native') @@ -235,24 +234,13 @@ export class UserResolver { user.description = loginUser.description user.pubkey = loginUserPubKeyString user.language = loginUser.language + + // Elopage Status & Stored PublisherId user.hasElopage = await this.hasElopage({ pubkey: loginUser.pubKey }) if (!user.hasElopage && publisherId) { user.publisherId = publisherId await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey }) } - // TODO: Get Method from PR (publisherId) - // Hack: Database Field is not validated properly and not nullable - // if (user.publisherId === 0) { - // user.publisherId = undefined - // } - // Save publisherId if Elopage is not yet registered - // if (!user.hasElopage && publisherId) { - // user.publisherId = publisherId - // await this.updateUserInfos( - // { publisherId }, - // { sessionId: result.data.session_id, pubKey: result.data.user.public_hex }, - // ) - // } // coinAnimation const userSettingRepository = getCustomRepository(UserSettingRepository) @@ -600,7 +588,6 @@ export class UserResolver { @Authorized() @Query(() => Boolean) async hasElopage(@Ctx() context: any): Promise { - // const result = await apiGet(CONFIG.LOGIN_API_URL + 'hasElopage?session_id=' + context.sessionId) const userRepository = getCustomRepository(UserRepository) const userEntity = await userRepository.findByPubkeyHex(context.pubKey).catch() if (!userEntity) { From a73a36b971b73bcbec0ebc8528200827cffce2a8 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 11 Nov 2021 10:09:08 +0100 Subject: [PATCH 24/44] Withdrew the JWT changes and store the Buffer again instead of the hex key. --- backend/src/graphql/resolver/UserResolver.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index ee44346e7..e70f67552 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -27,10 +27,10 @@ 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 { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys' // eslint-disable-next-line @typescript-eslint/no-var-requires const sodium = require('sodium-native') @@ -236,10 +236,11 @@ export class UserResolver { user.language = loginUser.language // Elopage Status & Stored PublisherId - user.hasElopage = await this.hasElopage({ pubkey: loginUser.pubKey }) + user.hasElopage = await this.hasElopage({ pubKey: loginUser.pubKey }) if (!user.hasElopage && publisherId) { user.publisherId = publisherId - await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey }) + // TODO: Merge login_call_updateUserInfos + // await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey }) } // coinAnimation @@ -589,12 +590,14 @@ export class UserResolver { @Query(() => Boolean) async hasElopage(@Ctx() context: any): Promise { const userRepository = getCustomRepository(UserRepository) - const userEntity = await userRepository.findByPubkeyHex(context.pubKey).catch() + const pubKey = Buffer.from(context.pubKey).toString('hex') + const userEntity = await userRepository.findByPubkeyHex(pubKey).catch() if (!userEntity) { 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 } } From 4389e47cabd5ddf196c46eed4e55cd0968ba4071 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 07:17:30 +0100 Subject: [PATCH 25/44] Adding a check that the user is activated before letting them login. --- login_server/src/cpp/JSONInterface/JsonUnsecureLogin.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/login_server/src/cpp/JSONInterface/JsonUnsecureLogin.cpp b/login_server/src/cpp/JSONInterface/JsonUnsecureLogin.cpp index 991e412a0..0e7df24e2 100644 --- a/login_server/src/cpp/JSONInterface/JsonUnsecureLogin.cpp +++ b/login_server/src/cpp/JSONInterface/JsonUnsecureLogin.cpp @@ -147,7 +147,6 @@ Poco::JSON::Object* JsonUnsecureLogin::handle(Poco::Dynamic::Var params) infos.add("set user.group_id to default group_id = 1"); case USER_NO_PRIVATE_KEY: case USER_COMPLETE: - case USER_EMAIL_NOT_ACTIVATED: result->set("state", "success"); result->set("user", session->getNewUser()->getJson()); result->set("session_id", session->getHandle()); @@ -158,6 +157,10 @@ Poco::JSON::Object* JsonUnsecureLogin::handle(Poco::Dynamic::Var params) AWAIT(hasElopageTask) result->set("hasElopage", hasElopageTask->hasElopage()); return result; + case USER_EMAIL_NOT_ACTIVATED: + result->set("state", "processing"); + result->set("msg", "user email not validated"); + break; default: result->set("state", "error"); result->set("msg", "unknown user state"); From 14db7bd058e523217009defa27cbab4eb8415c31 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 07:38:57 +0100 Subject: [PATCH 26/44] Added a no-email-verify to locale check if the error message contains the message email not verified then throw another message than normal. --- frontend/src/locales/de.json | 3 ++- frontend/src/locales/en.json | 3 ++- frontend/src/views/Pages/Login.vue | 7 +++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index ca5b20f82..56e759ab1 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -46,7 +46,8 @@ "change-password": "Fehler beim Ändern des Passworts", "error": "Fehler", "no-account": "Leider konnten wir keinen Account finden mit diesen Daten!", - "session-expired": "Sitzung abgelaufen!" + "session-expired": "Sitzung abgelaufen!", + "no-email-verify": "Email wurde noch nicht bestätigt, bitte überprüfen Sie ihre Emails und clicken Sie den Registrierungslink!" }, "form": { "amount": "Betrag", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index d3d5b05ab..c7410633e 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -46,7 +46,8 @@ "change-password": "Error while changing password", "error": "Error", "no-account": "Unfortunately we could not find an account to the given data!", - "session-expired": "The session expired" + "session-expired": "The session expired", + "no-email-verify": "Your email is not validated yet, please check your emails and click on the activation link!" }, "form": { "amount": "Amount", diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 0cdbeb942..3f5c840d4 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -102,9 +102,12 @@ export default { this.$router.push('/overview') loader.hide() }) - .catch(() => { + .catch((error) => { loader.hide() - this.$toasted.error(this.$t('error.no-account')) + const toastedError = !error.message.includes('user email not validated') + ? this.$t('error.no-account') + : this.$t('error.no-email-verify') + this.$toasted.error(toastedError) }) }, async onCreated() { From f5044e857984812cdd5f4fbcab859679fefdcf80 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 07:54:14 +0100 Subject: [PATCH 27/44] Change register message & error toast message account not active yet. --- frontend/src/locales/de.json | 4 ++-- frontend/src/locales/en.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 56e759ab1..f1fdf04ec 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -47,7 +47,7 @@ "error": "Fehler", "no-account": "Leider konnten wir keinen Account finden mit diesen Daten!", "session-expired": "Sitzung abgelaufen!", - "no-email-verify": "Email wurde noch nicht bestätigt, bitte überprüfen Sie ihre Emails und clicken Sie den Registrierungslink!" + "no-email-verify": "Die Email wurde noch nicht bestätigt, bitte überprüfe deine Emails und klicke auf den Aktivierungslink!" }, "form": { "amount": "Betrag", @@ -181,7 +181,7 @@ "thx": { "checkEmail": "Deine Email würde erfolgreich verifiziert.", "email": "Wir haben dir eine eMail gesendet.", - "register": "Du bist jetzt registriert.", + "register": "Du bist jetzt registriert, bitte überprüfe deine Emails und klicke auf den Aktivierungslink.", "reset": "Dein Passwort wurde geändert.", "title": "Danke!" } diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index c7410633e..bd0fa2d82 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -47,7 +47,7 @@ "error": "Error", "no-account": "Unfortunately we could not find an account to the given data!", "session-expired": "The session expired", - "no-email-verify": "Your email is not validated yet, please check your emails and click on the activation link!" + "no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!" }, "form": { "amount": "Amount", @@ -181,7 +181,7 @@ "thx": { "checkEmail": "Your email has been successfully verified.", "email": "We have sent you an email.", - "register": "You are registred now.", + "register": "You are registered now, please check your emails and click the activation link.", "reset": "Your password has been changed.", "title": "Thank you!" } From b1e419530c1ca887b02541a50ae5514226947cb6 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 08:31:48 +0100 Subject: [PATCH 28/44] Fix sorting of locale. --- frontend/src/locales/de.json | 4 ++-- frontend/src/locales/en.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index f1fdf04ec..1c298b416 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -46,8 +46,8 @@ "change-password": "Fehler beim Ändern des Passworts", "error": "Fehler", "no-account": "Leider konnten wir keinen Account finden mit diesen Daten!", - "session-expired": "Sitzung abgelaufen!", - "no-email-verify": "Die Email wurde noch nicht bestätigt, bitte überprüfe deine Emails und klicke auf den Aktivierungslink!" + "no-email-verify": "Die Email wurde noch nicht bestätigt, bitte überprüfe deine Emails und klicke auf den Aktivierungslink!", + "session-expired": "Sitzung abgelaufen!" }, "form": { "amount": "Betrag", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index bd0fa2d82..fd57798c4 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -46,8 +46,8 @@ "change-password": "Error while changing password", "error": "Error", "no-account": "Unfortunately we could not find an account to the given data!", - "session-expired": "The session expired", - "no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!" + "no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!", + "session-expired": "The session expired" }, "form": { "amount": "Amount", From fefcb7251ad92322f20623edec3788dc635e2207 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 10:06:31 +0100 Subject: [PATCH 29/44] Routes can route to /thx/login & /activateEmail , thx page now integrates email not activated logic. --- frontend/src/routes/routes.js | 6 +- frontend/src/views/Pages/ActivateEmail.vue | 76 ++++++++++++++++++++++ frontend/src/views/Pages/Login.vue | 10 +-- frontend/src/views/Pages/thx.vue | 10 +++ 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 frontend/src/views/Pages/ActivateEmail.vue diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index 8cc4d313d..3d16ef45e 100755 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -40,7 +40,7 @@ const routes = [ path: '/thx/:comingFrom', component: () => import('../views/Pages/thx.vue'), beforeEnter: (to, from, next) => { - const validFrom = ['password', 'reset', 'register'] + const validFrom = ['password', 'reset', 'register', 'login', 'activateEmail'] if (!validFrom.includes(from.path.split('/')[1])) { next({ path: '/login' }) } else { @@ -68,6 +68,10 @@ const routes = [ path: '/checkEmail/:optin', component: () => import('../views/Pages/CheckEmail.vue'), }, + { + path: '/activateEmail', + component: () => import('../views/Pages/ActivateEmail.vue'), + }, { path: '*', component: NotFound }, ] diff --git a/frontend/src/views/Pages/ActivateEmail.vue b/frontend/src/views/Pages/ActivateEmail.vue new file mode 100644 index 000000000..203065b3c --- /dev/null +++ b/frontend/src/views/Pages/ActivateEmail.vue @@ -0,0 +1,76 @@ + + + diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 3f5c840d4..4ef7f7fb6 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -103,11 +103,13 @@ export default { loader.hide() }) .catch((error) => { + if (!error.message.includes('user email not validated')) { + this.$toasted.error(this.$t('error.no-account')) + } else { + // : this.$t('error.no-email-verify') + this.$router.push('/thx/login') + } loader.hide() - const toastedError = !error.message.includes('user email not validated') - ? this.$t('error.no-account') - : this.$t('error.no-email-verify') - this.$toasted.error(toastedError) }) }, async onCreated() { diff --git a/frontend/src/views/Pages/thx.vue b/frontend/src/views/Pages/thx.vue index 9d9143456..5dc2bda19 100644 --- a/frontend/src/views/Pages/thx.vue +++ b/frontend/src/views/Pages/thx.vue @@ -36,6 +36,16 @@ const textFields = { button: 'login', linkTo: '/login', }, + login: { + subtitle: 'site.thx.activateEmail', + button: 'Send Activation Link', + linkTo: '/activateEmail', + }, + activateEmail: { + subtitle: 'site.thx.emailActivated', + button: 'login', + linkTo: '/login', + }, } export default { From 1bf8e8451da37e91db7233e45c83134430f47953 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 10:06:51 +0100 Subject: [PATCH 30/44] Textes for the new pages added. --- frontend/src/locales/de.json | 6 ++++++ frontend/src/locales/en.json | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 1c298b416..97f49b5e8 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -153,6 +153,10 @@ "ooops": "Ooops!", "text": "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zum Erkunden" }, + "activateEmail": { + "headline": "", + "subtitle": "" + }, "checkEmail": { "errorText": "Email konnte nicht verifiziert werden.", "title": "Email wird verifiziert" @@ -179,8 +183,10 @@ "uppercase": "Ein Großbuchstabe erforderlich." }, "thx": { + "activateEmail": "Deine Email wurde noch nicht aktiviert, email erneut senden?", "checkEmail": "Deine Email würde erfolgreich verifiziert.", "email": "Wir haben dir eine eMail gesendet.", + "emailActivated": "Danke dass Du deine Email bestätigt hast.", "register": "Du bist jetzt registriert, bitte überprüfe deine Emails und klicke auf den Aktivierungslink.", "reset": "Dein Passwort wurde geändert.", "title": "Danke!" diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index fd57798c4..236d607cf 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -153,6 +153,10 @@ "ooops": "Ooops!", "text": "Page not found. Do not worry though, we have plenty of other pages to explore" }, + "activateEmail": { + "headline": "", + "subtitle": "" + }, "checkEmail": { "errorText": "Could not verify the email.", "title": "Verifing email" @@ -179,8 +183,10 @@ "uppercase": "One uppercase letter required." }, "thx": { + "activateEmail": "Your email has not been activated yet, send again the activation email?", "checkEmail": "Your email has been successfully verified.", "email": "We have sent you an email.", + "emailActivated": "Thank you your email has been activated.", "register": "You are registered now, please check your emails and click the activation link.", "reset": "Your password has been changed.", "title": "Thank you!" From 9a75604a7a6f00c0e7350963ba5e01afec450601 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 12 Nov 2021 10:55:43 +0100 Subject: [PATCH 31/44] Change prozess so that a user that has not activate his account gets a warning that he needs to click the activation link in the email. Withdrew sendActivationMail again. --- frontend/src/locales/de.json | 3 +- frontend/src/locales/en.json | 3 +- frontend/src/routes/routes.js | 6 +- frontend/src/views/Pages/ActivateEmail.vue | 76 ---------------------- frontend/src/views/Pages/thx.vue | 17 ++--- 5 files changed, 14 insertions(+), 91 deletions(-) delete mode 100644 frontend/src/views/Pages/ActivateEmail.vue diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 97f49b5e8..95504407d 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -183,10 +183,11 @@ "uppercase": "Ein Großbuchstabe erforderlich." }, "thx": { - "activateEmail": "Deine Email wurde noch nicht aktiviert, email erneut senden?", + "activateEmail": "Deine Email wurde noch nicht aktiviert, bitte überprüfe deine Email und Klicke den Aktivierungslink!", "checkEmail": "Deine Email würde erfolgreich verifiziert.", "email": "Wir haben dir eine eMail gesendet.", "emailActivated": "Danke dass Du deine Email bestätigt hast.", + "errorTitle": "Achtung!", "register": "Du bist jetzt registriert, bitte überprüfe deine Emails und klicke auf den Aktivierungslink.", "reset": "Dein Passwort wurde geändert.", "title": "Danke!" diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 236d607cf..ac00b0d20 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -183,10 +183,11 @@ "uppercase": "One uppercase letter required." }, "thx": { - "activateEmail": "Your email has not been activated yet, send again the activation email?", + "activateEmail": "Your email has not been activated yet, please check your emails and click the activation link!", "checkEmail": "Your email has been successfully verified.", "email": "We have sent you an email.", "emailActivated": "Thank you your email has been activated.", + "errorTitle": "Attention!", "register": "You are registered now, please check your emails and click the activation link.", "reset": "Your password has been changed.", "title": "Thank you!" diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index 3d16ef45e..9c51bc688 100755 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -40,7 +40,7 @@ const routes = [ path: '/thx/:comingFrom', component: () => import('../views/Pages/thx.vue'), beforeEnter: (to, from, next) => { - const validFrom = ['password', 'reset', 'register', 'login', 'activateEmail'] + const validFrom = ['password', 'reset', 'register', 'login'] if (!validFrom.includes(from.path.split('/')[1])) { next({ path: '/login' }) } else { @@ -68,10 +68,6 @@ const routes = [ path: '/checkEmail/:optin', component: () => import('../views/Pages/CheckEmail.vue'), }, - { - path: '/activateEmail', - component: () => import('../views/Pages/ActivateEmail.vue'), - }, { path: '*', component: NotFound }, ] diff --git a/frontend/src/views/Pages/ActivateEmail.vue b/frontend/src/views/Pages/ActivateEmail.vue deleted file mode 100644 index 203065b3c..000000000 --- a/frontend/src/views/Pages/ActivateEmail.vue +++ /dev/null @@ -1,76 +0,0 @@ - - - diff --git a/frontend/src/views/Pages/thx.vue b/frontend/src/views/Pages/thx.vue index 5dc2bda19..d28b129e1 100644 --- a/frontend/src/views/Pages/thx.vue +++ b/frontend/src/views/Pages/thx.vue @@ -4,10 +4,12 @@
-

{{ $t('site.thx.title') }}

+

{{ $t(displaySetup.headline) }}

{{ $t(displaySetup.subtitle) }}


- {{ $t(displaySetup.button) }} + + {{ $t(displaySetup.button) }} +
@@ -17,34 +19,33 @@ diff --git a/admin/src/main.js b/admin/src/main.js index f5ec929f2..7375393d9 100644 --- a/admin/src/main.js +++ b/admin/src/main.js @@ -21,7 +21,7 @@ import { BootstrapVue } from 'bootstrap-vue' const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI }) const authLink = new ApolloLink((operation, forward) => { - const token = '' // store.state.token + const token = store.state.token operation.setContext({ headers: { Authorization: token && token.length > 0 ? `Bearer ${token}` : '', diff --git a/admin/src/router/routes.js b/admin/src/router/routes.js index 40f3ce325..604b03bee 100644 --- a/admin/src/router/routes.js +++ b/admin/src/router/routes.js @@ -3,9 +3,11 @@ import NotFound from '@/components/NotFoundPage.vue' const routes = [ { path: '/', + /* meta: { requiresAuth: true, }, + */ }, { path: '*', component: NotFound }, ] diff --git a/admin/src/store/store.js b/admin/src/store/store.js index 92fb37835..709ac52d0 100644 --- a/admin/src/store/store.js +++ b/admin/src/store/store.js @@ -12,7 +12,7 @@ export const mutations = { const store = new Vuex.Store({ mutations, state: { - token: null, + token: 'some-token', }, }) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index bd23b43b3..83f38a95f 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -8,8 +8,6 @@ services: image: gradido/frontend:development build: target: development - networks: - - external-net environment: - NODE_ENV="development" # - DEBUG=true @@ -27,8 +25,6 @@ services: image: gradido/admin:development build: target: development - networks: - - external-net environment: - NODE_ENV="development" # - DEBUG=true diff --git a/docker-compose.yml b/docker-compose.yml index b212c6f21..9352fd162 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,7 @@ services: context: ./frontend target: production networks: + - external-net - internal-net ports: - 3000:3000 @@ -39,6 +40,7 @@ services: context: ./admin target: production networks: + - external-net - internal-net ports: - 8080:8080 From d8def24e0c2f87a6973e3298a184a9b8e7c82867 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 18 Nov 2021 10:28:54 +0100 Subject: [PATCH 33/44] Their was an error in the UserResolver due to a check undefined and false would fall out of the update change it to !== undefined. --- backend/src/graphql/resolver/UserResolver.ts | 2 +- backend/src/typeorm/repository/UserSettingRepository.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 5c4625938..b10876d46 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -537,7 +537,7 @@ export class UserResolver { await queryRunner.startTransaction('READ UNCOMMITTED') try { - if (coinanimation) { + if (coinanimation !== undefined) { queryRunner.manager .getCustomRepository(UserSettingRepository) .setOrUpdate(userEntity.id, Setting.COIN_ANIMATION, coinanimation.toString()) diff --git a/backend/src/typeorm/repository/UserSettingRepository.ts b/backend/src/typeorm/repository/UserSettingRepository.ts index 80c44802b..7ec7ed3dd 100644 --- a/backend/src/typeorm/repository/UserSettingRepository.ts +++ b/backend/src/typeorm/repository/UserSettingRepository.ts @@ -18,7 +18,7 @@ export class UserSettingRepository extends Repository { let entity = await this.findOne({ userId: userId, key: key }) if (!entity) { - entity = new UserSetting() + entity = this.create() entity.userId = userId entity.key = key } From 8eb5c74ba84c6c9ff3a35c76660f7b1eccaa4315 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 17 Nov 2021 12:51:58 +0100 Subject: [PATCH 34/44] encode buffer to hex when decoding the jwt, not everytime we use it --- backend/src/graphql/directive/isAuthorized.ts | 2 +- backend/src/graphql/resolver/BalanceResolver.ts | 3 +-- backend/src/graphql/resolver/GdtResolver.ts | 3 +-- backend/src/graphql/resolver/TransactionResolver.ts | 6 ++---- backend/src/graphql/resolver/UserResolver.ts | 3 +-- 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts index 079e8e88c..6245ef8ba 100644 --- a/backend/src/graphql/directive/isAuthorized.ts +++ b/backend/src/graphql/directive/isAuthorized.ts @@ -10,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/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 902e50b8b..e067b4d68 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -18,8 +18,7 @@ export class BalanceResolver { const balanceRepository = getCustomRepository(BalanceRepository) const userRepository = getCustomRepository(UserRepository) - const pubKeyString = Buffer.from(context.pubKey).toString('hex') - const userEntity = await userRepository.findByPubkeyHex(pubKeyString) + const userEntity = await userRepository.findByPubkeyHex(context.pubKey) const balanceEntity = await balanceRepository.findByUser(userEntity.id) const now = new Date() diff --git a/backend/src/graphql/resolver/GdtResolver.ts b/backend/src/graphql/resolver/GdtResolver.ts index ba10d45bf..b4f9a512b 100644 --- a/backend/src/graphql/resolver/GdtResolver.ts +++ b/backend/src/graphql/resolver/GdtResolver.ts @@ -22,8 +22,7 @@ export class GdtResolver { ): Promise { // load user const userRepository = getCustomRepository(UserRepository) - const pubKeyString = Buffer.from(context.pubKey).toString('hex') - const userEntity = await userRepository.findByPubkeyHex(pubKeyString) + const userEntity = await userRepository.findByPubkeyHex(context.pubKey) const resultGDT = await apiGet( `${CONFIG.GDT_API_URL}/GdtEntries/listPerEmailApi/${userEntity.email}/${currentPage}/${pageSize}/${order}`, diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index fbdbaf1bc..968ce9d4c 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -473,8 +473,7 @@ export class TransactionResolver { ): Promise { // load user const userRepository = getCustomRepository(UserRepository) - const pubKeyString = Buffer.from(context.pubKey).toString('hex') - const userEntity = await userRepository.findByPubkeyHex(pubKeyString) + const userEntity = await userRepository.findByPubkeyHex(context.pubKey) const transactions = await listTransactions(currentPage, pageSize, order, userEntity) @@ -509,8 +508,7 @@ export class TransactionResolver { // TODO this is subject to replay attacks // validate sender user (logged in) const userRepository = getCustomRepository(UserRepository) - const pubKeyString = Buffer.from(context.pubKey).toString('hex') - const senderUser = await userRepository.findByPubkeyHex(pubKeyString) + const senderUser = await userRepository.findByPubkeyHex(context.pubKey) if (senderUser.pubkey.length !== 32) { throw new Error('invalid sender public key') } diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 436aee075..ad04a0e9f 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -621,8 +621,7 @@ export class UserResolver { @Query(() => Boolean) async hasElopage(@Ctx() context: any): Promise { const userRepository = getCustomRepository(UserRepository) - const pubKey = Buffer.from(context.pubKey).toString('hex') - const userEntity = await userRepository.findByPubkeyHex(pubKey).catch() + const userEntity = await userRepository.findByPubkeyHex(context.pubKey).catch() if (!userEntity) { return false } From 0fd2110fa1694039a55bbfa8c3c0642a4813fc65 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 22 Nov 2021 16:06:48 +0100 Subject: [PATCH 35/44] removed duplicate import --- backend/src/graphql/resolver/UserResolver.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index ad04a0e9f..8683dbf56 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -30,7 +30,6 @@ import { LoginUserBackup } from '@entity/LoginUserBackup' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { sendEMail } from '../../util/sendEMail' import { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys' -import { LoginUserRepository } from '../../typeorm/repository/LoginUser' // eslint-disable-next-line @typescript-eslint/no-var-requires const sodium = require('sodium-native') From 1d9042ca4bfe6ec80b7144bca7c62e68ce5d2f26 Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 21:42:09 +0100 Subject: [PATCH 36/44] Update backend/src/graphql/resolver/UserResolver.ts Co-authored-by: Ulf Gebhardt --- backend/src/graphql/resolver/UserResolver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 8683dbf56..3a8573680 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -220,6 +220,7 @@ export class UserResolver { 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 = loginUser.firstName userEntity.lastName = loginUser.lastName From 6dab777005c76f2ae63493ff86e135e57b572c19 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 22 Nov 2021 22:00:57 +0100 Subject: [PATCH 37/44] use correct pubKey, use hex instead of buffer --- 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 3a8573680..ad4566070 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -246,7 +246,7 @@ export class UserResolver { user.language = loginUser.language // Elopage Status & Stored PublisherId - user.hasElopage = await this.hasElopage({ pubKey: loginUser.pubKey }) + user.hasElopage = await this.hasElopage({ pubKey: loginUserPubKeyString }) if (!user.hasElopage && publisherId) { user.publisherId = publisherId // TODO: Check if we can use updateUserInfos From fccc7b4434646215acc10578ddbe1479bf6c7921 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 22 Nov 2021 23:17:11 +0100 Subject: [PATCH 38/44] Changed the Auto increment so that it is done after the rollback and not in the finally block. --- backend/src/graphql/resolver/TransactionResolver.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 968ce9d4c..ae9e318ae 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -613,9 +613,6 @@ export class TransactionResolver { await queryRunner.commitTransaction() } catch (e) { await queryRunner.rollbackTransaction() - throw e - } finally { - await queryRunner.release() // TODO: This is broken code - we should never correct an autoincrement index in production // according to dario it is required tho to properly work. The index of the table is used as // index for the transaction which requires a chain without gaps @@ -627,6 +624,9 @@ export class TransactionResolver { // eslint-disable-next-line no-console console.log('problems with reset auto increment: %o', error) }) + throw e + } finally { + await queryRunner.release() } // send notification email // TODO: translate From 38ee1d46b8f44c91d1c7be608f663cbed0b34a56 Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 23:27:02 +0100 Subject: [PATCH 39/44] Update frontend/src/locales/de.json --- frontend/src/locales/de.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 95504407d..de34b93ff 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -153,10 +153,6 @@ "ooops": "Ooops!", "text": "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zum Erkunden" }, - "activateEmail": { - "headline": "", - "subtitle": "" - }, "checkEmail": { "errorText": "Email konnte nicht verifiziert werden.", "title": "Email wird verifiziert" From 57e01cba27742f3afa895b371fc6c57b5a5f8bc0 Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 23:27:09 +0100 Subject: [PATCH 40/44] Update frontend/src/locales/en.json --- frontend/src/locales/en.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index ac00b0d20..0aaf6a22c 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -153,10 +153,6 @@ "ooops": "Ooops!", "text": "Page not found. Do not worry though, we have plenty of other pages to explore" }, - "activateEmail": { - "headline": "", - "subtitle": "" - }, "checkEmail": { "errorText": "Could not verify the email.", "title": "Verifing email" From 6bf0c032e979bfee40386f7f899eb607d1af255d Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 23:27:17 +0100 Subject: [PATCH 41/44] Update frontend/src/views/Pages/thx.vue --- frontend/src/views/Pages/thx.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/views/Pages/thx.vue b/frontend/src/views/Pages/thx.vue index d28b129e1..5884cc61c 100644 --- a/frontend/src/views/Pages/thx.vue +++ b/frontend/src/views/Pages/thx.vue @@ -45,7 +45,6 @@ const textFields = { login: { headline: 'site.thx.errorTitle', subtitle: 'site.thx.activateEmail', - button: 'Send Activation Link', }, } From 49db3d37fc8cd9bea1743b9290bbbff8db9d3c6c Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 23:33:04 +0100 Subject: [PATCH 42/44] Update backend/src/typeorm/repository/UserSettingRepository.ts --- backend/src/typeorm/repository/UserSettingRepository.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/typeorm/repository/UserSettingRepository.ts b/backend/src/typeorm/repository/UserSettingRepository.ts index 7ec7ed3dd..80c44802b 100644 --- a/backend/src/typeorm/repository/UserSettingRepository.ts +++ b/backend/src/typeorm/repository/UserSettingRepository.ts @@ -18,7 +18,7 @@ export class UserSettingRepository extends Repository { let entity = await this.findOne({ userId: userId, key: key }) if (!entity) { - entity = this.create() + entity = new UserSetting() entity.userId = userId entity.key = key } From ed01bca12b437e31163829fb80de8b3ff293886e Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 23:35:02 +0100 Subject: [PATCH 43/44] Update backend/src/graphql/resolver/UserResolver.ts --- 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 b10876d46..e5728d1d8 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -537,7 +537,7 @@ export class UserResolver { await queryRunner.startTransaction('READ UNCOMMITTED') try { - if (coinanimation !== undefined) { + if (coinanimation !== null && coinanimation !== undefined) { queryRunner.manager .getCustomRepository(UserSettingRepository) .setOrUpdate(userEntity.id, Setting.COIN_ANIMATION, coinanimation.toString()) From ab0d29bc3190175f391a0fff662fa6b2c72713f3 Mon Sep 17 00:00:00 2001 From: Hannes Heine Date: Mon, 22 Nov 2021 23:50:44 +0100 Subject: [PATCH 44/44] Update frontend/src/views/Pages/Register.vue --- frontend/src/views/Pages/Register.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/views/Pages/Register.vue b/frontend/src/views/Pages/Register.vue index 032ba6325..ea4000cff 100755 --- a/frontend/src/views/Pages/Register.vue +++ b/frontend/src/views/Pages/Register.vue @@ -190,7 +190,6 @@ export default { methods: { updateLanguage(e) { this.language = e - console.log('language', this.language) this.$store.commit('language', this.language) this.$i18n.locale = this.language localeChanged(this.language)