diff --git a/.gitmodules b/.gitmodules index 70fda6a17..22790ccc7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,6 @@ [submodule "login_server/src/proto"] path = login_server/src/proto url = https://github.com/gradido/gradido_protocol.git +[submodule "login_server/dependencies/protobuf"] + path = login_server/dependencies/protobuf + url = https://github.com/protocolbuffers/protobuf.git 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 f076e26c8..f293b93be 100644 --- a/community_server/src/Template/StateBalances/overview_gdt.ctp +++ b/community_server/src/Template/StateBalances/overview_gdt.ctp @@ -47,8 +47,12 @@ $this->assign('header', $header);
- element('printEuro', ['number' => $entry['amount']]); ?> - element('printEuro', ['number' => $entry['amount2']]) ?> + + element('printGDT', ['number' => $entry['amount']*100.0]); ?> + + element('printEuro', ['number' => $entry['amount']*100.0]); ?> + element('printEuro', ['number' => $entry['amount2']*100.0]) ?> +
Number->format($entry['factor']) ?> @@ -89,8 +93,12 @@ $this->assign('header', $header);
- element('printEuro', ['number' => $gdtEntry['amount']]) ?> - element('printEuro', ['number' => $gdtEntry['amount2']]) ?> + + element('printGDT', ['number' => $gdtEntry['amount']*100.0]); ?> + + element('printEuro', ['number' => $gdtEntry['amount']*100.0]); ?> + element('printEuro', ['number' => $gdtEntry['amount2']*100.0]) ?> +
Number->format($gdtEntry['factor']) ?> 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/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/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/login_server/README b/login_server/README deleted file mode 100644 index 400aee30a..000000000 --- a/login_server/README +++ /dev/null @@ -1,31 +0,0 @@ -sudo apt install libsodium-dev - -# get dependencies -git submodule update --init --recursive - - -cd dependencies/mariadb-connector-c -mkdir build -cd build -cmake -DWITH_SSL=OFF .. -cd ../../../ - - -# get more dependencies with conan (need conan from https://conan.io/) -mkdir build && cd build -# // not used anymore -# conan remote add inexor https://api.bintray.com/conan/inexorgame/inexor-conan -# not needed, but bincrafter -# conan install .. -s build_type=Debug -conan install .. - -# build Makefile with cmake -cmake .. - -make grpc -# under windows build at least release for protoc.exe and grpc c++ plugin -cd ../ -./unix_parse_proto.sh -cd build -make - diff --git a/login_server/README.md b/login_server/README.md new file mode 100644 index 000000000..73f5deea0 --- /dev/null +++ b/login_server/README.md @@ -0,0 +1,147 @@ +# Build Login-Server yourself +## Linux (Ubuntu) Packets +install build essentials + +```bash +sudo apt install -y gcovr build-essential gettext libcurl4-openssl-dev libssl-dev libsodium-dev libboost-dev +``` + +## CMake +CMake is used for build file generation and the Login-Server needs at least version v3.18.2 +You can build and install it from source. +The Version in apt is sadly to old. + +```bash +git clone https://github.com/Kitware/CMake.git --branch v3.18.2 +cd CMake +./bootstrap --parallel=$(nproc) && make -j$(nproc) && sudo make install +``` + +## dependencies +load git submodules if you haven't done it yet + +```bash +git submodule update --init --recursive +``` + +## build tools +build protoc and page compiler needed for generating some additional code + +```bash +cd scripts +./prepare_build.sh +``` + +## build +build login-server in debug mode + +```bash +cd scripts +./build_debug.sh +``` + +## multilanguage text +Login-Server uses gettext translations found after build in src/LOCALE +On Linux Login-Server expect the *.po files in folder /etc/grd_login/LOCALE +on windows next to Binary in Folder LOCALE. +So please copy them over by yourself on first run or after change. + +If you like to update some translations your find a messages.pot in src/LOCALE. +Use it together with poedit and don't forget to copy over *.po files after change to /etc/grd_login/LOCALE +To update messages.pot run + +```bash +./scripts/compile_pot.sh +``` +This will be also called by ./scripts/build_debug.sh + +## database +Login-Server needs a db to run, it is tested with mariadb +table definitions are found in folder ./skeema/gradido_login +Currently at least one group must be present in table groups. +For example: +```sql +INSERT INTO `groups` (`id`, `alias`, `name`, `url`, `host`, `home`, `description`) VALUES +(1, 'docker', 'docker gradido group', 'localhost', 'localhost', '/', 'gradido test group for docker with blockchain db'); +``` + +## configuration +Login-Server needs a configuration file to able to run. +On Linux it expect it to find the file /etc/grd_login/grd_login.properties +and /etc/grd_login/grd_login_test.properties for unittest + +Example configuration (ini-format) +```ini +# Port for Web-Interface +HTTPServer.port = 1200 +# Port for json-Interface (used by new backend) +JSONServer.port = 1201 +# default group id for new users, if no group was choosen +Gradido.group_id = 1 + +# currently not used +crypto.server_admin_public = f909a866baec97c5460b8d7a93b72d3d4d20cc45d9f15d78bd83944eb9286b7f +# Server admin Passphrase +# nerve execute merit pool talk hockey basic win cargo spin disagree ethics swear price purchase say clutch decrease slow half forest reform cheese able +# + +# TODO: auto-generate in docker build step +# expect valid hex 32 character long (16 Byte) +# salt for hashing user password, should be moved into db generated and saved per user, used for hardening against hash-tables +crypto.server_key = a51ef8ac7ef1abf162fb7a65261acd7a + +# TODO: auto-generate in docker build step +# salt for hashing user encryption key, expect valid hex, as long as you like, used in sha512 +crypto.app_secret = 21ffbbc616fe + +# for url forwarding to old frontend, path of community server +phpServer.url = http://localhost/ +# host for community server api calls +phpServer.host = localhost +# port for community server api calls +phpServer.port = 80 + +# Path for Login-Server Web-Interface used for link-generation +loginServer.path = http://localhost/account +# default language for new users and if no one is logged in +loginServer.default_locale = de + +# db setup tested with mariadb, should also work with mysql +loginServer.db.host = localhost +loginServer.db.name = gradido_login +loginServer.db.user = root +loginServer.db.password = +loginServer.db.port = 3306 + +# check email path for new frontend for link generation in emails +frontend.checkEmailPath = http://localhost/vue/reset + +# disable email all together +email.disable = true + +# setup email smtp server for sending emails +#email.username = +#email.sender = +#email.admin_receiver = +#email.password = +#email.smtp.url = +#email.smtp.port = + +# server setup types: test, staging or production +# used mainly to decide if using http or https for links +# test use http and staging and production uses https +ServerSetupType=test +dev.default_group = docker + +# Session timeout in minutes +session.timeout = 15 + +# Disabling security features for faster develop and testing +unsecure.allow_passwort_via_json_request = 1 +unsecure.allow_auto_sign_transactions = 1 +unsecure.allow_cors_all = 1 + +# default disable, passwords must contain a number, a lower character, a high character, special character, and be at least 8 characters long +unsecure.allow_all_passwords = 1 + +``` diff --git a/login_server/dependencies/protobuf b/login_server/dependencies/protobuf new file mode 160000 index 000000000..0b8d13a1d --- /dev/null +++ b/login_server/dependencies/protobuf @@ -0,0 +1 @@ +Subproject commit 0b8d13a1d4cd9be16ed8a2230577aa9c296aa1ca diff --git a/login_server/scripts/build_debug.sh b/login_server/scripts/build_debug.sh index 99a0d6d1a..27e5740dd 100755 --- a/login_server/scripts/build_debug.sh +++ b/login_server/scripts/build_debug.sh @@ -1,12 +1,9 @@ #!/bin/sh - -cd ../scripts - chmod +x compile_pot.sh +./compile_pot.sh cd ../build cmake -DCMAKE_BUILD_TYPE=Debug .. -./compile_pot.sh make -j$(nproc) Gradido_LoginServer chmod +x ./bin/Gradido_LoginServer diff --git a/login_server/scripts/prepare_build.sh b/login_server/scripts/prepare_build.sh index fe9c70e46..5598e0318 100755 --- a/login_server/scripts/prepare_build.sh +++ b/login_server/scripts/prepare_build.sh @@ -9,9 +9,9 @@ fi mkdir build cd build cmake -DWITH_SSL=OFF .. -cd ../../ +cd ../../../ -if [! -d "./build" ] ; then +if [ ! -d "./build" ] ; then mkdir build fi cd build diff --git a/login_server/scripts/unittest_coverage.sh b/login_server/scripts/unittest_coverage.sh new file mode 100644 index 000000000..b0bd1a4c9 --- /dev/null +++ b/login_server/scripts/unittest_coverage.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd ../build +cmake -DCMAKE_BUILD_TYPE=Debug -DCOLLECT_COVERAGE_DATA=ON -DCOVERAGE_TOOL=gcovr .. && \ +make -j$(nproc) Gradido_LoginServer_Test +make coverage + + 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;