additional tests for userRoles and userContact

This commit is contained in:
Claus-Peter Huebner 2023-07-07 17:55:52 +02:00
parent 0fca31799b
commit bbcb97abfb
6 changed files with 259 additions and 46 deletions

View File

@ -53,29 +53,24 @@ export class UserAdmin {
@Field(() => [String], { nullable: true })
roles: string[] | null
@Field(() => Boolean)
isAdmin(): boolean {
if (this.roles) {
return this.roles.includes(ROLE_NAMES.ROLE_NAME_ADMIN)
}
return false
}
@Field(() => Boolean)
isModerator(): boolean {
if (this.roles) {
return this.roles.includes(ROLE_NAMES.ROLE_NAME_MODERATOR)
}
return false
}
}
export function isAdmin(user: UserAdmin): boolean {
if (user.roles) {
for (const role of user.roles) {
if (role === ROLE_NAMES.ROLE_NAME_ADMIN) {
return true
}
}
}
return false
}
export function isModerator(user: UserAdmin): boolean {
if (user.roles) {
for (const role of user.roles) {
if (role === ROLE_NAMES.ROLE_NAME_MODERATOR) {
return true
}
}
}
return false
}
@ObjectType()
export class SearchUsersResult {

View File

@ -56,6 +56,7 @@ import {
searchUsers,
user as userQuery,
checkUsername,
userContact,
} from '@/seeds/graphql/queries'
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
@ -699,13 +700,15 @@ describe('UserResolver', () => {
firstName: 'Bibi',
hasElopage: false,
id: expect.any(Number),
roles: expect.any(Array),
klickTipp: {
newsletterState: false,
},
language: 'de',
lastName: 'Bloxberg',
publisherId: 1234,
roles: [],
isAdmin: false,
isModerator: false,
},
},
}),
@ -976,7 +979,9 @@ describe('UserResolver', () => {
},
hasElopage: false,
publisherId: 1234,
roles: expect.any(Array),
roles: [],
isAdmin: false,
isModerator: false,
},
},
}),
@ -992,6 +997,35 @@ describe('UserResolver', () => {
}),
)
})
it('returns usercontact object', async () => {
await expect(
query({
query: userContact,
variables: {
userId: user[0].id,
},
}),
).resolves.toEqual(
expect.objectContaining({
data: {
userContact: {
id: expect.any(Number),
type: UserContactType.USER_CONTACT_EMAIL,
userId: user[0].id,
email: 'bibi@bloxberg.de',
emailOptInTypeId: expect.any(Number),
emailResendCount: expect.any(Number),
emailChecked: expect.any(Boolean),
phone: null,
createdAt: expect.any(Date),
updatedAt: expect.any(Date),
deletedAt: null,
},
},
}),
)
})
})
})
})
@ -1417,6 +1451,7 @@ describe('UserResolver', () => {
expect.objectContaining({
firstName: 'Peter',
lastName: 'Lustig',
role: ROLE_NAMES.ROLE_NAME_ADMIN,
}),
]),
},
@ -1498,13 +1533,15 @@ describe('UserResolver', () => {
firstName: 'Bibi',
hasElopage: false,
id: expect.any(Number),
roles: expect.any(Array),
klickTipp: {
newsletterState: false,
},
language: 'de',
lastName: 'Bloxberg',
publisherId: 1234,
roles: [],
isAdmin: false,
isModerator: false,
},
},
}),
@ -1536,7 +1573,7 @@ describe('UserResolver', () => {
})
describe('authenticated', () => {
describe('without admin rights', () => {
describe('with user rights', () => {
beforeAll(async () => {
user = await userFactory(testEnv, bibiBloxberg)
await mutate({
@ -1564,8 +1601,45 @@ describe('UserResolver', () => {
})
})
describe('with moderator rights', () => {
beforeAll(async () => {
user = await userFactory(testEnv, bibiBloxberg)
admin = await userFactory(testEnv, peterLustig)
// set Moderator-Role for Peter
const userRole = await UserRole.findOneOrFail({ where: { userId: admin.id } })
userRole.role = ROLE_NAMES.ROLE_NAME_MODERATOR
userRole.userId = admin.id
await UserRole.save(userRole)
await mutate({
mutation: login,
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
})
})
afterAll(async () => {
await cleanDB()
resetToken()
})
it('returns an error', async () => {
await expect(
mutate({
mutation: setUserRole,
variables: { userId: user.id, role: ROLE_NAMES.ROLE_NAME_ADMIN },
}),
).resolves.toEqual(
expect.objectContaining({
errors: [new GraphQLError('401 Unauthorized')],
}),
)
})
})
describe('with admin rights', () => {
beforeAll(async () => {
user = await userFactory(testEnv, bibiBloxberg)
admin = await userFactory(testEnv, peterLustig)
await mutate({
mutation: login,
@ -1578,7 +1652,26 @@ describe('UserResolver', () => {
resetToken()
})
it('returns user with new moderator-role', async () => {
const result = await mutate({
mutation: setUserRole,
variables: { userId: user.id, role: ROLE_NAMES.ROLE_NAME_MODERATOR },
})
expect(result).toEqual(
expect.objectContaining({
data: {
setUserRole: ROLE_NAMES.ROLE_NAME_MODERATOR,
},
}),
)
})
describe('user to get a new role does not exist', () => {
afterAll(async () => {
await cleanDB()
resetToken()
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
@ -1601,11 +1694,21 @@ describe('UserResolver', () => {
describe('change role with success', () => {
beforeAll(async () => {
user = await userFactory(testEnv, bibiBloxberg)
admin = await userFactory(testEnv, peterLustig)
await mutate({
mutation: login,
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
})
})
afterAll(async () => {
await cleanDB()
resetToken()
})
describe('user gets new role', () => {
describe('to admin', () => {
it('returns date string', async () => {
it('returns admin-rolename', async () => {
const result = await mutate({
mutation: setUserRole,
variables: { userId: user.id, role: ROLE_NAMES.ROLE_NAME_ADMIN },
@ -1613,7 +1716,41 @@ describe('UserResolver', () => {
expect(result).toEqual(
expect.objectContaining({
data: {
setUserRole: expect.any(String),
setUserRole: ROLE_NAMES.ROLE_NAME_ADMIN,
},
}),
)
})
it('stores the ADMIN_USER_ROLE_SET event in the database', async () => {
const userContact = await UserContact.findOneOrFail({
where: { email: 'bibi@bloxberg.de' },
relations: ['user'],
})
const adminContact = await UserContact.findOneOrFail({
where: { email: 'peter@lustig.de' },
relations: ['user'],
})
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.ADMIN_USER_ROLE_SET,
affectedUserId: userContact.user.id,
actingUserId: adminContact.user.id,
}),
)
})
})
describe('to moderator', () => {
it('returns date string', async () => {
const result = await mutate({
mutation: setUserRole,
variables: { userId: user.id, role: ROLE_NAMES.ROLE_NAME_MODERATOR },
})
expect(result).toEqual(
expect.objectContaining({
data: {
setUserRole: ROLE_NAMES.ROLE_NAME_MODERATOR,
},
}),
)
@ -1656,7 +1793,21 @@ describe('UserResolver', () => {
})
describe('change role with error', () => {
describe('is own role', () => {
beforeAll(async () => {
user = await userFactory(testEnv, bibiBloxberg)
admin = await userFactory(testEnv, peterLustig)
await mutate({
mutation: login,
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
})
})
afterAll(async () => {
await cleanDB()
resetToken()
})
describe('his own role', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
@ -1672,6 +1823,29 @@ describe('UserResolver', () => {
})
})
describe('to not allowed role', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: setUserRole,
variables: { userId: user.id, role: 'unknown rolename' },
}),
).resolves.toEqual(
expect.objectContaining({
errors: [new GraphQLError('Not allowed to set user role=')],
}),
)
})
it('logs the error thrown', () => {
expect(logger.error).toBeCalledWith(
'Not allowed to set user role=',
'unknown rolename',
)
})
})
describe('user has already role to be set', () => {
describe('to admin', () => {
it('throws an error', async () => {
@ -1700,6 +1874,33 @@ describe('UserResolver', () => {
})
})
describe('to moderator', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: setUserRole,
variables: { userId: user.id, role: ROLE_NAMES.ROLE_NAME_MODERATOR },
})
await expect(
mutate({
mutation: setUserRole,
variables: { userId: user.id, role: ROLE_NAMES.ROLE_NAME_MODERATOR },
}),
).resolves.toEqual(
expect.objectContaining({
errors: [new GraphQLError('User already has role=')],
}),
)
})
it('logs the error thrown', () => {
expect(logger.error).toBeCalledWith(
'User already has role=',
ROLE_NAMES.ROLE_NAME_MODERATOR,
)
})
})
describe('to usual user', () => {
it('throws an error', async () => {
jest.clearAllMocks()

View File

@ -69,6 +69,7 @@ import { findUserByIdentifier } from './util/findUserByIdentifier'
import { findUsers } from './util/findUsers'
import { getKlicktippState } from './util/getKlicktippState'
import { validateAlias } from './util/validateAlias'
import { UserContact } from '../model/UserContact'
const LANGUAGES = ['de', 'en', 'es', 'fr', 'nl']
const DEFAULT_LANGUAGE = 'de'
@ -223,6 +224,7 @@ export class UserResolver {
// check if user with email still exists?
email = email.trim().toLowerCase()
if (await checkEmailExists(email)) {
// console.log('email still exists! email', email)
const foundUser = await findUserByEmail(email)
logger.info('DbUser.findOne', email, foundUser)
@ -355,7 +357,6 @@ export class UserResolver {
} else {
await EVENT_USER_REGISTER(dbUser)
}
console.log('createUser dbUser=', dbUser)
return new User(dbUser)
}
@ -723,44 +724,33 @@ export class UserResolver {
default:
throw new LogError('Not allowed to set user role=', role)
}
console.log('1')
const user = await DbUser.findOne({
where: { id: userId },
relations: ['userRoles'],
})
console.log('2')
// user exists ?
if (!user) {
throw new LogError('Could not find user with given ID', userId)
}
console.log('3')
// administrator user changes own role?
const moderator = getUser(context)
console.log('4')
if (moderator.id === userId) {
throw new LogError('Administrator can not change his own role')
}
console.log('5')
// if user role(s) should be deleted by role=null as parameter
if (role === null && user.userRoles) {
console.log('6')
if (user.userRoles.length > 0) {
console.log('7')
// remove all roles of the user
await UserRole.delete({ userId: user.id })
console.log('8')
user.userRoles.length = 0
} else if (user.userRoles.length === 0) {
console.log('9')
throw new LogError('User is already an usual user')
}
} else if (isUserInRole(user, role)) {
console.log('10')
throw new LogError('User already has role=', role)
}
// if role shoud be set
if (role) {
console.log('11 ', role)
if (user.userRoles === undefined) {
user.userRoles = [] as UserRole[]
}
@ -774,9 +764,7 @@ export class UserResolver {
}
// await user.save()
await EVENT_ADMIN_USER_ROLE_SET(user, moderator)
console.log('12 ')
const newUser = await DbUser.findOne({ where: { id: userId }, relations: ['userRoles'] })
console.log('13 ', newUser)
return newUser?.userRoles ? newUser.userRoles[0].role : null
}
@ -858,6 +846,18 @@ export class UserResolver {
async user(@Arg('identifier') identifier: string): Promise<User> {
return new User(await findUserByIdentifier(identifier))
}
@Authorized([RIGHTS.USER])
@Query(() => UserContact)
async userContact(@Arg('userId', () => Int) userId: number): Promise<UserContact> {
return new UserContact(
await DbUserContact.findOneOrFail({
where: { userId },
withDeleted: true,
relations: ['user'],
}),
)
}
}
export async function findUserByEmail(email: string): Promise<DbUser> {

View File

@ -19,10 +19,10 @@ export const userFactory = async (
createUser: { id },
},
} = await mutate({ mutation: createUser, variables: user })
console.log('creatUser:', { id }, { user })
// console.log('after creatUser:', { id }, { user })
// get user from database
let dbUser = await User.findOneOrFail({ where: { id }, relations: ['emailContact', 'userRoles'] })
console.log('dbUser:', dbUser)
// console.log('dbUser:', dbUser)
const emailContact = dbUser.emailContact
// console.log('emailContact:', emailContact)

View File

@ -387,3 +387,20 @@ export const user = gql`
}
}
`
export const userContact = gql`
query ($userId: Int!) {
userContact(userId: $userId) {
id
type
userId
email
emailOptInTypeId
emailResendCount
emailChecked
phone
createdAt
updatedAt
deletedAt
}
}
`

View File

@ -18,7 +18,7 @@ export class UserRole extends BaseEntity {
@Column({ name: 'updated_at', nullable: true, default: null, type: 'datetime' })
updatedAt: Date | null
@ManyToOne(() => User, (user) => user.userRoles)
@ManyToOne(() => User, (user) => user.userRoles, { nullable: true })
@JoinColumn({ name: 'user_id' })
user: User
user: User | null
}