fix(services): add missing real time

This commit is contained in:
Divlo 2022-03-02 11:47:13 +01:00
parent c23239c0da
commit 1bcee76324
No known key found for this signature in database
GPG Key ID: 8F9478F220CE65E9
5 changed files with 92 additions and 32 deletions

View File

@ -15,35 +15,44 @@ export const id = Type.Integer({ minimum: 1, description: 'Unique identifier' })
export const redirectURI = Type.String({ format: 'uri-reference' }) export const redirectURI = Type.String({ format: 'uri-reference' })
export const fastifyErrors = { export const fastifyErrorsSchema = {
400: Type.Object({ 400: {
statusCode: Type.Literal(400), statusCode: Type.Literal(400),
error: Type.Literal('Bad Request'), error: Type.Literal('Bad Request'),
message: Type.String() message: Type.String()
}), },
401: Type.Object({ 401: {
statusCode: Type.Literal(401), statusCode: Type.Literal(401),
error: Type.Literal('Unauthorized'), error: Type.Literal('Unauthorized'),
message: Type.Literal('Unauthorized') message: Type.Literal('Unauthorized')
}), },
403: Type.Object({ 403: {
statusCode: Type.Literal(403), statusCode: Type.Literal(403),
error: Type.Literal('Forbidden'), error: Type.Literal('Forbidden'),
message: Type.Literal('Forbidden') message: Type.Literal('Forbidden')
}), },
404: Type.Object({ 404: {
statusCode: Type.Literal(404), statusCode: Type.Literal(404),
error: Type.Literal('Not Found'), error: Type.Literal('Not Found'),
message: Type.Literal('Not Found') message: Type.Literal('Not Found')
}), },
431: Type.Object({ 431: {
statusCode: Type.Literal(431), statusCode: Type.Literal(431),
error: Type.Literal('Request Header Fields Too Large'), error: Type.Literal('Request Header Fields Too Large'),
message: Type.String() message: Type.String()
}), },
500: { 500: {
statusCode: Type.Literal(500), statusCode: Type.Literal(500),
error: Type.Literal('Internal Server Error'), error: Type.Literal('Internal Server Error'),
message: Type.Literal('Something went wrong') message: Type.Literal('Something went wrong')
} }
} }
export const fastifyErrors = {
400: Type.Object(fastifyErrorsSchema[400]),
401: Type.Object(fastifyErrorsSchema[401]),
403: Type.Object(fastifyErrorsSchema[403]),
404: Type.Object(fastifyErrorsSchema[404]),
431: Type.Object(fastifyErrorsSchema[431]),
500: Type.Object(fastifyErrorsSchema[500])
}

View File

@ -8,13 +8,13 @@ import { userExample } from '../../../../../../models/User.js'
describe('POST /guilds/[guildId]/members/join', () => { describe('POST /guilds/[guildId]/members/join', () => {
it('succeeds', async () => { it('succeeds', async () => {
prismaMock.guild.findUnique.mockResolvedValue(guildExample)
prismaMock.member.findFirst.mockResolvedValue(null) prismaMock.member.findFirst.mockResolvedValue(null)
prismaMock.member.create.mockResolvedValue({ prismaMock.member.create.mockResolvedValue({
...memberExample, ...memberExample,
user: userExample user: userExample
} as any) } as any)
prismaMock.channel.findFirst.mockResolvedValue(channelExample) prismaMock.channel.findFirst.mockResolvedValue(channelExample)
prismaMock.guild.findUnique.mockResolvedValue(guildExample)
const { accessToken, user } = await authenticateUserTest() const { accessToken, user } = await authenticateUserTest()
const response = await application.inject({ const response = await application.inject({
method: 'POST', method: 'POST',
@ -34,8 +34,10 @@ describe('POST /guilds/[guildId]/members/join', () => {
expect(responseJson.guild.defaultChannelId).toEqual(channelExample.id) expect(responseJson.guild.defaultChannelId).toEqual(channelExample.id)
}) })
it('fails if the user is already in the guild', async () => { it('fails if the guild is not found', async () => {
prismaMock.member.findFirst.mockResolvedValue(memberExample) prismaMock.guild.findUnique.mockResolvedValue(null)
prismaMock.member.findFirst.mockResolvedValue(null)
prismaMock.channel.findFirst.mockResolvedValue(channelExample)
const { accessToken } = await authenticateUserTest() const { accessToken } = await authenticateUserTest()
const response = await application.inject({ const response = await application.inject({
method: 'POST', method: 'POST',
@ -44,6 +46,27 @@ describe('POST /guilds/[guildId]/members/join', () => {
authorization: `Bearer ${accessToken}` authorization: `Bearer ${accessToken}`
} }
}) })
expect(response.statusCode).toEqual(404)
})
it('fails if the user is already in the guild', async () => {
const defaultChannelId = 5
prismaMock.guild.findUnique.mockResolvedValue(guildExample)
prismaMock.member.findFirst.mockResolvedValue(memberExample)
prismaMock.channel.findFirst.mockResolvedValue({
...channelExample,
id: defaultChannelId
})
const { accessToken } = await authenticateUserTest()
const response = await application.inject({
method: 'POST',
url: `/guilds/${guildExample.id}/members/join`,
headers: {
authorization: `Bearer ${accessToken}`
}
})
const responseJson = response.json()
expect(response.statusCode).toEqual(400) expect(response.statusCode).toEqual(400)
expect(responseJson.defaultChannelId).toEqual(defaultChannelId)
}) })
}) })

View File

@ -2,11 +2,16 @@ import { Static, Type } from '@sinclair/typebox'
import { FastifyPluginAsync, FastifySchema } from 'fastify' import { FastifyPluginAsync, FastifySchema } from 'fastify'
import prisma from '../../../../../tools/database/prisma.js' import prisma from '../../../../../tools/database/prisma.js'
import { fastifyErrors, id } from '../../../../../models/utils.js' import {
fastifyErrors,
fastifyErrorsSchema,
id
} from '../../../../../models/utils.js'
import authenticateUser from '../../../../../tools/plugins/authenticateUser.js' import authenticateUser from '../../../../../tools/plugins/authenticateUser.js'
import { guildSchema } from '../../../../../models/Guild.js' import { guildSchema } from '../../../../../models/Guild.js'
import { memberSchema } from '../../../../../models/Member.js' import { memberSchema } from '../../../../../models/Member.js'
import { userPublicWithoutSettingsSchema } from '../../../../../models/User.js' import { userPublicWithoutSettingsSchema } from '../../../../../models/User.js'
import { channelSchema } from '../../../../../models/Channel.js'
const parametersSchema = Type.Object({ const parametersSchema = Type.Object({
guildId: guildSchema.id guildId: guildSchema.id
@ -32,9 +37,13 @@ const postServiceSchema: FastifySchema = {
}), }),
user: Type.Object(userPublicWithoutSettingsSchema) user: Type.Object(userPublicWithoutSettingsSchema)
}), }),
400: fastifyErrors[400], 400: Type.Object({
...fastifyErrorsSchema[400],
defaultChannelId: channelSchema.id
}),
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
@ -54,15 +63,35 @@ export const postMemberService: FastifyPluginAsync = async (fastify) => {
} }
const { user } = request const { user } = request
const { guildId } = request.params const { guildId } = request.params
const memberCheck = await prisma.member.findFirst({ const guild = await prisma.guild.findUnique({
where: {
id: guildId
}
})
if (guild == null) {
throw fastify.httpErrors.notFound('Guild not found')
}
const defaultChannel = await prisma.channel.findFirst({
where: { where: {
userId: user.current.id,
guildId guildId
} }
}) })
if (defaultChannel == null) {
throw fastify.httpErrors.internalServerError()
}
const memberCheck = await prisma.member.findFirst({
where: {
userId: user.current.id,
guildId: guild.id
}
})
if (memberCheck != null) { if (memberCheck != null) {
throw fastify.httpErrors.badRequest( throw fastify.httpErrors.createError(
"Guild doesn't exist or you are already in the guild" 400,
'You are already in the guild',
{
defaultChannelId: defaultChannel.id
}
) )
} }
const member = await prisma.member.create({ const member = await prisma.member.create({
@ -85,16 +114,7 @@ export const postMemberService: FastifyPluginAsync = async (fastify) => {
} }
} }
}) })
const channel = await prisma.channel.findFirst({
where: {
guildId: member.guildId
}
})
const guild = await prisma.guild.findUnique({
where: {
id: member.guildId
}
})
const item = { const item = {
...member, ...member,
user: { user: {
@ -103,7 +123,7 @@ export const postMemberService: FastifyPluginAsync = async (fastify) => {
}, },
guild: { guild: {
...guild, ...guild,
defaultChannelId: channel?.id defaultChannelId: defaultChannel.id
} }
} }
await fastify.io.emitToMembers({ await fastify.io.emitToMembers({

View File

@ -131,6 +131,14 @@ export const putCurrentUser: FastifyPluginAsync = async (fastify) => {
website: parseStringNullish(request.user.current.website, website) website: parseStringNullish(request.user.current.website, website)
} }
}) })
await fastify.io.emitToAuthorizedUsers({
event: 'users',
isAuthorizedCallback: () => true,
payload: {
action: 'update',
item: user
}
})
reply.statusCode = 200 reply.statusCode = 200
return { return {
user: { user: {

View File

@ -15,7 +15,7 @@ interface EmitEventOptions {
interface EmitToAuthorizedUsersOptions extends EmitEventOptions { interface EmitToAuthorizedUsersOptions extends EmitEventOptions {
/** tests whether the current connected userId is authorized to get the event, if the callback returns true, the server will emit the event to that user */ /** tests whether the current connected userId is authorized to get the event, if the callback returns true, the server will emit the event to that user */
isAuthorizedCallback: (userId: number) => Promise<boolean> isAuthorizedCallback: (userId: number) => Promise<boolean> | boolean
} }
type EmitToAuthorizedUsers = ( type EmitToAuthorizedUsers = (