diff --git a/src/jukebox/juke-session/entities/membership.entity.ts b/src/jukebox/juke-session/entities/membership.entity.ts index b3d99af..345a936 100644 --- a/src/jukebox/juke-session/entities/membership.entity.ts +++ b/src/jukebox/juke-session/entities/membership.entity.ts @@ -1,9 +1,10 @@ import { EntityBase } from 'src/config/entities' import { QueuedTrack } from 'src/jukebox/queue/entities/queued-track.entity' -import { Column, Entity, ManyToOne, OneToMany } from 'typeorm' +import { Column, Entity, Index, ManyToOne, OneToMany } from 'typeorm' import { JukeSession } from './juke-session.entity' @Entity('juke_session_membership') +@Index('unique_user_per_session', ['juke_session', 'user_id'], { unique: true }) export class JukeSessionMembership extends EntityBase { @ManyToOne(() => JukeSession, (juke_session) => juke_session.memberships) juke_session: JukeSession diff --git a/src/jukebox/juke-session/juke-session.service.ts b/src/jukebox/juke-session/juke-session.service.ts index 438d709..787889f 100644 --- a/src/jukebox/juke-session/juke-session.service.ts +++ b/src/jukebox/juke-session/juke-session.service.ts @@ -214,7 +214,23 @@ export class JukeSessionService { juke_session: { id: jukeSessionId }, ...payload, }) - const createdMembership = await this.membershipRepo.save(preMembership) + + var createdMembership: JukeSessionMembership + try { + createdMembership = await this.membershipRepo.save(preMembership) + } catch (err) { + const dbError = err.driverError + // Checks Postgres Unique Constraint Error Code + if (err instanceof QueryFailedError && dbError?.code === '23505') { + if (dbError.constraint === 'unique_user_per_session') { + throw new InternalServerErrorException( + 'Failed to generate membership, an user_id already exists on this session', + ) + } + } + throw err + } + const membership = await this.getMembership(createdMembership.id) return membership }