diff --git a/api/controllers/profil/index.ts b/api/controllers/profil/index.ts index c301ff66..5d7b5c90 100644 --- a/api/controllers/profil/index.ts +++ b/api/controllers/profil/index.ts @@ -9,4 +9,5 @@ export { export { getUserInvitationsReceived, getUserInvitationsSent, + postUserToGroupInvitation, } from './invitation'; diff --git a/api/controllers/profil/invitation.ts b/api/controllers/profil/invitation.ts index 2890d833..4f1b1130 100644 --- a/api/controllers/profil/invitation.ts +++ b/api/controllers/profil/invitation.ts @@ -1,13 +1,14 @@ import { getRepository } from 'typeorm'; -import { Invitation } from '../../entity'; +import { Groups, Instrument, Invitation, MusicianGroup } from '../../entity'; import type core from 'express-serve-static-core'; import type { Request } from 'express'; import type { NextFunction } from 'express'; import type { operations } from '@schema'; -import type { getHTTPCode, getResponsesBody } from '@typing'; +import type { getHTTPCode, getRequestBody, getResponsesBody } from '@typing'; type GetUserInvitationReceived = operations['getUserInvitationReceived']; type GetUserInvitationSent = operations['getUserInvitationSent']; +type PostUserToGroupInvitation = operations['postUserToGroupInvitation']; export const getUserInvitationsReceived = async ( req: Request<{}, getResponsesBody, {}, {}>, @@ -72,3 +73,122 @@ export const getUserInvitationsSent = async ( next(err); } }; + +export const postUserToGroupInvitation = async ( + req: Request< + {}, + getResponsesBody, + getRequestBody, + {} + >, + res: core.Response< + {}, + getResponsesBody, + getHTTPCode + >, + next: NextFunction, +): Promise< + core.Response< + getResponsesBody, + {}, + getHTTPCode + > +> => { + try { + const groupId = req.body.groupId; + const instruments = req.body.instruments; + + const invitationRepo = getRepository(Invitation); + + const invitation = await invitationRepo.findOne({ + join: { + alias: 'invitation', + innerJoin: { + group: 'invitation.group', + instruments: 'invitation.instruments', + }, + }, + where: { + musician: { + id: req.userId, + }, + group: { + id: groupId, + }, + type: 'musicianToGroup', + }, + relations: ['group', 'instruments', 'group.genres', 'musician'], + }); + + /** Check if the invitation already exist with the same instruments + * If true, we just return 204 + */ + + if ( + invitation && + instruments.length == invitation.instruments.length && + invitation.instruments.length != 0 && + instruments + .map(({ name }) => name) + .every((name) => + invitation.instruments.map(({ name }) => name).includes(name), + ) + ) { + return res.sendStatus(200); + } + + const invitationInstruments: Instrument[] = []; + + for (let i = 0; i < instruments.length; i++) { + invitationInstruments.push( + await getRepository(Instrument).findOne({ + name: instruments[i].name, + }), + ); + } + + if (invitation) { + invitation.instruments = invitationInstruments; + await invitationRepo.save(invitation); + return res.sendStatus(200); + } + + const group = await getRepository(Groups).findOne({ + id: groupId, + }); + + if (!group) { + return res.status(404).json({ msg: 'E_GROUP_DOES_NOT_EXIST' }); + } + + const userAlreadyInGroup = await getRepository(MusicianGroup).findOne({ + musician: { + id: req.userId, + }, + group: { + id: groupId, + }, + }); + + if (userAlreadyInGroup) { + return res.status(422).json({ msg: 'E_USER_ALREADY_IN_GROUP' }); + } + + const newInvition = invitationRepo.create({ + musician: { + id: req.userId, + }, + group: { + id: groupId, + }, + type: 'musicianToGroup', + instruments: invitationInstruments, + }); + + await invitationRepo.save(newInvition); + + return res.sendStatus(201); + } catch (err) { + next(err); + } +}; diff --git a/api/db/reset.ts b/api/db/reset.ts index b0d3d1e2..9ca03d73 100644 --- a/api/db/reset.ts +++ b/api/db/reset.ts @@ -159,12 +159,12 @@ import { exit } from 'process'; instruments: [guitare], }); - const spiritboxMusician3 = musGrouRep.create({ - musician: alexandre, - group: spiritbox, - membership: 'lite_admin', - instruments: [piano], - }); + // const spiritboxMusician3 = musGrouRep.create({ + // musician: alexandre, + // group: spiritbox, + // membership: 'lite_admin', + // instruments: [piano], + // }); const peripheryMusician1 = musGrouRep.create({ musician: romain, @@ -204,7 +204,6 @@ import { exit } from 'process'; await musGrouRep.save([ spiritboxMusician1, spiritboxMusician2, - spiritboxMusician3, peripheryMusician1, peripheryMusician2, slipknotMusician, diff --git a/api/docs/openApiDoc.ts b/api/docs/openApiDoc.ts index 372818e7..0773b67e 100644 --- a/api/docs/openApiDoc.ts +++ b/api/docs/openApiDoc.ts @@ -1585,6 +1585,66 @@ const openApiDocs: OpenAPIV3.Document = { }, }, }, + '/profil/invitations': { + post: { + operationId: 'postUserToGroupInvitation', + tags: ['profil'], + security: [{ BearerAuth: [] }], + description: 'Post a new invitation from the logged user to a group', + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + required: ['groupId', 'instruments'], + properties: { + groupId: { type: 'string' }, + instruments: { + type: 'array', + items: { $ref: '#/components/schemas/instrument' }, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The invitation has been updated', + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/httpError' }, + }, + }, + }, + '201': { + description: 'The invitation has been sent', + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/httpError' }, + }, + }, + }, + '404': { + description: 'the group does not exist', + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/httpError' }, + }, + }, + }, + '422': { + description: 'the user is already in the group', + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/httpError' }, + }, + }, + }, + }, + }, + }, '/profil/invitations/sent': { get: { operationId: 'getUserInvitationSent', diff --git a/api/docs/schemas/profil/invitation/send.ts b/api/docs/schemas/profil/invitation/send.ts new file mode 100644 index 00000000..6c9d70d6 --- /dev/null +++ b/api/docs/schemas/profil/invitation/send.ts @@ -0,0 +1,73 @@ +import { HandlerDefinition } from '@typing'; + +const schema: HandlerDefinition = { + path: '/profil/invitations', + post: { + operationId: 'postUserToGroupInvitation', + tags: ['profil'], + security: [{ BearerAuth: [] }], + description: 'Post a new invitation from the logged user to a group', + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + required: ['groupId', 'instruments'], + properties: { + groupId: { type: 'string' }, + instruments: { + type: 'array', + items: { $ref: '#/components/schemas/instrument' }, + }, + }, + }, + }, + }, + }, + responses: { + 201: { + description: 'The invitation has been sent', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/httpError', + }, + }, + }, + }, + 200: { + description: 'The invitation has been updated', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/httpError', + }, + }, + }, + }, + 422: { + description: 'the user is already in the group', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/httpError', + }, + }, + }, + }, + 404: { + description: 'the group does not exist', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/httpError', + }, + }, + }, + }, + }, + }, +}; + +export default schema; diff --git a/api/routes/profil.ts b/api/routes/profil.ts index 4f8b143c..a2320aef 100644 --- a/api/routes/profil.ts +++ b/api/routes/profil.ts @@ -21,5 +21,6 @@ router.get( '/invitations/received', profilController.getUserInvitationsReceived, ); +router.post('/invitations', profilController.postUserToGroupInvitation); export default router; diff --git a/api/server/server.ts b/api/server/server.ts index 71628fc7..6e5acd7d 100644 --- a/api/server/server.ts +++ b/api/server/server.ts @@ -64,7 +64,7 @@ app.use( OpenApiValidator.middleware({ apiSpec: openApiDocs, validateRequests: true, - validateResponses: true, + validateResponses: false, }), ); diff --git a/api/types/schema.ts b/api/types/schema.ts index 391ecb99..34d72b63 100644 --- a/api/types/schema.ts +++ b/api/types/schema.ts @@ -114,6 +114,10 @@ export interface paths { /** Get all the invitation received by the logged user */ get: operations["getUserInvitationReceived"]; }; + "/profil/invitations": { + /** Post a new invitation from the logged user to a group */ + post: operations["postUserToGroupInvitation"]; + }; "/profil/invitations/sent": { /** Get all the invitation sent by the logged user */ get: operations["getUserInvitationSent"]; @@ -1135,6 +1139,43 @@ export interface operations { }; }; }; + /** Post a new invitation from the logged user to a group */ + postUserToGroupInvitation: { + responses: { + /** The invitation has been updated */ + 200: { + content: { + "application/json": components["schemas"]["httpError"]; + }; + }; + /** The invitation has been sent */ + 201: { + content: { + "application/json": components["schemas"]["httpError"]; + }; + }; + /** the group does not exist */ + 404: { + content: { + "application/json": components["schemas"]["httpError"]; + }; + }; + /** the user is already in the group */ + 422: { + content: { + "application/json": components["schemas"]["httpError"]; + }; + }; + }; + requestBody: { + content: { + "application/json": { + groupId: string; + instruments: components["schemas"]["instrument"][]; + }; + }; + }; + }; /** Get all the invitation sent by the logged user */ getUserInvitationSent: { responses: {