From 567b5aa2d8d37062f7677df3b5d0b31fbd692be5 Mon Sep 17 00:00:00 2001 From: Divlo Date: Tue, 28 Dec 2021 21:53:44 +0000 Subject: [PATCH] feat(services): add GET /channels/[channelId] --- .../channels/[channelId]/__test__/get.test.ts | 64 ++++++++++++++++++ src/services/channels/[channelId]/get.ts | 66 +++++++++++++++++++ src/services/channels/index.ts | 7 ++ .../[guildId]/channels/__test__/get.test.ts | 2 +- src/services/index.ts | 4 +- 5 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 src/services/channels/[channelId]/__test__/get.test.ts create mode 100644 src/services/channels/[channelId]/get.ts create mode 100644 src/services/channels/index.ts diff --git a/src/services/channels/[channelId]/__test__/get.test.ts b/src/services/channels/[channelId]/__test__/get.test.ts new file mode 100644 index 0000000..2cdfe8b --- /dev/null +++ b/src/services/channels/[channelId]/__test__/get.test.ts @@ -0,0 +1,64 @@ +import { application } from '../../../../application.js' +import { authenticateUserTest } from '../../../../__test__/utils/authenticateUserTest.js' +import { prismaMock } from '../../../../__test__/setup.js' +import { memberExample } from '../../../../models/Member' +import { channelExample } from '../../../../models/Channel.js' + +describe('GET /channels/[channelId]', () => { + it('succeeds', async () => { + prismaMock.channel.findUnique.mockResolvedValue(channelExample) + prismaMock.member.findFirst.mockResolvedValue(memberExample) + const { accessToken } = await authenticateUserTest() + const response = await application.inject({ + method: 'GET', + url: `/channels/${channelExample.id}`, + headers: { + authorization: `Bearer ${accessToken}` + } + }) + const responseJson = response.json() + expect(response.statusCode).toEqual(200) + expect(responseJson.channel.id).toEqual(channelExample.id) + expect(responseJson.channel.name).toEqual(channelExample.name) + expect(responseJson.channel.guildId).toEqual(channelExample.guildId) + }) + + it('fails with not found member', async () => { + prismaMock.channel.findUnique.mockResolvedValue(null) + const { accessToken } = await authenticateUserTest() + const response = await application.inject({ + method: 'GET', + url: '/channels/1', + headers: { + authorization: `Bearer ${accessToken}` + } + }) + const responseJson = response.json() + expect(response.statusCode).toEqual(404) + expect(responseJson.message).toEqual('Channel not found') + }) + + it('fails with not found member', async () => { + prismaMock.channel.findUnique.mockResolvedValue(channelExample) + prismaMock.member.findFirst.mockResolvedValue(null) + const { accessToken } = await authenticateUserTest() + const response = await application.inject({ + method: 'GET', + url: `/channels/${channelExample.id}`, + headers: { + authorization: `Bearer ${accessToken}` + } + }) + const responseJson = response.json() + expect(response.statusCode).toEqual(404) + expect(responseJson.message).toEqual('Channel not found') + }) + + it('fails with unauthenticated user', async () => { + const response = await application.inject({ + method: 'GET', + url: '/channels/1' + }) + expect(response.statusCode).toEqual(401) + }) +}) diff --git a/src/services/channels/[channelId]/get.ts b/src/services/channels/[channelId]/get.ts new file mode 100644 index 0000000..6a43c15 --- /dev/null +++ b/src/services/channels/[channelId]/get.ts @@ -0,0 +1,66 @@ +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 { channelSchema } from '../../../models/Channel' + +const parametersSchema = Type.Object({ + channelId: channelSchema.id +}) + +type Parameters = Static + +const getServiceSchema: FastifySchema = { + description: 'GET a channel with its id.', + tags: ['channels'] as string[], + security: [ + { + bearerAuth: [] + } + ] as Array<{ [key: string]: [] }>, + params: parametersSchema, + response: { + 200: Type.Object({ + channel: Type.Object(channelSchema) + }), + 400: fastifyErrors[400], + 401: fastifyErrors[401], + 403: fastifyErrors[403], + 404: fastifyErrors[404], + 500: fastifyErrors[500] + } +} as const + +export const getChannelByIdService: FastifyPluginAsync = async (fastify) => { + await fastify.register(authenticateUser) + + fastify.route<{ + Params: Parameters + }>({ + method: 'GET', + url: '/channels/:channelId', + schema: getServiceSchema, + handler: async (request, reply) => { + if (request.user == null) { + throw fastify.httpErrors.forbidden() + } + const { channelId } = request.params + const channel = await prisma.channel.findUnique({ + where: { id: channelId } + }) + if (channel == null) { + throw fastify.httpErrors.notFound('Channel not found') + } + const member = await prisma.member.findFirst({ + where: { guildId: channel.guildId, userId: request.user.current.id } + }) + if (member == null) { + throw fastify.httpErrors.notFound('Channel not found') + } + reply.statusCode = 200 + return { channel } + } + }) +} diff --git a/src/services/channels/index.ts b/src/services/channels/index.ts new file mode 100644 index 0000000..75e903a --- /dev/null +++ b/src/services/channels/index.ts @@ -0,0 +1,7 @@ +import { FastifyPluginAsync } from 'fastify' + +import { getChannelByIdService } from './[channelId]/get' + +export const channelsService: FastifyPluginAsync = async (fastify) => { + await fastify.register(getChannelByIdService) +} diff --git a/src/services/guilds/[guildId]/channels/__test__/get.test.ts b/src/services/guilds/[guildId]/channels/__test__/get.test.ts index 51497fe..bc60bca 100644 --- a/src/services/guilds/[guildId]/channels/__test__/get.test.ts +++ b/src/services/guilds/[guildId]/channels/__test__/get.test.ts @@ -26,8 +26,8 @@ describe('GET /guilds/[guildId]/channels', () => { }) it('fails with not found guild', async () => { - const { accessToken } = await authenticateUserTest() prismaMock.member.findFirst.mockResolvedValue(null) + const { accessToken } = await authenticateUserTest() const response = await application.inject({ method: 'GET', url: '/guilds/1/channels', diff --git a/src/services/index.ts b/src/services/index.ts index b4af361..a5d37f9 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -3,9 +3,11 @@ import { FastifyPluginAsync } from 'fastify' import { usersService } from './users/index.js' import { guildsService } from './guilds/index.js' import { uploadsService } from './uploads/index.js' +import { channelsService } from './channels/index.js' export const services: FastifyPluginAsync = async (fastify) => { - await fastify.register(usersService) + await fastify.register(channelsService) await fastify.register(guildsService) await fastify.register(uploadsService) + await fastify.register(usersService) }