@getanthill/datastore
Version:
Event-Sourced Datastore
115 lines • 4.36 kB
JavaScript
"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