test for updateUserInfo with geolocation but db-driver error

This commit is contained in:
Claus-Peter Huebner 2024-01-23 22:07:47 +01:00
parent 548a09fefd
commit f875214eff
5 changed files with 195 additions and 74 deletions

View File

@ -1,8 +1,13 @@
import { IsBoolean, IsInt, IsObject, IsString } from 'class-validator'
import { ArgsType, Field, Int } from 'type-graphql'
import { IsBoolean, IsInt, IsString } from 'class-validator'
import { ArgsType, Field, InputType, Int } from 'type-graphql'
import { Location } from '@model/Location'
import { isValidLocation } from '../validator/Location'
// import { isValidLocation } from '../validator/Location'
@InputType()
@ArgsType()
export class UpdateUserInfosArgs {
@Field({ nullable: true })
@ -50,7 +55,7 @@ export class UpdateUserInfosArgs {
gmsPublishName: number
@Field(() => Location, { nullable: true })
@IsObject()
@isValidLocation()
gmsLocation?: Location | null
@Field(() => Int, { nullable: false })

View File

@ -1,31 +1,10 @@
import { Point } from '@dbTools/typeorm'
import { ArgsType, Field, InputType, Int } from 'type-graphql'
import { ArgsType, Field, Int } from 'type-graphql'
@InputType()
@ArgsType()
// @ObjectType()
export class Location {
constructor(lon: number, lat: number) {
this.longitude = lon
this.latitude = lat
}
@Field(() => Int)
longitude: number
@Field(() => Int)
latitude: number
// point is no Field and not part of the graphql type
private point: Point
public getPoint(): Point {
const pointStr = '{ "type": "Point", "coordinates": ['
.concat(this.longitude.toString())
.concat(', ')
.concat(this.latitude.toString())
.concat('] }')
this.point = JSON.parse(pointStr) as Point
return this.point
}
}

View File

@ -23,6 +23,7 @@ import { PasswordEncryptionType } from '@enum/PasswordEncryptionType'
import { RoleNames } from '@enum/RoleNames'
import { UserContactType } from '@enum/UserContactType'
import { ContributionLink } from '@model/ContributionLink'
import { Location } from '@model/Location'
import { testEnvironment, headerPushMock, resetToken, cleanDB } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
@ -1237,6 +1238,9 @@ describe('UserResolver', () => {
firstName: 'Benjamin',
lastName: 'Blümchen',
language: 'en',
gmsAllowed: true,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
}),
])
})
@ -1275,6 +1279,93 @@ describe('UserResolver', () => {
await expect(User.find()).resolves.toEqual([
expect.objectContaining({
alias: 'bibi_Bloxberg',
gmsAllowed: true,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
}),
])
})
})
})
describe('gms attributes', () => {
beforeEach(() => {
jest.clearAllMocks()
})
describe('default settings', () => {
it('updates the user in DB', async () => {
await mutate({
mutation: updateUserInfos,
variables: {
gmsAllowed: true,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
},
})
await expect(User.find()).resolves.toEqual([
expect.objectContaining({
gmsAllowed: true,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
}),
])
})
})
describe('individual settings', () => {
it('updates the user in DB', async () => {
await mutate({
mutation: updateUserInfos,
variables: {
gmsAllowed: false,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_APPROXIMATE,
},
})
await expect(User.find()).resolves.toEqual([
expect.objectContaining({
gmsAllowed: false,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_APPROXIMATE,
}),
])
})
})
describe.only('with gms location', () => {
const loc = new Location()
loc.longitude = 9.573224
loc.latitude = 49.679437
console.log('with gms location:', loc)
it('updates the user in DB', async () => {
const usr = await User.find()
console.log('usr=', usr)
await mutate({
mutation: updateUserInfos,
variables: {
/*
firstName: usr[0].firstName,
lastName: usr[0].lastName,
alias: usr[0].alias,
language: usr[0].language,
password: usr[0].password,
passwordNew: usr[0].password,
hideAmountGDD: usr[0].hideAmountGDD,
hideAmountGDT: usr[0].hideAmountGDT,
*/
gmsAllowed: true,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
gmsLocation: loc,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
},
})
await expect(User.find()).resolves.toEqual([
expect.objectContaining({
gmsAllowed: true,
gmsPublishName: GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS,
location: loc,
gmsPublishLocation: GmsPublishLocationType.GMS_LOCATION_TYPE_RANDOM,
}),
])
})

View File

@ -24,6 +24,7 @@ import { Order } from '@enum/Order'
import { PasswordEncryptionType } from '@enum/PasswordEncryptionType'
import { UserContactType } from '@enum/UserContactType'
import { SearchAdminUsersResult } from '@model/AdminUser'
import { Location } from '@model/Location'
import { User } from '@model/User'
import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
@ -73,6 +74,7 @@ import { getKlicktippState } from './util/getKlicktippState'
import { setUserRole, deleteUserRole } from './util/modifyUserRole'
import { sendUserToGms } from './util/sendUserToGms'
import { validateAlias } from './util/validateAlias'
import { Location2Point } from './util/Location2Point'
const LANGUAGES = ['de', 'en', 'es', 'fr', 'nl']
const DEFAULT_LANGUAGE = 'de'
@ -554,75 +556,88 @@ export class UserResolver {
}: UpdateUserInfosArgs,
@Ctx() context: Context,
): Promise<boolean> {
console.log(
`updateUserInfos(${firstName}, ${lastName}, ${alias}, ${language}, ${password}, ${passwordNew}, ${hideAmountGDD}, ${hideAmountGDT}, ${gmsAllowed}, ${gmsPublishName}, ${gmsLocation}, ${gmsPublishLocation})`,
)
logger.info(
`updateUserInfos(${firstName}, ${lastName}, ${language}, ***, ***, ${gmsAllowed}, ${gmsPublishName}, ${gmsLocation}, ${gmsPublishLocation})...`,
`updateUserInfos(${firstName}, ${lastName}, ${alias}, ${language}, ***, ***, ${hideAmountGDD}, ${hideAmountGDT}, ${gmsAllowed}, ${gmsPublishName}, ${gmsLocation}, ${gmsPublishLocation})...`,
)
const user = getUser(context)
if (firstName) {
user.firstName = firstName
}
if (lastName) {
user.lastName = lastName
}
if (alias && (await validateAlias(alias))) {
user.alias = alias
}
if (language) {
if (!isLanguage(language)) {
throw new LogError('Given language is not a valid language', language)
}
user.language = language
i18n.setLocale(language)
}
if (password && passwordNew) {
// Validate Password
if (!isValidPassword(passwordNew)) {
throw new LogError(
'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!',
)
console.log('getUser:', user)
try {
if (firstName) {
user.firstName = firstName
}
if (!verifyPassword(user, password)) {
throw new LogError(`Old password is invalid`)
if (lastName) {
user.lastName = lastName
}
// Save new password hash and newly encrypted private key
user.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID
user.password = encryptPassword(user, passwordNew)
}
if (alias && (await validateAlias(alias))) {
user.alias = alias
}
// Save hideAmountGDD value
if (hideAmountGDD !== undefined) {
user.hideAmountGDD = hideAmountGDD
}
// Save hideAmountGDT value
if (hideAmountGDT !== undefined) {
user.hideAmountGDT = hideAmountGDT
}
if (language) {
if (!isLanguage(language)) {
throw new LogError('Given language is not a valid language', language)
}
user.language = language
i18n.setLocale(language)
}
user.gmsAllowed = gmsAllowed
user.gmsPublishName = gmsPublishName
if (gmsLocation) {
user.location = gmsLocation.getPoint()
}
user.gmsPublishLocation = gmsPublishLocation
if (password && passwordNew) {
// Validate Password
if (!isValidPassword(passwordNew)) {
throw new LogError(
'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!',
)
}
if (!verifyPassword(user, password)) {
throw new LogError(`Old password is invalid`)
}
// Save new password hash and newly encrypted private key
user.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID
user.password = encryptPassword(user, passwordNew)
}
// Save hideAmountGDD value
if (hideAmountGDD !== undefined) {
user.hideAmountGDD = hideAmountGDD
}
// Save hideAmountGDT value
if (hideAmountGDT !== undefined) {
user.hideAmountGDT = hideAmountGDT
}
console.log('gmsAllowed:', user.gmsAllowed, gmsAllowed)
user.gmsAllowed = gmsAllowed
console.log('gmsPublishName:', user.gmsPublishName, gmsPublishName)
user.gmsPublishName = gmsPublishName
if (gmsLocation) {
console.log('1. gmsLocation:', user.location, gmsLocation)
user.location = Location2Point(gmsLocation)
console.log('2. gmsLocation:', user.location)
}
console.log('gmsPublishLocation:', user.gmsPublishLocation, gmsPublishLocation)
user.gmsPublishLocation = gmsPublishLocation
console.log('vor commit user:', user)
} catch (err) {
console.log('error:', err)
}
const queryRunner = getConnection().createQueryRunner()
await queryRunner.connect()
await queryRunner.startTransaction('REPEATABLE READ')
try {
await queryRunner.manager.save(user).catch((error) => {
console.log('Error on saving user:', error)
throw new LogError('Error saving user', error)
})
await queryRunner.commitTransaction()
logger.debug('writing User data successful...')
logger.debug('writing User data successful...', user)
} catch (e) {
await queryRunner.rollbackTransaction()
throw new LogError('Error on writing updated user data', e)

View File

@ -0,0 +1,31 @@
import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator'
import { Location } from '@model/Location'
import { Location2Point } from '@/graphql/resolver/util/Location2Point'
export function isValidLocation(validationOptions?: ValidationOptions) {
// eslint-disable-next-line @typescript-eslint/ban-types
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'isValidLocation',
target: object.constructor,
propertyName,
options: validationOptions,
validator: {
validate(value: Location) {
// console.log('isValidLocation:', value, value.getPoint())
if (!value || Location2Point(value).type === 'Point') {
console.log('isValidLocation: true')
return true
}
console.log('isValidLocation: false')
return false
},
defaultMessage(args: ValidationArguments) {
return `${propertyName} must be a valid Location, ${args.property}`
},
},
})
}
}