UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

115 lines 4.36 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.obligations = exports.authorize = void 0; const typings_1 = require("../../typings"); const node_os_1 = __importDefault(require("node:os")); const authenticate_1 = require("./authenticate"); function authorize(services) { return async (req, res, next) => { const now = new Date(); const method = req.method.toLowerCase(); const path = `/api${req.path}`; const fragments = path.split('/').slice(1); const query = req.query; const headers = req.headers; const cookies = req.cookies ?? {}; const token = (0, authenticate_1.getAuthorizationToken)(req); const access = services.config.security.tokens.find(({ token: t }) => t === token); const modelConfig = services.models.MODELS.get(fragments[1]); const model = ['admin', 'stream', 'aggregate', 'graphql'].includes(fragments[1]) ? 'na' : modelConfig?.getModelConfig().name ?? 'unknown'; const correlationId = model === 'na' ? 'na' : fragments[2] ?? 'unknown'; const correlationField = modelConfig?.getCorrelationField() ?? 'unknown'; if (services.config.authz.onlyModels.length > 0 && !services.config.authz.onlyModels.includes(model)) { return next(); } if (services.config.authz.skipModels.length > 0 && services.config.authz.skipModels.includes(model)) { return next(); } const authorizationRequest = { action: { scope: [ 'action', ...fragments, method, correlationField, correlationId, ], method, path, query, headers, is_stream: model === 'stream', is_admin: model === 'admin', is_aggregate: model === 'aggregate', is_graphql: model === 'graphql', }, subject: { ...access, scope: ['subject', access?.id ?? 'na'], cookies, token, access, }, object: { scope: ['object'], model, correlation_id: correlationId, correlation_field: correlationField, }, context: { scope: ['context'], date: now.toISOString(), dow: now.getDay(), dom: now.getDate(), year: now.getFullYear(), month: now.getMonth() + 1, hostname: node_os_1.default.hostname(), }, }; const decision = await services.authz.authorize(authorizationRequest); services.telemetry.logger.debug('[middlewares#authorization] Authorization request', { request: authorizationRequest, decision }); if (decision.verb === typings_1.authorizations.AUTHORIZATION_VERB_DENY) { return next({ status: 403, message: 'Unauthorized', }); } res.locals.authz = { decision, request: authorizationRequest }; return next(); }; } exports.authorize = authorize; function obligations(services) { return async (req, res, next) => { const obligations = (res.locals?.authz?.decision.obligations ?? []); if (obligations.length === 0) { return next(); } const obj = services.authz.applyObligations({ // @ts-ignore body: res.body, payload: req.body, query: req.query, headers: req.headers, request: res.locals?.authz?.request, decision: res.locals?.authz?.decision, }, obligations); req.body = obj.payload; req.query = obj.query; // @ts-ignore res.body = obj.body; // @ts-ignore res.headers = obj.headers; return next(); }; } exports.obligations = obligations; //# sourceMappingURL=authorization.js.map