diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts index bd206d3..334aae4 100644 --- a/apps/backend/src/app.module.ts +++ b/apps/backend/src/app.module.ts @@ -4,9 +4,10 @@ import { PrismaModule } from 'nestjs-prisma'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { EventModule } from './event/event.module'; +import { GroupsModule } from './groups/groups.module'; @Module({ - imports: [PrismaModule.forRoot({ isGlobal: true }), EventModule], + imports: [PrismaModule.forRoot({ isGlobal: true }), EventModule, GroupsModule], controllers: [AppController], providers: [AppService], }) diff --git a/apps/backend/src/groups/groups.controller.ts b/apps/backend/src/groups/groups.controller.ts new file mode 100644 index 0000000..6af1128 --- /dev/null +++ b/apps/backend/src/groups/groups.controller.ts @@ -0,0 +1,54 @@ +import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common'; +import { Prisma, Role } from '@prisma/client'; + +import { GroupsService } from './groups.service'; + +@Controller('groups') +export class GroupsController { + constructor(private readonly groupsService: GroupsService) {} + + @Post() + create(@Body() data: Prisma.GroupCreateInput) { + return this.groupsService.create(data); + } + + @Get() + findAll() { + return this.groupsService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.groupsService.findOne(Number(id)); + } + + @Get(':id/members') + findMembers(@Param('id') id: string) { + return this.groupsService.findMembers(Number(id)); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() data: Prisma.GroupUpdateInput) { + return this.groupsService.update(Number(id), data); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.groupsService.remove(Number(id)); + } + + @Post(':id/members/:userId') + addMember(@Param('id') id: string, @Param('userId') userId: string) { + return this.groupsService.addMember(Number(id), Number(userId)); + } + + @Patch(':id/members/:userId') + updateRole(@Param('id') id: string, @Param('userId') userId: string, @Body() newRole: { role: Role }) { + return this.groupsService.updateMemberRole(Number(id), Number(userId), newRole); + } + + @Delete(':id/members/:userId') + removeMember(@Param('id') id: string, @Param('userId') userId: string) { + return this.groupsService.removeMember(Number(id), Number(userId)); + } +} diff --git a/apps/backend/src/groups/groups.module.ts b/apps/backend/src/groups/groups.module.ts new file mode 100644 index 0000000..befe35b --- /dev/null +++ b/apps/backend/src/groups/groups.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; + +import { GroupsController } from './groups.controller'; +import { GroupsService } from './groups.service'; + +@Module({ + controllers: [GroupsController], + providers: [GroupsService], +}) +export class GroupsModule {} diff --git a/apps/backend/src/groups/groups.service.ts b/apps/backend/src/groups/groups.service.ts new file mode 100644 index 0000000..61aab95 --- /dev/null +++ b/apps/backend/src/groups/groups.service.ts @@ -0,0 +1,120 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { Group, GroupMembers, Prisma, Role, User } from '@prisma/client'; +import { PrismaService } from 'nestjs-prisma'; + +@Injectable() +export class GroupsService { + constructor(private readonly prisma: PrismaService) {} + + async create(data: Prisma.GroupCreateInput): Promise { + try { + return await this.prisma.group.create({ data }); + } catch { + throw new NotFoundException('Group could not be created'); + } + } + + async findAll(): Promise { + try { + return await this.prisma.group.findMany(); + } catch { + throw new NotFoundException('Groups could not be found'); + } + } + + async findOne(id: number): Promise { + try { + return await this.prisma.group.findUnique({ where: { id } }); + } catch { + throw new NotFoundException(`Group with ID ${id} not found`); + } + } + + async findMembers(id: number): Promise<{ user: User; role: Role }[]> { + const groupMembers = await this.prisma.groupMembers.findMany({ + where: { groupId: id }, + include: { User: true }, + }); + if (!groupMembers) { + throw new NotFoundException(`Group with ID ${id} not found`); + } + return groupMembers.map((groupMember) => ({ + user: groupMember.User, + role: groupMember.role, + })); + } + + async update(id: number, data: Prisma.GroupUpdateInput): Promise { + try { + return await this.prisma.group.update({ where: { id }, data }); + } catch { + throw new NotFoundException(`Group with ID ${id} could not be updated`); + } + } + + async remove(id: number): Promise { + try { + return await this.prisma.group.delete({ where: { id } }); + } catch { + throw new NotFoundException(`Group with ID ${id} could not be deleted`); + } + } + + async addMember(groupId: number, userId: number): Promise { + if (await this.prisma.groupMembers.findUnique({ where: { groupId_userId: { groupId, userId } } })) { + throw new NotFoundException('User is already a member of the group'); + } + if (!(await this.prisma.user.findUnique({ where: { id: userId } }))) { + throw new NotFoundException('User does not exist'); + } + try { + return await this.prisma.groupMembers.create({ + data: { + groupId, + userId, + }, + }); + } catch { + throw new NotFoundException('User could not be added to the group'); + } + } + + async updateMemberRole(groupId: number, userId: number, newRole: { role: Role }): Promise { + if (!(await this.prisma.groupMembers.findUnique({ where: { groupId_userId: { groupId, userId } } }))) { + throw new NotFoundException(`User with id: ${userId} is not a member of the group.`); + } + try { + return await this.prisma.groupMembers.update({ + where: { + groupId_userId: { + groupId, + userId, + }, + }, + data: { + role: newRole.role, + }, + }); + } catch { + throw new NotFoundException('User role could not be updated.'); + } + } + + async removeMember(groupId: number, userId: number): Promise { + if (!(await this.prisma.groupMembers.findUnique({ where: { groupId_userId: { groupId, userId } } }))) { + throw new NotFoundException('User is not a member of the group'); + } + try { + return await this.prisma.groupMembers.delete({ + where: { + groupId_userId: { + groupId, + userId, + }, + }, + }); + } catch { + throw new NotFoundException('User could not be removed from the group'); + } + } +}