64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
import {
|
|
resolveRequestPrincipal,
|
|
type PrincipalResolution,
|
|
type RequestPrincipalResolver,
|
|
} from '@/lib/server/authz/principal';
|
|
import {
|
|
decideResourceAuthorization,
|
|
type ResourceAuthorizationAction,
|
|
type ResourceAuthorizationDecision,
|
|
type ResourceOwnership,
|
|
} from '@/lib/server/authz/resource-ownership';
|
|
|
|
export type IdentityEnforcementMode = 'shadow' | 'required';
|
|
|
|
/**
|
|
* Identity enforcement is explicitly activated. Until a real session or
|
|
* device-proof resolver is installed, the default remains shadow-compatible
|
|
* so existing desktop deployments keep working.
|
|
*/
|
|
export function resolveIdentityEnforcementMode(
|
|
raw = process.env.OPENMAIC_IDENTITY_ENFORCEMENT,
|
|
): IdentityEnforcementMode {
|
|
return raw?.trim().toLowerCase() === 'required' ? 'required' : 'shadow';
|
|
}
|
|
|
|
export interface ResourceAuthorizationEvaluation {
|
|
readonly principal: PrincipalResolution;
|
|
readonly decision: ResourceAuthorizationDecision;
|
|
}
|
|
|
|
export interface EvaluateResourceAuthorizationInput {
|
|
readonly request: Request;
|
|
readonly ownership: ResourceOwnership;
|
|
readonly action: ResourceAuthorizationAction;
|
|
readonly overrideCapability?: string;
|
|
}
|
|
|
|
export interface IdentityEvaluationDeps {
|
|
readonly resolvePrincipal?: RequestPrincipalResolver;
|
|
}
|
|
|
|
/** Evaluate a resource request without deciding how an API should respond. */
|
|
export async function evaluateResourceAuthorization(
|
|
input: EvaluateResourceAuthorizationInput,
|
|
deps: IdentityEvaluationDeps = {},
|
|
): Promise<ResourceAuthorizationEvaluation> {
|
|
let principal: PrincipalResolution;
|
|
try {
|
|
principal = await (deps.resolvePrincipal ?? resolveRequestPrincipal)(input.request);
|
|
} catch {
|
|
principal = { state: 'unavailable', reason: 'resolver_failed' };
|
|
}
|
|
|
|
return {
|
|
principal,
|
|
decision: decideResourceAuthorization({
|
|
principal,
|
|
ownership: input.ownership,
|
|
action: input.action,
|
|
...(input.overrideCapability ? { overrideCapability: input.overrideCapability } : {}),
|
|
}),
|
|
};
|
|
}
|