Merge branch 'master' into ADMINBEREICH-first-step

This commit is contained in:
Alexander Friedland 2021-11-23 10:24:04 +01:00 committed by GitHub
commit d2bfb213a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 386 additions and 236 deletions

View File

@ -35,6 +35,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "26.6.3",
"moment": "^2.29.1",
"regenerator-runtime": "^0.13.9",
"stats-webpack-plugin": "^0.7.0",
"vue": "^2.6.11",
"vue-apollo": "^3.0.8",

68
admin/src/App.spec.js Normal file
View File

@ -0,0 +1,68 @@
import { mount } from '@vue/test-utils'
import App from './App'
const localVue = global.localVue
const storeCommitMock = jest.fn()
const mocks = {
$store: {
commit: storeCommitMock,
},
}
const localStorageMock = (() => {
let store = {}
return {
getItem: (key) => {
return store[key] || null
},
setItem: (key, value) => {
store[key] = value.toString()
},
removeItem: (key) => {
delete store[key]
},
clear: () => {
store = {}
},
}
})()
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(() => {
Object.defineProperty(window, 'localStorage', {
value: localStorageMock,
})
window.localStorage.setItem('vuex', JSON.stringify({ token: 1234 }))
})
it.skip('commits the token to the store', () => {
expect(storeCommitMock).toBeCalledWith('token', 1234)
})
})
})

View File

@ -1,19 +1,9 @@
<template>
<div id="app">
<nav-bar class="wrapper-nav" />
<router-view class="wrapper p-3"></router-view>
<foo-ter />
</div>
<div id="app"></div>
</template>
<script>
import NavBar from '@/components/NavBar.vue'
import FooTer from '@/components/Footer.vue'
export default {
name: 'App',
components: {
NavBar,
FooTer,
},
}
</script>

View File

@ -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'
@ -22,7 +25,9 @@ import moment from 'vue-moment'
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}` : '',
@ -52,6 +57,7 @@ const apolloProvider = new VueApollo({
})
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)
Vue.use(moment)

View File

@ -14,6 +14,9 @@ export const mutations = {
resetOpenCreations: (state) => {
state.openCreations = 0
},
token: (state, token) => {
state.token = token
},
}
const store = new Vuex.Store({

View File

@ -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')
})
})
})
})

View File

@ -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)

View File

@ -10623,7 +10623,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==

View File

@ -51,7 +51,6 @@ const email = {
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'xxx',
EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'gmail.com',
EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '587',
EMAIL_LINK_VERIFICATION:
process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/vue/checkEmail/$1',
}

View File

@ -2,9 +2,6 @@
import { AuthChecker } from 'type-graphql'
import CONFIG from '../../config'
import { apiGet } from '../../apis/HttpRequest'
import decode from '../../jwt/decode'
import encode from '../../jwt/encode'
@ -13,7 +10,7 @@ const isAuthorized: AuthChecker<any> = 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
}

View File

@ -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)

View File

@ -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

View File

@ -22,14 +22,14 @@ import {
} from '../../middleware/klicktippMiddleware'
import { CheckEmailResponse } from '../model/CheckEmailResponse'
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
import { Setting } from '../enum/Setting'
import { UserRepository } from '../../typeorm/repository/User'
import { LoginUser } from '@entity/LoginUser'
import { LoginElopageBuys } from '@entity/LoginElopageBuys'
import { LoginUserBackup } from '@entity/LoginUserBackup'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { sendEMail } from '../../util/sendEMail'
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
import { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sodium = require('sodium-native')
@ -201,33 +201,32 @@ export class UserResolver {
@Ctx() context: any,
): Promise<User> {
email = email.trim().toLowerCase()
const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
// if there is no user, throw an authentication error
if (!result.success) {
throw new Error(result.data)
}
context.setHeaders.push({
key: 'token',
value: encode(result.data.user.public_hex),
// const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
// UnsecureLogin
const loginUserRepository = getCustomRepository(LoginUserRepository)
const loginUser = await loginUserRepository.findByEmail(email).catch(() => {
throw new Error('No user with this credentials')
})
const user = new User(result.data.user)
// Hack: Database Field is not validated properly and not nullable
if (user.publisherId === 0) {
user.publisherId = undefined
const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash
const loginUserPassword = BigInt(loginUser.password.toString())
if (loginUserPassword !== passwordHash[0].readBigUInt64LE()) {
throw new Error('No user with this credentials')
}
user.hasElopage = result.data.hasElopage
// read additional settings from settings table
// TODO: If user has no pubKey Create it again and update user.
const userRepository = getCustomRepository(UserRepository)
let userEntity: void | DbUser
userEntity = await userRepository.findByPubkeyHex(user.pubkey).catch(() => {
const loginUserPubKey = loginUser.pubKey
const loginUserPubKeyString = loginUserPubKey.toString('hex')
userEntity = await userRepository.findByPubkeyHex(loginUserPubKeyString).catch(() => {
// User not stored in state_users
// TODO: Check with production data - email is unique which can cause problems
userEntity = new DbUser()
userEntity.firstName = user.firstName
userEntity.lastName = user.lastName
userEntity.username = user.username
userEntity.email = user.email
userEntity.pubkey = Buffer.from(user.pubkey, 'hex')
userEntity.firstName = loginUser.firstName
userEntity.lastName = loginUser.lastName
userEntity.username = loginUser.username
userEntity.email = loginUser.email
userEntity.pubkey = loginUser.pubKey
userRepository.save(userEntity).catch(() => {
throw new Error('error by save userEntity')
@ -237,16 +236,28 @@ export class UserResolver {
throw new Error('error with cannot happen')
}
// Save publisherId if Elopage is not yet registered
const user = new User()
user.email = email
user.firstName = loginUser.firstName
user.lastName = loginUser.lastName
user.username = loginUser.username
user.description = loginUser.description
user.pubkey = loginUserPubKeyString
user.language = loginUser.language
// Elopage Status & Stored PublisherId
user.hasElopage = await this.hasElopage({ pubKey: loginUserPubKeyString })
if (!user.hasElopage && publisherId) {
user.publisherId = publisherId
// TODO: Check if we can use updateUserInfos
// await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey })
const loginUserRepository = getCustomRepository(LoginUserRepository)
const loginUser = await loginUserRepository.findOneOrFail({ email: userEntity.email })
loginUser.publisherId = publisherId
loginUserRepository.save(loginUser)
}
// coinAnimation
const userSettingRepository = getCustomRepository(UserSettingRepository)
const coinanimation = await userSettingRepository
.readBoolean(userEntity.id, Setting.COIN_ANIMATION)
@ -254,6 +265,12 @@ export class UserResolver {
throw new Error(error)
})
user.coinanimation = coinanimation
context.setHeaders.push({
key: 'token',
value: encode(loginUser.pubKey),
})
return user
}
@ -537,7 +554,7 @@ export class UserResolver {
await queryRunner.startTransaction('READ UNCOMMITTED')
try {
if (coinanimation) {
if (coinanimation !== null && coinanimation !== undefined) {
queryRunner.manager
.getCustomRepository(UserSettingRepository)
.setOrUpdate(userEntity.id, Setting.COIN_ANIMATION, coinanimation.toString())
@ -609,7 +626,8 @@ export class UserResolver {
return false
}
const elopageBuyCount = await LoginElopageBuys.count({ payerEmail: userEntity.email })
const loginElopageBuysRepository = getCustomRepository(LoginElopageBuysRepository)
const elopageBuyCount = await loginElopageBuysRepository.count({ payerEmail: userEntity.email })
return elopageBuyCount > 0
}
}

View File

@ -0,0 +1,5 @@
import { EntityRepository, Repository } from 'typeorm'
import { LoginElopageBuys } from '@entity/LoginElopageBuys'
@EntityRepository(LoginElopageBuys)
export class LoginElopageBuysRepository extends Repository<LoginElopageBuys> {}

View File

@ -2,4 +2,10 @@ import { EntityRepository, Repository } from 'typeorm'
import { LoginUser } from '@entity/LoginUser'
@EntityRepository(LoginUser)
export class LoginUserRepository extends Repository<LoginUser> {}
export class LoginUserRepository extends Repository<LoginUser> {
async findByEmail(email: string): Promise<LoginUser> {
return this.createQueryBuilder('loginUser')
.where('loginUser.email = :email', { email })
.getOneOrFail()
}
}

View File

@ -9,6 +9,15 @@ export class UserRepository extends Repository<User> {
.getOneOrFail()
}
async findByPubkeyHexBuffer(pubkeyHexBuffer: Buffer): Promise<User> {
const pubKeyString = pubkeyHexBuffer.toString('hex')
return await this.findByPubkeyHex(pubKeyString)
}
async findByEmail(email: string): Promise<User> {
return this.createQueryBuilder('user').where('user.email = :email', { email }).getOneOrFail()
}
async getUsersIndiced(userIds: number[]): Promise<User[]> {
if (!userIds.length) return []
const users = await this.createQueryBuilder('user')

View File

@ -1,170 +1,166 @@
version: "3.4"
services:
########################################################
# FRONTEND #############################################
########################################################
frontend:
image: gradido/frontend:development
build:
target: development
networks:
- external-net
environment:
- NODE_ENV="development"
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- frontend_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./frontend:/app
########################################################
# ADMIN INTERFACE ######################################
########################################################
admin:
image: gradido/admin:development
build:
target: development
networks:
- external-net
environment:
- NODE_ENV="development"
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- admin_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./admin:/app
########################################################
# BACKEND ##############################################
########################################################
backend:
image: gradido/backend:development
build:
target: development
networks:
- external-net
- internal-net
environment:
- NODE_ENV="development"
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- backend_node_modules:/app/node_modules
- backend_database_node_modules:/database/node_modules
- backend_database_build:/database/build
# bind the local folder to the docker to allow live reload
- ./backend:/app
- ./database:/database
########################################################
# DATABASE ##############################################
########################################################
database:
# we always run on production here since else the service lingers
# feel free to change this behaviour if it seems useful
# Due to problems with the volume caching the built files
# we changed this to test build. This keeps the service running.
image: gradido/database:test_up
build:
target: test_up
#networks:
# - external-net
# - internal-net
environment:
- NODE_ENV="development"
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- database_node_modules:/app/node_modules
- database_build:/app/build
# bind the local folder to the docker to allow live reload
- ./database:/app
#########################################################
## LOGIN SERVER #########################################
#########################################################
login-server:
build:
dockerfile: Dockerfiles/ubuntu/Dockerfile.debug
networks:
- external-net
- internal-net
security_opt:
- seccomp:unconfined
cap_add:
- SYS_PTRACE
volumes:
- ./logs:/var/log/grd_login
- ./login_server/src:/code/src
- ./login_server/dependencies:/code/dependencies
- ./login_server/scripts:/code/scripts
- ./configs/login_server:/etc/grd_login
- login_build_ubuntu_3.1:/code/build
#########################################################
## COMMUNITY SERVER (cakephp with php-fpm) ##############
#########################################################
community-server:
build:
context: .
target: community_server
dockerfile: ./community_server/Dockerfile
depends_on:
- mariadb
networks:
- internal-net
- external-net
volumes:
- ./community_server/config/php-fpm/php-ini-overrides.ini:/etc/php/7.4/fpm/conf.d/99-overrides.ini
- ./community_server/src:/var/www/cakephp/src
#########################################################
## MARIADB ##############################################
#########################################################
mariadb:
networks:
- internal-net
- external-net
#########################################################
## NGINX ################################################
#########################################################
nginx:
depends_on:
- frontend
- community-server
- login-server
volumes:
- ./logs/nginx:/var/log/nginx
#########################################################
## PHPMYADMIN ###########################################
#########################################################
phpmyadmin:
image: phpmyadmin
environment:
- PMA_ARBITRARY=1
#restart: always
ports:
- 8074:80
networks:
- internal-net
- external-net
volumes:
- /sessions
volumes:
frontend_node_modules:
admin_node_modules:
backend_node_modules:
backend_database_node_modules:
backend_database_build:
database_node_modules:
database_build:
version: "3.4"
services:
########################################################
# FRONTEND #############################################
########################################################
frontend:
image: gradido/frontend:development
build:
target: development
environment:
- NODE_ENV="development"
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- frontend_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./frontend:/app
########################################################
# ADMIN INTERFACE ######################################
########################################################
admin:
image: gradido/admin:development
build:
target: development
environment:
- NODE_ENV="development"
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- admin_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./admin:/app
########################################################
# BACKEND ##############################################
########################################################
backend:
image: gradido/backend:development
build:
target: development
networks:
- external-net
- internal-net
environment:
- NODE_ENV="development"
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- backend_node_modules:/app/node_modules
- backend_database_node_modules:/database/node_modules
- backend_database_build:/database/build
# bind the local folder to the docker to allow live reload
- ./backend:/app
- ./database:/database
########################################################
# DATABASE ##############################################
########################################################
database:
# we always run on production here since else the service lingers
# feel free to change this behaviour if it seems useful
# Due to problems with the volume caching the built files
# we changed this to test build. This keeps the service running.
image: gradido/database:test_up
build:
target: test_up
#networks:
# - external-net
# - internal-net
environment:
- NODE_ENV="development"
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- database_node_modules:/app/node_modules
- database_build:/app/build
# bind the local folder to the docker to allow live reload
- ./database:/app
#########################################################
## LOGIN SERVER #########################################
#########################################################
login-server:
build:
dockerfile: Dockerfiles/ubuntu/Dockerfile.debug
networks:
- external-net
- internal-net
security_opt:
- seccomp:unconfined
cap_add:
- SYS_PTRACE
volumes:
- ./logs:/var/log/grd_login
- ./login_server/src:/code/src
- ./login_server/dependencies:/code/dependencies
- ./login_server/scripts:/code/scripts
- ./configs/login_server:/etc/grd_login
- login_build_ubuntu_3.1:/code/build
#########################################################
## COMMUNITY SERVER (cakephp with php-fpm) ##############
#########################################################
community-server:
build:
context: .
target: community_server
dockerfile: ./community_server/Dockerfile
depends_on:
- mariadb
networks:
- internal-net
- external-net
volumes:
- ./community_server/config/php-fpm/php-ini-overrides.ini:/etc/php/7.4/fpm/conf.d/99-overrides.ini
- ./community_server/src:/var/www/cakephp/src
#########################################################
## MARIADB ##############################################
#########################################################
mariadb:
networks:
- internal-net
- external-net
#########################################################
## NGINX ################################################
#########################################################
nginx:
depends_on:
- frontend
- community-server
- login-server
volumes:
- ./logs/nginx:/var/log/nginx
#########################################################
## PHPMYADMIN ###########################################
#########################################################
phpmyadmin:
image: phpmyadmin
environment:
- PMA_ARBITRARY=1
#restart: always
ports:
- 8074:80
networks:
- internal-net
- external-net
volumes:
- /sessions
volumes:
frontend_node_modules:
admin_node_modules:
backend_node_modules:
backend_database_node_modules:
backend_database_build:
database_node_modules:
database_build:
login_build_ubuntu_3.1:

View File

@ -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

View File

@ -46,6 +46,7 @@
"change-password": "Fehler beim Ändern des Passworts",
"error": "Fehler",
"no-account": "Leider konnten wir keinen Account finden mit diesen Daten!",
"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": {
@ -180,9 +181,12 @@
"uppercase": "Ein Großbuchstabe erforderlich."
},
"thx": {
"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.",
"register": "Du bist jetzt registriert.",
"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!"
}

View File

@ -46,6 +46,7 @@
"change-password": "Error while changing password",
"error": "Error",
"no-account": "Unfortunately we could not find an account to the given data!",
"no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!",
"session-expired": "The session expired"
},
"form": {
@ -180,9 +181,12 @@
"uppercase": "One uppercase letter required."
},
"thx": {
"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.",
"register": "You are registred now.",
"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!"
}

View File

@ -47,7 +47,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']
if (!validFrom.includes(from.path.split('/')[1])) {
next({ path: '/login' })
} else {

View File

@ -104,9 +104,14 @@ export default {
this.$router.push('/overview')
loader.hide()
})
.catch(() => {
.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()
this.$toasted.error(this.$t('error.no-account'))
})
},
},

View File

@ -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'
import { getCommunityInfoMixin } from '../../mixins/getCommunityInfo'
export default {
@ -189,6 +190,9 @@ export default {
methods: {
updateLanguage(e) {
this.language = e
this.$store.commit('language', this.language)
this.$i18n.locale = this.language
localeChanged(this.language)
},
getValidationState({ dirty, validated, valid = null }) {
return dirty || validated ? valid : null

View File

@ -4,10 +4,12 @@
<div class="header py-7 py-lg-8 pt-lg-9">
<b-container>
<div class="header-body text-center mb-7">
<p class="h1">{{ $t('site.thx.title') }}</p>
<p class="h1">{{ $t(displaySetup.headline) }}</p>
<p class="h4">{{ $t(displaySetup.subtitle) }}</p>
<hr />
<b-button :to="displaySetup.linkTo">{{ $t(displaySetup.button) }}</b-button>
<b-button v-if="displaySetup.linkTo" :to="displaySetup.linkTo">
{{ $t(displaySetup.button) }}
</b-button>
</div>
</b-container>
</div>
@ -17,25 +19,33 @@
<script>
const textFields = {
password: {
headline: 'site.thx.title',
subtitle: 'site.thx.email',
button: 'login',
linkTo: '/login',
},
reset: {
headline: 'site.thx.title',
subtitle: 'site.thx.reset',
button: 'login',
linkTo: '/login',
},
register: {
headline: 'site.thx.title',
subtitle: 'site.thx.register',
button: 'site.login.signin',
linkTo: '/overview',
},
checkEmail: {
headline: 'site.thx.title',
subtitle: 'site.thx.checkEmail',
button: 'login',
linkTo: '/login',
},
login: {
headline: 'site.thx.errorTitle',
subtitle: 'site.thx.activateEmail',
},
}
export default {

View File

@ -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");