diff --git a/src/services/guilds/[guildId]/members/__test__/get.test.ts b/src/services/guilds/[guildId]/members/__test__/get.test.ts new file mode 100644 index 0000000..4c88fc3 --- /dev/null +++ b/src/services/guilds/[guildId]/members/__test__/get.test.ts @@ -0,0 +1,53 @@ +import { application } from '../../../../../application.js' +import { authenticateUserTest } from '../../../../../__test__/utils/authenticateUserTest.js' +import { prismaMock } from '../../../../../__test__/setup.js' +import { memberExample } from '../../../../../models/Member.js' +import { userExample } from '../../../../../models/User.js' + +describe('GET /guilds/[guildId]/members', () => { + it('succeeds', async () => { + prismaMock.member.findFirst.mockResolvedValue(memberExample) + prismaMock.member.findMany.mockResolvedValue([ + { ...memberExample, user: userExample } + ] as any) + const { accessToken } = await authenticateUserTest() + const response = await application.inject({ + method: 'GET', + url: `/guilds/${memberExample.guildId}/members`, + headers: { + authorization: `Bearer ${accessToken}` + } + }) + const responseJson = response.json() + expect(response.statusCode).toEqual(200) + expect(responseJson.length).toEqual(1) + expect(responseJson[0].id).toEqual(memberExample.id) + expect(responseJson[0].isOwner).toEqual(memberExample.isOwner) + expect(responseJson[0].user.id).toEqual(userExample.id) + expect(responseJson[0].user.name).toEqual(userExample.name) + expect(responseJson[0].user.email).toEqual(null) + }) + + it('fails with not found member', async () => { + prismaMock.member.findFirst.mockResolvedValue(null) + const { accessToken } = await authenticateUserTest() + const response = await application.inject({ + method: 'GET', + url: '/guilds/1/members', + headers: { + authorization: `Bearer ${accessToken}` + } + }) + const responseJson = response.json() + expect(response.statusCode).toEqual(404) + expect(responseJson.message).toEqual('Member not found') + }) + + it('fails with unauthenticated user', async () => { + const response = await application.inject({ + method: 'GET', + url: '/guilds/1/members' + }) + expect(response.statusCode).toEqual(401) + }) +}) diff --git a/src/services/guilds/[guildId]/members/get.ts b/src/services/guilds/[guildId]/members/get.ts new file mode 100644 index 0000000..aea53f8 --- /dev/null +++ b/src/services/guilds/[guildId]/members/get.ts @@ -0,0 +1,103 @@ +import { Static, Type } from '@sinclair/typebox' +import { FastifyPluginAsync, FastifySchema } from 'fastify' + +import prisma from '../../../../tools/database/prisma.js' +import { fastifyErrors } from '../../../../models/utils.js' +import authenticateUser from '../../../../tools/plugins/authenticateUser.js' +import { guildSchema } from '../../../../models/Guild.js' +import { + getPaginationOptions, + queryPaginationObjectSchema +} from '../../../../tools/database/pagination.js' +import { memberSchema } from '../../../../models/Member.js' +import { userPublicWithoutSettingsSchema } from '../../../../models/User.js' + +type QuerySchemaType = Static + +const parametersSchema = Type.Object({ + guildId: guildSchema.id +}) + +type Parameters = Static + +const getServiceSchema: FastifySchema = { + description: 'GET all the members of a guild with its id.', + tags: ['members'] as string[], + security: [ + { + bearerAuth: [] + } + ] as Array<{ [key: string]: [] }>, + params: parametersSchema, + querystring: queryPaginationObjectSchema, + response: { + 200: Type.Array( + Type.Object({ + ...memberSchema, + user: Type.Object(userPublicWithoutSettingsSchema) + }) + ), + 400: fastifyErrors[400], + 401: fastifyErrors[401], + 403: fastifyErrors[403], + 404: fastifyErrors[404], + 500: fastifyErrors[500] + } +} as const + +export const getMembersByGuildIdService: FastifyPluginAsync = async ( + fastify +) => { + await fastify.register(authenticateUser) + + fastify.route<{ + Params: Parameters + Querystring: QuerySchemaType + }>({ + method: 'GET', + url: '/guilds/:guildId/members', + schema: getServiceSchema, + handler: async (request, reply) => { + if (request.user == null) { + throw fastify.httpErrors.forbidden() + } + const { guildId } = request.params + const memberCheck = await prisma.member.findFirst({ + where: { guildId, userId: request.user.current.id } + }) + if (memberCheck == null) { + throw fastify.httpErrors.notFound('Member not found') + } + const membersRequest = await prisma.member.findMany({ + ...getPaginationOptions(request.query), + orderBy: { createdAt: 'asc' }, + where: { guildId }, + include: { + user: { + select: { + id: true, + name: true, + logo: true, + status: true, + biography: true, + website: true, + createdAt: true, + updatedAt: true + } + } + } + }) + const members = membersRequest.map((member) => { + return { + ...member, + user: { + ...member.user, + email: null + } + } + }) + reply.statusCode = 200 + return members + } + }) +} diff --git a/src/services/guilds/index.ts b/src/services/guilds/index.ts index 968f826..1a06843 100644 --- a/src/services/guilds/index.ts +++ b/src/services/guilds/index.ts @@ -6,6 +6,7 @@ import { getGuildsPublic } from './public/get.js' import { getChannelsByGuildIdService } from './[guildId]/channels/get.js' import { getGuildMemberByIdService } from './[guildId]/get.js' import { putGuildIconById } from './[guildId]/icon/put.js' +import { getMembersByGuildIdService } from './[guildId]/members/get.js' export const guildsService: FastifyPluginAsync = async (fastify) => { await fastify.register(postGuilds) @@ -14,4 +15,5 @@ export const guildsService: FastifyPluginAsync = async (fastify) => { await fastify.register(getGuildMemberByIdService) await fastify.register(getChannelsByGuildIdService) await fastify.register(getGuildsPublic) + await fastify.register(getMembersByGuildIdService) }