UNPKG

@solid/community-server

Version:

Community Solid Server: an open and modular implementation of the Solid specifications

108 lines 4.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WacAllowHttpHandler = void 0; const policy_engine_1 = require("@solidlab/policy-engine"); const global_logger_factory_1 = require("global-logger-factory"); const NotModifiedHttpError_1 = require("../util/errors/NotModifiedHttpError"); const Vocabularies_1 = require("../util/Vocabularies"); const OperationHttpHandler_1 = require("./OperationHttpHandler"); const VALID_METHODS = new Set(['HEAD', 'GET']); /** * Adds all the available permissions to the response metadata, * which can be used to generate the correct WAC-Allow header. * * This class does many things similar to the {@link AuthorizingHttpHandler}, * so in general it is a good idea to make sure all these classes cache their results. */ class WacAllowHttpHandler extends OperationHttpHandler_1.OperationHttpHandler { logger = (0, global_logger_factory_1.getLoggerFor)(this); credentialsExtractor; modesExtractor; permissionReader; operationHandler; constructor(args) { super(); this.credentialsExtractor = args.credentialsExtractor; this.modesExtractor = args.modesExtractor; this.permissionReader = args.permissionReader; this.operationHandler = args.operationHandler; } async handle(input) { const { request, operation } = input; let response; try { response = await this.operationHandler.handleSafe(input); } catch (error) { // WAC-Allow headers need to be added to 304 responses // as the value can differ even if the representation is the same. if (NotModifiedHttpError_1.NotModifiedHttpError.isInstance(error)) { response = error; } else { throw error; } } const { metadata } = response; // WAC-Allow is only needed for HEAD/GET requests if (!VALID_METHODS.has(operation.method) || !metadata) { return response; } this.logger.debug('Determining available permissions.'); const credentials = await this.credentialsExtractor.handleSafe(request); const requestedModes = await this.modesExtractor.handleSafe(operation); const availablePermissions = await this.permissionReader.handleSafe({ credentials, requestedModes }); const permissionSet = availablePermissions.get(operation.target); if (permissionSet) { const user = permissionSet; let everyone; if (credentials.agent?.webId) { // Need to determine public permissions this.logger.debug('Determining public permissions'); // Note that this call can potentially create a new lock on a resource that is already locked, // so a locker that allows multiple read locks on the same resource is required. const permissionMap = await this.permissionReader.handleSafe({ credentials: {}, requestedModes }); everyone = permissionMap.get(operation.target) ?? {}; } else { // User is not authenticated so public permissions are the same as agent permissions this.logger.debug('User is not authenticated so has public permissions'); everyone = user; } this.logger.debug('Adding WAC-Allow metadata'); this.addWacAllowMetadata(metadata, everyone, user); } if (NotModifiedHttpError_1.NotModifiedHttpError.isInstance(response)) { throw response; } return response; } /** * Converts the found permissions to triples and puts them in the metadata. */ addWacAllowMetadata(metadata, everyone, user) { const modes = new Set([...Object.keys(user), ...Object.keys(everyone)]); for (const mode of modes) { const aclMode = this.toAclMode(mode); if (aclMode) { if (everyone[mode]) { metadata.add(Vocabularies_1.AUTH.terms.publicMode, aclMode); } if (user[mode]) { metadata.add(Vocabularies_1.AUTH.terms.userMode, aclMode); } } } } toAclMode(mode) { switch (mode) { case policy_engine_1.PERMISSIONS.Read: return policy_engine_1.ACL.terms.Read; case policy_engine_1.PERMISSIONS.Append: return policy_engine_1.ACL.terms.Append; case policy_engine_1.PERMISSIONS.Modify: return policy_engine_1.ACL.terms.Write; case policy_engine_1.ACL.Control: return policy_engine_1.ACL.terms.Control; default: } } } exports.WacAllowHttpHandler = WacAllowHttpHandler; //# sourceMappingURL=WacAllowHttpHandler.js.map