feat(services): add GET /guilds/[guildId]/channels

This commit is contained in:
Divlo 2021-12-28 21:52:28 +00:00
parent 265ac006a0
commit 2871c4c9e0
No known key found for this signature in database
GPG Key ID: 8F9478F220CE65E9
8 changed files with 149 additions and 8 deletions

View File

@ -0,0 +1,14 @@
-- DropIndex
DROP INDEX "Channel_guildId_key";
-- DropIndex
DROP INDEX "Member_guildId_key";
-- DropIndex
DROP INDEX "Member_userId_key";
-- DropIndex
DROP INDEX "Message_channelId_key";
-- DropIndex
DROP INDEX "Message_memberId_key";

View File

@ -64,9 +64,9 @@ model Member {
Message Message[] Message Message[]
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt updatedAt DateTime @default(now()) @updatedAt
userId Int @unique userId Int
user User? @relation(fields: [userId], references: [id]) user User? @relation(fields: [userId], references: [id])
guildId Int @unique guildId Int
guild Guild? @relation(fields: [guildId], references: [id]) guild Guild? @relation(fields: [guildId], references: [id])
} }
@ -86,7 +86,7 @@ model Channel {
name String @db.VarChar(20) name String @db.VarChar(20)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt updatedAt DateTime @default(now()) @updatedAt
guildId Int @unique guildId Int
guild Guild? @relation(fields: [guildId], references: [id]) guild Guild? @relation(fields: [guildId], references: [id])
messages Message[] messages Message[]
} }
@ -98,8 +98,8 @@ model Message {
mimetype String @default("text/plain") @db.VarChar(127) mimetype String @default("text/plain") @db.VarChar(127)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt updatedAt DateTime @default(now()) @updatedAt
memberId Int @unique memberId Int
member Member? @relation(fields: [memberId], references: [id]) member Member? @relation(fields: [memberId], references: [id])
channelId Int @unique channelId Int
channel Channel? @relation(fields: [channelId], references: [id]) channel Channel? @relation(fields: [channelId], references: [id])
} }

View File

@ -0,0 +1,50 @@
import { application } from '../../../../../application.js'
import { authenticateUserTest } from '../../../../../__test__/utils/authenticateUserTest.js'
import { prismaMock } from '../../../../../__test__/setup.js'
import { memberExample } from '../../../../../models/Member'
import { guildExample } from '../../../../../models/Guild'
import { channelExample } from '../../../../../models/Channel.js'
describe('GET /guilds/[guildId]/channels', () => {
it('succeeds', async () => {
prismaMock.member.findFirst.mockResolvedValue(memberExample)
prismaMock.channel.findMany.mockResolvedValue([channelExample])
const { accessToken } = await authenticateUserTest()
const response = await application.inject({
method: 'GET',
url: `/guilds/${guildExample.id}/channels`,
headers: {
authorization: `Bearer ${accessToken}`
}
})
const responseJson = response.json()
expect(response.statusCode).toEqual(200)
expect(responseJson.length).toEqual(1)
expect(responseJson[0].id).toEqual(channelExample.id)
expect(responseJson[0].name).toEqual(channelExample.name)
expect(responseJson[0].guildId).toEqual(channelExample.guildId)
})
it('fails with not found guild', async () => {
const { accessToken } = await authenticateUserTest()
prismaMock.member.findFirst.mockResolvedValue(null)
const response = await application.inject({
method: 'GET',
url: '/guilds/1/channels',
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/channels'
})
expect(response.statusCode).toEqual(401)
})
})

View File

@ -0,0 +1,75 @@
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'
import { channelSchema } from '../../../../models/Channel.js'
import {
getPaginationOptions,
queryPaginationObjectSchema
} from '../../../../tools/database/pagination.js'
type QuerySchemaType = Static<typeof queryPaginationObjectSchema>
const parametersSchema = Type.Object({
guildId: guildSchema.id
})
type Parameters = Static<typeof parametersSchema>
const getServiceSchema: FastifySchema = {
description: 'GET all the channels of a guild with its id.',
tags: ['channels'] as string[],
security: [
{
bearerAuth: []
}
] as Array<{ [key: string]: [] }>,
params: parametersSchema,
querystring: queryPaginationObjectSchema,
response: {
200: Type.Array(Type.Object(channelSchema)),
400: fastifyErrors[400],
401: fastifyErrors[401],
403: fastifyErrors[403],
404: fastifyErrors[404],
500: fastifyErrors[500]
}
} as const
export const getChannelsByGuildIdService: FastifyPluginAsync = async (
fastify
) => {
await fastify.register(authenticateUser)
fastify.route<{
Params: Parameters
Querystring: QuerySchemaType
}>({
method: 'GET',
url: '/guilds/:guildId/channels',
schema: getServiceSchema,
handler: async (request, reply) => {
if (request.user == null) {
throw fastify.httpErrors.forbidden()
}
const { guildId } = request.params
const member = await prisma.member.findFirst({
where: { guildId, userId: request.user.current.id }
})
if (member == null) {
throw fastify.httpErrors.notFound('Member not found')
}
const channels = await prisma.channel.findMany({
...getPaginationOptions(request.query),
where: {
guildId
}
})
reply.statusCode = 200
return channels
}
})
}

View File

@ -34,6 +34,7 @@ const getServiceSchema: FastifySchema = {
400: fastifyErrors[400], 400: fastifyErrors[400],
401: fastifyErrors[401], 401: fastifyErrors[401],
403: fastifyErrors[403], 403: fastifyErrors[403],
404: fastifyErrors[404],
500: fastifyErrors[500] 500: fastifyErrors[500]
} }
} as const } as const

View File

@ -16,8 +16,7 @@ describe('GET /guilds', () => {
url: '/guilds', url: '/guilds',
headers: { headers: {
authorization: `Bearer ${accessToken}` authorization: `Bearer ${accessToken}`
}, }
payload: {}
}) })
const responseJson = response.json() const responseJson = response.json()
expect(response.statusCode).toEqual(200) expect(response.statusCode).toEqual(200)

View File

@ -10,7 +10,7 @@ import {
queryPaginationObjectSchema queryPaginationObjectSchema
} from '../../tools/database/pagination.js' } from '../../tools/database/pagination.js'
export type QuerySchemaType = Static<typeof queryPaginationObjectSchema> type QuerySchemaType = Static<typeof queryPaginationObjectSchema>
const getServiceSchema: FastifySchema = { const getServiceSchema: FastifySchema = {
description: 'GET all the guilds of an user.', description: 'GET all the guilds of an user.',

View File

@ -3,6 +3,7 @@ import { FastifyPluginAsync } from 'fastify'
import { getGuilds } from './get.js' import { getGuilds } from './get.js'
import { postGuilds } from './post.js' import { postGuilds } from './post.js'
import { getGuildsPublic } from './public/get.js' import { getGuildsPublic } from './public/get.js'
import { getChannelsByGuildIdService } from './[guildId]/channels/get.js'
import { getGuildMemberByIdService } from './[guildId]/get.js' import { getGuildMemberByIdService } from './[guildId]/get.js'
import { putGuildIconById } from './[guildId]/icon/put.js' import { putGuildIconById } from './[guildId]/icon/put.js'
@ -11,5 +12,6 @@ export const guildsService: FastifyPluginAsync = async (fastify) => {
await fastify.register(getGuilds) await fastify.register(getGuilds)
await fastify.register(putGuildIconById) await fastify.register(putGuildIconById)
await fastify.register(getGuildMemberByIdService) await fastify.register(getGuildMemberByIdService)
await fastify.register(getChannelsByGuildIdService)
await fastify.register(getGuildsPublic) await fastify.register(getGuildsPublic)
} }