Merge pull request #3291 from gradido/3287-feature-gms-user-update-after-change-user-settings

feat(backend): 3287 feature gms user update after change user settings
This commit is contained in:
clauspeterhuebner 2024-03-18 23:40:01 +01:00 committed by GitHub
commit 04e0a0f042
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 193 additions and 34 deletions

View File

@ -117,30 +117,69 @@ export async function userByUuid(uuid: string): Promise<GmsUser[] | string | und
*/
export async function createGmsUser(apiKey: string, user: GmsUser): Promise<boolean> {
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<boolean> {
if (CONFIG.GMS_ACTIVE) {
const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/')
const service = 'community-user'
const config = {
headers: {
accept: 'application/json',
language: 'en',
timezone: 'UTC',
connection: 'keep-alive',
authorization: apiKey,
},
}
try {
const result = await axios.patch(baseUrl.concat(service), user, config)
logger.debug('PATCH-Response of community-user:', result)
if (result.status !== 200) {
throw new LogError('HTTP Status Error in community-user:', result.status, result.statusText)
}
logger.debug('responseData:', result.data.responseData)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// const gmsUser = JSON.parse(result.data.responseData)
// logger.debug('gmsUser:', gmsUser)
return true
} catch (error: any) {
logger.error('Error in patch community-user:', error)
throw new LogError(error.message)
}
} else {
logger.info('GMS-Communication disabled per ConfigKey GMS_ACTIVE=false!')
return false
}
}

View File

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

View File

@ -143,6 +143,7 @@ const federation = {
const gms = {
GMS_ACTIVE: process.env.GMS_ACTIVE === 'true' || false,
GMS_CREATE_USER_THROW_ERRORS: process.env.GMS_CREATE_USER_THROW_ERRORS === 'true' || false,
// koordinates of Illuminz-instance of GMS
GMS_URL: process.env.GMS_HOST ?? 'http://localhost:4044/',
}

View File

@ -28,6 +28,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'
@ -67,6 +69,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'
@ -373,7 +376,11 @@ export class UserResolver {
await sendUserToGms(dbUser, homeCom)
}
} catch (err) {
logger.error('Error publishing new created user to GMS:', err)
if (CONFIG.GMS_CREATE_USER_THROW_ERRORS) {
throw new LogError('Error publishing new created user to GMS:', err)
} else {
logger.error('Error publishing new created user to GMS:', err)
}
}
}
return new User(dbUser)
@ -393,7 +400,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`,
@ -539,8 +545,10 @@ export class UserResolver {
@Authorized([RIGHTS.UPDATE_USER_INFOS])
@Mutation(() => Boolean)
async updateUserInfos(
@Args()
{
@Args() updateUserInfosArgs: UpdateUserInfosArgs,
@Ctx() context: Context,
): Promise<boolean> {
const {
firstName,
lastName,
alias,
@ -553,13 +561,13 @@ export class UserResolver {
gmsPublishName,
gmsLocation,
gmsPublishLocation,
}: UpdateUserInfosArgs,
@Ctx() context: Context,
): Promise<boolean> {
} = updateUserInfosArgs
logger.info(
`updateUserInfos(${firstName}, ${lastName}, ${alias}, ${language}, ***, ***, ${hideAmountGDD}, ${hideAmountGDT}, ${gmsAllowed}, ${gmsPublishName}, ${gmsLocation}, ${gmsPublishLocation})...`,
)
const user = getUser(context)
const updateUserInGMS = compareGmsRelevantUserSettings(user, updateUserInfosArgs)
// try {
if (firstName) {
user.firstName = firstName
@ -642,6 +650,17 @@ export class UserResolver {
logger.info('updateUserInfos() successfully finished...')
await EVENT_USER_INFO_UPDATE(user)
// validate if user settings are changed with relevance to update gms-user
if (CONFIG.GMS_ACTIVE && updateUserInGMS) {
logger.debug(`changed user-settings relevant for gms-user update...`)
const homeCom = await getHomeCommunity()
if (homeCom.gmsApiKey !== null) {
logger.debug(`gms-user update...`, user)
await updateGmsUser(homeCom.gmsApiKey, new GmsUser(user))
logger.debug(`gms-user update successfully.`)
}
}
return true
}

View File

@ -0,0 +1,90 @@
import { Point } from '@dbTools/typeorm'
import { User as DbUser } from '@entity/User'
import { UpdateUserInfosArgs } from '@/graphql/arg/UpdateUserInfosArgs'
import { GmsPublishNameType } from '@/graphql/enum/GmsPublishNameType'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { Point2Location } from './Location2Point'
export function compareGmsRelevantUserSettings(
orgUser: DbUser,
updateUserInfosArgs: UpdateUserInfosArgs,
): boolean {
if (!orgUser) {
throw new LogError('comparison without any user is impossible')
}
logger.debug('compareGmsRelevantUserSettings:', orgUser, updateUserInfosArgs)
// nach GMS updaten, wenn alias gesetzt wird oder ist und PublishLevel die alias-Übermittlung erlaubt
if (
updateUserInfosArgs.alias &&
orgUser.alias !== updateUserInfosArgs.alias &&
((updateUserInfosArgs.gmsPublishName &&
updateUserInfosArgs.gmsPublishName.valueOf ===
GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS.valueOf) ||
(!updateUserInfosArgs.gmsPublishName &&
orgUser.gmsPublishName &&
orgUser.gmsPublishName.valueOf ===
GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS.valueOf))
) {
return true
}
if (
(updateUserInfosArgs.firstName && orgUser.firstName !== updateUserInfosArgs.firstName) ||
(updateUserInfosArgs.lastName && orgUser.lastName !== updateUserInfosArgs.lastName)
) {
return true
}
if (
updateUserInfosArgs.gmsAllowed !== undefined &&
updateUserInfosArgs.gmsAllowed &&
orgUser.gmsAllowed !== updateUserInfosArgs.gmsAllowed
) {
return true
}
if (
updateUserInfosArgs.gmsPublishLocation &&
orgUser.gmsPublishLocation !== updateUserInfosArgs.gmsPublishLocation
) {
return true
}
if (
updateUserInfosArgs.gmsPublishName &&
orgUser.gmsPublishName !== updateUserInfosArgs.gmsPublishName
) {
return true
}
if (updateUserInfosArgs.language && orgUser.language !== updateUserInfosArgs.language) {
return true
}
if (
updateUserInfosArgs.gmsLocation &&
orgUser.location === null &&
updateUserInfosArgs.gmsLocation !== null
) {
return true
}
if (
updateUserInfosArgs.gmsLocation &&
orgUser.location !== null &&
updateUserInfosArgs.gmsLocation === null
) {
return true
}
if (
updateUserInfosArgs.gmsLocation &&
orgUser.location !== null &&
updateUserInfosArgs.gmsLocation !== null
) {
const orgLocation = Point2Location(orgUser.location as Point)
const changedLocation = updateUserInfosArgs.gmsLocation
if (
orgLocation.latitude !== changedLocation.latitude ||
orgLocation.longitude !== changedLocation.longitude
) {
return true
}
}
return false
}

View File

@ -3,6 +3,7 @@ import { User as DbUser } from '@entity/User'
import { createGmsUser } from '@/apis/gms/GmsClient'
import { GmsUser } from '@/apis/gms/model/GmsUser'
import { CONFIG } from '@/config'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
@ -22,6 +23,10 @@ export async function sendUserToGms(user: DbUser, homeCom: DbCommunity): Promise
logger.debug('mark user as gms published:', user)
}
} catch (err) {
logger.warn('publishing user fails with ', err)
if (CONFIG.GMS_CREATE_USER_THROW_ERRORS) {
throw new LogError('publishing user fails with ', err)
} else {
logger.warn('publishing user fails with ', err)
}
}
}

View File

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