diff --git a/backend/package.json b/backend/package.json index c337b8e35..e62085b2d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -18,6 +18,7 @@ "apollo-server-express": "^2.25.2", "axios": "^0.21.1", "class-validator": "^0.13.1", + "cors": "^2.8.5", "dotenv": "^10.0.0", "express": "^4.17.1", "graphql": "^15.5.1", diff --git a/backend/src/auth/auth.ts b/backend/src/auth/auth.ts index 0d9014b15..ff7a07735 100644 --- a/backend/src/auth/auth.ts +++ b/backend/src/auth/auth.ts @@ -4,6 +4,7 @@ import { AuthChecker } from 'type-graphql' import decode from '../jwt/decode' import { apiGet } from '../apis/loginAPI' import CONFIG from '../config' +import encode from '../jwt/encode' /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ export const isAuthorized: AuthChecker = async ({ root, args, context, info }, roles) => { @@ -14,6 +15,7 @@ export const isAuthorized: AuthChecker = async ({ root, args, context, info `${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`, ) context.sessionId = decoded.sessionId + context.setHeaders.push({ key: 'token', value: encode(decoded.sessionId) }) return result.success } } diff --git a/backend/src/graphql/resolvers/UserResolver.ts b/backend/src/graphql/resolvers/UserResolver.ts index dd8240e02..e23ff5976 100644 --- a/backend/src/graphql/resolvers/UserResolver.ts +++ b/backend/src/graphql/resolvers/UserResolver.ts @@ -4,10 +4,11 @@ import { Resolver, Query, Args, Arg, Authorized, Ctx } from 'type-graphql' import CONFIG from '../../config' import { CheckUsernameResponse } from '../models/CheckUsernameResponse' -import { User } from '../models/User' import { LoginViaVerificationCode } from '../models/LoginViaVerificationCode' import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse' import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse' +import { User } from '../models/User' +import encode from '../../jwt/encode' import { ChangePasswordArgs, CheckUsernameArgs, @@ -16,12 +17,11 @@ import { UpdateUserInfosArgs, } from '../inputs/LoginUserInput' import { apiPost, apiGet } from '../../apis/loginAPI' -import encode from '../../jwt/encode' @Resolver() export class UserResolver { - @Query(() => String) - async login(@Args() { email, password }: UnsecureLoginArgs): Promise { + @Query(() => User) + async login(@Args() { email, password }: UnsecureLoginArgs, @Ctx() context: any): Promise { email = email.trim().toLowerCase() const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password }) @@ -30,10 +30,9 @@ export class UserResolver { throw new Error(result.data) } - const data = result.data - const sessionId = data.session_id - delete data.session_id - return encode({ sessionId, user: new User(data.user) }) + context.setHeaders.push({ key: 'token', value: encode(result.data.session_id) }) + + return new User(result.data.user) } @Query(() => LoginViaVerificationCode) diff --git a/backend/src/index.ts b/backend/src/index.ts index 067403508..b99e5bee4 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -2,6 +2,7 @@ import 'reflect-metadata' import express from 'express' +import cors from 'cors' import { buildSchema } from 'type-graphql' import { ApolloServer } from 'apollo-server-express' import { RowDataPacket } from 'mysql2/promise' @@ -22,14 +23,15 @@ import { isAuthorized } from './auth/auth' const DB_VERSION = '0001-init_db' -const context = (req: any) => { - const authorization = req.req.headers.authorization +const context = (args: any) => { + const authorization = args.req.headers.authorization let token = null if (authorization) { - token = req.req.headers.authorization.replace(/^Bearer /, '') + token = authorization.replace(/^Bearer /, '') } const context = { token, + setHeaders: [], } return context } @@ -61,8 +63,31 @@ async function main() { // Express Server const server = express() + const corsOptions = { + origin: '*', + exposedHeaders: ['token'], + } + + server.use(cors(corsOptions)) + + const plugins = [ + { + requestDidStart() { + return { + willSendResponse(requestContext: any) { + const { setHeaders = [] } = requestContext.context + setHeaders.forEach(({ key, value }: { [key: string]: string }) => { + requestContext.response.http.headers.append(key, value) + }) + return requestContext + }, + } + }, + }, + ] + // Apollo Server - const apollo = new ApolloServer({ schema, playground, context }) + const apollo = new ApolloServer({ schema, playground, context, plugins }) apollo.applyMiddleware({ app: server }) // Start Server diff --git a/backend/src/jwt/decode.ts b/backend/src/jwt/decode.ts index a414e0c41..47cf62154 100644 --- a/backend/src/jwt/decode.ts +++ b/backend/src/jwt/decode.ts @@ -7,15 +7,12 @@ import CONFIG from '../config/' export default (token: string): any => { if (!token) return null let sessionId = null - const email = null try { const decoded = jwt.verify(token, CONFIG.JWT_SECRET) sessionId = decoded.sub - // email = decoded.email return { token, sessionId, - email, } } catch (err) { return null diff --git a/backend/src/jwt/encode.ts b/backend/src/jwt/encode.ts index 477644dc7..9c5145e6d 100644 --- a/backend/src/jwt/encode.ts +++ b/backend/src/jwt/encode.ts @@ -5,13 +5,9 @@ import jwt from 'jsonwebtoken' import CONFIG from '../config/' // Generate an Access Token -export default function encode(data: any): string { - const { user, sessionId } = data - const { email, language, firstName, lastName } = user - const token = jwt.sign({ email, language, firstName, lastName, sessionId }, CONFIG.JWT_SECRET, { +export default function encode(sessionId: string): string { + const token = jwt.sign({ sessionId }, CONFIG.JWT_SECRET, { expiresIn: CONFIG.JWT_EXPIRES_IN, - // issuer: CONFIG.GRAPHQL_URI, - // audience: CONFIG.CLIENT_URI, subject: sessionId.toString(), }) return token diff --git a/community_server/src/Template/StateBalances/overview_gdt.ctp b/community_server/src/Template/StateBalances/overview_gdt.ctp index 198256e23..f293b93be 100644 --- a/community_server/src/Template/StateBalances/overview_gdt.ctp +++ b/community_server/src/Template/StateBalances/overview_gdt.ctp @@ -50,8 +50,8 @@ $this->assign('header', $header); element('printGDT', ['number' => $entry['amount']*100.0]); ?> - element('printEuro', ['number' => $entry['amount']]); ?> - element('printEuro', ['number' => $entry['amount2']]) ?> + element('printEuro', ['number' => $entry['amount']*100.0]); ?> + element('printEuro', ['number' => $entry['amount2']*100.0]) ?>
@@ -96,8 +96,8 @@ $this->assign('header', $header); element('printGDT', ['number' => $gdtEntry['amount']*100.0]); ?> - element('printEuro', ['number' => $gdtEntry['amount']]); ?> - element('printEuro', ['number' => $gdtEntry['amount2']]) ?> + element('printEuro', ['number' => $gdtEntry['amount']*100.0]); ?> + element('printEuro', ['number' => $gdtEntry['amount2']*100.0]) ?>
diff --git a/configs/login_server/grd_login.properties b/configs/login_server/grd_login.properties index f14568a16..96b0ea928 100644 --- a/configs/login_server/grd_login.properties +++ b/configs/login_server/grd_login.properties @@ -22,7 +22,8 @@ loginServer.db.user = root loginServer.db.password = loginServer.db.port = 3306 -frontend.checkEmailPath = http://localhost/reset +frontend.checkEmailPath = vue/checkEmail +frontend.resetPasswordPath = vue/reset email.disable = true diff --git a/frontend/package.json b/frontend/package.json index 59b34cc9d..4bc621916 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -72,7 +72,6 @@ "vue-good-table": "^2.21.3", "vue-i18n": "^8.22.4", "vue-jest": "^3.0.7", - "vue-jwt-decode": "^0.1.0", "vue-loading-overlay": "^3.4.2", "vue-moment": "^4.1.0", "vue-qrcode": "^0.3.5", diff --git a/frontend/src/components/Transaction.spec.js b/frontend/src/components/Transaction.spec.js new file mode 100644 index 000000000..43dc44782 --- /dev/null +++ b/frontend/src/components/Transaction.spec.js @@ -0,0 +1,31 @@ +import { mount } from '@vue/test-utils' +import Transaction from './Transaction' + +const localVue = global.localVue + +describe('Transaction', () => { + let wrapper + + const mocks = { + $i18n: { + locale: 'en', + }, + $t: jest.fn((t) => t), + $n: jest.fn((n) => n), + $d: jest.fn((d) => d), + } + + const Wrapper = () => { + return mount(Transaction, { localVue, mocks }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders the component', () => { + expect(wrapper.find('div.gdt-transaction-list-item').exists()).toBeTruthy() + }) + }) +}) diff --git a/frontend/src/components/Transaction.vue b/frontend/src/components/Transaction.vue new file mode 100644 index 000000000..03b559463 --- /dev/null +++ b/frontend/src/components/Transaction.vue @@ -0,0 +1,124 @@ + + diff --git a/frontend/src/components/TransactionCollapse.spec.js b/frontend/src/components/TransactionCollapse.spec.js new file mode 100644 index 000000000..f27c3ae66 --- /dev/null +++ b/frontend/src/components/TransactionCollapse.spec.js @@ -0,0 +1,152 @@ +import { mount } from '@vue/test-utils' +import TransactionCollapse from './TransactionCollapse' + +const localVue = global.localVue + +describe('TransactionCollapse', () => { + let wrapper + + const mocks = { + $t: jest.fn((t) => t), + $n: jest.fn((n) => n), + } + + const Wrapper = (propsData) => { + return mount(TransactionCollapse, { localVue, mocks, propsData }) + } + + describe('mount with gdtEntryType: 1', () => { + beforeEach(() => { + const propsData = { + amount: 100, + gdt: 110, + factor: 22, + gdtEntryType: 1, + } + + wrapper = Wrapper(propsData) + }) + + it('renders the component', () => { + expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy() + }) + + it('checks the prop gdtEntryType ', () => { + expect(wrapper.props().gdtEntryType).toBe(1) + }) + + it('renders the component collapse-header', () => { + expect(wrapper.find('.gdt-list-collapse-header-text')).toBeTruthy() + }) + + it('renders the component collapse-headline', () => { + expect(wrapper.find('#collapse-headline').text()).toBe('gdt.calculation') + }) + + it('renders the component collapse-first', () => { + expect(wrapper.find('#collapse-first').text()).toBe('gdt.factor') + }) + + it('renders the component collapse-second', () => { + expect(wrapper.find('#collapse-second').text()).toBe('gdt.formula') + }) + + it('renders the component collapse-firstMath', () => { + expect(wrapper.find('#collapse-firstMath').text()).toBe('22 GDT pro €') + }) + + it('renders the component collapse-secondMath', () => { + expect(wrapper.find('#collapse-secondMath').text()).toBe('100 € * 22 GDT / € = 110 GDT') + }) + }) + + describe('mount with gdtEntryType: 7', () => { + beforeEach(() => { + const propsData = { + amount: 100, + gdt: 2200, + factor: 22, + gdtEntryType: 7, + } + + wrapper = Wrapper(propsData) + }) + + it('renders the component', () => { + expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy() + }) + + it('checks the prop gdtEntryType ', () => { + expect(wrapper.props().gdtEntryType).toBe(7) + }) + + it('renders the component collapse-header', () => { + expect(wrapper.find('.gdt-list-collapse-header-text')).toBeTruthy() + }) + + it('renders the component collapse-headline', () => { + expect(wrapper.find('#collapse-headline').text()).toBe('gdt.conversion-gdt-euro') + }) + + it('renders the component collapse-first', () => { + expect(wrapper.find('#collapse-first').text()).toBe('gdt.raise') + }) + + it('renders the component collapse-second', () => { + expect(wrapper.find('#collapse-second').text()).toBe('gdt.conversion') + }) + + it('renders the component collapse-firstMath', () => { + expect(wrapper.find('#collapse-firstMath').text()).toBe('2200 %') + }) + + it('renders the component collapse-secondMath', () => { + expect(wrapper.find('#collapse-secondMath').text()).toBe('100 GDT * 2200 % = 2200 GDT') + }) + }) + + describe('mount with gdtEntryType: 4', () => { + beforeEach(() => { + const propsData = { + amount: 100, + gdt: 2200, + factor: 22, + gdtEntryType: 4, + } + + wrapper = Wrapper(propsData) + }) + + it('renders the component', () => { + expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy() + }) + + it('checks the prop gdtEntryType ', () => { + expect(wrapper.props().gdtEntryType).toBe(4) + }) + + it('renders the component collapse-header', () => { + expect(wrapper.find('.gdt-list-collapse-header-text')).toBeTruthy() + }) + + it('renders the component collapse-headline', () => { + expect(wrapper.find('#collapse-headline').text()).toBe('gdt.publisher') + }) + + it('renders the component collapse-first', () => { + expect(wrapper.find('#collapse-first').text()).toBe('') + }) + + it('renders the component collapse-second', () => { + expect(wrapper.find('#collapse-second').text()).toBe('') + }) + + it('renders the component collapse-firstMath', () => { + expect(wrapper.find('#collapse-firstMath').text()).toBe('') + }) + + it('renders the component collapse-secondMath', () => { + expect(wrapper.find('#collapse-secondMath').text()).toBe('') + }) + }) +}) diff --git a/frontend/src/components/TransactionCollapse.vue b/frontend/src/components/TransactionCollapse.vue new file mode 100644 index 000000000..854282a43 --- /dev/null +++ b/frontend/src/components/TransactionCollapse.vue @@ -0,0 +1,76 @@ + + diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 0aa11ce13..7414414b2 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -2,7 +2,14 @@ import gql from 'graphql-tag' export const login = gql` query($email: String!, $password: String!) { - login(email: $email, password: $password) + login(email: $email, password: $password) { + email + username + firstName + lastName + language + description + } } ` diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index b4c87b8ce..908d7b12c 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -138,15 +138,6 @@ "send_gradido":"Gradido versenden", "add_work":"neuer Gemeinschaftsbeitrag" }, - "profil": { - "activity": { - "new":"Neue Gemeinschaftsstunden eintragen", - "list":"Meine Gemeinschaftsstunden Liste" - }, - "user-data": { - "change-success": "Deine Daten wurden gespeichert." - } - }, "navbar" : { "my-profil":"Mein Profil", "settings":"Einstellungen", @@ -184,8 +175,8 @@ "formula":"Berechungsformel", "no-transactions":"Du hast zur Zeit keine Transaktionen", "publisher":"Dein geworbenes Mitglied hat einen Beitrag bezahlt", - "gdt-receive":"Aktion", - "your-share":"Geworbenes Mitglied", + "action":"Aktion", + "recruited-member":"Geworbenes Mitglied", "contribution":"Beitrag" } } diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 50d22c2bd..f9e17b38b 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -138,16 +138,6 @@ "send_gradido":"Send Gradido", "add_work":"New Community Contribution" }, - "profil": { - "transactions":"transactions", - "activity": { - "new":"Register new community hours", - "list":"My Community Hours List" - }, - "user-data": { - "change-success": "Your data has been saved." - } - }, "navbar" : { "my-profil":"My profile", "settings":"Settings", @@ -185,8 +175,8 @@ "formula": "Calculation formula", "no-transactions":"You currently have no transactions", "publisher":"A member you referred has paid a contribution", - "gdt-receive":"GDT receive", - "your-share":"Your share", + "action":"Action", + "recruited-member":"Recruited Member", "contribution":"Contribution" } } diff --git a/frontend/src/main.js b/frontend/src/main.js index 823df516c..0b0e98e2d 100755 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -20,7 +20,11 @@ const authLink = new ApolloLink((operation, forward) => { Authorization: token && token.length > 0 ? `Bearer ${token}` : '', }, }) - return forward(operation) + return forward(operation).map((response) => { + const newToken = operation.getContext().response.headers.get('token') + if (newToken) store.commit('token', newToken) + return response + }) }) const apolloClient = new ApolloClient({ diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index 77c7096ad..00f8369d2 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -1,7 +1,6 @@ import Vue from 'vue' import Vuex from 'vuex' import createPersistedState from 'vuex-persistedstate' -import VueJwtDecode from 'vue-jwt-decode' Vue.use(Vuex) @@ -30,15 +29,13 @@ export const mutations = { } export const actions = { - login: ({ dispatch, commit }, token) => { - const decoded = VueJwtDecode.decode(token) - commit('token', token) - commit('email', decoded.email) - commit('language', decoded.language) - commit('username', decoded.username) - commit('firstName', decoded.firstName) - commit('lastName', decoded.lastName) - commit('description', decoded.description) + login: ({ dispatch, commit }, data) => { + commit('email', data.email) + commit('language', data.language) + commit('username', data.username) + commit('firstName', data.firstName) + commit('lastName', data.lastName) + commit('description', data.description) }, logout: ({ commit, state }) => { commit('token', null) diff --git a/frontend/src/store/store.test.js b/frontend/src/store/store.test.js index 99a37451e..c067a6e49 100644 --- a/frontend/src/store/store.test.js +++ b/frontend/src/store/store.test.js @@ -1,15 +1,4 @@ import { mutations, actions } from './store' -import VueJwtDecode from 'vue-jwt-decode' - -jest.mock('vue-jwt-decode') -VueJwtDecode.decode.mockReturnValue({ - email: 'user@example.org', - language: 'de', - username: 'peter', - firstName: 'Peter', - lastName: 'Lustig', - description: 'Nickelbrille', -}) const { language, email, token, username, firstName, lastName, description } = mutations const { login, logout } = actions @@ -77,46 +66,48 @@ describe('Vuex store', () => { describe('login', () => { const commit = jest.fn() const state = {} - const commitedData = 'token' + const commitedData = { + email: 'user@example.org', + language: 'de', + username: 'peter', + firstName: 'Peter', + lastName: 'Lustig', + description: 'Nickelbrille', + } it('calls seven commits', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenCalledTimes(7) - }) - - it('commits token', () => { - login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(1, 'token', 'token') + expect(commit).toHaveBeenCalledTimes(6) }) it('commits email', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(2, 'email', 'user@example.org') + expect(commit).toHaveBeenNthCalledWith(1, 'email', 'user@example.org') }) it('commits language', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(3, 'language', 'de') + expect(commit).toHaveBeenNthCalledWith(2, 'language', 'de') }) it('commits username', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(4, 'username', 'peter') + expect(commit).toHaveBeenNthCalledWith(3, 'username', 'peter') }) it('commits firstName', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(5, 'firstName', 'Peter') + expect(commit).toHaveBeenNthCalledWith(4, 'firstName', 'Peter') }) it('commits lastName', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(6, 'lastName', 'Lustig') + expect(commit).toHaveBeenNthCalledWith(5, 'lastName', 'Lustig') }) it('commits description', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(7, 'description', 'Nickelbrille') + expect(commit).toHaveBeenNthCalledWith(6, 'description', 'Nickelbrille') }) }) diff --git a/frontend/src/views/Pages/AccountOverview/GdtTransactionList.vue b/frontend/src/views/Pages/AccountOverview/GdtTransactionList.vue index 3bdc9f42c..1ad4ba13e 100644 --- a/frontend/src/views/Pages/AccountOverview/GdtTransactionList.vue +++ b/frontend/src/views/Pages/AccountOverview/GdtTransactionList.vue @@ -17,134 +17,14 @@ } in transactionsGdt" :key="transactionId" > -
- -
- -
- - -
- - i - -
- - - - - -
-
{{ $t('gdt.gdt-receive') }}
-
{{ $t('gdt.credit') }}
-
-
-
{{ comment }}
-
{{ $n(gdt, 'decimal') }} GDT
-
-
- - -
-
{{ $t('gdt.your-share') }}
-
{{ $t('gdt.credit') }}
-
-
-
5%
-
{{ $n(amount, 'decimal') }} GDT
-
-
- - -
-
{{ $t('gdt.contribution') }}
-
{{ $t('gdt.credit') }}
-
-
-
{{ $n(amount, 'decimal') }} €
-
{{ $n(gdt, 'decimal') }} GDT
-
-
- - - - - -
- {{ $t('form.memo') }} -
-
- {{ comment }} -
-
- - - -
- {{ $t('form.date') }} -
-
- {{ $d($moment(date), 'long') }} {{ $i18n.locale === 'de' ? 'Uhr' : '' }} -
-
-
- - - - -
- - -
- {{ $t('gdt.conversion-gdt-euro') }} -
-
- {{ $t('gdt.publisher') }} -
-
{{ $t('gdt.calculation') }}
-
- - - -
-
{{ $t('gdt.raise') }}
-
{{ $t('gdt.conversion') }}
-
-
-
{{ factor * 100 }} %
-
- {{ $n(amount, 'decimal') }} GDT * {{ factor * 100 }} % = - {{ $n(gdt, 'decimal') }} GDT -
-
-
- - -
-
-
- - - -
-
{{ $t('gdt.factor') }}
-
{{ $t('gdt.formula') }}
-
-
-
{{ factor }} GDT pro €
-
- {{ $n(amount, 'decimal') }} € * {{ factor }} GDT / € = - {{ $n(gdt, 'decimal') }} GDT -
-
-
-
-
- +
import { listGDTEntriesQuery } from '../../../graphql/queries' import PaginationButtons from '../../../components/PaginationButtons' - -function iconByType(typeId) { - switch (typeId) { - case 1: - case 2: - case 3: - case 5: - case 6: - return { icon: 'heart', classes: 'gradido-global-color-accent' } - case 4: - return { icon: 'person-check', classes: 'gradido-global-color-accent' } - case 7: - return { icon: 'gift', classes: 'gradido-global-color-accent' } - } -} +import Transaction from '../../../components/Transaction.vue' export default { name: 'gdt-transaction-list', components: { PaginationButtons, + Transaction, }, data() { return { @@ -223,18 +90,6 @@ export default { this.$toasted.error(error.message) }) }, - getIcon(givenType) { - const type = iconByType(givenType) - if (type) - return { - icon: type.icon, - class: type.classes + ' m-mb-1 font2em', - } - this.throwError('no icon to given type: ' + givenType) - }, - throwError(msg) { - throw new Error(msg) - }, showNext() { this.currentPage++ this.updateGdt() diff --git a/login_server/src/cpp/JSONInterface/JsonSendEmail.cpp b/login_server/src/cpp/JSONInterface/JsonSendEmail.cpp index f278c393f..281c55c51 100644 --- a/login_server/src/cpp/JSONInterface/JsonSendEmail.cpp +++ b/login_server/src/cpp/JSONInterface/JsonSendEmail.cpp @@ -105,12 +105,13 @@ Poco::JSON::Object* JsonSendEmail::handle(Poco::Dynamic::Var params) return stateSuccess(); } auto receiver_user_id = receiver_user->getModel()->getID(); - std::string checkEmailUrl = receiver_user->getGroupBaseUrl() + ServerConfig::g_frontend_checkEmailPath; + std::string linkInEmail = ""; if (emailVerificationCodeType == model::table::EMAIL_OPT_IN_RESET_PASSWORD) { + linkInEmail = receiver_user->getGroupBaseUrl() + ServerConfig::g_frontend_resetPasswordPath; session = sm->getNewSession(); if (emailType == model::EMAIL_USER_RESET_PASSWORD) { - auto r = session->sendResetPasswordEmail(receiver_user, true, checkEmailUrl); + auto r = session->sendResetPasswordEmail(receiver_user, true, linkInEmail); if (1 == r) { return stateWarning("email already sended"); } @@ -120,7 +121,7 @@ Poco::JSON::Object* JsonSendEmail::handle(Poco::Dynamic::Var params) } else if (emailType == model::EMAIL_CUSTOM_TEXT) { auto email_verification_code_object = controller::EmailVerificationCode::loadOrCreate(receiver_user_id, model::table::EMAIL_OPT_IN_RESET_PASSWORD); - email_verification_code_object->setBaseUrl(checkEmailUrl); + email_verification_code_object->setBaseUrl(linkInEmail); auto email = new model::Email(email_verification_code_object, receiver_user, emailCustomText, emailCustomSubject); em->addEmail(email); } @@ -131,12 +132,13 @@ Poco::JSON::Object* JsonSendEmail::handle(Poco::Dynamic::Var params) } else { + linkInEmail = receiver_user->getGroupBaseUrl() + ServerConfig::g_frontend_checkEmailPath; if (session->getNewUser()->getModel()->getRole() != model::table::ROLE_ADMIN) { return stateError("admin needed"); } auto email_verification_code_object = controller::EmailVerificationCode::loadOrCreate(receiver_user_id, emailVerificationCodeType); - email_verification_code_object->setBaseUrl(checkEmailUrl); + email_verification_code_object->setBaseUrl(linkInEmail); model::Email* email = nullptr; if (emailType == model::EMAIL_CUSTOM_TEXT) { email = new model::Email(email_verification_code_object, receiver_user, emailCustomText, emailCustomSubject); diff --git a/login_server/src/cpp/ServerConfig.cpp b/login_server/src/cpp/ServerConfig.cpp index a453cc956..81a7b2511 100644 --- a/login_server/src/cpp/ServerConfig.cpp +++ b/login_server/src/cpp/ServerConfig.cpp @@ -51,6 +51,7 @@ namespace ServerConfig { std::string g_php_serverPath; std::string g_php_serverHost; std::string g_frontend_checkEmailPath; + std::string g_frontend_resetPasswordPath; int g_phpServerPort; Poco::Mutex g_TimeMutex; int g_FakeLoginSleepTime = 820; @@ -238,8 +239,9 @@ namespace ServerConfig { if ("" != app_secret_string) { g_CryptoAppSecret = DataTypeConverter::hexToBin(app_secret_string); } - std::string defaultCheckEmailPath = g_serverPath + "/checkEmail"; + std::string defaultCheckEmailPath = "/account/checkEmail"; g_frontend_checkEmailPath = cfg.getString("frontend.checkEmailPath", defaultCheckEmailPath); + g_frontend_resetPasswordPath = cfg.getString("frontend.resetPasswordPath", defaultCheckEmailPath); //g_CryptoAppSecret // unsecure flags diff --git a/login_server/src/cpp/ServerConfig.h b/login_server/src/cpp/ServerConfig.h index 5608a638e..a5d4a7a38 100644 --- a/login_server/src/cpp/ServerConfig.h +++ b/login_server/src/cpp/ServerConfig.h @@ -67,6 +67,7 @@ namespace ServerConfig { extern std::string g_php_serverPath; extern std::string g_php_serverHost; extern std::string g_frontend_checkEmailPath; + extern std::string g_frontend_resetPasswordPath; extern int g_phpServerPort; extern Poco::Mutex g_TimeMutex; extern int g_FakeLoginSleepTime;