All files / src/common/services authorization.service.ts

90% Statements 18/20
76.92% Branches 10/13
100% Functions 2/2
92.3% Lines 12/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3713x 13x     13x 13x               10x       10x 9x     9x     7x     1x 1x 1x              
import { Injectable, ForbiddenException, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@app/modules/prisma/prisma.service';
 
@Injectable()
export class AuthorizationService {
  constructor(private readonly prisma: PrismaService) {}
 
  /**
   * Verify whether the acting user can manage the given listing.
   * Admin: always allowed. Agency owner: allowed for listings under their agency.
   * Agent/Pro/Private: only allowed for own listings.
   */
  async verifyCanManageListing(listingId: number, actingUserId: number): Promise<boolean> {
    const [listing, actingUser] = await Promise.all([
      this.prisma.client.listing.findUnique({ where: { id: listingId }, include: { user: true } }),
      this.prisma.client.user.findUnique({ where: { id: actingUserId }, include: { ownerOf: true } as any }),
    ]);
    if (!listing) throw new NotFoundException(`Listing with ID ${listingId} not found.`);
    Iif (!actingUser) throw new ForbiddenException('Unknown user');
 
    // Admin override
    if ((actingUser as any).role === 'ADMIN') return true;
 
    // Direct owner
    if ((listing as any).userId === actingUserId) return true;
 
    // Agency owner can manage listings of their agency members
    const ownerAgencyId = (actingUser as any).ownerOf?.id;
    const listingOwnerAgencyId = (listing as any).user?.agencyId ?? null;
    if (ownerAgencyId && ownerAgencyId === listingOwnerAgencyId) return true;
 
    throw new ForbiddenException('You are not authorized to perform this action.');
  }
}