import { Injectable } from '@nestjs/common';
import { DatabaseService } from '../../../infrastructure/database/database.service';
import { ForbiddenException } from '@nestjs/common';
@Injectable()
export class FileAuthorizationService {
constructor(private readonly database:DatabaseService) {}
async assertRead(input:{
organizationId:string;
locationId?:string;
userId:string;
asset:any;
}) {
if(input.asset.organization_id!==input.organizationId) {
throw new ForbiddenException({code:'files.cross_tenant_forbidden'});
}
if(input.asset.location_id && input.locationId && input.asset.location_id!==input.locationId) {
const cross=await this.hasPermission(input,'reporting.cross_location.read');
if(!cross) throw new ForbiddenException({code:'files.cross_location_forbidden'});
}
const purpose=input.asset.purpose;
const required =
purpose==='employee_document' ? 'employees.read'
: purpose==='invoice_document' ? 'reporting.financial.read'
: purpose==='incident_evidence' ? 'incidents.read'
: purpose==='safety_evidence' ? 'safety.read'
: purpose==='supplier_document' ? 'purchasing.read'
: purpose==='export_result' ? 'exports.read'
: 'files.read';
if(!(await this.hasPermission(input,required)) && !(await this.hasPermission(input,'files.manage'))) {
throw new ForbiddenException({code:'files.permission_forbidden',required});
}
}
private async hasPermission(input:any,permission:string) {
const rows=await this.database.query<any>(
`select 1
from memberships m
join membership_roles mr on mr.membership_id=m.id
join roles r on r.id=mr.role_id
join role_permissions rp on rp.role_id=r.id
join permissions p on p.id=rp.permission_id
where m.user_account_id=$1
and m.organization_id=$2
and m.status='active'
and (mr.location_id is null or $3::uuid is null or mr.location_id=$3)
and p.permission_key=$4
limit 1`,
[input.userId,input.organizationId,input.locationId??null,permission],
);
return Boolean(rows[0]);
}
}
