@solid/community-server
Version:
Community Solid Server: an open and modular implementation of the Solid specifications
66 lines • 3.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MethodModesExtractor = void 0;
const policy_engine_1 = require("@solidlab/policy-engine");
const NotImplementedHttpError_1 = require("../../util/errors/NotImplementedHttpError");
const IdentifierMap_1 = require("../../util/map/IdentifierMap");
const PathUtil_1 = require("../../util/PathUtil");
const ModesExtractor_1 = require("./ModesExtractor");
const READ_METHODS = new Set(['OPTIONS', 'GET', 'HEAD']);
const SUPPORTED_METHODS = new Set([...READ_METHODS, 'PUT', 'POST', 'DELETE']);
/**
* Generates permissions for the base set of methods that always require the same permissions.
* Specifically: GET, HEAD, POST, PUT and DELETE.
*/
class MethodModesExtractor extends ModesExtractor_1.ModesExtractor {
resourceSet;
/**
* Certain permissions depend on the existence of the target resource.
* The provided {@link ResourceSet} will be used for that.
*
* @param resourceSet - {@link ResourceSet} that can verify the target resource existence.
*/
constructor(resourceSet) {
super();
this.resourceSet = resourceSet;
}
async canHandle({ method }) {
if (!SUPPORTED_METHODS.has(method)) {
throw new NotImplementedHttpError_1.NotImplementedHttpError(`Cannot determine permissions of ${method}`);
}
}
async handle({ method, target }) {
const requiredModes = new IdentifierMap_1.IdentifierSetMultiMap();
// Reading requires Read permissions on the resource
if (READ_METHODS.has(method)) {
requiredModes.add(target, policy_engine_1.PERMISSIONS.Read);
}
if (method === 'PUT') {
if (await this.resourceSet.hasResource(target)) {
// Replacing a resource's representation with PUT requires Write permissions
requiredModes.add(target, policy_engine_1.PERMISSIONS.Modify);
}
else {
// ... while creating a new resource with PUT requires Append and Create permissions.
requiredModes.add(target, policy_engine_1.PERMISSIONS.Append);
requiredModes.add(target, policy_engine_1.PERMISSIONS.Create);
}
}
// Creating a new resource in a container requires Append access to that container
if (method === 'POST') {
requiredModes.add(target, policy_engine_1.PERMISSIONS.Append);
}
// Deleting a resource requires Delete access
if (method === 'DELETE') {
requiredModes.add(target, policy_engine_1.PERMISSIONS.Delete);
// …and, if the target is a container, Read permissions are required as well
// as this exposes if a container is empty or not
if ((0, PathUtil_1.isContainerIdentifier)(target)) {
requiredModes.add(target, policy_engine_1.PERMISSIONS.Read);
}
}
return requiredModes;
}
}
exports.MethodModesExtractor = MethodModesExtractor;
//# sourceMappingURL=MethodModesExtractor.js.map