import type { IdentityContext } from "@metis/identity/module"; import type { RelationshipContext, RelationshipReadAccess } from "@metis/relationship-contracts"; import { RelationshipContextSchema, RelationshipReadError } from "@metis/relationship-contracts"; import { Result } from "@repo/rdx-utils"; /** Contextos emitidos desde sesión; copiar sus campos no produce una credencial válida. */ export class SessionRelationshipReadAccess implements RelationshipReadAccess { private readonly sessions = new WeakMap(); constructor( private readonly isAuthenticated: (session: IdentityContext) => Promise, private readonly companyExists: (companyId: string) => Promise ) {} async createContext(session: IdentityContext, companyId: string, requestId: string) { const parsed = RelationshipContextSchema.safeParse({ operatorId: session.userId, companyId, requestId, }); if ( !( parsed.success && (await this.isAuthenticated(session)) && (await this.companyExists(parsed.data.companyId)) ) ) { return Result.fail(new RelationshipReadError("FORBIDDEN")); } this.sessions.set(parsed.data, Object.freeze({ ...session })); return Result.ok(parsed.data); } async authorize(context: RelationshipContext): Promise> { const session = this.sessions.get(context); if ( !session || session.userId !== context.operatorId || !(await this.isAuthenticated(session)) || !(await this.companyExists(context.companyId)) ) { return Result.fail(new RelationshipReadError("FORBIDDEN")); } return Result.ok(true); } }