From cf13a9a7ecfadf3af71ad7acdaeebd7e19ad7053 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Fri, 16 Feb 2024 21:50:49 +0100 Subject: [PATCH 01/88] first draft for update gmsUser --- backend/src/apis/gms/GmsClient.ts | 87 ++++++++++++++----- backend/src/apis/gms/model/GmsUser.ts | 1 + backend/src/graphql/resolver/UserResolver.ts | 16 ++++ .../util/compareGmsRelevantUserSettings.ts | 49 +++++++++++ 4 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 backend/src/graphql/resolver/util/compareGmsRelevantUserSettings.ts diff --git a/backend/src/apis/gms/GmsClient.ts b/backend/src/apis/gms/GmsClient.ts index 46fa64006..87b4c0e95 100644 --- a/backend/src/apis/gms/GmsClient.ts +++ b/backend/src/apis/gms/GmsClient.ts @@ -117,30 +117,69 @@ export async function userByUuid(uuid: string): Promise { - 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) + 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, + }, } - 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 Get community-user:', error) - throw new LogError(error.message) + 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 { + 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 } } diff --git a/backend/src/apis/gms/model/GmsUser.ts b/backend/src/apis/gms/model/GmsUser.ts index 7f7db7660..0b16f00fb 100644 --- a/backend/src/apis/gms/model/GmsUser.ts +++ b/backend/src/apis/gms/model/GmsUser.ts @@ -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) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 3f70ce112..fa7f1582b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -30,6 +30,8 @@ import { SearchAdminUsersResult } from '@model/AdminUser' 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' @@ -69,6 +71,7 @@ import { randombytes_random } from 'sodium-native' import { FULL_CREATION_AVAILABLE } from './const/const' 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' @@ -573,6 +576,8 @@ export class UserResolver { } const user = getUser(context) + const backupOriginalUser = user + // try { if (firstName) { user.firstName = firstName @@ -649,6 +654,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 (compareGmsRelevantUserSettings(user, backupOriginalUser)) { + 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 } diff --git a/backend/src/graphql/resolver/util/compareGmsRelevantUserSettings.ts b/backend/src/graphql/resolver/util/compareGmsRelevantUserSettings.ts new file mode 100644 index 000000000..330086278 --- /dev/null +++ b/backend/src/graphql/resolver/util/compareGmsRelevantUserSettings.ts @@ -0,0 +1,49 @@ +import { Point } from '@dbTools/typeorm' +import { User as DbUser } from '@entity/User' + +import { LogError } from '@/server/LogError' +import { backendLogger as logger } from '@/server/logger' + +import { Point2Location } from './Location2Point' + +export function compareGmsRelevantUserSettings(orgUser: DbUser, changedUser: DbUser): boolean { + if (!orgUser && !changedUser) { + throw new LogError('comparison without any user is impossible') + } + logger.debug('compareGmsRelevantUserSettings:', orgUser, changedUser) + if (orgUser.alias !== changedUser.alias) { + return true + } + if (orgUser.firstName !== changedUser.firstName || orgUser.lastName !== changedUser.lastName) { + return true + } + if (orgUser.gmsAllowed !== changedUser.gmsAllowed) { + return true + } + if (orgUser.gmsPublishLocation !== changedUser.gmsPublishLocation) { + return true + } + if (orgUser.gmsPublishName !== changedUser.gmsPublishName) { + return true + } + if (orgUser.language !== changedUser.language) { + return true + } + if (orgUser.location === null && changedUser.location !== null) { + return true + } + if (orgUser.location !== null && changedUser.location === null) { + return true + } + if (orgUser.location !== null && changedUser.location !== null) { + const orgLocation = Point2Location(orgUser.location as Point) + const changedLocation = Point2Location(changedUser.location as Point) + if ( + orgLocation.latitude !== changedLocation.latitude || + orgLocation.longitude !== changedLocation.longitude + ) { + return true + } + } + return false +} From 420febfa9e7812702591668ab771afc6f1101fb3 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 20 Feb 2024 09:57:42 +0100 Subject: [PATCH 02/88] fix problems with deploy script, lost update? --- deployment/hetzner_cloud/install.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/deployment/hetzner_cloud/install.sh b/deployment/hetzner_cloud/install.sh index 06b92ecaf..798e77862 100755 --- a/deployment/hetzner_cloud/install.sh +++ b/deployment/hetzner_cloud/install.sh @@ -127,7 +127,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 < $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 @@ -149,7 +155,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 @@ -163,4 +169,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 \ No newline at end of file +sudo -u gradido $SCRIPT_PATH/start.sh $1 \ No newline at end of file From 8241907bc7df8ad05616d45ee25885e15d89d6b3 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Wed, 21 Feb 2024 16:22:35 +0100 Subject: [PATCH 03/88] =?UTF-8?q?test=20workaround=20f=C3=BCr=20forgotPass?= =?UTF-8?q?word?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/graphql/resolver/UserResolver.test.ts | 6 ++++++ backend/src/graphql/resolver/UserResolver.ts | 1 - backend/src/seeds/factory/user.ts | 8 ++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index c570dbd9f..51d5b0694 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -1043,6 +1043,12 @@ describe('UserResolver', () => { describe('duration not expired', () => { it('throws an error', async () => { + // TODO: because of confusing time settings in user.createdAt and user.updatedAt increases duration a lot more than 10min necessary + // example: user directly created in userFactory for the testcase + // user.emailContacts.updatedAt=2024-02-21T12:18:30.000Z createdAt=2024-02-21T12:18:30.382Z + // timeElapsed = Date.now() - new Date(updatedAt).getTime() + // BUT HERE: Date.now=2024-02-21T13:18:30.889Z differs one hour from the user date settings !?!?!?!?!?!?! + CONFIG.EMAIL_CODE_REQUEST_TIME = 1000 await expect(mutate({ mutation: forgotPassword, variables })).resolves.toEqual( expect.objectContaining({ errors: [ diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index fa7f1582b..607ef21a6 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -398,7 +398,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`, diff --git a/backend/src/seeds/factory/user.ts b/backend/src/seeds/factory/user.ts index 3ddddf336..f0bda3a3f 100644 --- a/backend/src/seeds/factory/user.ts +++ b/backend/src/seeds/factory/user.ts @@ -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) } From 15eccbb315894dc66bbd228b8a788942889437cc Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Wed, 21 Feb 2024 17:20:55 +0100 Subject: [PATCH 04/88] remove workaround for forgotPassword-test --- backend/src/graphql/resolver/UserResolver.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 51d5b0694..c570dbd9f 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -1043,12 +1043,6 @@ describe('UserResolver', () => { describe('duration not expired', () => { it('throws an error', async () => { - // TODO: because of confusing time settings in user.createdAt and user.updatedAt increases duration a lot more than 10min necessary - // example: user directly created in userFactory for the testcase - // user.emailContacts.updatedAt=2024-02-21T12:18:30.000Z createdAt=2024-02-21T12:18:30.382Z - // timeElapsed = Date.now() - new Date(updatedAt).getTime() - // BUT HERE: Date.now=2024-02-21T13:18:30.889Z differs one hour from the user date settings !?!?!?!?!?!?! - CONFIG.EMAIL_CODE_REQUEST_TIME = 1000 await expect(mutate({ mutation: forgotPassword, variables })).resolves.toEqual( expect.objectContaining({ errors: [ From ffddfea699a9162c6373302393172243bc4d1014 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 26 Feb 2024 10:02:52 +0100 Subject: [PATCH 05/88] update remade, add migration script --- deployment/hetzner_cloud/README.md | 6 +- .../migration/2_2_0-2_2_1/README.md | 18 +++++ .../migration/2_2_0-2_2_1/fixInstall.sh | 66 +++++++++++++++++++ 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 deployment/hetzner_cloud/migration/2_2_0-2_2_1/README.md create mode 100644 deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh diff --git a/deployment/hetzner_cloud/README.md b/deployment/hetzner_cloud/README.md index d03ff0b46..5aec75ed5 100644 --- a/deployment/hetzner_cloud/README.md +++ b/deployment/hetzner_cloud/README.md @@ -1,7 +1,7 @@ -# Setup on Hetzner Cloud Server -Suggested minimal Plan: CX41 -4x vCPU, 16 GB Ram, 160 GB Disk Space, 20.71 € per month (04.01.2024) +# 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 diff --git a/deployment/hetzner_cloud/migration/2_2_0-2_2_1/README.md b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/README.md new file mode 100644 index 000000000..38c4e8330 --- /dev/null +++ b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/README.md @@ -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 + diff --git a/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh new file mode 100644 index 000000000..5aad9c12d --- /dev/null +++ b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh @@ -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 < $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 \ No newline at end of file From 93f68e4d475bec171bed265da8283df8edd2e4b9 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 26 Feb 2024 10:04:00 +0100 Subject: [PATCH 06/88] release --- CHANGELOG.md | 8 ++++++++ admin/package.json | 2 +- backend/package.json | 2 +- database/package.json | 2 +- dht-node/package.json | 2 +- dlt-connector/package.json | 2 +- federation/package.json | 2 +- frontend/package.json | 2 +- package.json | 2 +- 9 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb49eaf5..b05bd3e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/admin/package.json b/admin/package.json index a28adad43..8157bbdaa 100644 --- a/admin/package.json +++ b/admin/package.json @@ -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": { diff --git a/backend/package.json b/backend/package.json index cdf35b725..e08d5ea5e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -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", diff --git a/database/package.json b/database/package.json index 2b31e033b..31ccfcc1f 100644 --- a/database/package.json +++ b/database/package.json @@ -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", diff --git a/dht-node/package.json b/dht-node/package.json index 7a73791d5..a4859e394 100644 --- a/dht-node/package.json +++ b/dht-node/package.json @@ -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/", diff --git a/dlt-connector/package.json b/dlt-connector/package.json index 5bc9673de..9713e740f 100644 --- a/dlt-connector/package.json +++ b/dlt-connector/package.json @@ -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/", diff --git a/federation/package.json b/federation/package.json index fcfaa0e46..9a74201ab 100644 --- a/federation/package.json +++ b/federation/package.json @@ -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", diff --git a/frontend/package.json b/frontend/package.json index 2a3eeb56a..22ad16c5d 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -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", diff --git a/package.json b/package.json index b85be6f24..8ed31de63 100644 --- a/package.json +++ b/package.json @@ -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", From f750603151f691a0f962f70aca127bb07e3db417 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 26 Feb 2024 10:05:17 +0100 Subject: [PATCH 07/88] make script runnable --- deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh diff --git a/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh old mode 100644 new mode 100755 From 7c18fd6736535a5466e255595dafc77a36346eb4 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 26 Feb 2024 10:06:32 +0100 Subject: [PATCH 08/88] fix --- deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh index 5aad9c12d..1995b220d 100755 --- a/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh +++ b/deployment/hetzner_cloud/migration/2_2_0-2_2_1/fixInstall.sh @@ -10,7 +10,7 @@ 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/../../.. +PROJECT_ROOT=$SCRIPT_DIR/.. set +o allexport From 03c566919cb59203b300d40ec40608b55e426f93 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 26 Feb 2024 14:06:13 +0100 Subject: [PATCH 09/88] add gms switch and name type --- .../src/graphql/arg/UpdateUserInfosArgs.ts | 12 +- backend/src/graphql/model/User.ts | 8 + backend/src/graphql/resolver/UserResolver.ts | 23 +-- .../UserSettings/UserGMSNamingFormat.vue | 84 ++++++++ .../components/UserSettings/UserGMSSwitch.vue | 45 ++++ frontend/src/graphql/mutations.js | 4 +- frontend/src/locales/de.json | 16 ++ frontend/src/locales/en.json | 16 ++ frontend/src/pages/Settings.vue | 192 +++++++++++------- frontend/src/store/store.js | 12 ++ 10 files changed, 317 insertions(+), 95 deletions(-) create mode 100644 frontend/src/components/UserSettings/UserGMSNamingFormat.vue create mode 100644 frontend/src/components/UserSettings/UserGMSSwitch.vue diff --git a/backend/src/graphql/arg/UpdateUserInfosArgs.ts b/backend/src/graphql/arg/UpdateUserInfosArgs.ts index 0920fb3bc..22b548f91 100644 --- a/backend/src/graphql/arg/UpdateUserInfosArgs.ts +++ b/backend/src/graphql/arg/UpdateUserInfosArgs.ts @@ -1,6 +1,7 @@ -import { IsBoolean, IsInt, IsString } from 'class-validator' +import { IsBoolean, IsEnum, IsInt, IsString } from 'class-validator' import { ArgsType, Field, InputType, Int } from 'type-graphql' +import { GmsPublishNameType } from '@enum/GmsPublishNameType' import { Location } from '@model/Location' import { isValidLocation } from '@/graphql/validator/Location' @@ -48,9 +49,12 @@ export class UpdateUserInfosArgs { @IsBoolean() gmsAllowed?: boolean - @Field(() => Int, { nullable: true, defaultValue: 0 }) - @IsInt() - gmsPublishName?: number | null + @Field(() => GmsPublishNameType, { + nullable: true, + defaultValue: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS, + }) + @IsEnum(GmsPublishNameType) + gmsPublishName?: GmsPublishNameType | null @Field(() => Location, { nullable: true }) @isValidLocation() diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index d24a717c4..0d3cfccc7 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -29,6 +29,8 @@ export class User { this.hasElopage = null this.hideAmountGDD = user.hideAmountGDD this.hideAmountGDT = user.hideAmountGDT + this.gmsAllowed = user.gmsAllowed + this.gmsPublishName = user.gmsPublishName } } @@ -74,6 +76,12 @@ export class User { @Field(() => Boolean) hideAmountGDT: boolean + @Field(() => Boolean) + gmsAllowed: boolean + + @Field(() => Int, { nullable: true }) + gmsPublishName: number | null + // This is not the users publisherId, but the one of the users who recommend him @Field(() => Int, { nullable: true }) publisherId: number | null diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 3f70ce112..8f6b36652 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -561,17 +561,6 @@ export class UserResolver { 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) // try { if (firstName) { @@ -620,12 +609,18 @@ export class UserResolver { user.hideAmountGDT = hideAmountGDT } - user.gmsAllowed = gmsAllowed - user.gmsPublishName = gmsPublishName + if (gmsAllowed) { + user.gmsAllowed = gmsAllowed + } + if (gmsPublishName) { + user.gmsPublishName = gmsPublishName + } if (gmsLocation) { user.location = Location2Point(gmsLocation) } - user.gmsPublishLocation = gmsPublishLocation + if (gmsPublishLocation) { + user.gmsPublishLocation = gmsPublishLocation + } // } catch (err) { // console.log('error:', err) // } diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.vue b/frontend/src/components/UserSettings/UserGMSNamingFormat.vue new file mode 100644 index 000000000..d12dde0ce --- /dev/null +++ b/frontend/src/components/UserSettings/UserGMSNamingFormat.vue @@ -0,0 +1,84 @@ + + + diff --git a/frontend/src/components/UserSettings/UserGMSSwitch.vue b/frontend/src/components/UserSettings/UserGMSSwitch.vue new file mode 100644 index 000000000..6958f4e57 --- /dev/null +++ b/frontend/src/components/UserSettings/UserGMSSwitch.vue @@ -0,0 +1,45 @@ + + diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index cade098da..184a712ab 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -35,7 +35,7 @@ export const updateUserInfos = gql` $hideAmountGDD: Boolean $hideAmountGDT: Boolean $gmsAllowed: Boolean - $gmsPublishName: Int + $gmsPublishName: GmsPublishNameType $gmsLocation: Location $gmsPublishLocation: Int ) { @@ -172,6 +172,8 @@ export const login = gql` klickTipp { newsletterState } + gmsAllowed + gmsPublishName hasElopage publisherId roles diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 337722940..f1ba3b2f7 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -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,20 @@ }, "settings": { "emailInfo": "Kann aktuell noch nicht geändert werden.", + "GMS": { + "disabled": "Daten werden nicht nach GMS exportiert", + "enabled": "Daten werden nach GMS exportiert", + "naming-format": "Namensformat im GMS", + "publish-name": { + "alias-or-initials": "Benutzername, falls vorhanden, oder die Initialen von Vorname und Nachname", + "first": "nur Vornamen", + "first-initial": "Vorname plus Anfangsbuchstabe des Nachnamens", + "initials": "Initialen von Vor- und Nachname unabhängig von der Existenz des Benutzernamens", + "name-full": "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.", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 982d22159..4756c00bf 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -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,20 @@ }, "settings": { "emailInfo": "Cannot be changed at this time.", + "GMS": { + "disabled": "Data not exported to GMS", + "enabled": "Data exported to GMS", + "naming-format": "Format of name in GMS", + "publish-name": { + "alias-or-initials": "username if exists or Initials of firstname and lastname", + "first": "firstname only", + "first-initial": "firstname plus initial of lastname", + "initials": "Initials of firstname and lastname independent if username exists", + "name-full": "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.", diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue index 1530e5e97..38a3317bf 100644 --- a/frontend/src/pages/Settings.vue +++ b/frontend/src/pages/Settings.vue @@ -1,81 +1,113 @@ From 1a40d690976d324a8f6cd3df54aecd6e3612ba73 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 4 Apr 2024 22:40:17 +0200 Subject: [PATCH 43/88] change config for gms-usage --- backend/.env.dist | 6 ++++-- backend/.env.template | 5 ++++- deployment/bare_metal/.env.dist | 5 +++-- frontend/src/locales/de.json | 2 +- frontend/src/locales/en.json | 2 +- frontend/src/locales/fr.json | 2 +- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index 4ec60d856..6a407fa9c 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -68,5 +68,7 @@ FEDERATION_XCOM_SENDCOINS_ENABLED=false # GMS # GMS_ACTIVE=true # Coordinates of Illuminz test instance -#GMS_URL=http://54.176.169.179:3071 -GMS_URL=http://localhost:4044/ +#GMS_API_URL=http://54.176.169.179:3071 +GMS_API_URL=http://localhost:4044/ +GMS_DASHBOARD_URL=http://localhost:8080/ + diff --git a/backend/.env.template b/backend/.env.template index 1cff23d5a..3d1d1298f 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -66,4 +66,7 @@ FEDERATION_XCOM_SENDCOINS_ENABLED=$FEDERATION_XCOM_SENDCOINS_ENABLED # GMS GMS_ACTIVE=$GMS_ACTIVE -GMS_URL=$GMS_URL +GMS_API_URL=$GMS_API_URL +GMS_DASHBOARD_URL=$GMS_DASHBOARD_URL +GMS_WEBHOOK_SECRET=$GMS_WEBHOOK_SECRET +GMS_CREATE_USER_THROW_ERRORS=$GMS_CREATE_USER_THROW_ERRORS diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 3da4bd319..d3f6c356b 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -122,5 +122,6 @@ WEBHOOK_ELOPAGE_SECRET=secret # GMS GMS_ACTIVE=false # Coordinates of Illuminz test instance -#GMS_URL=http://54.176.169.179:3071 -GMS_URL=http://localhost:4044/ +#GMS_API_URL=http://54.176.169.179:3071 +GMS_API_URL=http://localhost:4044/ +GMS_DASHBOARD_URL=http://localhost:8080/ diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index f2f4f6205..658357e2f 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -415,7 +415,7 @@ }, "usersearch": { "headline": "Gradido GMS-Nutzersuche", - "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden.", + "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden. Mit dem Button wird ein neues Browser-Fenster geöffnet und dir direkt die Nutzer in deinem Umfeld auf einer Karte angezeigt.", "button": "Starte die Nutzersuche..." }, "via_link": "über einen Link", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index c3bf40e29..b0d6b4bb9 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -415,7 +415,7 @@ }, "usersearch": { "headline": "Gradido GMS-UserSearch", - "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden.", + "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden. Mit dem Button wird ein neues Browser-Fenster geöffnet und dir direkt die Nutzer in deinem Umfeld auf einer Karte angezeigt.", "button": "Start the User-Search..." }, "via_link": "via Link", diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index 4581a3c07..28141edbf 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -356,7 +356,7 @@ }, "usersearch": { "headline": "Gradido GMS-Recherche d'Utilisateur", - "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden.", + "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden. Mit dem Button wird ein neues Browser-Fenster geöffnet und dir direkt die Nutzer in deinem Umfeld auf einer Karte angezeigt.", "button": "Lancer le Recherche d'Utilisateur..." }, "via_link": "par lien", From 7366aef1e3ca3c073922b4b8e1c39737553128d5 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Tue, 9 Apr 2024 21:12:26 +0200 Subject: [PATCH 44/88] multi line usersearch text for all supported languages --- frontend/src/locales/de.json | 6 +++--- frontend/src/locales/en.json | 10 +++++----- frontend/src/locales/es.json | 19 ++++++++++++++++++- frontend/src/locales/fr.json | 10 +++++----- frontend/src/locales/nl.json | 19 ++++++++++++++++++- frontend/src/pages/UserSearch.vue | 8 +++++++- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 658357e2f..4e68b4efc 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -280,7 +280,7 @@ "send": "Sende Gradidos", "settings": "Einstellungen", "transactions": "Deine Transaktionen", - "usersearch": "GMS Nutzersuche" + "usersearch": "Geografische Nutzersuche" }, "qrCode": "QR Code", "send_gdd": "GDD versenden", @@ -414,8 +414,8 @@ "send_you": "sendet dir" }, "usersearch": { - "headline": "Gradido GMS-Nutzersuche", - "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden. Mit dem Button wird ein neues Browser-Fenster geöffnet und dir direkt die Nutzer in deinem Umfeld auf einer Karte angezeigt.", + "headline": "Geografische Nutzersuche", + "text": "Ganz gleich zu welcher Community du gehörst, mit dem Geo Matching System findest du Mitglieder aller Communities auf einer Landkarte. Du kannst nach Angeboten und Bedürfnissen filtern und dir die Nutzer anzeigen lassen, die zu Dir passen.\n\nMit dem Button wird ein neues Browser-Fenster geöffnet, in dem dir die Nutzer in deinem Umfeld auf einer Karte angezeigt werden.", "button": "Starte die Nutzersuche..." }, "via_link": "über einen Link", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index b0d6b4bb9..364e0a830 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -269,7 +269,7 @@ "settings": "Settings", "support": "Support", "transactions": "Transactions", - "usersearch": "User Search" + "usersearch": "Geographical User Search" }, "openHours": "Open Hours", "pageTitle": { @@ -280,7 +280,7 @@ "send": "Send Gradidos", "settings": "Settings", "transactions": "Your transactions", - "usersearch": "GMS User-Search" + "usersearch": "User search" }, "qrCode": "QR Code", "send_gdd": "Send GDD", @@ -414,9 +414,9 @@ "send_you": "wants to send you" }, "usersearch": { - "headline": "Gradido GMS-UserSearch", - "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden. Mit dem Button wird ein neues Browser-Fenster geöffnet und dir direkt die Nutzer in deinem Umfeld auf einer Karte angezeigt.", - "button": "Start the User-Search..." + "headline": "Geographical User Search", + "text": "No matter which community you belong to, with the Geo Matching System you can find members of all communities on a map. You can filter according to offers and needs and display the users that match you.\n\nThe button opens a new browser window in which the users in your area are displayed on a map.", + "button": "Start user search... " }, "via_link": "via Link", "welcome": "Welcome to the community" diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 6e52fd9a1..2f3bbf50d 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -242,7 +242,19 @@ "profile": "Mi Perfil", "send": "Enviar", "support": "Soporte", - "transactions": "Transacciones" + "transactions": "Transacciones", + "usersearch": "Buscar usuarios" + }, + "openHours": "Open Hours", + "pageTitle": { + "community": "Create Gradido", + "gdt": "Your GDT transactions", + "information": "{community}", + "overview": "Welcome {name}", + "send": "Enviar Gradidos", + "settings": "Settings", + "transactions": "Your transactions", + "usersearch": "Búsqueda geográfica de usuarios" }, "qrCode": "Código QR", "send_gdd": "Enviar GDD", @@ -334,6 +346,11 @@ "transaction-link": { "send_you": "te envía" }, + "usersearch": { + "headline": "Búsqueda geográfica de usuarios", + "text": "No importa a qué comunidad pertenezcas, con el Geo Matching System puedes encontrar miembros de todas las comunidades en un mapa. Puedes filtrar según ofertas y requisitos y visualizar los usuarios que coinciden con tu perfil.\n\nEl botón abre una nueva ventana del navegador en la que se muestran en un mapa los usuarios de tu zona.", + "button": "Iniciar la búsqueda de usuarios..." + }, "via_link": "atraves de un enlace", "welcome": "Bienvenido a la comunidad." } diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index 28141edbf..999060f21 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -251,7 +251,7 @@ "settings": "Configuration", "support": "Aide", "transactions": "Transactions", - "usersearch": "Recherche d'Utilisateur" + "usersearch": "Recherche d'utilisateurs" }, "openHours": "Heures ouverte", "pageTitle": { @@ -262,7 +262,7 @@ "send": "Envoyé Gradidos", "settings": "Configuration", "transactions": "Vos transactions", - "usersearch": "GMS Recherche d'Utilisateur" + "usersearch": "Recherche géographique d'utilisateurs" }, "qrCode": "QR Code", "send_gdd": "Envoyer GDD", @@ -355,9 +355,9 @@ "send_you": "veut vous envoyer" }, "usersearch": { - "headline": "Gradido GMS-Recherche d'Utilisateur", - "text": "Ganz gleich zu welcher Community du gehörst, über die Gradido-Nutzersuche kannst du in einer geographischen Karte deine Community-Mitglieder als auch andere Communities und deren Mitglieder finden. Mit dem Button wird ein neues Browser-Fenster geöffnet und dir direkt die Nutzer in deinem Umfeld auf einer Karte angezeigt.", - "button": "Lancer le Recherche d'Utilisateur..." + "headline": "Recherche géographique d'utilisateurs", + "text": "Quelle que soit la communauté à laquelle tu appartiens, le système de géo-matching te permet de trouver des membres de toutes les communautés sur une carte géographique. Tu peux filtrer selon les offres et les besoins et afficher les utilisateurs qui te correspondent.\n\nEn cliquant sur le bouton, une nouvelle fenêtre de navigateur s'ouvre et t'affiche les utilisateurs de ton entourage sur une carte.", + "button": "Commence la recherche d'utilisateurs..." }, "via_link": "par lien", "welcome": "Bienvenu dans la communauté" diff --git a/frontend/src/locales/nl.json b/frontend/src/locales/nl.json index a1f612f39..2e50f2968 100644 --- a/frontend/src/locales/nl.json +++ b/frontend/src/locales/nl.json @@ -242,7 +242,19 @@ "profile": "Mijn profiel", "send": "Sturen", "support": "Support", - "transactions": "Transacties" + "transactions": "Transacties", + "usersearch": "Gebruiker zoeken" + }, + "openHours": "Open Hours", + "pageTitle": { + "community": "Create Gradido", + "gdt": "Your GDT transactions", + "information": "{community}", + "overview": "Welcome {name}", + "send": "Send Gradidos", + "settings": "Settings", + "transactions": "Your transactions", + "usersearch": "Geografisch zoeken naar gebruikers" }, "qrCode": "QR Code", "send_gdd": "GDD sturen", @@ -334,6 +346,11 @@ "transaction-link": { "send_you": "stuurt jou" }, + "usersearch": { + "headline": "Geografisch zoeken naar gebruikers", + "text": "Het maakt niet uit tot welke community je behoort, met het Geo Matching System kun je leden van alle communities vinden op een kaart. Je kunt filteren op aanbiedingen en vereisten en de gebruikers weergeven die aan je profiel voldoen.\n\nDe knop opent een nieuw browservenster waarin de gebruikers in je omgeving op een kaart worden weergegeven.", + "button": "Start het zoeken naar gebruikers..." + }, "via_link": "via een link", "welcome": "Welkom in de gemeenschap" } diff --git a/frontend/src/pages/UserSearch.vue b/frontend/src/pages/UserSearch.vue index 7123e6619..070a96d7b 100644 --- a/frontend/src/pages/UserSearch.vue +++ b/frontend/src/pages/UserSearch.vue @@ -3,7 +3,13 @@
{{ $t('usersearch.headline') }}
- {{ $t('usersearch.text') }} + + {{ line }} +
+
From 6c31480e31c7b97d0f366eab099b59d82629347a Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Tue, 9 Apr 2024 21:24:29 +0200 Subject: [PATCH 45/88] correct pagetitles for language, but still needs a review --- frontend/src/locales/en.json | 2 +- frontend/src/locales/es.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 364e0a830..9db96439e 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -280,7 +280,7 @@ "send": "Send Gradidos", "settings": "Settings", "transactions": "Your transactions", - "usersearch": "User search" + "usersearch": "Geographical User Search" }, "qrCode": "QR Code", "send_gdd": "Send GDD", diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 2f3bbf50d..bc5479029 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -248,12 +248,12 @@ "openHours": "Open Hours", "pageTitle": { "community": "Create Gradido", - "gdt": "Your GDT transactions", + "gdt": "Tu GDT Transacciones", "information": "{community}", "overview": "Welcome {name}", "send": "Enviar Gradidos", - "settings": "Settings", - "transactions": "Your transactions", + "settings": "Soporte", + "transactions": "Tu Transacciones", "usersearch": "Búsqueda geográfica de usuarios" }, "qrCode": "Código QR", From 051e7212f29a972c28fb0d0e10c938dd0e67cd77 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Wed, 10 Apr 2024 18:13:50 +0200 Subject: [PATCH 46/88] add tests for usersearch --- frontend/src/components/Menu/Sidebar.spec.js | 6 +- frontend/src/pages/UserSearch.spec.js | 80 ++++++++++++++++++++ frontend/src/routes/router.test.js | 15 +++- 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 frontend/src/pages/UserSearch.spec.js diff --git a/frontend/src/components/Menu/Sidebar.spec.js b/frontend/src/components/Menu/Sidebar.spec.js index 23c855557..77a525f3b 100644 --- a/frontend/src/components/Menu/Sidebar.spec.js +++ b/frontend/src/components/Menu/Sidebar.spec.js @@ -34,7 +34,7 @@ describe('Sidebar', () => { describe('the genaral section', () => { it('has six nav-items', () => { - expect(wrapper.findAll('ul').at(0).findAll('.nav-item')).toHaveLength(6) + expect(wrapper.findAll('ul').at(0).findAll('.nav-item')).toHaveLength(7) }) it('has nav-item "navigation.overview" in navbar', () => { @@ -60,6 +60,10 @@ describe('Sidebar', () => { it('has nav-item "navigation.info" in navbar', () => { expect(wrapper.findAll('.nav-item').at(5).text()).toContain('navigation.info') }) + + it('has nav-item "usersearch" in navbar', () => { + expect(wrapper.findAll('.nav-item').at(6).text()).toContain('navigation.usersearch') + }) }) describe('the specific section', () => { diff --git a/frontend/src/pages/UserSearch.spec.js b/frontend/src/pages/UserSearch.spec.js new file mode 100644 index 000000000..20116b523 --- /dev/null +++ b/frontend/src/pages/UserSearch.spec.js @@ -0,0 +1,80 @@ +import { mount, RouterLinkStub } from '@vue/test-utils' +import UserSearch from './UserSearch' +import { toastErrorSpy } from '../../test/testSetup' +import { authenticateGmsUserSearch } from '@/graphql/queries' + +const localVue = global.localVue + +window.scrollTo = jest.fn() + +const stubs = { + RouterLink: RouterLinkStub, +} + +const apolloQueryMock = jest + .fn() + .mockResolvedValueOnce({ + data: { + authenticateGmsUserSearch: { + gmsUri: 'http://localhost:8080/playground?not initialized', + }, + }, + }) + .mockResolvedValue('default') + + +describe('UserSearch', () => { + let wrapper + + const mocks = { + $t: jest.fn((t) => t), + $n: jest.fn(), + $i18n: { + locale: 'en', + }, + $apollo: { + query: apolloQueryMock, + }, + } + + const Wrapper = () => { + return mount(UserSearch, { + localVue, + mocks, + }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders the usersearch page', () => { + expect(wrapper.find('div.usersearch').exists()).toBeTruthy() + }) + + it('calls authenticateGmsUserSearch', () => { + expect(apolloQueryMock).toBeCalledWith( + expect.objectContaining({ + query: authenticateGmsUserSearch, + }), + ) + }) + + describe('error apolloQueryMock', () => { + beforeEach(async () => { + jest.clearAllMocks() + apolloQueryMock.mockRejectedValue({ + message: 'uups', + }) + wrapper = Wrapper() + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith( + 'authenticateGmsUserSearch failed!', + ) + }) + }) + }) +}) diff --git a/frontend/src/routes/router.test.js b/frontend/src/routes/router.test.js index 6d7e7b2a0..af6b1c431 100644 --- a/frontend/src/routes/router.test.js +++ b/frontend/src/routes/router.test.js @@ -49,8 +49,8 @@ describe('router', () => { expect(routes.find((r) => r.path === '/').redirect()).toEqual({ path: '/login' }) }) - it('has 19 routes defined', () => { - expect(routes).toHaveLength(19) + it('has 20 routes defined', () => { + expect(routes).toHaveLength(20) }) describe('overview', () => { @@ -142,6 +142,17 @@ describe('router', () => { }) }) + describe('usersearch', () => { + it('requires authorization', () => { + expect(routes.find((r) => r.path === '/usersearch').meta.requiresAuth).toBeTruthy() + }) + + it('loads the "UserSearch" page', async () => { + const component = await routes.find((r) => r.path === '/usersearch').component() + expect(component.default.name).toBe('UserSearch') + }) + }) + describe('gdt', () => { it('requires authorization', () => { expect(routes.find((r) => r.path === '/gdt').meta.requiresAuth).toBeTruthy() From 569a89ce2dc74796ed837e0b2b388cb40ac80509 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Wed, 10 Apr 2024 21:02:22 +0200 Subject: [PATCH 47/88] linting --- frontend/src/pages/UserSearch.spec.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/UserSearch.spec.js b/frontend/src/pages/UserSearch.spec.js index 20116b523..7a991ac0f 100644 --- a/frontend/src/pages/UserSearch.spec.js +++ b/frontend/src/pages/UserSearch.spec.js @@ -1,4 +1,4 @@ -import { mount, RouterLinkStub } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import UserSearch from './UserSearch' import { toastErrorSpy } from '../../test/testSetup' import { authenticateGmsUserSearch } from '@/graphql/queries' @@ -7,10 +7,6 @@ const localVue = global.localVue window.scrollTo = jest.fn() -const stubs = { - RouterLink: RouterLinkStub, -} - const apolloQueryMock = jest .fn() .mockResolvedValueOnce({ @@ -22,7 +18,6 @@ const apolloQueryMock = jest }) .mockResolvedValue('default') - describe('UserSearch', () => { let wrapper @@ -71,9 +66,7 @@ describe('UserSearch', () => { }) it('toasts an error message', () => { - expect(toastErrorSpy).toBeCalledWith( - 'authenticateGmsUserSearch failed!', - ) + expect(toastErrorSpy).toBeCalledWith('authenticateGmsUserSearch failed!') }) }) }) From e44da4d6a3298bdd0247cf7d0f76ed21bbb17989 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 11 Apr 2024 00:40:38 +0200 Subject: [PATCH 48/88] rework review comments --- backend/src/apis/gms/GmsClient.ts | 19 +++++++------------ backend/src/util/utilities.ts | 4 ++++ deployment/bare_metal/.env.dist | 2 ++ frontend/public/img/{svg => }/loupe.png | Bin frontend/src/components/Menu/Sidebar.vue | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) rename frontend/public/img/{svg => }/loupe.png (100%) diff --git a/backend/src/apis/gms/GmsClient.ts b/backend/src/apis/gms/GmsClient.ts index 6708c5fc2..e5ce08bbf 100644 --- a/backend/src/apis/gms/GmsClient.ts +++ b/backend/src/apis/gms/GmsClient.ts @@ -9,10 +9,11 @@ import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' import { GmsUser } from './model/GmsUser' +import { ensureUrlEndsWithSlash } from '@/util/utilities' /* export async function communityList(): Promise { - const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/') + const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_URL) const service = 'community/list?page=1&perPage=20' const config = { headers: { @@ -44,7 +45,7 @@ export async function communityList(): Promise { - const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/') + const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_URL) const service = 'community-user/list?page=1&perPage=20' const config = { headers: { @@ -80,7 +81,7 @@ export async function userList(): Promise { } export async function userByUuid(uuid: string): Promise { - const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/') + const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_URL) const service = 'community-user/list?page=1&perPage=20' const config = { headers: { @@ -118,9 +119,7 @@ export async function userByUuid(uuid: string): Promise { if (CONFIG.GMS_ACTIVE) { - const baseUrl = CONFIG.GMS_API_URL.endsWith('/') - ? CONFIG.GMS_API_URL - : CONFIG.GMS_API_URL.concat('/') + const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_API_URL) const service = 'community-user' const config = { headers: { @@ -154,9 +153,7 @@ export async function createGmsUser(apiKey: string, user: GmsUser): Promise { if (CONFIG.GMS_ACTIVE) { - const baseUrl = CONFIG.GMS_API_URL.endsWith('/') - ? CONFIG.GMS_API_URL - : CONFIG.GMS_API_URL.concat('/') + const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_API_URL) const service = 'community-user' const config = { headers: { @@ -193,9 +190,7 @@ export async function verifyAuthToken( communityUuid: string, token: string, ): Promise { - const baseUrl = CONFIG.GMS_API_URL.endsWith('/') - ? CONFIG.GMS_API_URL - : CONFIG.GMS_API_URL.concat('/') + const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_API_URL) const service = 'verify-auth-token?token='.concat(token).concat('&uuid=').concat(communityUuid) const config = { headers: { diff --git a/backend/src/util/utilities.ts b/backend/src/util/utilities.ts index c3895cb9e..bc2c2198a 100644 --- a/backend/src/util/utilities.ts +++ b/backend/src/util/utilities.ts @@ -29,3 +29,7 @@ export function resetInterface>(obj: T): T { } return obj } + +export const ensureUrlEndsWithSlash = (url: string): string => { + return url.endsWith('/') ? url : url.concat('/') +} diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index d3f6c356b..64ba8f66b 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -125,3 +125,5 @@ GMS_ACTIVE=false #GMS_API_URL=http://54.176.169.179:3071 GMS_API_URL=http://localhost:4044/ GMS_DASHBOARD_URL=http://localhost:8080/ +GMS_WEBHOOK_SECRET=secret +GMS_CREATE_USER_THROW_ERRORS=false \ No newline at end of file diff --git a/frontend/public/img/svg/loupe.png b/frontend/public/img/loupe.png similarity index 100% rename from frontend/public/img/svg/loupe.png rename to frontend/public/img/loupe.png diff --git a/frontend/src/components/Menu/Sidebar.vue b/frontend/src/components/Menu/Sidebar.vue index 2421c82c2..227275786 100644 --- a/frontend/src/components/Menu/Sidebar.vue +++ b/frontend/src/components/Menu/Sidebar.vue @@ -33,7 +33,7 @@ {{ $t('navigation.info') }} - + {{ $t('navigation.usersearch') }} From 6f71c3a4e4c2e7c0aa5e886042144147ed7cb729 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 11 Apr 2024 00:44:48 +0200 Subject: [PATCH 49/88] linting --- backend/src/apis/gms/GmsClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/apis/gms/GmsClient.ts b/backend/src/apis/gms/GmsClient.ts index e5ce08bbf..a59f7f6b5 100644 --- a/backend/src/apis/gms/GmsClient.ts +++ b/backend/src/apis/gms/GmsClient.ts @@ -7,9 +7,9 @@ import axios from 'axios' import { CONFIG } from '@/config' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' +import { ensureUrlEndsWithSlash } from '@/util/utilities' import { GmsUser } from './model/GmsUser' -import { ensureUrlEndsWithSlash } from '@/util/utilities' /* export async function communityList(): Promise { From eac886e7b2af8255fdc9427972608fbf8be9d265 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 11 Apr 2024 16:42:09 +0200 Subject: [PATCH 50/88] refactor to use ensureUrlEndsWithSlash() instead of duplicate code --- backend/src/federation/authenticateCommunities.ts | 5 ++--- backend/src/federation/client/1_0/AuthenticationClient.ts | 5 ++--- backend/src/federation/client/1_0/FederationClient.ts | 5 ++--- backend/src/federation/client/1_0/SendCoinsClient.ts | 5 ++--- backend/src/federation/client/FederationClientFactory.ts | 6 ++---- backend/src/graphql/model/FederatedCommunity.ts | 4 +++- .../graphql/resolver/util/authenticateGmsUserPlayground.ts | 5 ++--- 7 files changed, 15 insertions(+), 20 deletions(-) diff --git a/backend/src/federation/authenticateCommunities.ts b/backend/src/federation/authenticateCommunities.ts index 8da8306fd..56899d4b0 100644 --- a/backend/src/federation/authenticateCommunities.ts +++ b/backend/src/federation/authenticateCommunities.ts @@ -6,6 +6,7 @@ import { CONFIG } from '@/config' // eslint-disable-next-line camelcase import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient' import { backendLogger as logger } from '@/server/logger' +import { ensureUrlEndsWithSlash } from '@/util/utilities' import { OpenConnectionArgs } from './client/1_0/model/OpenConnectionArgs' import { AuthenticationClientFactory } from './client/AuthenticationClientFactory' @@ -39,9 +40,7 @@ export async function startCommunityAuthentication( const args = new OpenConnectionArgs() args.publicKey = homeCom.publicKey.toString('hex') // TODO encrypt url with foreignCom.publicKey and sign it with homeCom.privateKey - args.url = homeFedCom.endPoint.endsWith('/') - ? homeFedCom.endPoint - : homeFedCom.endPoint + '/' + homeFedCom.apiVersion + args.url = ensureUrlEndsWithSlash(homeFedCom.endPoint).concat(homeFedCom.apiVersion) logger.debug( 'Authentication: before client.openConnection() args:', homeCom.publicKey.toString('hex'), diff --git a/backend/src/federation/client/1_0/AuthenticationClient.ts b/backend/src/federation/client/1_0/AuthenticationClient.ts index f73393255..6ee69d00d 100644 --- a/backend/src/federation/client/1_0/AuthenticationClient.ts +++ b/backend/src/federation/client/1_0/AuthenticationClient.ts @@ -2,6 +2,7 @@ import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCom import { GraphQLClient } from 'graphql-request' import { backendLogger as logger } from '@/server/logger' +import { ensureUrlEndsWithSlash } from '@/util/utilities' import { OpenConnectionArgs } from './model/OpenConnectionArgs' import { openConnection } from './query/openConnection' @@ -13,9 +14,7 @@ export class AuthenticationClient { constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom - this.endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${ - dbCom.apiVersion - }/` + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) this.client = new GraphQLClient(this.endpoint, { method: 'POST', jsonSerializer: { diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts index b9939a12c..4612e6d62 100644 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ b/backend/src/federation/client/1_0/FederationClient.ts @@ -4,6 +4,7 @@ import { GraphQLClient } from 'graphql-request' import { getPublicCommunityInfo } from '@/federation/client/1_0/query/getPublicCommunityInfo' import { getPublicKey } from '@/federation/client/1_0/query/getPublicKey' import { backendLogger as logger } from '@/server/logger' +import { ensureUrlEndsWithSlash } from '@/util/utilities' import { PublicCommunityInfoLoggingView } from './logging/PublicCommunityInfoLogging.view' import { GetPublicKeyResult } from './model/GetPublicKeyResult' @@ -16,9 +17,7 @@ export class FederationClient { constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom - this.endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${ - dbCom.apiVersion - }/` + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) this.client = new GraphQLClient(this.endpoint, { method: 'GET', jsonSerializer: { diff --git a/backend/src/federation/client/1_0/SendCoinsClient.ts b/backend/src/federation/client/1_0/SendCoinsClient.ts index bcf303584..03fefe70a 100644 --- a/backend/src/federation/client/1_0/SendCoinsClient.ts +++ b/backend/src/federation/client/1_0/SendCoinsClient.ts @@ -3,6 +3,7 @@ import { GraphQLClient } from 'graphql-request' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' +import { ensureUrlEndsWithSlash } from '@/util/utilities' import { SendCoinsArgsLoggingView } from './logging/SendCoinsArgsLogging.view' import { SendCoinsResultLoggingView } from './logging/SendCoinsResultLogging.view' @@ -20,9 +21,7 @@ export class SendCoinsClient { constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom - this.endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${ - dbCom.apiVersion - }/` + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) this.client = new GraphQLClient(this.endpoint, { method: 'POST', jsonSerializer: { diff --git a/backend/src/federation/client/FederationClientFactory.ts b/backend/src/federation/client/FederationClientFactory.ts index fe2ff0dbd..6010fa5eb 100644 --- a/backend/src/federation/client/FederationClientFactory.ts +++ b/backend/src/federation/client/FederationClientFactory.ts @@ -5,6 +5,7 @@ import { FederationClient as V1_0_FederationClient } from '@/federation/client/1 // eslint-disable-next-line camelcase import { FederationClient as V1_1_FederationClient } from '@/federation/client/1_1/FederationClient' import { ApiVersionType } from '@/federation/enum/apiVersionType' +import { ensureUrlEndsWithSlash } from '@/util/utilities' // eslint-disable-next-line camelcase type FederationClient = V1_0_FederationClient | V1_1_FederationClient @@ -47,10 +48,7 @@ export class FederationClientFactory { const instance = FederationClientFactory.instanceArray.find( (instance) => instance.id === dbCom.id, ) - // TODO: found a way to prevent double code with FederationClient::constructor - const endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${ - dbCom.apiVersion - }/` + const endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) // check if endpoint is still the same and not changed meanwhile if (instance && instance.client.getEndpoint() === endpoint) { return instance.client diff --git a/backend/src/graphql/model/FederatedCommunity.ts b/backend/src/graphql/model/FederatedCommunity.ts index fb30b0292..01a3996ce 100644 --- a/backend/src/graphql/model/FederatedCommunity.ts +++ b/backend/src/graphql/model/FederatedCommunity.ts @@ -1,6 +1,8 @@ import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' import { ObjectType, Field, Int } from 'type-graphql' +import { ensureUrlEndsWithSlash } from '@/util/utilities' + @ObjectType() export class FederatedCommunity { constructor(dbCom: DbFederatedCommunity) { @@ -8,7 +10,7 @@ export class FederatedCommunity { this.foreign = dbCom.foreign this.publicKey = dbCom.publicKey.toString('hex') this.apiVersion = dbCom.apiVersion - this.endPoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/' + this.endPoint = ensureUrlEndsWithSlash(dbCom.endPoint) this.lastAnnouncedAt = dbCom.lastAnnouncedAt this.verifiedAt = dbCom.verifiedAt this.lastErrorAt = dbCom.lastErrorAt diff --git a/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts b/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts index 3f1677244..ef3c199c9 100644 --- a/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts +++ b/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts @@ -4,15 +4,14 @@ import { verifyAuthToken } from '@/apis/gms/GmsClient' import { CONFIG } from '@/config' import { GmsUserAuthenticationResult } from '@/graphql/model/GmsUserAuthenticationResult' import { backendLogger as logger } from '@/server/logger' +import { ensureUrlEndsWithSlash } from '@/util/utilities' export async function authenticateGmsUserPlayground( token: string, dbUser: DbUser, ): Promise { const result = new GmsUserAuthenticationResult() - const dashboardUrl = CONFIG.GMS_DASHBOARD_URL.endsWith('/') - ? CONFIG.GMS_DASHBOARD_URL - : CONFIG.GMS_DASHBOARD_URL.concat('/') + const dashboardUrl = ensureUrlEndsWithSlash(CONFIG.GMS_DASHBOARD_URL) result.url = dashboardUrl.concat('playground') result.token = await verifyAuthToken(dbUser.communityUuid, token) From ad182c2948436643955f768be112f977ba5b8850 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 11 Apr 2024 16:54:31 +0200 Subject: [PATCH 51/88] correct refactoring --- backend/src/federation/client/1_0/AuthenticationClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/federation/client/1_0/AuthenticationClient.ts b/backend/src/federation/client/1_0/AuthenticationClient.ts index 6ee69d00d..c1d921823 100644 --- a/backend/src/federation/client/1_0/AuthenticationClient.ts +++ b/backend/src/federation/client/1_0/AuthenticationClient.ts @@ -14,7 +14,7 @@ export class AuthenticationClient { constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom - this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion).concat('/') this.client = new GraphQLClient(this.endpoint, { method: 'POST', jsonSerializer: { From fdc5850e8ea8515bef486376607a605141b190ef Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 11 Apr 2024 16:56:42 +0200 Subject: [PATCH 52/88] correct refactoring --- backend/src/federation/client/1_0/FederationClient.ts | 2 +- backend/src/federation/client/1_0/SendCoinsClient.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts index 4612e6d62..0c2b4101b 100644 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ b/backend/src/federation/client/1_0/FederationClient.ts @@ -17,7 +17,7 @@ export class FederationClient { constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom - this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion).concat('/') this.client = new GraphQLClient(this.endpoint, { method: 'GET', jsonSerializer: { diff --git a/backend/src/federation/client/1_0/SendCoinsClient.ts b/backend/src/federation/client/1_0/SendCoinsClient.ts index 03fefe70a..2c3fcce4c 100644 --- a/backend/src/federation/client/1_0/SendCoinsClient.ts +++ b/backend/src/federation/client/1_0/SendCoinsClient.ts @@ -21,7 +21,7 @@ export class SendCoinsClient { constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom - this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion) + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion).concat('/') this.client = new GraphQLClient(this.endpoint, { method: 'POST', jsonSerializer: { From fcd02b6a9b572a5bd3ff4564a7edb2ba9fd6b201 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 12 Apr 2024 19:43:36 +0200 Subject: [PATCH 53/88] add humhub switch and name format, refactor and reuse gms code --- backend/src/config/index.ts | 2 +- .../src/graphql/arg/UpdateUserInfosArgs.ts | 8 + backend/src/graphql/model/User.ts | 8 + .../src/graphql/resolver/UserResolver.test.ts | 2 + backend/src/graphql/resolver/UserResolver.ts | 12 +- backend/src/util/communityUser.ts | 2 + .../User.ts | 176 ++++++++++++++++++ database/entity/User.ts | 2 +- .../0084-introduce_humhub_registration.ts | 16 ++ deployment/bare_metal/.env.dist | 3 + dht-node/src/config/index.ts | 2 +- federation/src/config/index.ts | 2 +- frontend/.env.dist | 1 + frontend/.env.template | 3 +- .../components/UserSettings/UserGMSSwitch.vue | 45 ----- ...ormat.spec.js => UserNamingFormat.spec.js} | 17 +- ...SNamingFormat.vue => UserNamingFormat.vue} | 27 +-- .../UserSettings/UserSettingsSwitch.vue | 50 +++++ frontend/src/config/index.js | 1 + frontend/src/graphql/mutations.js | 6 + frontend/src/locales/de.json | 11 ++ frontend/src/locales/en.json | 11 ++ frontend/src/pages/Settings.vue | 125 ++++++++++--- frontend/src/store/store.js | 12 ++ frontend/src/store/store.test.js | 78 ++++++-- 25 files changed, 503 insertions(+), 119 deletions(-) create mode 100644 database/entity/0084-introduce_humhub_registration/User.ts create mode 100644 database/migrations/0084-introduce_humhub_registration.ts delete mode 100644 frontend/src/components/UserSettings/UserGMSSwitch.vue rename frontend/src/components/UserSettings/{UserGMSNamingFormat.spec.js => UserNamingFormat.spec.js} (79%) rename frontend/src/components/UserSettings/{UserGMSNamingFormat.vue => UserNamingFormat.vue} (77%) create mode 100644 frontend/src/components/UserSettings/UserSettingsSwitch.vue diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index dd35d180e..2815db440 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -12,7 +12,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0083-join_community_federated_communities', + DB_VERSION: '0084-introduce_humhub_registration', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info diff --git a/backend/src/graphql/arg/UpdateUserInfosArgs.ts b/backend/src/graphql/arg/UpdateUserInfosArgs.ts index a6c80cddd..d3e3dc744 100644 --- a/backend/src/graphql/arg/UpdateUserInfosArgs.ts +++ b/backend/src/graphql/arg/UpdateUserInfosArgs.ts @@ -46,6 +46,10 @@ export class UpdateUserInfosArgs { @IsBoolean() hideAmountGDT?: boolean + @Field({ nullable: true }) + @IsBoolean() + humhubAllowed?: boolean + @Field({ nullable: true }) @IsBoolean() gmsAllowed?: boolean @@ -54,6 +58,10 @@ export class UpdateUserInfosArgs { @IsEnum(GmsPublishNameType) gmsPublishName?: GmsPublishNameType | null + @Field(() => GmsPublishNameType, { nullable: true }) + @IsEnum(GmsPublishNameType) + humhubPublishName?: GmsPublishNameType | null + @Field(() => Location, { nullable: true }) @isValidLocation() gmsLocation?: Location | null diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index 166367fd1..a6a5ad199 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -32,8 +32,10 @@ export class User { this.hasElopage = null this.hideAmountGDD = user.hideAmountGDD this.hideAmountGDT = user.hideAmountGDT + this.humhubAllowed = user.humhubAllowed this.gmsAllowed = user.gmsAllowed this.gmsPublishName = user.gmsPublishName + this.humhubPublishName = user.humhubPublishName this.gmsPublishLocation = user.gmsPublishLocation } } @@ -80,12 +82,18 @@ export class User { @Field(() => Boolean) hideAmountGDT: boolean + @Field(() => Boolean) + humhubAllowed: boolean + @Field(() => Boolean) gmsAllowed: boolean @Field(() => GmsPublishNameType, { nullable: true }) gmsPublishName: GmsPublishNameType | null + @Field(() => GmsPublishNameType, { nullable: true }) + humhubPublishName: GmsPublishNameType | null + @Field(() => GmsPublishLocationType, { nullable: true }) gmsPublishLocation: GmsPublishLocationType | null diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index e7c873fc4..4fdf387b7 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -183,7 +183,9 @@ describe('UserResolver', () => { communityUuid: homeCom.communityUuid, foreign: false, gmsAllowed: true, + humhubAllowed: false, gmsPublishName: 0, + humhubPublishName: 0, gmsPublishLocation: 2, location: null, gmsRegistered: false, diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 7c11776df..436c0aa83 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -394,8 +394,8 @@ export class UserResolver { logger.addContext('user', 'unknown') logger.info(`forgotPassword(${email})...`) email = email.trim().toLowerCase() - const user = await findUserByEmail(email).catch(() => { - logger.warn(`fail on find UserContact per ${email}`) + const user = await findUserByEmail(email).catch((error) => { + logger.warn(`fail on find UserContact per ${email} because: ${error}`) }) if (!user || user.deletedAt) { @@ -559,8 +559,10 @@ export class UserResolver { passwordNew, hideAmountGDD, hideAmountGDT, + humhubAllowed, gmsAllowed, gmsPublishName, + humhubPublishName, gmsLocation, gmsPublishLocation, } = updateUserInfosArgs @@ -617,12 +619,18 @@ export class UserResolver { if (hideAmountGDT !== undefined) { user.hideAmountGDT = hideAmountGDT } + if (humhubAllowed !== undefined) { + user.humhubAllowed = humhubAllowed + } if (gmsAllowed !== undefined) { user.gmsAllowed = gmsAllowed } if (gmsPublishName !== null && gmsPublishName !== undefined) { user.gmsPublishName = gmsPublishName } + if (humhubPublishName !== null && humhubPublishName !== undefined) { + user.humhubPublishName = humhubPublishName + } if (gmsLocation) { user.location = Location2Point(gmsLocation) } diff --git a/backend/src/util/communityUser.ts b/backend/src/util/communityUser.ts index 732c585d0..45a142ce8 100644 --- a/backend/src/util/communityUser.ts +++ b/backend/src/util/communityUser.ts @@ -52,7 +52,9 @@ const communityDbUser: dbUser = { communityUuid: '55555555-4444-4333-2222-11111111', community: null, gmsPublishName: 0, + humhubPublishName: 0, gmsAllowed: false, + humhubAllowed: false, location: null, gmsPublishLocation: 2, gmsRegistered: false, diff --git a/database/entity/0084-introduce_humhub_registration/User.ts b/database/entity/0084-introduce_humhub_registration/User.ts new file mode 100644 index 000000000..a375f6748 --- /dev/null +++ b/database/entity/0084-introduce_humhub_registration/User.ts @@ -0,0 +1,176 @@ +import { + BaseEntity, + Entity, + PrimaryGeneratedColumn, + Column, + DeleteDateColumn, + OneToMany, + JoinColumn, + OneToOne, + Geometry, + ManyToOne, +} from 'typeorm' +import { Contribution } from '../Contribution' +import { ContributionMessage } from '../ContributionMessage' +import { UserContact } from '../UserContact' +import { UserRole } from '../UserRole' +import { GeometryTransformer } from '../../src/typeorm/GeometryTransformer' +import { Community } from '../Community' + +@Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) +export class User extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ type: 'bool', default: false }) + foreign: boolean + + @Column({ + name: 'gradido_id', + length: 36, + nullable: false, + collation: 'utf8mb4_unicode_ci', + }) + gradidoID: string + + @Column({ + name: 'community_uuid', + type: 'char', + length: 36, + nullable: true, + collation: 'utf8mb4_unicode_ci', + }) + communityUuid: string + + @ManyToOne(() => Community, (community) => community.users) + @JoinColumn({ name: 'community_uuid', referencedColumnName: 'communityUuid' }) + community: Community | null + + @Column({ + name: 'alias', + length: 20, + nullable: true, + default: null, + collation: 'utf8mb4_unicode_ci', + }) + alias: string + + @OneToOne(() => UserContact, (emailContact: UserContact) => emailContact.user) + @JoinColumn({ name: 'email_id' }) + emailContact: UserContact + + @Column({ name: 'email_id', type: 'int', unsigned: true, nullable: true, default: null }) + emailId: number | null + + @Column({ + name: 'first_name', + length: 255, + nullable: true, + default: null, + collation: 'utf8mb4_unicode_ci', + }) + firstName: string + + @Column({ + name: 'last_name', + length: 255, + nullable: true, + default: null, + collation: 'utf8mb4_unicode_ci', + }) + lastName: string + + @Column({ name: 'gms_publish_name', type: 'int', unsigned: true, nullable: false, default: 0 }) + gmsPublishName: number + + @Column({ name: 'humhub_publish_name', type: 'int', unsigned: true, nullable: false, default: 0 }) + humhubPublishName: number + + @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false }) + createdAt: Date + + @DeleteDateColumn({ name: 'deleted_at', nullable: true }) + deletedAt: Date | null + + @Column({ type: 'bigint', default: 0, unsigned: true }) + password: BigInt + + @Column({ + name: 'password_encryption_type', + type: 'int', + unsigned: true, + nullable: false, + default: 0, + }) + passwordEncryptionType: number + + @Column({ length: 4, default: 'de', collation: 'utf8mb4_unicode_ci', nullable: false }) + language: string + + @Column({ type: 'bool', default: false }) + hideAmountGDD: boolean + + @Column({ type: 'bool', default: false }) + hideAmountGDT: boolean + + @OneToMany(() => UserRole, (userRole) => userRole.user) + @JoinColumn({ name: 'user_id' }) + userRoles: UserRole[] + + @Column({ name: 'referrer_id', type: 'int', unsigned: true, nullable: true, default: null }) + referrerId?: number | null + + @Column({ + name: 'contribution_link_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + contributionLinkId?: number | null + + @Column({ name: 'publisher_id', default: 0 }) + publisherId: number + + @Column({ name: 'gms_allowed', type: 'bool', default: true }) + gmsAllowed: boolean + + @Column({ + name: 'location', + type: 'geometry', + default: null, + nullable: true, + transformer: GeometryTransformer, + }) + location: Geometry | null + + @Column({ + name: 'gms_publish_location', + type: 'int', + unsigned: true, + nullable: false, + default: 2, + }) + gmsPublishLocation: number + + @Column({ name: 'gms_registered', type: 'bool', default: false }) + gmsRegistered: boolean + + @Column({ name: 'gms_registered_at', type: 'datetime', default: null, nullable: true }) + gmsRegisteredAt: Date | null + + @Column({ name: 'humhub_allowed', type: 'bool', default: false }) + humhubAllowed: boolean + + @OneToMany(() => Contribution, (contribution) => contribution.user) + @JoinColumn({ name: 'user_id' }) + contributions?: Contribution[] + + @OneToMany(() => ContributionMessage, (message) => message.user) + @JoinColumn({ name: 'user_id' }) + messages?: ContributionMessage[] + + @OneToMany(() => UserContact, (userContact: UserContact) => userContact.user) + @JoinColumn({ name: 'user_id' }) + userContacts?: UserContact[] +} diff --git a/database/entity/User.ts b/database/entity/User.ts index e3f15113d..993d983ef 100644 --- a/database/entity/User.ts +++ b/database/entity/User.ts @@ -1 +1 @@ -export { User } from './0082-introduce_gms_registration/User' +export { User } from './0084-introduce_humhub_registration/User' diff --git a/database/migrations/0084-introduce_humhub_registration.ts b/database/migrations/0084-introduce_humhub_registration.ts new file mode 100644 index 000000000..858283602 --- /dev/null +++ b/database/migrations/0084-introduce_humhub_registration.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'ALTER TABLE `users` ADD COLUMN IF NOT EXISTS `humhub_allowed` tinyint(1) NOT NULL DEFAULT 0 AFTER `gms_registered_at`;', + ) + await queryFn( + 'ALTER TABLE `users` ADD COLUMN IF NOT EXISTS `humhub_publish_name` int unsigned NOT NULL DEFAULT 0 AFTER `gms_publish_name`;', + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE `users` DROP COLUMN IF EXISTS `humhub_allowed`;') + await queryFn('ALTER TABLE `users` DROP COLUMN IF EXISTS `humhub_publish_name`;') +} diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 3da4bd319..c3c7112d7 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -124,3 +124,6 @@ GMS_ACTIVE=false # Coordinates of Illuminz test instance #GMS_URL=http://54.176.169.179:3071 GMS_URL=http://localhost:4044/ + +# HUMHUB +HUMHUB_ACTIVE=false \ No newline at end of file diff --git a/dht-node/src/config/index.ts b/dht-node/src/config/index.ts index 4e66aa5f9..f557eee83 100644 --- a/dht-node/src/config/index.ts +++ b/dht-node/src/config/index.ts @@ -4,7 +4,7 @@ import dotenv from 'dotenv' dotenv.config() const constants = { - DB_VERSION: '0083-join_community_federated_communities', + DB_VERSION: '0084-introduce_humhub_registration', LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info LOG_LEVEL: process.env.LOG_LEVEL ?? 'info', diff --git a/federation/src/config/index.ts b/federation/src/config/index.ts index f8992a360..26b727841 100644 --- a/federation/src/config/index.ts +++ b/federation/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0083-join_community_federated_communities', + DB_VERSION: '0084-introduce_humhub_registration', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info diff --git a/frontend/.env.dist b/frontend/.env.dist index f680d9a50..f11a70873 100644 --- a/frontend/.env.dist +++ b/frontend/.env.dist @@ -23,3 +23,4 @@ META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Econo META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" GMS_ACTIVE=false +HUMHUB_ACTIVE=false diff --git a/frontend/.env.template b/frontend/.env.template index c121545da..40d0e7ee1 100644 --- a/frontend/.env.template +++ b/frontend/.env.template @@ -25,4 +25,5 @@ META_KEYWORDS_DE=$META_KEYWORDS_DE META_KEYWORDS_EN=$META_KEYWORDS_EN META_AUTHOR=$META_AUTHOR -GMS_ACTIVE=$GMS_ACTIVE \ No newline at end of file +GMS_ACTIVE=$GMS_ACTIVE +HUMHUB_ACTIVE=$HUMHUB_ACTIVE \ No newline at end of file diff --git a/frontend/src/components/UserSettings/UserGMSSwitch.vue b/frontend/src/components/UserSettings/UserGMSSwitch.vue deleted file mode 100644 index 355beeff2..000000000 --- a/frontend/src/components/UserSettings/UserGMSSwitch.vue +++ /dev/null @@ -1,45 +0,0 @@ - - diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js b/frontend/src/components/UserSettings/UserNamingFormat.spec.js similarity index 79% rename from frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js rename to frontend/src/components/UserSettings/UserNamingFormat.spec.js index 3dbbfdb2c..f07f5e3f2 100644 --- a/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js +++ b/frontend/src/components/UserSettings/UserNamingFormat.spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils' -import UserGMSNamingFormat from './UserGMSNamingFormat.vue' +import UserNamingFormat from './UserNamingFormat.vue' import { toastErrorSpy } from '@test/testSetup' const mockAPIcall = jest.fn() @@ -8,10 +8,10 @@ const storeCommitMock = jest.fn() const localVue = global.localVue -describe('UserGMSNamingFormat', () => { +describe('UserNamingFormat', () => { let wrapper beforeEach(() => { - wrapper = mount(UserGMSNamingFormat, { + wrapper = mount(UserNamingFormat, { mocks: { $t: (key) => key, // Mocking the translation function $store: { @@ -27,6 +27,9 @@ describe('UserGMSNamingFormat', () => { localVue, propsData: { selectedOption: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS', + initialValue: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS', + attrName: 'gmsPublishName', + successMessage: 'success message', }, }) }) @@ -53,16 +56,16 @@ describe('UserGMSNamingFormat', () => { 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']) + expect(wrapper.emitted().valueChanged).toBeTruthy() + expect(wrapper.emitted().valueChanged.length).toBe(1) + expect(wrapper.emitted().valueChanged[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() + expect(wrapper.emitted().valueChanged).toBeFalsy() }) describe('update with error', () => { diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.vue b/frontend/src/components/UserSettings/UserNamingFormat.vue similarity index 77% rename from frontend/src/components/UserSettings/UserGMSNamingFormat.vue rename to frontend/src/components/UserSettings/UserNamingFormat.vue index 29b4cd384..510541219 100644 --- a/frontend/src/components/UserSettings/UserGMSNamingFormat.vue +++ b/frontend/src/components/UserSettings/UserNamingFormat.vue @@ -1,5 +1,5 @@ diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index e9eab2dd7..e574aa008 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -38,9 +38,15 @@ export const mutations = { gmsAllowed: (state, gmsAllowed) => { state.gmsAllowed = gmsAllowed }, + humhubAllowed: (state, humhubAllowed) => { + state.humhubAllowed = humhubAllowed + }, gmsPublishName: (state, gmsPublishName) => { state.gmsPublishName = gmsPublishName }, + humhubPublishName: (state, humhubPublishName) => { + state.humhubPublishName = humhubPublishName + }, gmsPublishLocation: (state, gmsPublishLocation) => { state.gmsPublishLocation = gmsPublishLocation }, @@ -81,7 +87,9 @@ export const actions = { commit('lastName', data.lastName) commit('newsletterState', data.klickTipp.newsletterState) commit('gmsAllowed', data.gmsAllowed) + commit('humhubAllowed', data.humhubAllowed) commit('gmsPublishName', data.gmsPublishName) + commit('humhubPublishName', data.humhubPublishName) commit('gmsPublishLocation', data.gmsPublishLocation) commit('hasElopage', data.hasElopage) commit('publisherId', data.publisherId) @@ -98,7 +106,9 @@ export const actions = { commit('lastName', '') commit('newsletterState', null) commit('gmsAllowed', null) + commit('humhubAllowed', null) commit('gmsPublishName', null) + commit('humhubPublishName', null) commit('gmsPublishLocation', null) commit('hasElopage', false) commit('publisherId', null) @@ -133,7 +143,9 @@ try { roles: [], newsletterState: null, gmsAllowed: null, + humhubAllowed: null, gmsPublishName: null, + humhubPublishName: null, gmsPublishLocation: null, hasElopage: false, publisherId: null, diff --git a/frontend/src/store/store.test.js b/frontend/src/store/store.test.js index 75ab308fd..6d06a3724 100644 --- a/frontend/src/store/store.test.js +++ b/frontend/src/store/store.test.js @@ -29,7 +29,9 @@ const { username, newsletterState, gmsAllowed, + humhubAllowed, gmsPublishName, + humhubPublishName, gmsPublishLocation, publisherId, roles, @@ -133,6 +135,14 @@ describe('Vuex store', () => { }) }) + describe('humhubAllowed', () => { + it('sets the state of humhubAllowed', () => { + const state = { humhubAllowed: null } + humhubAllowed(state, true) + expect(state.humhubAllowed).toEqual(true) + }) + }) + describe('gmsPublishName', () => { it('sets gmsPublishName', () => { const state = { gmsPublishName: null } @@ -141,6 +151,14 @@ describe('Vuex store', () => { }) }) + describe('humhubPublishName', () => { + it('sets humhubPublishName', () => { + const state = { humhubPublishName: null } + humhubPublishName(state, 'GMS_PUBLISH_NAME_INITIALS') + expect(state.humhubPublishName).toEqual('GMS_PUBLISH_NAME_INITIALS') + }) + }) + describe('gmsPublishLocation', () => { it('sets gmsPublishLocation', () => { const state = { gmsPublishLocation: null } @@ -218,7 +236,9 @@ describe('Vuex store', () => { newsletterState: true, }, gmsAllowed: true, + humhubAllowed: false, gmsPublishName: 'GMS_PUBLISH_NAME_FULL', + humhubPublishName: 'GMS_PUBLISH_NAME_FULL', gmsPublishLocation: 'GMS_LOCATION_TYPE_EXACT', hasElopage: false, publisherId: 1234, @@ -227,9 +247,9 @@ describe('Vuex store', () => { hideAmountGDT: true, } - it('calls fifteen commits', () => { + it('calls seventeen commits', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenCalledTimes(15) + expect(commit).toHaveBeenCalledTimes(17) }) it('commits gradidoID', () => { @@ -267,39 +287,49 @@ describe('Vuex store', () => { expect(commit).toHaveBeenNthCalledWith(7, 'gmsAllowed', true) }) + it('commits humhubAllowed', () => { + login({ commit, state }, commitedData) + expect(commit).toHaveBeenNthCalledWith(8, 'humhubAllowed', false) + }) + it('commits gmsPublishName', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(8, 'gmsPublishName', 'GMS_PUBLISH_NAME_FULL') + expect(commit).toHaveBeenNthCalledWith(9, 'gmsPublishName', 'GMS_PUBLISH_NAME_FULL') + }) + + it('commits humhubPublishName', () => { + login({ commit, state }, commitedData) + expect(commit).toHaveBeenNthCalledWith(10, 'humhubPublishName', 'GMS_PUBLISH_NAME_FULL') }) it('commits gmsPublishLocation', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(9, 'gmsPublishLocation', 'GMS_LOCATION_TYPE_EXACT') + expect(commit).toHaveBeenNthCalledWith(11, 'gmsPublishLocation', 'GMS_LOCATION_TYPE_EXACT') }) it('commits hasElopage', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(10, 'hasElopage', false) + expect(commit).toHaveBeenNthCalledWith(12, 'hasElopage', false) }) it('commits publisherId', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(11, 'publisherId', 1234) + expect(commit).toHaveBeenNthCalledWith(13, 'publisherId', 1234) }) it('commits roles', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(12, 'roles', ['admin']) + expect(commit).toHaveBeenNthCalledWith(14, 'roles', ['admin']) }) it('commits hideAmountGDD', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(13, 'hideAmountGDD', false) + expect(commit).toHaveBeenNthCalledWith(15, 'hideAmountGDD', false) }) it('commits hideAmountGDT', () => { login({ commit, state }, commitedData) - expect(commit).toHaveBeenNthCalledWith(14, 'hideAmountGDT', true) + expect(commit).toHaveBeenNthCalledWith(16, 'hideAmountGDT', true) }) }) @@ -307,9 +337,9 @@ describe('Vuex store', () => { const commit = jest.fn() const state = {} - it('calls seventeen commits', () => { + it('calls nineteen commits', () => { logout({ commit, state }) - expect(commit).toHaveBeenCalledTimes(17) + expect(commit).toHaveBeenCalledTimes(19) }) it('commits token', () => { @@ -347,44 +377,54 @@ describe('Vuex store', () => { expect(commit).toHaveBeenNthCalledWith(7, 'gmsAllowed', null) }) + it('commits humhubAllowed', () => { + logout({ commit, state }) + expect(commit).toHaveBeenNthCalledWith(8, 'humhubAllowed', null) + }) + it('commits gmsPublishName', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(8, 'gmsPublishName', null) + expect(commit).toHaveBeenNthCalledWith(9, 'gmsPublishName', null) + }) + + it('commits humhubPublishName', () => { + logout({ commit, state }) + expect(commit).toHaveBeenNthCalledWith(10, 'humhubPublishName', null) }) it('commits gmsPublishLocation', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(9, 'gmsPublishLocation', null) + expect(commit).toHaveBeenNthCalledWith(11, 'gmsPublishLocation', null) }) it('commits hasElopage', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(10, 'hasElopage', false) + expect(commit).toHaveBeenNthCalledWith(12, 'hasElopage', false) }) it('commits publisherId', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(11, 'publisherId', null) + expect(commit).toHaveBeenNthCalledWith(13, 'publisherId', null) }) it('commits roles', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(12, 'roles', null) + expect(commit).toHaveBeenNthCalledWith(14, 'roles', null) }) it('commits hideAmountGDD', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(13, 'hideAmountGDD', false) + expect(commit).toHaveBeenNthCalledWith(15, 'hideAmountGDD', false) }) it('commits hideAmountGDT', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(14, 'hideAmountGDT', true) + expect(commit).toHaveBeenNthCalledWith(16, 'hideAmountGDT', true) }) it('commits email', () => { logout({ commit, state }) - expect(commit).toHaveBeenNthCalledWith(15, 'email', '') + expect(commit).toHaveBeenNthCalledWith(17, 'email', '') }) // how to get this working? From 37e91f86fd5d1d85be016b544b447bea65ce81fe Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 15 Apr 2024 12:48:12 +0200 Subject: [PATCH 54/88] change default alias, add logic class for publishName enum --- backend/src/apis/humhub/model/Account.ts | 5 +- backend/src/data/PublishName.logic.ts | 67 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 backend/src/data/PublishName.logic.ts diff --git a/backend/src/apis/humhub/model/Account.ts b/backend/src/apis/humhub/model/Account.ts index 7b5e794bb..52777e8c8 100644 --- a/backend/src/apis/humhub/model/Account.ts +++ b/backend/src/apis/humhub/model/Account.ts @@ -7,10 +7,7 @@ export class Account { if (user.alias && user.alias.length > 2) { this.username = user.alias } else { - // Use the replace method to remove the part after '+' and before '@' - // source: https://people.cs.rutgers.edu/~watrous/plus-signs-in-email-addresses.html - // email address with + exist but humhub doesn't allow username with + - this.username = user.emailContact.email.replace(/\+(.*)@/, '@') + this.username = user.gradidoID } this.email = user.emailContact.email diff --git a/backend/src/data/PublishName.logic.ts b/backend/src/data/PublishName.logic.ts new file mode 100644 index 000000000..e68a29f86 --- /dev/null +++ b/backend/src/data/PublishName.logic.ts @@ -0,0 +1,67 @@ +import { User } from '@entity/User' + +import { GmsPublishNameType } from '@/graphql/enum/GmsPublishNameType'; + +export class PublishNameLogic { + constructor(private user: User) {} + + /** + * get first name based on publishNameType: GmsPublishNameType value + * @param publishNameType + * @returns user.firstName for GMS_PUBLISH_NAME_FIRST, GMS_PUBLISH_NAME_FIRST_INITIAL or GMS_PUBLISH_NAME_FULL + * first initial from user.firstName for GMS_PUBLISH_NAME_INITIALS or GMS_PUBLISH_NAME_ALIAS_OR_INITALS and empty alias + */ + public getFirstName(publishNameType: GmsPublishNameType): string | undefined { + if ( + [ + GmsPublishNameType.GMS_PUBLISH_NAME_FIRST, + GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL, + GmsPublishNameType.GMS_PUBLISH_NAME_FULL, + ].includes(publishNameType) + ) { + return this.user.firstName + } + if ( + (!this.user.alias && + publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS) || + publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_INITIALS + ) { + return this.user.firstName.substring(0, 1) + } + } + + /** + * get last name based on publishNameType: GmsPublishNameType value + * @param publishNameType + * @returns user.lastName for GMS_PUBLISH_NAME_FULL + * first initial from user.lastName for GMS_PUBLISH_NAME_FIRST_INITIAL, GMS_PUBLISH_NAME_INITIALS or GMS_PUBLISH_NAME_ALIAS_OR_INITALS and empty alias + */ + public getLastName(publishNameType: GmsPublishNameType): string | undefined { + if (publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_FULL) { + return this.user.lastName + } + if ( + (!this.user.alias && + publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS) || + publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL || + publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_INITIALS + ) { + return this.user.lastName.substring(0, 1) + } + } + + public getUsername(publishNameType: GmsPublishNameType): string { + if ( + this.user.alias && + publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS + ) { + return this.user.alias + } + const firstName = this.getFirstName(publishNameType) + const lastName = this.getLastName(publishNameType) + if (firstName && lastName) { + return `${firstName} ${lastName}` + } + return this.user.gradidoID + } +} From cbf8439d6e5d5491c19c4adf0a4477da7b89f770 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 15 Apr 2024 18:54:31 +0200 Subject: [PATCH 55/88] separat enum for multi purpose publish name type --- .../src/graphql/arg/UpdateUserInfosArgs.ts | 7 +- backend/src/graphql/enum/PublishNameType.ts | 19 ++++ backend/src/graphql/model/User.ts | 5 +- .../UserSettings/UserGMSNamingFormat.spec.js | 84 +++++++++++++++++ .../UserSettings/UserGMSNamingFormat.vue | 92 +++++++++++++++++++ .../UserSettings/UserNamingFormat.spec.js | 22 +++-- .../UserSettings/UserNamingFormat.vue | 42 +++++---- frontend/src/graphql/mutations.js | 2 +- frontend/src/locales/de.json | 17 +++- frontend/src/locales/en.json | 17 +++- frontend/src/pages/Settings.vue | 11 ++- 11 files changed, 280 insertions(+), 38 deletions(-) create mode 100644 backend/src/graphql/enum/PublishNameType.ts create mode 100644 frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js create mode 100644 frontend/src/components/UserSettings/UserGMSNamingFormat.vue diff --git a/backend/src/graphql/arg/UpdateUserInfosArgs.ts b/backend/src/graphql/arg/UpdateUserInfosArgs.ts index d3e3dc744..b9617f6df 100644 --- a/backend/src/graphql/arg/UpdateUserInfosArgs.ts +++ b/backend/src/graphql/arg/UpdateUserInfosArgs.ts @@ -3,6 +3,7 @@ import { ArgsType, Field, InputType, Int } from 'type-graphql' import { GmsPublishLocationType } from '@enum/GmsPublishLocationType' import { GmsPublishNameType } from '@enum/GmsPublishNameType' +import { PublishNameType } from '@enum/PublishNameType' import { Location } from '@model/Location' import { isValidLocation } from '@/graphql/validator/Location' @@ -58,9 +59,9 @@ export class UpdateUserInfosArgs { @IsEnum(GmsPublishNameType) gmsPublishName?: GmsPublishNameType | null - @Field(() => GmsPublishNameType, { nullable: true }) - @IsEnum(GmsPublishNameType) - humhubPublishName?: GmsPublishNameType | null + @Field(() => PublishNameType, { nullable: true }) + @IsEnum(PublishNameType) + humhubPublishName?: PublishNameType | null @Field(() => Location, { nullable: true }) @isValidLocation() diff --git a/backend/src/graphql/enum/PublishNameType.ts b/backend/src/graphql/enum/PublishNameType.ts new file mode 100644 index 000000000..5fa86ee9f --- /dev/null +++ b/backend/src/graphql/enum/PublishNameType.ts @@ -0,0 +1,19 @@ +import { registerEnumType } from 'type-graphql' + +/** + * Enum for decide which parts from first- and last-name are allowed to be published in an extern service + */ +export enum PublishNameType { + PUBLISH_NAME_NONE = 0, + PUBLISH_NAME_INITIALS = 1, + PUBLISH_NAME_FIRST = 2, + PUBLISH_NAME_FIRST_INITIAL = 3, + PUBLISH_NAME_LAST = 4, + PUBLISH_NAME_INITIAL_LAST = 5, + PUBLISH_NAME_FULL = 6, +} + +registerEnumType(PublishNameType, { + name: 'PublishNameType', // this one is mandatory + description: 'Type of first- and last-name publishing for extern service', // this one is optional +}) diff --git a/backend/src/graphql/model/User.ts b/backend/src/graphql/model/User.ts index a6a5ad199..aa4baaac0 100644 --- a/backend/src/graphql/model/User.ts +++ b/backend/src/graphql/model/User.ts @@ -3,6 +3,7 @@ import { ObjectType, Field, Int } from 'type-graphql' import { GmsPublishLocationType } from '@enum/GmsPublishLocationType' import { GmsPublishNameType } from '@enum/GmsPublishNameType' +import { PublishNameType } from '@enum/PublishNameType' import { KlickTipp } from './KlickTipp' @@ -91,8 +92,8 @@ export class User { @Field(() => GmsPublishNameType, { nullable: true }) gmsPublishName: GmsPublishNameType | null - @Field(() => GmsPublishNameType, { nullable: true }) - humhubPublishName: GmsPublishNameType | null + @Field(() => PublishNameType, { nullable: true }) + humhubPublishName: PublishNameType | null @Field(() => GmsPublishLocationType, { nullable: true }) gmsPublishLocation: GmsPublishLocationType | null diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js b/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js new file mode 100644 index 000000000..e48f6baba --- /dev/null +++ b/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js @@ -0,0 +1,84 @@ +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('UserNamingFormat', () => { + 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', + initialValue: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS', + attrName: 'gmsPublishName', + successMessage: 'success message', + }, + }) + }) + + 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().valueChanged).toBeTruthy() + expect(wrapper.emitted().valueChanged.length).toBe(1) + expect(wrapper.emitted().valueChanged[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().valueChanged).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') + }) + }) +}) diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.vue b/frontend/src/components/UserSettings/UserGMSNamingFormat.vue new file mode 100644 index 000000000..98e0911ed --- /dev/null +++ b/frontend/src/components/UserSettings/UserGMSNamingFormat.vue @@ -0,0 +1,92 @@ + + + diff --git a/frontend/src/components/UserSettings/UserNamingFormat.spec.js b/frontend/src/components/UserSettings/UserNamingFormat.spec.js index f07f5e3f2..8ded29ca7 100644 --- a/frontend/src/components/UserSettings/UserNamingFormat.spec.js +++ b/frontend/src/components/UserSettings/UserNamingFormat.spec.js @@ -26,9 +26,9 @@ describe('UserNamingFormat', () => { }, localVue, propsData: { - selectedOption: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS', - initialValue: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS', - attrName: 'gmsPublishName', + selectedOption: 'PUBLISH_NAME_NONE', + initialValue: 'PUBLISH_NAME_NONE', + attrName: 'publishName', successMessage: 'success message', }, }) @@ -40,15 +40,17 @@ describe('UserNamingFormat', () => { it('renders the correct dropdown options', () => { const dropdownItems = wrapper.findAll('.dropdown-item') - expect(dropdownItems.length).toBe(5) + expect(dropdownItems.length).toBe(7) 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', + 'settings.publish-name.none', + 'settings.publish-name.initials', + 'settings.publish-name.first', + 'settings.publish-name.first-initial', + 'settings.publish-name.last', + 'settings.publish-name.last-initial', + 'settings.publish-name.full', ]) }) @@ -58,7 +60,7 @@ describe('UserNamingFormat', () => { expect(wrapper.emitted().valueChanged).toBeTruthy() expect(wrapper.emitted().valueChanged.length).toBe(1) - expect(wrapper.emitted().valueChanged[0]).toEqual(['GMS_PUBLISH_NAME_FIRST_INITIAL']) + expect(wrapper.emitted().valueChanged[0]).toEqual(['PUBLISH_NAME_FIRST_INITIAL']) }) it('does not update when clicking on already selected option', async () => { diff --git a/frontend/src/components/UserSettings/UserNamingFormat.vue b/frontend/src/components/UserSettings/UserNamingFormat.vue index 510541219..658f276ca 100644 --- a/frontend/src/components/UserSettings/UserNamingFormat.vue +++ b/frontend/src/components/UserSettings/UserNamingFormat.vue @@ -20,7 +20,7 @@ import { updateUserInfos } from '@/graphql/mutations' export default { name: 'UserNamingFormat', props: { - initialValue: { type: String, default: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS' }, + initialValue: { type: String, default: 'PUBLISH_NAME_NONE' }, attrName: { type: String }, successMessage: { type: String }, }, @@ -29,29 +29,39 @@ export default { selectedOption: this.initialValue, 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.publish-name.none'), + title: this.$t('settings.publish-name.none-tooltip'), + value: 'PUBLISH_NAME_NONE', }, { - 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.publish-name.initials'), + title: this.$t('settings.publish-name.initials-tooltip'), + value: '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.publish-name.first'), + title: this.$t('settings.publish-name.first-tooltip'), + value: '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.publish-name.first-initial'), + title: this.$t('settings.publish-name.first-initial-tooltip'), + value: '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', + label: this.$t('settings.publish-name.last'), + title: this.$t('settings.publish-name.last-tooltip'), + value: 'PUBLISH_NAME_LAST', + }, + { + label: this.$t('settings.publish-name.last-initial'), + title: this.$t('settings.publish-name.last-initial-tooltip'), + value: 'PUBLISH_NAME_INITIAL_LAST', + }, + { + label: this.$t('settings.publish-name.full'), + title: this.$t('settings.publish-name.full-tooltip'), + value: 'PUBLISH_NAME_FULL', }, ], } diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index ab78ca03b..efcbcffb3 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -37,7 +37,7 @@ export const updateUserInfos = gql` $gmsAllowed: Boolean $humhubAllowed: Boolean $gmsPublishName: GmsPublishNameType - $humhubPublishName: GmsPublishNameType + $humhubPublishName: PublishNameType $gmsLocation: Location $gmsPublishLocation: GmsPublishLocationType ) { diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index df59f05b2..da212d379 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -330,7 +330,6 @@ "humhub": { "disabled": "Daten werden nicht in die Gradido Community exportiert", "enabled": "Daten werden in die Gradido Community exportiert", - "export-consequences": "In der Gradido Community können dich alle Benutzer mit deinem Vor- und Nachnamen finden.", "naming-format": "Namensformat in der Gradido Community", "publish-name": { "updated": "Namensformat für die Gradido Community aktualisiert." @@ -374,6 +373,22 @@ }, "subtitle": "Wenn du dein Passwort vergessen hast, kannst du es hier zurücksetzen." }, + "publish-name": { + "none": "Keine", + "none-tooltip": "Vorname und Nachname bleiben leer", + "first": "Vorname", + "first-tooltip": "Nur der Vornamen, z.B. Max", + "first-initial": "Vorname und Initiale", + "first-initial-tooltip": "Vornamen plus Anfangsbuchstabe des Nachnamens, z.B. Max M.", + "last": "Nachname", + "last-tooltip": "Nur der Nachname, z.B. Mustermann", + "last-initial": "Initiale und Nachname", + "last-initial-tooltip": "Anfangsbuchstabe des Vornamen plus Nachname, z.B. M. Mustermann", + "initials": "Initialen", + "initials-tooltip": "Nur die Initialen von Vor- und Nachname, z.B. M. M.", + "full": "Ganzer Name", + "full-tooltip": "Vollständiger Name: Vorname plus Nachname, z.B. Max Mustermann" + }, "showAmountGDD": "Dein GDD Betrag ist sichtbar.", "showAmountGDT": "Dein GDT Betrag ist sichtbar.", "username": { diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 0377a3eec..7bba0d5eb 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -330,7 +330,6 @@ "humhub": { "disabled": "Data not exported into the Gradido Community", "enabled": "Data exported into the Gradido Community", - "export-consequences": "In the Gradido Community, all users can find you by your first and last name.", "naming-format": "Format of name in the Gradido Community", "publish-name": { "updated": "Format of name for the Gradido Community updated." @@ -374,6 +373,22 @@ }, "subtitle": "If you have forgotten your password, you can reset it here." }, + "publish-name": { + "none": "None", + "none-tooltip": "first name and last name are empty", + "first": "first name", + "first-tooltip": "the first name only", + "first-initial": "first name and initial", + "first-initial-tooltip": "first name plus initial of last name", + "last": "last name", + "last-tooltip": "last name only", + "last-initial": "initial and last name", + "last-initial-tooltip": "First letter of the first name plus last name", + "initials": "initials", + "initials-tooltip": "Initials of first name and last name", + "full": "full name", + "full-tooltip": "full name: firstname plus lastname" + }, "showAmountGDD": "Your GDD amount is visible.", "showAmountGDT": "Your GDT amount is visible.", "username": { diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue index 1fb84318e..57fb9dc11 100644 --- a/frontend/src/pages/Settings.vue +++ b/frontend/src/pages/Settings.vue @@ -107,7 +107,7 @@ {{ $t('settings.GMS.naming-format') }} -
{{ $t('Humhub') }}
- {{ $t('settings.humhub.export-consequences') }} {{ $t('settings.humhub.switch') }} @@ -181,6 +180,7 @@ diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index d8f85b858..ad819f889 100755 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -88,6 +88,14 @@ const routes = [ pageTitle: 'usersearch', }, }, + { + path: '/social-network', + component: () => import('@/pages/SocialNetwork'), + meta: { + requiresAuth: true, + pageTitle: 'social-network', + }, + }, // { // path: '/storys', // component: () => import('@/pages/TopStorys'), From adaece0efe4ddaea08f47243d5c15bfd6401f181 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Thu, 25 Apr 2024 13:15:18 +0200 Subject: [PATCH 64/88] rename to cirlces, route to setting extern service tab from circles if humhubAllowed is false --- backend/src/apis/humhub/HumHubClient.ts | 13 ++++ backend/src/auth/RIGHTS.ts | 1 + backend/src/auth/USER_RIGHTS.ts | 1 + backend/src/graphql/resolver/UserResolver.ts | 9 +++ .../graphql/resolver/util/syncHumhub.test.ts | 4 -- .../svg/{social_network.svg => circles.svg} | 0 frontend/src/components/Menu/Sidebar.vue | 6 +- .../UserSettings/UserSettingsSwitch.vue | 1 - frontend/src/graphql/queries.js | 6 ++ frontend/src/locales/de.json | 5 +- frontend/src/locales/en.json | 5 +- frontend/src/pages/Circles.vue | 65 +++++++++++++++++++ frontend/src/pages/Settings.vue | 11 +++- frontend/src/pages/SocialNetwork.vue | 38 ----------- frontend/src/routes/routes.js | 8 +-- 15 files changed, 116 insertions(+), 57 deletions(-) rename frontend/public/img/svg/{social_network.svg => circles.svg} (100%) create mode 100644 frontend/src/pages/Circles.vue delete mode 100644 frontend/src/pages/SocialNetwork.vue diff --git a/backend/src/apis/humhub/HumHubClient.ts b/backend/src/apis/humhub/HumHubClient.ts index b69944773..596d74597 100644 --- a/backend/src/apis/humhub/HumHubClient.ts +++ b/backend/src/apis/humhub/HumHubClient.ts @@ -8,6 +8,7 @@ import { backendLogger as logger } from '@/server/logger' import { GetUser } from './model/GetUser' import { PostUser } from './model/PostUser' import { UsersResponse } from './model/UsersResponse' +import { User } from '@entity/User' /** * HumHubClient as singleton class @@ -58,6 +59,18 @@ export class HumHubClient { return token } + public static async createAutoLoginUrl(user: User) { + const secret = new TextEncoder().encode(CONFIG.HUMHUB_JWT_KEY) + const username = user.alias ?? user.gradidoID + logger.info(`user ${username} as username for humhub auto-login`) + const token = await new SignJWT({ username }) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime('2m') + .sign(secret) + return `${CONFIG.HUMHUB_API_URL}user/auth/login?jwt=${token}` + } + /** * Get all users from humhub * https://marketplace.humhub.com/module/rest/docs/html/user.html#tag/User/paths/~1user/get diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index c7a23c13b..579fb7f0e 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -38,6 +38,7 @@ export enum RIGHTS { OPEN_CREATIONS = 'OPEN_CREATIONS', USER = 'USER', GMS_USER_PLAYGROUND = 'GMS_USER_PLAYGROUND', + CIRCLES_AUTO_LOGIN = 'CIRCLES_AUTO_LOGIN', // Moderator SEARCH_USERS = 'SEARCH_USERS', ADMIN_CREATE_CONTRIBUTION = 'ADMIN_CREATE_CONTRIBUTION', diff --git a/backend/src/auth/USER_RIGHTS.ts b/backend/src/auth/USER_RIGHTS.ts index 0c56b0d02..d649a0649 100644 --- a/backend/src/auth/USER_RIGHTS.ts +++ b/backend/src/auth/USER_RIGHTS.ts @@ -30,4 +30,5 @@ export const USER_RIGHTS = [ RIGHTS.OPEN_CREATIONS, RIGHTS.USER, RIGHTS.GMS_USER_PLAYGROUND, + RIGHTS.CIRCLES_AUTO_LOGIN, ] diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 33a351730..2c18876a1 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -81,6 +81,7 @@ import { setUserRole, deleteUserRole } from './util/modifyUserRole' import { sendUserToGms } from './util/sendUserToGms' import { syncHumhub } from './util/syncHumhub' import { validateAlias } from './util/validateAlias' +import { HumHubClient } from '@/apis/humhub/HumHubClient' const LANGUAGES = ['de', 'en', 'es', 'fr', 'nl'] const DEFAULT_LANGUAGE = 'de' @@ -703,6 +704,14 @@ export class UserResolver { return result } + @Authorized([RIGHTS.CIRCLES_AUTO_LOGIN]) + @Query(() => String) + async authenticateCirclesAutoLogin(@Ctx() context: Context): Promise { + logger.info(`authenticateCirclesAutoLogin()...`) + const dbUser = getUser(context) + return await HumHubClient.createAutoLoginUrl(dbUser) + } + @Authorized([RIGHTS.SEARCH_ADMIN_USERS]) @Query(() => SearchAdminUsersResult) async searchAdminUsers( diff --git a/backend/src/graphql/resolver/util/syncHumhub.test.ts b/backend/src/graphql/resolver/util/syncHumhub.test.ts index c7b187f23..a5a8a87e4 100644 --- a/backend/src/graphql/resolver/util/syncHumhub.test.ts +++ b/backend/src/graphql/resolver/util/syncHumhub.test.ts @@ -22,10 +22,6 @@ const mockUpdateUserInfosArg = new UpdateUserInfosArgs() const mockHumHubUser = new GetUser(mockUser, 1) describe('syncHumhub', () => { - beforeAll(() => { - // humhubClientMockbBeforeAll() - }) - beforeEach(() => { jest.spyOn(logger, 'debug').mockImplementation() jest.spyOn(logger, 'info').mockImplementation() diff --git a/frontend/public/img/svg/social_network.svg b/frontend/public/img/svg/circles.svg similarity index 100% rename from frontend/public/img/svg/social_network.svg rename to frontend/public/img/svg/circles.svg diff --git a/frontend/src/components/Menu/Sidebar.vue b/frontend/src/components/Menu/Sidebar.vue index a6b096299..b1017ec86 100644 --- a/frontend/src/components/Menu/Sidebar.vue +++ b/frontend/src/components/Menu/Sidebar.vue @@ -32,9 +32,9 @@ {{ $t('navigation.info') }} - - - {{ $t('navigation.social_network') }} + + + {{ $t('navigation.circles') }} diff --git a/frontend/src/components/UserSettings/UserSettingsSwitch.vue b/frontend/src/components/UserSettings/UserSettingsSwitch.vue index 8e819cba8..53d0f6df8 100644 --- a/frontend/src/components/UserSettings/UserSettingsSwitch.vue +++ b/frontend/src/components/UserSettings/UserSettingsSwitch.vue @@ -29,7 +29,6 @@ export default { async onChange() { const variables = [] variables[this.attrName] = this.value - this.$apollo .mutate({ mutation: updateUserInfos, diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 696963b78..adb11bc8d 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -28,6 +28,12 @@ export const authenticateGmsUserSearch = gql` } ` +export const authenticateCirclesAutoLogin = gql` + query { + authenticateCirclesAutoLogin + } +` + export const transactionsQuery = gql` query($currentPage: Int = 1, $pageSize: Int = 25, $order: Order = DESC) { transactionList(currentPage: $currentPage, pageSize: $pageSize, order: $order) { diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 84e3f2d8c..e1bfd3392 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -268,7 +268,7 @@ "overview": "Übersicht", "send": "Senden", "settings": "Einstellung", - "social_network": "Kreise", + "circles": "Kreise", "support": "Support", "transactions": "Transaktionen", "usersearch": "Nutzersuche" @@ -281,6 +281,7 @@ "overview": "Willkommen {name}", "send": "Sende Gradidos", "settings": "Einstellungen", + "circles": "Gradido Kreise", "transactions": "Deine Transaktionen", "usersearch": "Geografische Nutzersuche" }, @@ -418,7 +419,7 @@ "uppercase": "Großbuchstabe erforderlich." } }, - "social-network": { + "circles": { "headline": "Gradido Kreise", "text": "Was soll hier für ein Text rein?", "button": "Beginne dich zu vernetzen..." diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index a1b7cd8d6..09538c8d7 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -268,7 +268,7 @@ "overview": "Overview", "send": "Send", "settings": "Settings", - "social_network": "Circle", + "circles": "Circle", "support": "Support", "transactions": "Transactions", "usersearch": "Geographical User Search" @@ -282,6 +282,7 @@ "send": "Send Gradidos", "settings": "Settings", "transactions": "Your transactions", + "circles": "Gradido Circles", "usersearch": "Geographical User Search" }, "qrCode": "QR Code", @@ -418,7 +419,7 @@ "uppercase": "One uppercase letter required." } }, - "social-network": { + "circles": { "headline": "Gradido Circle", "text": "Placeholder", "button": "Start to connect..." diff --git a/frontend/src/pages/Circles.vue b/frontend/src/pages/Circles.vue new file mode 100644 index 000000000..aa7e810d9 --- /dev/null +++ b/frontend/src/pages/Circles.vue @@ -0,0 +1,65 @@ + + diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue index 57fb9dc11..fc4a29ca4 100644 --- a/frontend/src/pages/Settings.vue +++ b/frontend/src/pages/Settings.vue @@ -1,7 +1,7 @@ - diff --git a/frontend/src/components/UserSettings/UserNamingFormat.spec.js b/frontend/src/components/UserSettings/UserNamingFormat.spec.js index 8ded29ca7..c92cca138 100644 --- a/frontend/src/components/UserSettings/UserNamingFormat.spec.js +++ b/frontend/src/components/UserSettings/UserNamingFormat.spec.js @@ -26,9 +26,9 @@ describe('UserNamingFormat', () => { }, localVue, propsData: { - selectedOption: 'PUBLISH_NAME_NONE', - initialValue: 'PUBLISH_NAME_NONE', - attrName: 'publishName', + selectedOption: 'PUBLISH_NAME_ALIAS_OR_INITALS', + initialValue: 'PUBLISH_NAME_ALIAS_OR_INITALS', + attrName: 'gmsPublishName', successMessage: 'success message', }, }) @@ -40,17 +40,15 @@ describe('UserNamingFormat', () => { it('renders the correct dropdown options', () => { const dropdownItems = wrapper.findAll('.dropdown-item') - expect(dropdownItems.length).toBe(7) + expect(dropdownItems.length).toBe(5) const labels = dropdownItems.wrappers.map((item) => item.text()) expect(labels).toEqual([ - 'settings.publish-name.none', + 'settings.publish-name.alias-or-initials', 'settings.publish-name.initials', 'settings.publish-name.first', 'settings.publish-name.first-initial', - 'settings.publish-name.last', - 'settings.publish-name.last-initial', - 'settings.publish-name.full', + 'settings.publish-name.name-full', ]) }) diff --git a/frontend/src/components/UserSettings/UserNamingFormat.vue b/frontend/src/components/UserSettings/UserNamingFormat.vue index 658f276ca..2879e37e0 100644 --- a/frontend/src/components/UserSettings/UserNamingFormat.vue +++ b/frontend/src/components/UserSettings/UserNamingFormat.vue @@ -20,7 +20,7 @@ import { updateUserInfos } from '@/graphql/mutations' export default { name: 'UserNamingFormat', props: { - initialValue: { type: String, default: 'PUBLISH_NAME_NONE' }, + initialValue: { type: String, default: 'PUBLISH_NAME_ALIAS_OR_INITALS' }, attrName: { type: String }, successMessage: { type: String }, }, @@ -29,9 +29,9 @@ export default { selectedOption: this.initialValue, dropdownOptions: [ { - label: this.$t('settings.publish-name.none'), - title: this.$t('settings.publish-name.none-tooltip'), - value: 'PUBLISH_NAME_NONE', + label: this.$t('settings.publish-name.alias-or-initials'), + title: this.$t('settings.publish-name.alias-or-initials-tooltip'), + value: 'PUBLISH_NAME_ALIAS_OR_INITALS', }, { label: this.$t('settings.publish-name.initials'), @@ -49,18 +49,8 @@ export default { value: 'PUBLISH_NAME_FIRST_INITIAL', }, { - label: this.$t('settings.publish-name.last'), - title: this.$t('settings.publish-name.last-tooltip'), - value: 'PUBLISH_NAME_LAST', - }, - { - label: this.$t('settings.publish-name.last-initial'), - title: this.$t('settings.publish-name.last-initial-tooltip'), - value: 'PUBLISH_NAME_INITIAL_LAST', - }, - { - label: this.$t('settings.publish-name.full'), - title: this.$t('settings.publish-name.full-tooltip'), + label: this.$t('settings.publish-name.name-full'), + title: this.$t('settings.publish-name.name-full-tooltip'), value: 'PUBLISH_NAME_FULL', }, ], diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index efcbcffb3..dd812db4b 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -36,7 +36,7 @@ export const updateUserInfos = gql` $hideAmountGDT: Boolean $gmsAllowed: Boolean $humhubAllowed: Boolean - $gmsPublishName: GmsPublishNameType + $gmsPublishName: PublishNameType $humhubPublishName: PublishNameType $gmsLocation: Location $gmsPublishLocation: GmsPublishLocationType diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 0ea569735..ed55a0990 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -325,16 +325,6 @@ "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." @@ -388,20 +378,16 @@ "subtitle": "Wenn du dein Passwort vergessen hast, kannst du es hier zurücksetzen." }, "publish-name": { - "none": "Keine", - "none-tooltip": "Vorname und Nachname bleiben leer", + "alias-or-initials": "Benutzername oder Initialen (Default)", + "alias-or-initials-tooltip": "Benutzername, falls vorhanden, oder die Initialen von Vorname und Nachname", "first": "Vorname", - "first-tooltip": "Nur der Vornamen, z.B. Max", - "first-initial": "Vorname und Initiale", - "first-initial-tooltip": "Vornamen plus Anfangsbuchstabe des Nachnamens, z.B. Max M.", - "last": "Nachname", - "last-tooltip": "Nur der Nachname, z.B. Mustermann", - "last-initial": "Initiale und Nachname", - "last-initial-tooltip": "Anfangsbuchstabe des Vornamen plus Nachname, z.B. M. Mustermann", + "first-tooltip": "Nur der Vornamen", + "first-initial": "Vorname und Initial", + "first-initial-tooltip": "Vornamen plus Anfangsbuchstabe des Nachnamens", "initials": "Initialen", - "initials-tooltip": "Nur die Initialen von Vor- und Nachname, z.B. M. M.", - "full": "Ganzer Name", - "full-tooltip": "Vollständiger Name: Vorname plus Nachname, z.B. Max Mustermann" + "initials-tooltip": "Initialen von Vor- und Nachname unabhängig von der Existenz des Benutzernamens", + "name-full": "Vorname und Nachname", + "name-full-tooltip": "Vollständiger Name: Vorname plus Nachname" }, "showAmountGDD": "Dein GDD Betrag ist sichtbar.", "showAmountGDT": "Dein GDT Betrag ist sichtbar.", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 4c90732fe..9bd79448a 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -325,16 +325,6 @@ "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" @@ -388,20 +378,16 @@ "subtitle": "If you have forgotten your password, you can reset it here." }, "publish-name": { - "none": "None", - "none-tooltip": "first name and last name are empty", - "first": "first name", - "first-tooltip": "the first name only", - "first-initial": "first name and initial", - "first-initial-tooltip": "first name plus initial of last name", - "last": "last name", - "last-tooltip": "last name only", - "last-initial": "initial and last name", - "last-initial-tooltip": "First letter of the first name plus last name", - "initials": "initials", - "initials-tooltip": "Initials of first name and last name", - "full": "full name", - "full-tooltip": "full name: firstname plus lastname" + "alias-or-initials": "Username or initials (Default)", + "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", + "initials-tooltip": "Initials of firstname and lastname independent if username exists", + "name-full": "firstname and lastname", + "name-full-tooltip": "fullname: firstname plus lastname" }, "showAmountGDD": "Your GDD amount is visible.", "showAmountGDT": "Your GDT amount is visible.", diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue index 94f10f018..14a1df920 100644 --- a/frontend/src/pages/Settings.vue +++ b/frontend/src/pages/Settings.vue @@ -108,7 +108,7 @@ {{ $t('settings.GMS.naming-format') }} - - + {{ $t('settings.humhub.naming-format') }} @@ -182,7 +182,6 @@