import { Injectable } from '@nestjs/common'; import { AuthUser } from '../../auth/interfaces/auth-user.interface'; import { UserRole } from '../../users/enums/user-role.enum'; import { UpdateReserveDto } from '../../reserves/dto/update-reserve.dto'; import { Reserve } from '../../reserves/entities/reserve.entity'; import { ReserveStatus } from '../../reserves/enums/reserve-status.enum'; import { AuthorizationService } from '../authorization.service'; @Injectable() export class ReservePolicy { constructor(private readonly authorizationService: AuthorizationService) {} canCreate( user: AuthUser, reserve: Pick, ): boolean { if (this.authorizationService.isAdmin(user)) { return true; } if (user.role === UserRole.SALON) { return reserve.salon.ownerId === user.id; } if (user.role === UserRole.CUSTOMER) { return reserve.customer.userId === user.id; } return false; } canRead(user: AuthUser, reserve: Reserve): boolean { if (this.authorizationService.isAdmin(user)) { return true; } if (user.role === UserRole.SALON) { return reserve.salon.ownerId === user.id; } if (user.role === UserRole.CUSTOMER) { return reserve.customer.userId === user.id; } return false; } canUpdate( user: AuthUser, reserve: Reserve, updateDto: UpdateReserveDto, ): boolean { if (!this.canRead(user, reserve)) { return false; } if (this.authorizationService.isAdmin(user)) { return true; } if (user.role === UserRole.SALON) { return true; } if (user.role === UserRole.CUSTOMER) { return this.isCustomerCancellationUpdate(updateDto); } return false; } private isCustomerCancellationUpdate(updateDto: UpdateReserveDto): boolean { const providedFields = ( Object.keys(updateDto) as (keyof UpdateReserveDto)[] ).filter((key) => updateDto[key] !== undefined); if (providedFields.length === 0) { return false; } const allowedFields: (keyof UpdateReserveDto)[] = [ 'status', 'cancellationReason', ]; if (!providedFields.every((field) => allowedFields.includes(field))) { return false; } if ( updateDto.status !== undefined && updateDto.status !== ReserveStatus.CANCELLED ) { return false; } return updateDto.status === ReserveStatus.CANCELLED; } }