From 69bc95899126604d8dff1bca3bf2f6067676b171 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Mon, 1 Dec 2025 21:15:39 +0100 Subject: [PATCH] Implement sessions management --- src/app.module.ts | 11 ++++-- src/controller/session.controller.ts | 50 +++++++++++++++++++++++ src/dto/session.ts | 17 ++++++++ src/dto/user.ts | 14 ++++++- src/service/session.service.ts | 59 ++++++++++++++++++++++++++++ src/service/user.service.ts | 1 + 6 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 src/controller/session.controller.ts create mode 100644 src/dto/session.ts create mode 100644 src/service/session.service.ts diff --git a/src/app.module.ts b/src/app.module.ts index a02a623..00b3751 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,6 +7,9 @@ import { StripeService } from './service/stripe.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './dto/user'; import { Purchase } from './dto/purchase'; +import { SessionService } from './service/session.service'; +import { SessionController } from './controller/session.controller'; +import { Session } from './dto/session'; @Module({ imports: [ @@ -18,12 +21,12 @@ import { Purchase } from './dto/purchase'; username: process.env.DB_USER || 'postgres', password: process.env.DB_PASSWORD || 'postgres', database: process.env.DB_NAME || 'appdb', - entities: [User, Purchase], + entities: [User, Purchase, Session], synchronize: true, }), - TypeOrmModule.forFeature([User, Purchase]), + TypeOrmModule.forFeature([User, Purchase, Session]), ], - controllers: [AccessController, BuyController], - providers: [UserService, PurchaseService, StripeService], + controllers: [AccessController, BuyController, SessionController], + providers: [UserService, PurchaseService, StripeService, SessionService], }) export class AppModule {} diff --git a/src/controller/session.controller.ts b/src/controller/session.controller.ts new file mode 100644 index 0000000..c77a8fe --- /dev/null +++ b/src/controller/session.controller.ts @@ -0,0 +1,50 @@ +import { Body, Controller, Get, Post, Query } from '@nestjs/common'; +import { SessionService } from 'src/service/session.service'; +import { UserService } from 'src/service/user.service'; + +@Controller('/session') +export class SessionController { + constructor( + private readonly userService: UserService, + private readonly sessionService: SessionService, + ) {} + + @Post('/create') + public createSession() { + this.sessionService.createSession( + new Date(Date.now() + 24 * 3600 * 1000), + 10, + ); + } + + @Get() + public async getAllSessions(@Query('userId') userId: string) { + const sessions = await this.sessionService.getAllSessions(); + const user = await this.userService.getUserById(userId); + return sessions.map((session) => ({ + id: session.id, + size: session.size, + userCount: session.users.length, + includesRequester: session.users.includes(user), + date: session.date, + })); + } + + @Post('/join') + public async joinSession( + @Body('userId') userId: string, + @Body('sessionId') sessionId: string, + ) { + const user = await this.userService.getUserById(userId); + this.sessionService.joinSession(user, sessionId); + } + + @Post('/leave') + public async leaveSession( + @Body('userId') userId: string, + @Body('sessionId') sessionId: string, + ) { + const user = await this.userService.getUserById(userId); + this.sessionService.leaveSession(user, sessionId); + } +} diff --git a/src/dto/session.ts b/src/dto/session.ts new file mode 100644 index 0000000..860634f --- /dev/null +++ b/src/dto/session.ts @@ -0,0 +1,17 @@ +import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { User } from './user'; + +@Entity('SESSIONS') +export class Session { + @PrimaryGeneratedColumn('uuid') + id: string; + + @ManyToMany(() => User, (user) => user.joinedSessions) + users: User[]; + + @Column() + size: number; + + @Column() + date: Date; +} diff --git a/src/dto/user.ts b/src/dto/user.ts index c029fbd..c4cbf25 100644 --- a/src/dto/user.ts +++ b/src/dto/user.ts @@ -1,5 +1,13 @@ -import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { + Column, + Entity, + JoinTable, + ManyToMany, + OneToMany, + PrimaryGeneratedColumn, +} from 'typeorm'; import { Purchase } from './purchase'; +import { Session } from './session'; @Entity('USERS') export class User { @@ -14,4 +22,8 @@ export class User { @OneToMany(() => Purchase, (purchase) => purchase.purchasedBy) purchases: Purchase[]; + + @ManyToMany(() => Session, (session) => session.users) + @JoinTable() + joinedSessions: Session[]; } diff --git a/src/service/session.service.ts b/src/service/session.service.ts new file mode 100644 index 0000000..3f2a5a4 --- /dev/null +++ b/src/service/session.service.ts @@ -0,0 +1,59 @@ +import { Injectable, Logger, NotFoundException } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Session } from 'src/dto/session'; +import { User } from 'src/dto/user'; +import { Repository } from 'typeorm'; + +@Injectable() +export class SessionService { + private readonly logger = new Logger(SessionService.name); + + constructor( + @InjectRepository(Session) private sessionRepo: Repository, + ) {} + + public createSession(date: Date, size: number) { + const session = this.sessionRepo.create({ + users: [], + date, + size, + }); + this.sessionRepo.save(session); + } + + public getAllSessions() { + return this.sessionRepo.find({ relations: { users: true } }); + } + + public async joinSession(user: User, sessionId: string) { + const session = await this.sessionRepo.findOneOrFail({ + where: { + id: sessionId, + }, + }); + if (!session) { + throw new NotFoundException(); + } + if ( + session.users.find((u) => u === user) || + session.users.length >= session.size + ) { + return; + } + session.users.push(user); + await this.sessionRepo.save(session); + } + + public async leaveSession(user: User, sessionId: string) { + const session = await this.sessionRepo.findOneOrFail({ + where: { + id: sessionId, + }, + }); + if (!session) { + throw new NotFoundException(); + } + session.users = session.users.filter((u) => u !== user); + await this.sessionRepo.save(session); + } +} diff --git a/src/service/user.service.ts b/src/service/user.service.ts index dba4e6c..5521482 100644 --- a/src/service/user.service.ts +++ b/src/service/user.service.ts @@ -40,6 +40,7 @@ export class UserService { name, password, purchases: [], + joinedSessions: [], }); return this.userRepo.save(user); }