diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index 22be48e40..3f39f1424 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -36,6 +36,7 @@ export enum RIGHTS { CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE', LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES', OPEN_CREATIONS = 'OPEN_CREATIONS', + USER = 'USER', // Admin SEARCH_USERS = 'SEARCH_USERS', SET_USER_ROLE = 'SET_USER_ROLE', diff --git a/backend/src/auth/ROLES.ts b/backend/src/auth/ROLES.ts index 2f3b4e081..df1ee0271 100644 --- a/backend/src/auth/ROLES.ts +++ b/backend/src/auth/ROLES.ts @@ -34,6 +34,7 @@ export const ROLE_USER = new Role('user', [ RIGHTS.CREATE_CONTRIBUTION_MESSAGE, RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES, RIGHTS.OPEN_CREATIONS, + RIGHTS.USER, ]) export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index a57346583..c75678439 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -26,7 +26,13 @@ import { unDeleteUser, sendActivationEmail, } from '@/seeds/graphql/mutations' -import { verifyLogin, queryOptIn, searchAdminUsers, searchUsers } from '@/seeds/graphql/queries' +import { + verifyLogin, + queryOptIn, + searchAdminUsers, + searchUsers, + user as userQuery, +} from '@/seeds/graphql/queries' import { GraphQLError } from 'graphql' import { User } from '@entity/User' import CONFIG from '@/config' @@ -2189,6 +2195,102 @@ describe('UserResolver', () => { }) }) }) + + describe('user', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + describe('unauthenticated', () => { + it('throws and logs "401 Unauthorized" error', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: 'identifier', + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('401 Unauthorized')], + }), + ) + expect(logger.error).toBeCalledWith('401 Unauthorized') + }) + }) + + describe('authenticated', () => { + beforeAll(async () => { + user = await userFactory(testEnv, bibiBloxberg) + await mutate({ + mutation: login, + variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, + }) + }) + + describe('identifier is no gradido ID', () => { + it('throws and logs "No valid gradido ID" error', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: 'identifier', + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('No valid gradido ID')], + }), + ) + expect(logger.error).toBeCalledWith('No valid gradido ID', 'identifier') + }) + }) + + describe('identifier is not found', () => { + it('throws and logs "No user found to given identifier" error', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: '00000000-0000-0000-0000-000000000000', + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('No user found to given identifier')], + }), + ) + expect(logger.error).toBeCalledWith( + 'No user found to given identifier', + '00000000-0000-0000-0000-000000000000', + ) + }) + }) + + describe('identifier is found', () => { + it('returns user', async () => { + await expect( + query({ + query: userQuery, + variables: { + identifier: user.gradidoID, + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + data: { + user: { + firstName: 'Bibi', + lastName: 'Bloxberg', + }, + }, + errors: undefined, + }), + ) + }) + }) + }) + }) }) describe('printTimeDuration', () => { diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 078a29a8e..c07946f0b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -811,6 +811,21 @@ export class UserResolver { return true } + + @Authorized([RIGHTS.USER]) + @Query(() => User, { nullable: true }) + async user(@Arg('identifier') identifier: string): Promise { + const isGradidoID = + /^[0-9a-f]{8,8}-[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]{12,12}$/.exec(identifier) + if (!isGradidoID) { + throw new LogError('No valid gradido ID', identifier) + } + const user = await DbUser.findOne({ where: { gradidoID: identifier } }) + if (!user) { + throw new LogError('No user found to given identifier', identifier) + } + return new User(user) + } } export async function findUserByEmail(email: string): Promise { diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 299a0103d..7c893586a 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -322,3 +322,12 @@ export const listContributionMessages = gql` } } ` + +export const user = gql` + query ($identifier: String!) { + user(identifier: $identifier) { + firstName + lastName + } + } +`