mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
Merge branch 'master' into humhub_export_user
This commit is contained in:
commit
a4ab5212c7
@ -4,8 +4,16 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [2.2.1](https://github.com/gradido/gradido/compare/2.2.0...2.2.1)
|
||||
|
||||
- fix(other): deployment bugfixes [`#3290`](https://github.com/gradido/gradido/pull/3290)
|
||||
|
||||
#### [2.2.0](https://github.com/gradido/gradido/compare/2.1.1...2.2.0)
|
||||
|
||||
> 9 February 2024
|
||||
|
||||
- chore(release): v2.2.0 [`#3283`](https://github.com/gradido/gradido/pull/3283)
|
||||
- fix(backend): prevent warning, fix env error [`#3282`](https://github.com/gradido/gradido/pull/3282)
|
||||
- feat(frontend): update news text [`#3279`](https://github.com/gradido/gradido/pull/3279)
|
||||
- feat(frontend): use params instead of query for send/identifier route [`#3277`](https://github.com/gradido/gradido/pull/3277)
|
||||
- fix(other): deployment bugfixes [`#3276`](https://github.com/gradido/gradido/pull/3276)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"description": "Administraion Interface for Gradido",
|
||||
"main": "index.js",
|
||||
"author": "Moriz Wahl",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"license": "Apache-2.0",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
|
||||
@ -7,7 +7,7 @@ module.exports = {
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 84,
|
||||
lines: 83,
|
||||
},
|
||||
},
|
||||
setupFiles: ['<rootDir>/test/testSetup.ts'],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido-backend",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Gradido unified backend providing an API-Service for Gradido Transactions",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/backend",
|
||||
|
||||
@ -117,30 +117,106 @@ export async function userByUuid(uuid: string): Promise<GmsUser[] | string | und
|
||||
*/
|
||||
|
||||
export async function createGmsUser(apiKey: string, user: GmsUser): Promise<boolean> {
|
||||
if (CONFIG.GMS_ACTIVE) {
|
||||
const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/')
|
||||
const service = 'community-user'
|
||||
const config = {
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
language: 'en',
|
||||
timezone: 'UTC',
|
||||
connection: 'keep-alive',
|
||||
authorization: apiKey,
|
||||
},
|
||||
}
|
||||
try {
|
||||
const result = await axios.post(baseUrl.concat(service), user, config)
|
||||
logger.debug('POST-Response of community-user:', result)
|
||||
if (result.status !== 200) {
|
||||
throw new LogError('HTTP Status Error in community-user:', result.status, result.statusText)
|
||||
}
|
||||
logger.debug('responseData:', result.data.responseData)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
// const gmsUser = JSON.parse(result.data.responseData)
|
||||
// logger.debug('gmsUser:', gmsUser)
|
||||
return true
|
||||
} catch (error: any) {
|
||||
logger.error('Error in post community-user:', error)
|
||||
throw new LogError(error.message)
|
||||
}
|
||||
} else {
|
||||
logger.info('GMS-Communication disabled per ConfigKey GMS_ACTIVE=false!')
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateGmsUser(apiKey: string, user: GmsUser): Promise<boolean> {
|
||||
if (CONFIG.GMS_ACTIVE) {
|
||||
const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/')
|
||||
const service = 'community-user'
|
||||
const config = {
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
language: 'en',
|
||||
timezone: 'UTC',
|
||||
connection: 'keep-alive',
|
||||
authorization: apiKey,
|
||||
},
|
||||
}
|
||||
try {
|
||||
const result = await axios.patch(baseUrl.concat(service), user, config)
|
||||
logger.debug('PATCH-Response of community-user:', result)
|
||||
if (result.status !== 200) {
|
||||
throw new LogError('HTTP Status Error in community-user:', result.status, result.statusText)
|
||||
}
|
||||
logger.debug('responseData:', result.data.responseData)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
// const gmsUser = JSON.parse(result.data.responseData)
|
||||
// logger.debug('gmsUser:', gmsUser)
|
||||
return true
|
||||
} catch (error: any) {
|
||||
logger.error('Error in patch community-user:', error)
|
||||
throw new LogError(error.message)
|
||||
}
|
||||
} else {
|
||||
logger.info('GMS-Communication disabled per ConfigKey GMS_ACTIVE=false!')
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function verifyAuthToken(
|
||||
// apiKey: string,
|
||||
communityUuid: string,
|
||||
token: string,
|
||||
): Promise<string> {
|
||||
const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/')
|
||||
const service = 'community-user'
|
||||
const service = 'verify-auth-token?token='.concat(token).concat('&uuid=').concat(communityUuid)
|
||||
const config = {
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
language: 'en',
|
||||
timezone: 'UTC',
|
||||
connection: 'keep-alive',
|
||||
authorization: apiKey,
|
||||
// authorization: apiKey,
|
||||
},
|
||||
}
|
||||
try {
|
||||
const result = await axios.post(baseUrl.concat(service), user, config)
|
||||
logger.debug('POST-Response of community-user:', result)
|
||||
const result = await axios.get(baseUrl.concat(service), config)
|
||||
logger.debug('GET-Response of verify-auth-token:', result)
|
||||
if (result.status !== 200) {
|
||||
throw new LogError('HTTP Status Error in community-user:', result.status, result.statusText)
|
||||
throw new LogError(
|
||||
'HTTP Status Error in verify-auth-token:',
|
||||
result.status,
|
||||
result.statusText,
|
||||
)
|
||||
}
|
||||
logger.debug('responseData:', result.data.responseData)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
// const gmsUser = JSON.parse(result.data.responseData)
|
||||
// logger.debug('gmsUser:', gmsUser)
|
||||
return true
|
||||
const token: string = result.data.responseData.token
|
||||
logger.debug('verifyAuthToken=', token)
|
||||
return token
|
||||
} catch (error: any) {
|
||||
logger.error('Error in Get community-user:', error)
|
||||
logger.error('Error in verifyAuthToken:', error)
|
||||
throw new LogError(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ export class GmsUser {
|
||||
constructor(user: dbUser) {
|
||||
this.userUuid = user.gradidoID
|
||||
// this.communityUuid = user.communityUuid
|
||||
this.language = user.language
|
||||
this.email = this.getGmsEmail(user)
|
||||
this.countryCode = this.getGmsCountryCode(user)
|
||||
this.mobile = this.getGmsPhone(user)
|
||||
|
||||
@ -37,6 +37,7 @@ export enum RIGHTS {
|
||||
LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES',
|
||||
OPEN_CREATIONS = 'OPEN_CREATIONS',
|
||||
USER = 'USER',
|
||||
GMS_USER_PLAYGROUND = 'GMS_USER_PLAYGROUND',
|
||||
// Moderator
|
||||
SEARCH_USERS = 'SEARCH_USERS',
|
||||
ADMIN_CREATE_CONTRIBUTION = 'ADMIN_CREATE_CONTRIBUTION',
|
||||
|
||||
@ -29,4 +29,5 @@ export const USER_RIGHTS = [
|
||||
RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES,
|
||||
RIGHTS.OPEN_CREATIONS,
|
||||
RIGHTS.USER,
|
||||
RIGHTS.GMS_USER_PLAYGROUND,
|
||||
]
|
||||
|
||||
@ -19,7 +19,11 @@ const constants = {
|
||||
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
|
||||
CONFIG_VERSION: {
|
||||
DEFAULT: 'DEFAULT',
|
||||
<<<<<<< HEAD
|
||||
EXPECTED: 'v22.2024-03-06',
|
||||
=======
|
||||
EXPECTED: 'v22.2024-03-14',
|
||||
>>>>>>> master
|
||||
CURRENT: '',
|
||||
},
|
||||
}
|
||||
@ -143,8 +147,11 @@ const federation = {
|
||||
|
||||
const gms = {
|
||||
GMS_ACTIVE: process.env.GMS_ACTIVE === 'true' || false,
|
||||
GMS_CREATE_USER_THROW_ERRORS: process.env.GMS_CREATE_USER_THROW_ERRORS === 'true' || false,
|
||||
// koordinates of Illuminz-instance of GMS
|
||||
GMS_URL: process.env.GMS_HOST ?? 'http://localhost:4044/',
|
||||
// used as secret postfix attached at the gms community-auth-url endpoint ('/hook/gms/' + 'secret')
|
||||
GMS_WEBHOOK_SECRET: process.env.GMS_WEBHOOK_SECRET ?? 'secret',
|
||||
}
|
||||
|
||||
const humhub = {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { IsBoolean, IsInt, IsString } from 'class-validator'
|
||||
import { IsBoolean, IsEnum, IsInt, IsString } from 'class-validator'
|
||||
import { ArgsType, Field, InputType, Int } from 'type-graphql'
|
||||
|
||||
import { GmsPublishLocationType } from '@enum/GmsPublishLocationType'
|
||||
import { GmsPublishNameType } from '@enum/GmsPublishNameType'
|
||||
import { Location } from '@model/Location'
|
||||
|
||||
import { isValidLocation } from '@/graphql/validator/Location'
|
||||
@ -44,19 +46,19 @@ export class UpdateUserInfosArgs {
|
||||
@IsBoolean()
|
||||
hideAmountGDT?: boolean
|
||||
|
||||
@Field({ nullable: true, defaultValue: true })
|
||||
@Field({ nullable: true })
|
||||
@IsBoolean()
|
||||
gmsAllowed?: boolean
|
||||
|
||||
@Field(() => Int, { nullable: true, defaultValue: 0 })
|
||||
@IsInt()
|
||||
gmsPublishName?: number | null
|
||||
@Field(() => GmsPublishNameType, { nullable: true })
|
||||
@IsEnum(GmsPublishNameType)
|
||||
gmsPublishName?: GmsPublishNameType | null
|
||||
|
||||
@Field(() => Location, { nullable: true })
|
||||
@isValidLocation()
|
||||
gmsLocation?: Location | null
|
||||
|
||||
@Field(() => Int, { nullable: true, defaultValue: 2 })
|
||||
@IsInt()
|
||||
gmsPublishLocation?: number | null
|
||||
@Field(() => GmsPublishLocationType, { nullable: true })
|
||||
@IsEnum(GmsPublishLocationType)
|
||||
gmsPublishLocation?: GmsPublishLocationType | null
|
||||
}
|
||||
|
||||
10
backend/src/graphql/model/GmsUserAuthenticationResult.ts
Normal file
10
backend/src/graphql/model/GmsUserAuthenticationResult.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class GmsUserAuthenticationResult {
|
||||
@Field(() => String)
|
||||
url: string
|
||||
|
||||
@Field(() => String)
|
||||
token: string
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
import { User as dbUser } from '@entity/User'
|
||||
import { ObjectType, Field, Int } from 'type-graphql'
|
||||
|
||||
import { GmsPublishLocationType } from '@enum/GmsPublishLocationType'
|
||||
import { GmsPublishNameType } from '@enum/GmsPublishNameType'
|
||||
|
||||
import { KlickTipp } from './KlickTipp'
|
||||
|
||||
@ObjectType()
|
||||
@ -29,6 +32,9 @@ export class User {
|
||||
this.hasElopage = null
|
||||
this.hideAmountGDD = user.hideAmountGDD
|
||||
this.hideAmountGDT = user.hideAmountGDT
|
||||
this.gmsAllowed = user.gmsAllowed
|
||||
this.gmsPublishName = user.gmsPublishName
|
||||
this.gmsPublishLocation = user.gmsPublishLocation
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +80,15 @@ export class User {
|
||||
@Field(() => Boolean)
|
||||
hideAmountGDT: boolean
|
||||
|
||||
@Field(() => Boolean)
|
||||
gmsAllowed: boolean
|
||||
|
||||
@Field(() => GmsPublishNameType, { nullable: true })
|
||||
gmsPublishName: GmsPublishNameType | null
|
||||
|
||||
@Field(() => GmsPublishLocationType, { nullable: true })
|
||||
gmsPublishLocation: GmsPublishLocationType | null
|
||||
|
||||
// This is not the users publisherId, but the one of the users who recommend him
|
||||
@Field(() => Int, { nullable: true })
|
||||
publisherId: number | null
|
||||
|
||||
@ -15,8 +15,6 @@ import { ApolloServerTestClient } from 'apollo-server-testing'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import { GmsPublishLocationType } from '@enum/GmsPublishLocationType'
|
||||
import { GmsPublishNameType } from '@enum/GmsPublishNameType'
|
||||
import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
import { logger } from '@test/testSetup'
|
||||
|
||||
@ -530,13 +528,12 @@ describe('send coins', () => {
|
||||
|
||||
describe('send coins via alias', () => {
|
||||
beforeAll(async () => {
|
||||
// first set alias to null, because updating alias isn't allowed
|
||||
await User.update({ alias: 'MeisterBob' }, { alias: () => 'NULL' })
|
||||
await mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
alias: 'bob',
|
||||
gmsAllowed: true,
|
||||
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
|
||||
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
|
||||
@ -1258,6 +1258,8 @@ describe('UserResolver', () => {
|
||||
|
||||
describe('valid alias', () => {
|
||||
it('updates the user in DB', async () => {
|
||||
// first empty alias, because currently updating alias isn't allowed
|
||||
await User.update({ alias: 'BBB' }, { alias: () => 'NULL' })
|
||||
await mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
@ -1303,8 +1305,10 @@ describe('UserResolver', () => {
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
gmsAllowed: false,
|
||||
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL,
|
||||
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_APPROXIMATE,
|
||||
gmsPublishName:
|
||||
GmsPublishNameType[GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL],
|
||||
gmsPublishLocation:
|
||||
GmsPublishLocationType[GmsPublishLocationType.GMS_LOCATION_TYPE_APPROXIMATE],
|
||||
},
|
||||
})
|
||||
await expect(User.find()).resolves.toEqual([
|
||||
@ -1326,9 +1330,11 @@ describe('UserResolver', () => {
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
gmsAllowed: true,
|
||||
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
|
||||
gmsPublishName:
|
||||
GmsPublishNameType[GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS],
|
||||
gmsLocation: loc,
|
||||
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
|
||||
gmsPublishLocation:
|
||||
GmsPublishLocationType[GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM],
|
||||
},
|
||||
})
|
||||
await expect(User.find()).resolves.toEqual([
|
||||
@ -2670,13 +2676,12 @@ describe('UserResolver', () => {
|
||||
mutation: login,
|
||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||
})
|
||||
// first set alias to null, because updating alias isn't currently allowed
|
||||
await User.update({ alias: 'BBB' }, { alias: () => 'NULL' })
|
||||
await mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
alias: 'bibi',
|
||||
gmsAllowed: true,
|
||||
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
|
||||
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@ -19,17 +19,18 @@ import { SearchUsersFilters } from '@arg/SearchUsersFilters'
|
||||
import { SetUserRoleArgs } from '@arg/SetUserRoleArgs'
|
||||
import { UnsecureLoginArgs } from '@arg/UnsecureLoginArgs'
|
||||
import { UpdateUserInfosArgs } from '@arg/UpdateUserInfosArgs'
|
||||
import { GmsPublishLocationType } from '@enum/GmsPublishLocationType'
|
||||
import { GmsPublishNameType } from '@enum/GmsPublishNameType'
|
||||
import { OptInType } from '@enum/OptInType'
|
||||
import { Order } from '@enum/Order'
|
||||
import { PasswordEncryptionType } from '@enum/PasswordEncryptionType'
|
||||
import { UserContactType } from '@enum/UserContactType'
|
||||
import { SearchAdminUsersResult } from '@model/AdminUser'
|
||||
// import { Location } from '@model/Location'
|
||||
import { GmsUserAuthenticationResult } from '@model/GmsUserAuthenticationResult'
|
||||
import { User } from '@model/User'
|
||||
import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
|
||||
|
||||
import { updateGmsUser } from '@/apis/gms/GmsClient'
|
||||
import { GmsUser } from '@/apis/gms/model/GmsUser'
|
||||
import { subscribe } from '@/apis/KlicktippController'
|
||||
import { encode } from '@/auth/JWT'
|
||||
import { RIGHTS } from '@/auth/RIGHTS'
|
||||
@ -68,7 +69,9 @@ import random from 'random-bigint'
|
||||
import { randombytes_random } from 'sodium-native'
|
||||
|
||||
import { FULL_CREATION_AVAILABLE } from './const/const'
|
||||
import { authenticateGmsUserPlayground } from './util/authenticateGmsUserPlayground'
|
||||
import { getHomeCommunity } from './util/communities'
|
||||
import { compareGmsRelevantUserSettings } from './util/compareGmsRelevantUserSettings'
|
||||
import { getUserCreations } from './util/creations'
|
||||
import { findUserByIdentifier } from './util/findUserByIdentifier'
|
||||
import { findUsers } from './util/findUsers'
|
||||
@ -375,7 +378,11 @@ export class UserResolver {
|
||||
await sendUserToGms(dbUser, homeCom)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Error publishing new created user to GMS:', err)
|
||||
if (CONFIG.GMS_CREATE_USER_THROW_ERRORS) {
|
||||
throw new LogError('Error publishing new created user to GMS:', err)
|
||||
} else {
|
||||
logger.error('Error publishing new created user to GMS:', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return new User(dbUser)
|
||||
@ -395,7 +402,6 @@ export class UserResolver {
|
||||
logger.warn(`no user found with ${email}`)
|
||||
return true
|
||||
}
|
||||
|
||||
if (!canEmailResend(user.emailContact.updatedAt || user.emailContact.createdAt)) {
|
||||
throw new LogError(
|
||||
`Email already sent less than ${printTimeDuration(CONFIG.EMAIL_CODE_REQUEST_TIME)} ago`,
|
||||
@ -541,8 +547,10 @@ export class UserResolver {
|
||||
@Authorized([RIGHTS.UPDATE_USER_INFOS])
|
||||
@Mutation(() => Boolean)
|
||||
async updateUserInfos(
|
||||
@Args()
|
||||
{
|
||||
@Args() updateUserInfosArgs: UpdateUserInfosArgs,
|
||||
@Ctx() context: Context,
|
||||
): Promise<boolean> {
|
||||
const {
|
||||
firstName,
|
||||
lastName,
|
||||
alias,
|
||||
@ -555,24 +563,13 @@ export class UserResolver {
|
||||
gmsPublishName,
|
||||
gmsLocation,
|
||||
gmsPublishLocation,
|
||||
}: UpdateUserInfosArgs,
|
||||
@Ctx() context: Context,
|
||||
): Promise<boolean> {
|
||||
} = updateUserInfosArgs
|
||||
logger.info(
|
||||
`updateUserInfos(${firstName}, ${lastName}, ${alias}, ${language}, ***, ***, ${hideAmountGDD}, ${hideAmountGDT}, ${gmsAllowed}, ${gmsPublishName}, ${gmsLocation}, ${gmsPublishLocation})...`,
|
||||
)
|
||||
// check default arg settings
|
||||
if (gmsAllowed === null || gmsAllowed === undefined) {
|
||||
gmsAllowed = true
|
||||
}
|
||||
if (!gmsPublishName) {
|
||||
gmsPublishName = GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS
|
||||
}
|
||||
if (!gmsPublishLocation) {
|
||||
gmsPublishLocation = GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM
|
||||
}
|
||||
|
||||
const user = getUser(context)
|
||||
const updateUserInGMS = compareGmsRelevantUserSettings(user, updateUserInfosArgs)
|
||||
|
||||
// try {
|
||||
if (firstName) {
|
||||
user.firstName = firstName
|
||||
@ -582,7 +579,8 @@ export class UserResolver {
|
||||
user.lastName = lastName
|
||||
}
|
||||
|
||||
if (alias && (await validateAlias(alias))) {
|
||||
// currently alias can only be set, not updated
|
||||
if (alias && !user.alias && (await validateAlias(alias))) {
|
||||
user.alias = alias
|
||||
}
|
||||
|
||||
@ -619,13 +617,18 @@ export class UserResolver {
|
||||
if (hideAmountGDT !== undefined) {
|
||||
user.hideAmountGDT = hideAmountGDT
|
||||
}
|
||||
|
||||
user.gmsAllowed = gmsAllowed
|
||||
user.gmsPublishName = gmsPublishName
|
||||
if (gmsAllowed !== undefined) {
|
||||
user.gmsAllowed = gmsAllowed
|
||||
}
|
||||
if (gmsPublishName !== null && gmsPublishName !== undefined) {
|
||||
user.gmsPublishName = gmsPublishName
|
||||
}
|
||||
if (gmsLocation) {
|
||||
user.location = Location2Point(gmsLocation)
|
||||
}
|
||||
user.gmsPublishLocation = gmsPublishLocation
|
||||
if (gmsPublishLocation !== null && gmsPublishLocation !== undefined) {
|
||||
user.gmsPublishLocation = gmsPublishLocation
|
||||
}
|
||||
// } catch (err) {
|
||||
// console.log('error:', err)
|
||||
// }
|
||||
@ -649,6 +652,17 @@ export class UserResolver {
|
||||
logger.info('updateUserInfos() successfully finished...')
|
||||
await EVENT_USER_INFO_UPDATE(user)
|
||||
|
||||
// validate if user settings are changed with relevance to update gms-user
|
||||
if (CONFIG.GMS_ACTIVE && updateUserInGMS) {
|
||||
logger.debug(`changed user-settings relevant for gms-user update...`)
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (homeCom.gmsApiKey !== null) {
|
||||
logger.debug(`gms-user update...`, user)
|
||||
await updateGmsUser(homeCom.gmsApiKey, new GmsUser(user))
|
||||
logger.debug(`gms-user update successfully.`)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -662,6 +676,21 @@ export class UserResolver {
|
||||
return elopageBuys
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.GMS_USER_PLAYGROUND])
|
||||
@Query(() => GmsUserAuthenticationResult)
|
||||
async authenticateGmsUserSearch(@Ctx() context: Context): Promise<GmsUserAuthenticationResult> {
|
||||
logger.info(`authUserForGmsUserSearch()...`)
|
||||
const dbUser = getUser(context)
|
||||
let result: GmsUserAuthenticationResult
|
||||
if (context.token) {
|
||||
result = await authenticateGmsUserPlayground(context.token, dbUser)
|
||||
logger.info('authUserForGmsUserSearch=', result)
|
||||
} else {
|
||||
throw new LogError('authUserForGmsUserSearch without token')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.SEARCH_ADMIN_USERS])
|
||||
@Query(() => SearchAdminUsersResult)
|
||||
async searchAdminUsers(
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { verifyAuthToken } from '@/apis/gms/GmsClient'
|
||||
import { CONFIG } from '@/config'
|
||||
import { GmsUserAuthenticationResult } from '@/graphql/model/GmsUserAuthenticationResult'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
export async function authenticateGmsUserPlayground(
|
||||
token: string,
|
||||
dbUser: DbUser,
|
||||
): Promise<GmsUserAuthenticationResult> {
|
||||
const result = new GmsUserAuthenticationResult()
|
||||
result.url = CONFIG.GMS_URL.concat('/playground')
|
||||
result.token = await verifyAuthToken(dbUser.communityUuid, token)
|
||||
logger.info('GmsUserAuthenticationResult:', result)
|
||||
return result
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
import { Point } from '@dbTools/typeorm'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { UpdateUserInfosArgs } from '@/graphql/arg/UpdateUserInfosArgs'
|
||||
import { GmsPublishNameType } from '@/graphql/enum/GmsPublishNameType'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
import { Point2Location } from './Location2Point'
|
||||
|
||||
export function compareGmsRelevantUserSettings(
|
||||
orgUser: DbUser,
|
||||
updateUserInfosArgs: UpdateUserInfosArgs,
|
||||
): boolean {
|
||||
if (!orgUser) {
|
||||
throw new LogError('comparison without any user is impossible')
|
||||
}
|
||||
logger.debug('compareGmsRelevantUserSettings:', orgUser, updateUserInfosArgs)
|
||||
// nach GMS updaten, wenn alias gesetzt wird oder ist und PublishLevel die alias-Übermittlung erlaubt
|
||||
if (
|
||||
updateUserInfosArgs.alias &&
|
||||
orgUser.alias !== updateUserInfosArgs.alias &&
|
||||
((updateUserInfosArgs.gmsPublishName &&
|
||||
updateUserInfosArgs.gmsPublishName.valueOf ===
|
||||
GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS.valueOf) ||
|
||||
(!updateUserInfosArgs.gmsPublishName &&
|
||||
orgUser.gmsPublishName &&
|
||||
orgUser.gmsPublishName.valueOf ===
|
||||
GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS.valueOf))
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
(updateUserInfosArgs.firstName && orgUser.firstName !== updateUserInfosArgs.firstName) ||
|
||||
(updateUserInfosArgs.lastName && orgUser.lastName !== updateUserInfosArgs.lastName)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
updateUserInfosArgs.gmsAllowed !== undefined &&
|
||||
updateUserInfosArgs.gmsAllowed &&
|
||||
orgUser.gmsAllowed !== updateUserInfosArgs.gmsAllowed
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
updateUserInfosArgs.gmsPublishLocation &&
|
||||
orgUser.gmsPublishLocation !== updateUserInfosArgs.gmsPublishLocation
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
updateUserInfosArgs.gmsPublishName &&
|
||||
orgUser.gmsPublishName !== updateUserInfosArgs.gmsPublishName
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (updateUserInfosArgs.language && orgUser.language !== updateUserInfosArgs.language) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
updateUserInfosArgs.gmsLocation &&
|
||||
orgUser.location === null &&
|
||||
updateUserInfosArgs.gmsLocation !== null
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
updateUserInfosArgs.gmsLocation &&
|
||||
orgUser.location !== null &&
|
||||
updateUserInfosArgs.gmsLocation === null
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
updateUserInfosArgs.gmsLocation &&
|
||||
orgUser.location !== null &&
|
||||
updateUserInfosArgs.gmsLocation !== null
|
||||
) {
|
||||
const orgLocation = Point2Location(orgUser.location as Point)
|
||||
const changedLocation = updateUserInfosArgs.gmsLocation
|
||||
if (
|
||||
orgLocation.latitude !== changedLocation.latitude ||
|
||||
orgLocation.longitude !== changedLocation.longitude
|
||||
) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -3,6 +3,7 @@ import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { createGmsUser } from '@/apis/gms/GmsClient'
|
||||
import { GmsUser } from '@/apis/gms/model/GmsUser'
|
||||
import { CONFIG } from '@/config'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
@ -22,6 +23,10 @@ export async function sendUserToGms(user: DbUser, homeCom: DbCommunity): Promise
|
||||
logger.debug('mark user as gms published:', user)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn('publishing user fails with ', err)
|
||||
if (CONFIG.GMS_CREATE_USER_THROW_ERRORS) {
|
||||
throw new LogError('publishing user fails with ', err)
|
||||
} else {
|
||||
logger.warn('publishing user fails with ', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,8 +39,12 @@ export const userFactory = async (
|
||||
dbUser = await User.findOneOrFail({ where: { id }, relations: ['userRoles'] })
|
||||
|
||||
if (user.createdAt || user.deletedAt || user.role) {
|
||||
if (user.createdAt) dbUser.createdAt = user.createdAt
|
||||
if (user.deletedAt) dbUser.deletedAt = user.deletedAt
|
||||
if (user.createdAt) {
|
||||
dbUser.createdAt = user.createdAt
|
||||
}
|
||||
if (user.deletedAt) {
|
||||
dbUser.deletedAt = user.deletedAt
|
||||
}
|
||||
if (user.role && (user.role === RoleNames.ADMIN || user.role === RoleNames.MODERATOR)) {
|
||||
await setUserRole(dbUser, user.role)
|
||||
}
|
||||
|
||||
@ -35,9 +35,9 @@ export const updateUserInfos = gql`
|
||||
$hideAmountGDD: Boolean
|
||||
$hideAmountGDT: Boolean
|
||||
$gmsAllowed: Boolean
|
||||
$gmsPublishName: Int
|
||||
$gmsPublishName: GmsPublishNameType
|
||||
$gmsLocation: Location
|
||||
$gmsPublishLocation: Int
|
||||
$gmsPublishLocation: GmsPublishLocationType
|
||||
) {
|
||||
updateUserInfos(
|
||||
firstName: $firstName
|
||||
|
||||
@ -15,6 +15,14 @@ export const verifyLogin = gql`
|
||||
}
|
||||
}
|
||||
`
|
||||
export const authenticateGmsUserSearch = gql`
|
||||
query {
|
||||
authenticateGmsUserSearch {
|
||||
url
|
||||
token
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const queryOptIn = gql`
|
||||
query ($optIn: String!) {
|
||||
|
||||
@ -13,6 +13,7 @@ import { schema } from '@/graphql/schema'
|
||||
import { Connection } from '@/typeorm/connection'
|
||||
import { checkDBVersion } from '@/typeorm/DBVersion'
|
||||
import { elopageWebhook } from '@/webhook/elopage'
|
||||
import { gmsWebhook } from '@/webhook/gms'
|
||||
|
||||
import { context as serverContext } from './context'
|
||||
import { cors } from './cors'
|
||||
@ -94,6 +95,10 @@ export const createServer = async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
app.post('/hook/elopage/' + CONFIG.WEBHOOK_ELOPAGE_SECRET, elopageWebhook)
|
||||
|
||||
// GMS Webhook
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
app.get('/hook/gms/' + CONFIG.GMS_WEBHOOK_SECRET, gmsWebhook)
|
||||
|
||||
// Apollo Server
|
||||
const apollo = new ApolloServer({
|
||||
schema: await schema(),
|
||||
|
||||
@ -37,6 +37,7 @@ const logPlugin = {
|
||||
const { logger } = requestContext
|
||||
const { query, mutation, variables, operationName } = requestContext.request
|
||||
if (operationName !== 'IntrospectionQuery') {
|
||||
logger.debug('requestDidStart:', requestContext)
|
||||
logger.info(`Request:
|
||||
${mutation || query}variables: ${JSON.stringify(filterVariables(variables), null, 2)}`)
|
||||
}
|
||||
|
||||
36
backend/src/webhook/gms.ts
Normal file
36
backend/src/webhook/gms.ts
Normal file
@ -0,0 +1,36 @@
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { decode } from '@/auth/JWT'
|
||||
|
||||
export const gmsWebhook = async (req: any, res: any): Promise<void> => {
|
||||
console.log('GMS Hook received', req.query)
|
||||
const { token } = req.query
|
||||
|
||||
if (!token) {
|
||||
console.log('gmsWebhook: missing token')
|
||||
res.status(400).json({ message: 'false' })
|
||||
return
|
||||
}
|
||||
const payload = await decode(token)
|
||||
console.log('gmsWebhook: decoded token=', payload)
|
||||
if (!payload) {
|
||||
console.log('gmsWebhook: invalid token')
|
||||
res.status(400).json({ message: 'false' })
|
||||
return
|
||||
}
|
||||
const user = await DbUser.findOne({ where: { gradidoID: payload.gradidoID } })
|
||||
if (!user) {
|
||||
console.log('gmsWebhook: missing user')
|
||||
res.status(400).json({ message: 'false' })
|
||||
return
|
||||
}
|
||||
console.log('gmsWebhook: authenticate user=', user.gradidoID, user.firstName, user.lastName)
|
||||
console.log('gmsWebhook: authentication successful')
|
||||
res.status(200).json({ userUuid: user.gradidoID })
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido-database",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Gradido Database Tool to execute database migrations",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/database",
|
||||
|
||||
@ -26,7 +26,7 @@ EMAIL_CODE_REQUEST_TIME=10
|
||||
# config versions
|
||||
DATABASE_CONFIG_VERSION=v1.2022-03-18
|
||||
BACKEND_CONFIG_VERSION=v21.2024-01-06
|
||||
FRONTEND_CONFIG_VERSION=v5.2024-01-08
|
||||
FRONTEND_CONFIG_VERSION=v6.2024-02-27
|
||||
ADMIN_CONFIG_VERSION=v2.2024-01-04
|
||||
FEDERATION_CONFIG_VERSION=v2.2023-08-24
|
||||
FEDERATION_DHT_CONFIG_VERSION=v4.2024-01-17
|
||||
@ -120,12 +120,13 @@ DEFAULT_PUBLISHER_ID=2896
|
||||
WEBHOOK_ELOPAGE_SECRET=secret
|
||||
|
||||
# GMS
|
||||
#GMS_ACTIVE=true
|
||||
GMS_ACTIVE=false
|
||||
# Coordinates of Illuminz test instance
|
||||
#GMS_URL=http://54.176.169.179:3071
|
||||
#GMS_URL=http://localhost:4044/
|
||||
GMS_URL=http://localhost:4044/
|
||||
|
||||
# HUMHUB
|
||||
HUMHUB_ACTIVE=false
|
||||
#HUMHUB_API_URL=https://community.gradido.net
|
||||
#HUMHUB_JWT_KEY=
|
||||
#HUMHUB_JWT_KEY=
|
||||
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
# Migration
|
||||
[Migration from 2.2.0 to 2.2.1](migration/2_2_0-2_2_1/README.md)
|
||||
|
||||
# Setup on Hetzner Cloud Server
|
||||
Suggested OS:
|
||||
Debian 12
|
||||
|
||||
@ -144,7 +144,13 @@ cp $SCRIPT_PATH/logrotate/gradido.conf /etc/logrotate.d/gradido.conf
|
||||
export DB_USER=gradido
|
||||
# create a new password only if it not already exist
|
||||
if [ -z "${DB_PASSWORD}" ]; then
|
||||
export DB_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
|
||||
export DB_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32; echo);
|
||||
fi
|
||||
|
||||
# Check if DB_PASSWORD is still empty, then exit with an error
|
||||
if [ -z "${DB_PASSWORD}" ]; then
|
||||
echo "Error: Failed to generate DB_PASSWORD."
|
||||
exit 1
|
||||
fi
|
||||
mysql <<EOFMYSQL
|
||||
CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
|
||||
@ -156,7 +162,7 @@ EOFMYSQL
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/database/.env.template > $PROJECT_ROOT/database/.env
|
||||
|
||||
# Configure backend
|
||||
export JWT_SECRET=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
|
||||
export JWT_SECRET=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32; echo);
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/backend/.env.template > $PROJECT_ROOT/backend/.env
|
||||
|
||||
# Configure frontend
|
||||
@ -166,7 +172,7 @@ envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/frontend/.env
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/admin/.env.template > $PROJECT_ROOT/admin/.env
|
||||
|
||||
# Configure dht-node
|
||||
export FEDERATION_DHT_SEED=$(< /dev/urandom tr -dc a-f0-9 | head -c 32;echo);
|
||||
export FEDERATION_DHT_SEED=$(< /dev/urandom tr -dc a-f0-9 | head -c 32; echo);
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/dht-node/.env.template > $PROJECT_ROOT/dht-node/.env
|
||||
|
||||
# Configure federation
|
||||
@ -180,4 +186,4 @@ sudo -u gradido crontab < $LOCAL_SCRIPT_DIR/crontabs.txt
|
||||
|
||||
# Start gradido
|
||||
# Note: on first startup some errors will occur - nothing serious
|
||||
sudo -u gradido $SCRIPT_PATH/start.sh
|
||||
sudo -u gradido $SCRIPT_PATH/start.sh $1
|
||||
18
deployment/hetzner_cloud/migration/2_2_0-2_2_1/README.md
Normal file
18
deployment/hetzner_cloud/migration/2_2_0-2_2_1/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
## Migrate from Gradido Version 2.2.0 to 2.2.1
|
||||
### What was wrong
|
||||
In [hetzner_cloud/install.sh](../../install.sh) there was an error.
|
||||
$DB_PASSWORD and $JWT_SECRET password generation method don't work with `release-2_2_0` as parameter for install.sh
|
||||
|
||||
The Parameter forwarding from branch, `release-2_2_0` in this case to start.sh was also missing.
|
||||
|
||||
### What you can do now
|
||||
You need to only run this [fixInstall.sh](fixInstall.sh) with `release_2_2_1` as parameter
|
||||
```bash
|
||||
cd /home/gradido/gradido/deployment/hetzner_cloud/migration/2_2_0-2_2_1
|
||||
sudo ./fixInstall.sh `release_2_2_1`
|
||||
```
|
||||
|
||||
Basically it will create a new $DB_PASSWORD, $JWT_SECRET and $FEDERATION_DHT_SEED,
|
||||
update db user with new db password and update .env files in module folders.
|
||||
Then it will call start.sh with first parameter if ./fixInstall.sh as his first parameter
|
||||
|
||||
66
deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh
Executable file
66
deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh
Executable file
@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
# check for parameter
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: Please provide a branch name as the first argument."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -o allexport
|
||||
SCRIPT_PATH=$(realpath ../../../bare_metal)
|
||||
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
|
||||
LOCAL_SCRIPT_PATH=$(realpath $0)
|
||||
LOCAL_SCRIPT_DIR=$(dirname $LOCAL_SCRIPT_PATH)
|
||||
PROJECT_ROOT=$SCRIPT_DIR/..
|
||||
set +o allexport
|
||||
|
||||
|
||||
# Load .env or .env.dist if not present
|
||||
# NOTE: all config values will be in process.env when starting
|
||||
# the services and will therefore take precedence over the .env
|
||||
if [ -f "$SCRIPT_PATH/.env" ]; then
|
||||
set -o allexport
|
||||
source $SCRIPT_PATH/.env
|
||||
set +o allexport
|
||||
else
|
||||
set -o allexport
|
||||
source $SCRIPT_PATH/.env.dist
|
||||
set +o allexport
|
||||
fi
|
||||
|
||||
# create db user
|
||||
export DB_USER=gradido
|
||||
# create a new password only if it not already exist
|
||||
export DB_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32; echo);
|
||||
|
||||
|
||||
mysql <<EOFMYSQL
|
||||
ALTER USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
|
||||
FLUSH PRIVILEGES;
|
||||
EOFMYSQL
|
||||
|
||||
# Configure database
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/database/.env.template > $PROJECT_ROOT/database/.env
|
||||
|
||||
# Configure backend
|
||||
export JWT_SECRET=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32; echo);
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/backend/.env.template > $PROJECT_ROOT/backend/.env
|
||||
|
||||
# Configure frontend
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/frontend/.env.template > $PROJECT_ROOT/frontend/.env
|
||||
|
||||
# Configure admin
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/admin/.env.template > $PROJECT_ROOT/admin/.env
|
||||
|
||||
# Configure dht-node
|
||||
export FEDERATION_DHT_SEED=$(< /dev/urandom tr -dc a-f0-9 | head -c 32; echo);
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/dht-node/.env.template > $PROJECT_ROOT/dht-node/.env
|
||||
|
||||
# Configure federation
|
||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/federation/.env.template > $PROJECT_ROOT/federation/.env
|
||||
|
||||
# set all created or modified files back to belonging to gradido
|
||||
chown -R gradido:gradido $PROJECT_ROOT
|
||||
|
||||
# Start gradido
|
||||
# Note: on first startup some errors will occur - nothing serious
|
||||
sudo -u gradido $SCRIPT_PATH/start.sh $1
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido-dht-node",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Gradido dht-node module",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido-dlt-connector",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Gradido DLT-Connector",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/",
|
||||
|
||||
@ -275,28 +275,45 @@ It contains a map-component of the leaflet library and offers to capture the use
|
||||
|
||||
There is no user-specific authentication nor autorization necessary for this dialog as mentioned above.
|
||||
|
||||
### GMS user playground dialog (gms efforts)
|
||||
### GMS user playground dialog
|
||||
|
||||
As described in the chapter "User search" above, we need a dialog in GMS to display in a graphical map:
|
||||
|
||||
* the location of the user as a red needle, who opens the user search-dialog
|
||||
* the location of his community as a circle, the invoker belongs to
|
||||
* the locations of all other users as white needles, belonging to the same community
|
||||
* the locations of all other users belonging to the same community as white/gray or black needles - depending on the location-type of the user
|
||||
* circles and needles of all other communities and users, which are nearby the requesting user and community location
|
||||
|
||||
There is no user-specific authentication nor autorization necessary for this dialog as mentioned above.
|
||||
On activation of the menu-entry _user-search_ a technical flow in the background have to prepare the connection between the gradido-system and the gms-component. The following list will describe the necessary steps of all involved components:
|
||||
|
||||
Which (filter-)components this playground-dialog should have next to the graphical location map is not clear at the moment. In the first run to display the above mentioned locations of users and communities with circles and needles will be sufficient.
|
||||
* **gradido-frontend:** user press the menu entry _user search_
|
||||
* **(1.a) gradido-frontend:** invokes the gradido-backend `authUserForGmsUserSearch`
|
||||
* **(1.b) gradido-backend:** the method `authUserForGmsUserSearch` reads the context-user of the current request and the uuid of the user's home-community. With these values it prepares the parameters for invokation of the `gms.verifyAuthToken` method. The first parameter is set by the `community-uuid` and the second parameter is a JWT-token with the encrypted `user-uuid` in the payload and signed by the community's privateKey
|
||||
* **(2.a) gradido-backend:** invokes the `gms.verifyAuthToken` with community-uuid as 1st parameter and JWT-Token as 2nd parameter
|
||||
* **(2.b) gms-backend:** recieving the request `verifyAuthToken` with the community-uuid and the JWT-token. After searching and verifing the given community-uuid exists in gms, it prepares the invokation of the configured endpoint `community-Auth-Url` of this community by sending the given JWT-token as parameter back to gradido.
|
||||
* **(3.a) gms-backend:** invokes the endpoint configured in `gms.community-auth-url` with the previous received JWT-token
|
||||
* **(3.b) gradido-backend:** receives the request at the endpoint "communityAuthUrl" with the previously sent JWT-token. The JWT-token will be verified if the signature is valid and afterwards the payload is decrypted to verify the contained user-data will match with the current context-user of request (1).
|
||||
* **(4.a) gradido-backend:** in case of valid JWT-token signature and valid payload data the gradido-backend returns TRUE as result of the authentication-request otherwise FALSE.
|
||||
* **(4.b) gms-backend:** receives the response of request (3) and in case of TRUE the gms-backend prepares to return a complete URI including a _JWT-access-token_ to be used for entering the user-playground. *It will not return gms-data used for the user-playground as the current implementation of the api `verify-auth-token` do.* In case of FALSE prepare returning an authentication-error.
|
||||
* **(5.a) gms-backend:** returning the complete URI including a _JWT-access-token_ as response of request (2) or an authentication-error
|
||||
* **(5.b) gradido-backend:** receiving as response of request (2) a complete URI including a _JWT-access-token_ for entering the users-playground on gms or an authentication-error
|
||||
* **(6.a) gradido-backend:** returning the complete URI including a _JWT-access-token_ as response of request (1) or an expressive error message
|
||||
* **(6.b) gradido-frontend:** receiving the complete URI including a _JWT-access-token_ after activation of menu-entry "user-search" or an expressive error-message, which will end the _user search_-flow without requesting the gms-frontend (7).
|
||||
* **(7.a) gradido-frontend:** on opening a new browser-window the gradido-frontend uses the received URI with the _JWT-access-token_ to enter the gms user-playground
|
||||
* **(7.b) gms-frontend:** receiving the request for the user-playground with an _JWT-access-token_. After verifying the access-token the gms-frontend will read the data for the user given by the access-token and loads all necessary data to render the users playground
|
||||
|
||||
The detailed requirements will come up as soon as we get some user expiriences and feedbacks.
|
||||
The following picture shows the logical flow and interaction between the involved components:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
The detailed requirements for the playground-dialog will come up as soon as we get some user expiriences and feedbacks.
|
||||
|
||||
### GMS Offer Capture dialog (gms efforts)
|
||||
|
||||
will come later...
|
||||
|
||||
|
||||
|
||||
### GMS Need Capture dialog (gms efforts)
|
||||
|
||||
will come later...
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 42 KiB |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido-federation",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Gradido federation module providing Gradido-Hub-Federation and versioned API for inter community communication",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/federation",
|
||||
|
||||
@ -21,3 +21,5 @@ META_DESCRIPTION_EN="Gratitude is the currency of the new age. More and more peo
|
||||
META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natürliche Ökonomie des Lebens, Ökonomie, Ökologie, Potenzialentfaltung, Schenken und Danken, Kreislauf des Lebens, Geldsystem"
|
||||
META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System"
|
||||
META_AUTHOR="Bernd Hückstädt - Gradido-Akademie"
|
||||
|
||||
GMS_ACTIVE=false
|
||||
|
||||
@ -24,3 +24,5 @@ META_DESCRIPTION_EN=$META_DESCRIPTION_EN
|
||||
META_KEYWORDS_DE=$META_KEYWORDS_DE
|
||||
META_KEYWORDS_EN=$META_KEYWORDS_EN
|
||||
META_AUTHOR=$META_AUTHOR
|
||||
|
||||
GMS_ACTIVE=$GMS_ACTIVE
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bootstrap-vue-gradido-wallet",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node run/server.js",
|
||||
|
||||
@ -71,4 +71,16 @@ export default {
|
||||
.text-color-gdd-yellow {
|
||||
color: rgb(197 141 56);
|
||||
}
|
||||
|
||||
.dropdown > .dropdown-toggle {
|
||||
border-radius: 17px;
|
||||
height: 50px;
|
||||
text-align: left;
|
||||
}
|
||||
.dropdown-toggle::after {
|
||||
float: right;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -90,20 +90,3 @@ export default {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.community-switch > div,
|
||||
.community-switch ul.dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
.community-switch > div > button {
|
||||
border-radius: 17px;
|
||||
height: 50px;
|
||||
text-align: left;
|
||||
}
|
||||
.community-switch .dropdown-toggle::after {
|
||||
float: right;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
8
frontend/src/components/UserSettings/UserGMSLocation.vue
Normal file
8
frontend/src/components/UserSettings/UserGMSLocation.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<b-button>{{ $t('settings.GMS.location.button') }}</b-button>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'UserGMSLocation',
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,79 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import UserGMSLocationFormat from './UserGMSLocationFormat.vue'
|
||||
import { toastErrorSpy } from '@test/testSetup'
|
||||
|
||||
const mockAPIcall = jest.fn()
|
||||
|
||||
const storeCommitMock = jest.fn()
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('UserGMSLocationFormat', () => {
|
||||
let wrapper
|
||||
beforeEach(() => {
|
||||
wrapper = mount(UserGMSLocationFormat, {
|
||||
mocks: {
|
||||
$t: (key) => key, // Mocking the translation function
|
||||
$store: {
|
||||
state: {
|
||||
gmsPublishLocation: null,
|
||||
},
|
||||
commit: storeCommitMock,
|
||||
},
|
||||
$apollo: {
|
||||
mutate: mockAPIcall,
|
||||
},
|
||||
},
|
||||
localVue,
|
||||
propsData: {
|
||||
selectedOption: 'GMS_LOCATION_TYPE_RANDOM',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy()
|
||||
})
|
||||
|
||||
it('renders the correct dropdown options', () => {
|
||||
const dropdownItems = wrapper.findAll('.dropdown-item')
|
||||
expect(dropdownItems.length).toBe(3)
|
||||
|
||||
const labels = dropdownItems.wrappers.map((item) => item.text())
|
||||
expect(labels).toEqual([
|
||||
'settings.GMS.publish-location.exact',
|
||||
'settings.GMS.publish-location.approximate',
|
||||
'settings.GMS.publish-location.random',
|
||||
])
|
||||
})
|
||||
|
||||
it('updates selected option on click', async () => {
|
||||
const dropdownItem = wrapper.findAll('.dropdown-item').at(1) // Click the second item
|
||||
await dropdownItem.trigger('click')
|
||||
|
||||
expect(wrapper.emitted().gmsPublishLocation).toBeTruthy()
|
||||
expect(wrapper.emitted().gmsPublishLocation.length).toBe(1)
|
||||
expect(wrapper.emitted().gmsPublishLocation[0]).toEqual(['GMS_LOCATION_TYPE_APPROXIMATE'])
|
||||
})
|
||||
|
||||
it('does not update when clicking on already selected option', async () => {
|
||||
const dropdownItem = wrapper.findAll('.dropdown-item').at(2) // Click the third item (which is already selected)
|
||||
await dropdownItem.trigger('click')
|
||||
|
||||
expect(wrapper.emitted().gmsPublishLocation).toBeFalsy()
|
||||
})
|
||||
|
||||
describe('update with error', () => {
|
||||
beforeEach(async () => {
|
||||
mockAPIcall.mockRejectedValue({
|
||||
message: 'Ouch',
|
||||
})
|
||||
const dropdownItem = wrapper.findAll('.dropdown-item').at(1) // Click the second item
|
||||
await dropdownItem.trigger('click')
|
||||
})
|
||||
|
||||
it('toasts an error message', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Ouch')
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div class="user-gms-location-format">
|
||||
<b-dropdown v-model="selectedOption">
|
||||
<template slot="button-content">{{ selectedOptionLabel }}</template>
|
||||
<b-dropdown-item
|
||||
v-for="option in dropdownOptions"
|
||||
@click.prevent="update(option)"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.label }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
|
||||
export default {
|
||||
name: 'UserGMSLocationFormat',
|
||||
data() {
|
||||
return {
|
||||
selectedOption: this.$store.state.gmsPublishLocation ?? 'GMS_LOCATION_TYPE_RANDOM',
|
||||
dropdownOptions: [
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-location.exact'),
|
||||
value: 'GMS_LOCATION_TYPE_EXACT',
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-location.approximate'),
|
||||
value: 'GMS_LOCATION_TYPE_APPROXIMATE',
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-location.random'),
|
||||
value: 'GMS_LOCATION_TYPE_RANDOM',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedOptionLabel() {
|
||||
return this.dropdownOptions.find((option) => option.value === this.selectedOption).label
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async update(option) {
|
||||
if (option.value === this.selectedOption) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
gmsPublishLocation: option.value,
|
||||
},
|
||||
})
|
||||
this.toastSuccess(this.$t('settings.GMS.publish-location.updated'))
|
||||
this.selectedOption = option.value
|
||||
this.$store.commit('gmsPublishLocation', option.value)
|
||||
this.$emit('gmsPublishLocation', option.value)
|
||||
} catch (error) {
|
||||
this.toastError(error.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.user-gms-location-format > .dropdown,
|
||||
.user-gms-location-format > .dropdown > .dropdown-toggle > ul.dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,81 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import UserGMSNamingFormat from './UserGMSNamingFormat.vue'
|
||||
import { toastErrorSpy } from '@test/testSetup'
|
||||
|
||||
const mockAPIcall = jest.fn()
|
||||
|
||||
const storeCommitMock = jest.fn()
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('UserGMSNamingFormat', () => {
|
||||
let wrapper
|
||||
beforeEach(() => {
|
||||
wrapper = mount(UserGMSNamingFormat, {
|
||||
mocks: {
|
||||
$t: (key) => key, // Mocking the translation function
|
||||
$store: {
|
||||
state: {
|
||||
gmsPublishName: null,
|
||||
},
|
||||
commit: storeCommitMock,
|
||||
},
|
||||
$apollo: {
|
||||
mutate: mockAPIcall,
|
||||
},
|
||||
},
|
||||
localVue,
|
||||
propsData: {
|
||||
selectedOption: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy()
|
||||
})
|
||||
|
||||
it('renders the correct dropdown options', () => {
|
||||
const dropdownItems = wrapper.findAll('.dropdown-item')
|
||||
expect(dropdownItems.length).toBe(5)
|
||||
|
||||
const labels = dropdownItems.wrappers.map((item) => item.text())
|
||||
expect(labels).toEqual([
|
||||
'settings.GMS.publish-name.alias-or-initials',
|
||||
'settings.GMS.publish-name.initials',
|
||||
'settings.GMS.publish-name.first',
|
||||
'settings.GMS.publish-name.first-initial',
|
||||
'settings.GMS.publish-name.name-full',
|
||||
])
|
||||
})
|
||||
|
||||
it('updates selected option on click', async () => {
|
||||
const dropdownItem = wrapper.findAll('.dropdown-item').at(3) // Click the fourth item
|
||||
await dropdownItem.trigger('click')
|
||||
|
||||
expect(wrapper.emitted().gmsPublishName).toBeTruthy()
|
||||
expect(wrapper.emitted().gmsPublishName.length).toBe(1)
|
||||
expect(wrapper.emitted().gmsPublishName[0]).toEqual(['GMS_PUBLISH_NAME_FIRST_INITIAL'])
|
||||
})
|
||||
|
||||
it('does not update when clicking on already selected option', async () => {
|
||||
const dropdownItem = wrapper.findAll('.dropdown-item').at(0) // Click the first item (which is already selected)
|
||||
await dropdownItem.trigger('click')
|
||||
|
||||
expect(wrapper.emitted().gmsPublishName).toBeFalsy()
|
||||
})
|
||||
|
||||
describe('update with error', () => {
|
||||
beforeEach(async () => {
|
||||
mockAPIcall.mockRejectedValue({
|
||||
message: 'Ouch',
|
||||
})
|
||||
const dropdownItem = wrapper.findAll('.dropdown-item').at(2) // Click the third item
|
||||
await dropdownItem.trigger('click')
|
||||
})
|
||||
|
||||
it('toasts an error message', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Ouch')
|
||||
})
|
||||
})
|
||||
})
|
||||
87
frontend/src/components/UserSettings/UserGMSNamingFormat.vue
Normal file
87
frontend/src/components/UserSettings/UserGMSNamingFormat.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="user-gms-naming-format">
|
||||
<b-dropdown v-model="selectedOption">
|
||||
<template slot="button-content">{{ selectedOptionLabel }}</template>
|
||||
<b-dropdown-item
|
||||
v-for="option in dropdownOptions"
|
||||
@click.prevent="update(option)"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
:title="option.title"
|
||||
>
|
||||
{{ option.label }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
|
||||
export default {
|
||||
name: 'UserGMSNamingFormat',
|
||||
data() {
|
||||
return {
|
||||
selectedOption: this.$store.state.gmsPublishName ?? 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS',
|
||||
dropdownOptions: [
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-name.alias-or-initials'),
|
||||
title: this.$t('settings.GMS.publish-name.alias-or-initials-tooltip'),
|
||||
value: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS',
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-name.initials'),
|
||||
title: this.$t('settings.GMS.publish-name.initials-tooltip'),
|
||||
value: 'GMS_PUBLISH_NAME_INITIALS',
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-name.first'),
|
||||
title: this.$t('settings.GMS.publish-name.first-tooltip'),
|
||||
value: 'GMS_PUBLISH_NAME_FIRST',
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-name.first-initial'),
|
||||
title: this.$t('settings.GMS.publish-name.first-initial-tooltip'),
|
||||
value: 'GMS_PUBLISH_NAME_FIRST_INITIAL',
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.GMS.publish-name.name-full'),
|
||||
title: this.$t('settings.GMS.publish-name.name-full-tooltip'),
|
||||
value: 'GMS_PUBLISH_NAME_FULL',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedOptionLabel() {
|
||||
return this.dropdownOptions.find((option) => option.value === this.selectedOption).label
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async update(option) {
|
||||
if (option.value === this.selectedOption) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
gmsPublishName: option.value,
|
||||
},
|
||||
})
|
||||
this.toastSuccess(this.$t('settings.GMS.publish-name.updated'))
|
||||
this.selectedOption = option.value
|
||||
this.$store.commit('gmsPublishName', option.value)
|
||||
this.$emit('gmsPublishName', option.value)
|
||||
} catch (error) {
|
||||
this.toastError(error.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.user-gms-naming-format > .dropdown,
|
||||
.user-gms-naming-format > .dropdown > .dropdown-toggle > ul.dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
45
frontend/src/components/UserSettings/UserGMSSwitch.vue
Normal file
45
frontend/src/components/UserSettings/UserGMSSwitch.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="form-user-gms-switch">
|
||||
<b-form-checkbox
|
||||
test="BFormCheckbox"
|
||||
v-model="gmsAllowed"
|
||||
name="check-button"
|
||||
switch
|
||||
@change="onChange"
|
||||
></b-form-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
|
||||
export default {
|
||||
name: 'UserGMSSwitch',
|
||||
data() {
|
||||
return {
|
||||
gmsAllowed: this.$store.state.gmsAllowed,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onChange() {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
gmsAllowed: this.gmsAllowed,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.commit('gmsAllowed', this.gmsAllowed)
|
||||
this.$emit('gmsAllowed', this.gmsAllowed)
|
||||
this.toastSuccess(
|
||||
this.gmsAllowed ? this.$t('settings.GMS.enabled') : this.$t('settings.GMS.disabled'),
|
||||
)
|
||||
})
|
||||
.catch((error) => {
|
||||
this.gmsAllowed = this.$store.state.gmsAllowed
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -8,7 +8,7 @@ const constants = {
|
||||
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
|
||||
CONFIG_VERSION: {
|
||||
DEFAULT: 'DEFAULT',
|
||||
EXPECTED: 'v5.2024-01-08',
|
||||
EXPECTED: 'v6.2024-02-27',
|
||||
CURRENT: '',
|
||||
},
|
||||
}
|
||||
@ -20,6 +20,10 @@ const version = {
|
||||
BUILD_COMMIT_SHORT: (process.env.BUILD_COMMIT ?? '0000000').slice(0, 7),
|
||||
}
|
||||
|
||||
const features = {
|
||||
GMS_ACTIVE: process.env.GMS_ACTIVE ?? false,
|
||||
}
|
||||
|
||||
const environment = {
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
DEBUG: process.env.NODE_ENV !== 'production' ?? false,
|
||||
@ -81,6 +85,7 @@ if (
|
||||
const CONFIG = {
|
||||
...constants,
|
||||
...version,
|
||||
...features,
|
||||
...environment,
|
||||
...endpoints,
|
||||
...community,
|
||||
|
||||
@ -35,9 +35,9 @@ export const updateUserInfos = gql`
|
||||
$hideAmountGDD: Boolean
|
||||
$hideAmountGDT: Boolean
|
||||
$gmsAllowed: Boolean
|
||||
$gmsPublishName: Int
|
||||
$gmsPublishName: GmsPublishNameType
|
||||
$gmsLocation: Location
|
||||
$gmsPublishLocation: Int
|
||||
$gmsPublishLocation: GmsPublishLocationType
|
||||
) {
|
||||
updateUserInfos(
|
||||
firstName: $firstName
|
||||
@ -172,6 +172,9 @@ export const login = gql`
|
||||
klickTipp {
|
||||
newsletterState
|
||||
}
|
||||
gmsAllowed
|
||||
gmsPublishName
|
||||
gmsPublishLocation
|
||||
hasElopage
|
||||
publisherId
|
||||
roles
|
||||
|
||||
@ -5,8 +5,10 @@
|
||||
"1000thanks": "1000 Dank, weil du bei uns bist!",
|
||||
"125": "125%",
|
||||
"85": "85%",
|
||||
"ExternServices": "Verknüpfte Dienste",
|
||||
"GDD": "GDD",
|
||||
"GDT": "GDT",
|
||||
"GMS": "Gradido Karte",
|
||||
"PersonalDetails": "Persönliche Angaben",
|
||||
"advanced-calculation": "Vorausberechnung",
|
||||
"asterisks": "****",
|
||||
@ -290,6 +292,36 @@
|
||||
},
|
||||
"settings": {
|
||||
"emailInfo": "Kann aktuell noch nicht geändert werden.",
|
||||
"GMS": {
|
||||
"disabled": "Daten werden nicht nach GMS exportiert",
|
||||
"enabled": "Daten werden nach GMS exportiert",
|
||||
"location": {
|
||||
"label": "Positionsbestimmung",
|
||||
"button": "Klick mich!"
|
||||
},
|
||||
"location-format": "Positionstyp",
|
||||
"naming-format": "Namensformat im GMS",
|
||||
"publish-location": {
|
||||
"exact": "Genaue Position",
|
||||
"approximate": "Ungefähre Position",
|
||||
"random": "Zufallsposition",
|
||||
"updated": "Positionstyp für GMS aktualisiert"
|
||||
},
|
||||
"publish-name": {
|
||||
"alias-or-initials": "Benutzername oder Initialen",
|
||||
"alias-or-initials-tooltip": "Benutzername, falls vorhanden, oder die Initialen von Vorname und Nachname",
|
||||
"first": "Vorname",
|
||||
"first-tooltip": "Nur der Vornamen",
|
||||
"first-initial": "Vorname und Initiale",
|
||||
"first-initial-tooltip": "Vornamen plus Anfangsbuchstabe des Nachnamens",
|
||||
"initials": "Initialen",
|
||||
"initials-tooltip": "Initialen von Vor- und Nachname unabhängig von der Existenz des Benutzernamens",
|
||||
"name-full": "Ganzer Name",
|
||||
"name-full-tooltip": "Vollständiger Name: Vorname plus Nachname",
|
||||
"updated": "Namensformat für GMS aktualisiert"
|
||||
},
|
||||
"switch": "Erlaubnis Daten nach GMS zu exportieren."
|
||||
},
|
||||
"hideAmountGDD": "Dein GDD Betrag ist versteckt.",
|
||||
"hideAmountGDT": "Dein GDT Betrag ist versteckt.",
|
||||
"info": "Transaktionen können nun per Benutzername oder E-Mail-Adresse getätigt werden.",
|
||||
|
||||
@ -5,8 +5,10 @@
|
||||
"1000thanks": "1000 thanks for being with us!",
|
||||
"125": "125%",
|
||||
"85": "85%",
|
||||
"ExternServices": "Extern Services",
|
||||
"GDD": "GDD",
|
||||
"GDT": "GDT",
|
||||
"GMS": "Gradido Map",
|
||||
"PersonalDetails": "Personal details",
|
||||
"advanced-calculation": "Advanced calculation",
|
||||
"asterisks": "****",
|
||||
@ -290,6 +292,36 @@
|
||||
},
|
||||
"settings": {
|
||||
"emailInfo": "Cannot be changed at this time.",
|
||||
"GMS": {
|
||||
"disabled": "Data not exported to GMS",
|
||||
"enabled": "Data exported to GMS",
|
||||
"location": {
|
||||
"label": "pinpoint location",
|
||||
"button": "click me!"
|
||||
},
|
||||
"location-format": "location type",
|
||||
"naming-format": "Format of name in GMS",
|
||||
"publish-location": {
|
||||
"exact": "exact position",
|
||||
"approximate": "approximate position",
|
||||
"random": "random position",
|
||||
"updated": "format of location for GMS updated"
|
||||
},
|
||||
"publish-name": {
|
||||
"alias-or-initials": "Username or initials",
|
||||
"alias-or-initials-tooltip": "username if exists or Initials of firstname and lastname",
|
||||
"first": "firstname",
|
||||
"first-tooltip": "the firstname only",
|
||||
"first-initial": "firstname and initial",
|
||||
"first-initial-tooltip": "firstname plus initial of lastname",
|
||||
"initials": "Initials of firstname and lastname independent if username exists",
|
||||
"initials-tooltip": "Initials of firstname and lastname independent if username exists",
|
||||
"name-full": "fullname",
|
||||
"name-full-tooltip": "fullname: firstname plus lastname",
|
||||
"updated": "format of name for GMS updated"
|
||||
},
|
||||
"switch": "Allow data export to GMS"
|
||||
},
|
||||
"hideAmountGDD": "Your GDD amount is hidden.",
|
||||
"hideAmountGDT": "Your GDT amount is hidden.",
|
||||
"info": "Transactions can now be made by username or email address.",
|
||||
|
||||
@ -1,81 +1,129 @@
|
||||
<template>
|
||||
<div class="card bg-white gradido-border-radius appBoxShadow p-4 mt--3">
|
||||
<div class="h2">{{ $t('PersonalDetails') }}</div>
|
||||
<div class="my-4 text-small">
|
||||
{{ $t('settings.info') }}
|
||||
</div>
|
||||
|
||||
<b-row>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<user-name />
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<b-form-group :label="$t('form.email')" :description="$t('settings.emailInfo')">
|
||||
<b-form-input v-model="email" readonly></b-form-input>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<hr />
|
||||
<b-form>
|
||||
<b-row class="mt-3">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<label>{{ $t('form.firstname') }}</label>
|
||||
<b-form-input
|
||||
v-model="firstName"
|
||||
:placeholder="$t('settings.name.enterFirstname')"
|
||||
data-test="firstname"
|
||||
trim
|
||||
></b-form-input>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<label>{{ $t('form.lastname') }}</label>
|
||||
<b-form-input
|
||||
v-model="lastName"
|
||||
:placeholder="$t('settings.name.enterLastname')"
|
||||
data-test="lastname"
|
||||
trim
|
||||
></b-form-input>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<div v-if="!isDisabled" class="mt-4 pt-4 text-center">
|
||||
<b-button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
@click.prevent="onSubmit"
|
||||
data-test="submit-userdata"
|
||||
>
|
||||
{{ $t('form.save') }}
|
||||
</b-button>
|
||||
</div>
|
||||
</b-form>
|
||||
<hr />
|
||||
<b-row>
|
||||
<b-col cols="12" md="6" lg="6">{{ $t('language') }}</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-right">
|
||||
<user-language />
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<hr />
|
||||
<div class="mt-5">{{ $t('form.password') }}</div>
|
||||
<user-password />
|
||||
<hr />
|
||||
<b-row class="mb-5">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
{{ $t('settings.newsletter.newsletter') }}
|
||||
<div class="text-small">
|
||||
{{
|
||||
newsletterState
|
||||
? $t('settings.newsletter.newsletterTrue')
|
||||
: $t('settings.newsletter.newsletterFalse')
|
||||
}}
|
||||
<b-tabs content-class="mt-3">
|
||||
<b-tab :title="$t('PersonalDetails')" active>
|
||||
<div class="h2">{{ $t('PersonalDetails') }}</div>
|
||||
<div class="my-4 text-small">
|
||||
{{ $t('settings.info') }}
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-right">
|
||||
<user-newsletter />
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<b-row>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<user-name />
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<b-form-group :label="$t('form.email')" :description="$t('settings.emailInfo')">
|
||||
<b-form-input v-model="email" readonly></b-form-input>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<hr />
|
||||
<b-form>
|
||||
<b-row class="mt-3">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<label>{{ $t('form.firstname') }}</label>
|
||||
<b-form-input
|
||||
v-model="firstName"
|
||||
:placeholder="$t('settings.name.enterFirstname')"
|
||||
data-test="firstname"
|
||||
trim
|
||||
></b-form-input>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<label>{{ $t('form.lastname') }}</label>
|
||||
<b-form-input
|
||||
v-model="lastName"
|
||||
:placeholder="$t('settings.name.enterLastname')"
|
||||
data-test="lastname"
|
||||
trim
|
||||
></b-form-input>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<div v-if="!isDisabled" class="mt-4 pt-4 text-center">
|
||||
<b-button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
@click.prevent="onSubmit"
|
||||
data-test="submit-userdata"
|
||||
>
|
||||
{{ $t('form.save') }}
|
||||
</b-button>
|
||||
</div>
|
||||
</b-form>
|
||||
<hr />
|
||||
<b-row>
|
||||
<b-col cols="12" md="6" lg="6">{{ $t('language') }}</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-right">
|
||||
<user-language />
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<hr />
|
||||
<div class="mt-5">{{ $t('form.password') }}</div>
|
||||
<user-password />
|
||||
<hr />
|
||||
<b-row class="mb-5">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
{{ $t('settings.newsletter.newsletter') }}
|
||||
<div class="text-small">
|
||||
{{
|
||||
newsletterState
|
||||
? $t('settings.newsletter.newsletterTrue')
|
||||
: $t('settings.newsletter.newsletterFalse')
|
||||
}}
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-right">
|
||||
<user-newsletter />
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-tab>
|
||||
<div v-if="isGMS">
|
||||
<b-tab :title="$t('ExternServices')">
|
||||
<div class="h2">{{ $t('ExternServices') }}</div>
|
||||
<div class="h3">{{ $t('GMS') }}</div>
|
||||
<b-row class="mb-3">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
{{ $t('settings.GMS.switch') }}
|
||||
<div class="text-small">
|
||||
{{ gmsAllowed ? $t('settings.GMS.enabled') : $t('settings.GMS.disabled') }}
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-right">
|
||||
<user-g-m-s-switch @gmsAllowed="gmsStateSwitch" />
|
||||
</b-col>
|
||||
</b-row>
|
||||
<div v-if="gmsAllowed">
|
||||
<b-row class="mb-4">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
{{ $t('settings.GMS.naming-format') }}
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<user-g-m-s-naming-format />
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row class="mb-4">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
{{ $t('settings.GMS.location-format') }}
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<user-g-m-s-location-format />
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row class="mb-5">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
{{ $t('settings.GMS.location.label') }}
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<user-g-m-s-location />
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</b-tab>
|
||||
</div>
|
||||
</b-tabs>
|
||||
|
||||
<!-- TODO<b-row>
|
||||
<b-col cols="12" md="6" lg="6">{{ $t('settings.darkMode') }}</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-right">
|
||||
@ -85,15 +133,24 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import UserGMSSwitch from '@/components/UserSettings/UserGMSSwitch'
|
||||
import UserGMSNamingFormat from '@/components/UserSettings/UserGMSNamingFormat'
|
||||
import UserGMSLocationFormat from '@/components/UserSettings/UserGMSLocationFormat'
|
||||
import UserGMSLocation from '@/components/UserSettings/UserGMSLocation'
|
||||
import UserName from '@/components/UserSettings/UserName.vue'
|
||||
import UserPassword from '@/components/UserSettings/UserPassword'
|
||||
import UserLanguage from '@/components/LanguageSwitch2.vue'
|
||||
import UserNewsletter from '@/components/UserSettings/UserNewsletter.vue'
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
import CONFIG from '../config'
|
||||
|
||||
export default {
|
||||
name: 'Profile',
|
||||
components: {
|
||||
UserGMSSwitch,
|
||||
UserGMSNamingFormat,
|
||||
UserGMSLocationFormat,
|
||||
UserGMSLocation,
|
||||
UserName,
|
||||
UserPassword,
|
||||
UserLanguage,
|
||||
@ -106,7 +163,7 @@ export default {
|
||||
|
||||
data() {
|
||||
const { state } = this.$store
|
||||
const { darkMode, firstName, lastName, email, newsletterState } = state
|
||||
const { darkMode, firstName, lastName, email, newsletterState, gmsAllowed } = state
|
||||
|
||||
return {
|
||||
darkMode,
|
||||
@ -115,6 +172,7 @@ export default {
|
||||
lastName,
|
||||
email,
|
||||
newsletterState,
|
||||
gmsAllowed,
|
||||
mutation: '',
|
||||
variables: {},
|
||||
}
|
||||
@ -125,6 +183,9 @@ export default {
|
||||
const { firstName, lastName } = this.$store.state
|
||||
return firstName === this.firstName && lastName === this.lastName
|
||||
},
|
||||
isGMS() {
|
||||
return CONFIG.GMS_ACTIVE
|
||||
},
|
||||
},
|
||||
// TODO: watch: {
|
||||
// darkMode(val) {
|
||||
@ -150,6 +211,9 @@ export default {
|
||||
this.toastSuccess(this.$t('settings.name.change-success'))
|
||||
} catch (error) {}
|
||||
},
|
||||
gmsStateSwitch(eventData) {
|
||||
this.gmsAllowed = eventData
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -35,6 +35,15 @@ export const mutations = {
|
||||
newsletterState: (state, newsletterState) => {
|
||||
state.newsletterState = newsletterState
|
||||
},
|
||||
gmsAllowed: (state, gmsAllowed) => {
|
||||
state.gmsAllowed = gmsAllowed
|
||||
},
|
||||
gmsPublishName: (state, gmsPublishName) => {
|
||||
state.gmsPublishName = gmsPublishName
|
||||
},
|
||||
gmsPublishLocation: (state, gmsPublishLocation) => {
|
||||
state.gmsPublishLocation = gmsPublishLocation
|
||||
},
|
||||
publisherId: (state, publisherId) => {
|
||||
let pubId = parseInt(publisherId)
|
||||
if (isNaN(pubId)) pubId = null
|
||||
@ -71,6 +80,9 @@ export const actions = {
|
||||
commit('firstName', data.firstName)
|
||||
commit('lastName', data.lastName)
|
||||
commit('newsletterState', data.klickTipp.newsletterState)
|
||||
commit('gmsAllowed', data.gmsAllowed)
|
||||
commit('gmsPublishName', data.gmsPublishName)
|
||||
commit('gmsPublishLocation', data.gmsPublishLocation)
|
||||
commit('hasElopage', data.hasElopage)
|
||||
commit('publisherId', data.publisherId)
|
||||
commit('roles', data.roles)
|
||||
@ -85,6 +97,9 @@ export const actions = {
|
||||
commit('firstName', '')
|
||||
commit('lastName', '')
|
||||
commit('newsletterState', null)
|
||||
commit('gmsAllowed', null)
|
||||
commit('gmsPublishName', null)
|
||||
commit('gmsPublishLocation', null)
|
||||
commit('hasElopage', false)
|
||||
commit('publisherId', null)
|
||||
commit('roles', null)
|
||||
@ -117,6 +132,9 @@ try {
|
||||
tokenTime: null,
|
||||
roles: [],
|
||||
newsletterState: null,
|
||||
gmsAllowed: null,
|
||||
gmsPublishName: null,
|
||||
gmsPublishLocation: null,
|
||||
hasElopage: false,
|
||||
publisherId: null,
|
||||
hideAmountGDD: null,
|
||||
@ -126,7 +144,7 @@ try {
|
||||
redirectPath: '/overview',
|
||||
},
|
||||
getters: {},
|
||||
// Syncronous mutation of the state
|
||||
// Synchronous mutation of the state
|
||||
mutations,
|
||||
actions,
|
||||
})
|
||||
|
||||
@ -28,6 +28,9 @@ const {
|
||||
lastName,
|
||||
username,
|
||||
newsletterState,
|
||||
gmsAllowed,
|
||||
gmsPublishName,
|
||||
gmsPublishLocation,
|
||||
publisherId,
|
||||
roles,
|
||||
hasElopage,
|
||||
@ -122,6 +125,30 @@ describe('Vuex store', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('gmsAllowed', () => {
|
||||
it('sets the state of gmsAllowed', () => {
|
||||
const state = { gmsAllowed: null }
|
||||
gmsAllowed(state, true)
|
||||
expect(state.gmsAllowed).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('gmsPublishName', () => {
|
||||
it('sets gmsPublishName', () => {
|
||||
const state = { gmsPublishName: null }
|
||||
gmsPublishName(state, 'GMS_PUBLISH_NAME_INITIALS')
|
||||
expect(state.gmsPublishName).toEqual('GMS_PUBLISH_NAME_INITIALS')
|
||||
})
|
||||
})
|
||||
|
||||
describe('gmsPublishLocation', () => {
|
||||
it('sets gmsPublishLocation', () => {
|
||||
const state = { gmsPublishLocation: null }
|
||||
gmsPublishLocation(state, 'GMS_LOCATION_TYPE_APPROXIMATE')
|
||||
expect(state.gmsPublishLocation).toEqual('GMS_LOCATION_TYPE_APPROXIMATE')
|
||||
})
|
||||
})
|
||||
|
||||
describe('publisherId', () => {
|
||||
it('sets the state of publisherId', () => {
|
||||
const state = {}
|
||||
@ -190,6 +217,9 @@ describe('Vuex store', () => {
|
||||
klickTipp: {
|
||||
newsletterState: true,
|
||||
},
|
||||
gmsAllowed: true,
|
||||
gmsPublishName: 'GMS_PUBLISH_NAME_FULL',
|
||||
gmsPublishLocation: 'GMS_LOCATION_TYPE_EXACT',
|
||||
hasElopage: false,
|
||||
publisherId: 1234,
|
||||
roles: ['admin'],
|
||||
@ -197,9 +227,9 @@ describe('Vuex store', () => {
|
||||
hideAmountGDT: true,
|
||||
}
|
||||
|
||||
it('calls eleven commits', () => {
|
||||
it('calls fifteen commits', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenCalledTimes(12)
|
||||
expect(commit).toHaveBeenCalledTimes(15)
|
||||
})
|
||||
|
||||
it('commits gradidoID', () => {
|
||||
@ -232,29 +262,44 @@ describe('Vuex store', () => {
|
||||
expect(commit).toHaveBeenNthCalledWith(6, 'newsletterState', true)
|
||||
})
|
||||
|
||||
it('commits gmsAllowed', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(7, 'gmsAllowed', true)
|
||||
})
|
||||
|
||||
it('commits gmsPublishName', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(8, 'gmsPublishName', 'GMS_PUBLISH_NAME_FULL')
|
||||
})
|
||||
|
||||
it('commits gmsPublishLocation', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(9, 'gmsPublishLocation', 'GMS_LOCATION_TYPE_EXACT')
|
||||
})
|
||||
|
||||
it('commits hasElopage', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(7, 'hasElopage', false)
|
||||
expect(commit).toHaveBeenNthCalledWith(10, 'hasElopage', false)
|
||||
})
|
||||
|
||||
it('commits publisherId', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(8, 'publisherId', 1234)
|
||||
expect(commit).toHaveBeenNthCalledWith(11, 'publisherId', 1234)
|
||||
})
|
||||
|
||||
it('commits roles', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(9, 'roles', ['admin'])
|
||||
expect(commit).toHaveBeenNthCalledWith(12, 'roles', ['admin'])
|
||||
})
|
||||
|
||||
it('commits hideAmountGDD', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(10, 'hideAmountGDD', false)
|
||||
expect(commit).toHaveBeenNthCalledWith(13, 'hideAmountGDD', false)
|
||||
})
|
||||
|
||||
it('commits hideAmountGDT', () => {
|
||||
login({ commit, state }, commitedData)
|
||||
expect(commit).toHaveBeenNthCalledWith(11, 'hideAmountGDT', true)
|
||||
expect(commit).toHaveBeenNthCalledWith(14, 'hideAmountGDT', true)
|
||||
})
|
||||
})
|
||||
|
||||
@ -262,9 +307,9 @@ describe('Vuex store', () => {
|
||||
const commit = jest.fn()
|
||||
const state = {}
|
||||
|
||||
it('calls twelve commits', () => {
|
||||
it('calls seventeen commits', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenCalledTimes(14)
|
||||
expect(commit).toHaveBeenCalledTimes(17)
|
||||
})
|
||||
|
||||
it('commits token', () => {
|
||||
@ -297,34 +342,49 @@ describe('Vuex store', () => {
|
||||
expect(commit).toHaveBeenNthCalledWith(6, 'newsletterState', null)
|
||||
})
|
||||
|
||||
it('commits gmsAllowed', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(7, 'gmsAllowed', null)
|
||||
})
|
||||
|
||||
it('commits gmsPublishName', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(8, 'gmsPublishName', null)
|
||||
})
|
||||
|
||||
it('commits gmsPublishLocation', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(9, 'gmsPublishLocation', null)
|
||||
})
|
||||
|
||||
it('commits hasElopage', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(7, 'hasElopage', false)
|
||||
expect(commit).toHaveBeenNthCalledWith(10, 'hasElopage', false)
|
||||
})
|
||||
|
||||
it('commits publisherId', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(8, 'publisherId', null)
|
||||
expect(commit).toHaveBeenNthCalledWith(11, 'publisherId', null)
|
||||
})
|
||||
|
||||
it('commits roles', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(9, 'roles', null)
|
||||
expect(commit).toHaveBeenNthCalledWith(12, 'roles', null)
|
||||
})
|
||||
|
||||
it('commits hideAmountGDD', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(10, 'hideAmountGDD', false)
|
||||
expect(commit).toHaveBeenNthCalledWith(13, 'hideAmountGDD', false)
|
||||
})
|
||||
|
||||
it('commits hideAmountGDT', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(11, 'hideAmountGDT', true)
|
||||
expect(commit).toHaveBeenNthCalledWith(14, 'hideAmountGDT', true)
|
||||
})
|
||||
|
||||
it('commits email', () => {
|
||||
logout({ commit, state })
|
||||
expect(commit).toHaveBeenNthCalledWith(12, 'email', '')
|
||||
expect(commit).toHaveBeenNthCalledWith(15, 'email', '')
|
||||
})
|
||||
|
||||
// how to get this working?
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Gradido",
|
||||
"main": "index.js",
|
||||
"repository": "git@github.com:gradido/gradido.git",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user