mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add more extensive permission parsing support
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Algebra } from 'sparqlalgebrajs';
|
||||
import { Patch } from './Patch';
|
||||
import { Update } from 'sparqlalgebrajs/lib/algebra';
|
||||
|
||||
/**
|
||||
* A specific type of {@link Patch} corresponding to a SPARQL update.
|
||||
@@ -8,5 +8,5 @@ export interface SparqlUpdatePatch extends Patch {
|
||||
/**
|
||||
* Algebra corresponding to the SPARQL update.
|
||||
*/
|
||||
algebra: Update;
|
||||
algebra: Algebra.Update;
|
||||
}
|
||||
|
||||
32
src/ldp/permissions/BasePermissionsExtractor.ts
Normal file
32
src/ldp/permissions/BasePermissionsExtractor.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Operation } from '../operations/Operation';
|
||||
import { PermissionSet } from './PermissionSet';
|
||||
import { PermissionsExtractor } from './PermissionsExtractor';
|
||||
import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError';
|
||||
|
||||
/**
|
||||
* Generates permissions for the base set of methods that always require the same permissions.
|
||||
* Specifically: GET, HEAD, POST, PUT and DELETE.
|
||||
*/
|
||||
export class BasePermissionsExtractor extends PermissionsExtractor {
|
||||
public async canHandle(input: Operation): Promise<void> {
|
||||
if (!/^(?:HEAD|GET|POST|PUT|DELETE)$/u.test(input.method)) {
|
||||
throw new UnsupportedHttpError(`Unsupported method: ${input.method}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async handle(input: Operation): Promise<PermissionSet> {
|
||||
const requiredPermissions = {
|
||||
read: /^(?:HEAD|GET)$/u.test(input.method),
|
||||
append: false,
|
||||
write: /^(?:POST|PUT|DELETE)$/u.test(input.method),
|
||||
};
|
||||
|
||||
const read = /^(?:HEAD|GET)$/u.test(input.method);
|
||||
const write = /^(?:POST|PUT|DELETE)$/u.test(input.method);
|
||||
|
||||
// Since `append` is a specific type of write, it is true if `write` is true.
|
||||
const append = requiredPermissions.write;
|
||||
|
||||
return { read, append, write };
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Operation } from '../operations/Operation';
|
||||
import { PermissionSet } from './PermissionSet';
|
||||
import { PermissionsExtractor } from './PermissionsExtractor';
|
||||
|
||||
/**
|
||||
* Makes some simplified assumption based on the {@link Operation} method to generate a {@link PermissionSet}.
|
||||
*/
|
||||
export class SimplePermissionsExtractor extends PermissionsExtractor {
|
||||
public async canHandle(): Promise<void> {
|
||||
// Supports all operations
|
||||
}
|
||||
|
||||
public async handle(input: Operation): Promise<PermissionSet> {
|
||||
const result = {
|
||||
read: input.method === 'GET',
|
||||
append: false,
|
||||
write: input.method === 'POST' || input.method === 'PUT' || input.method === 'DELETE',
|
||||
};
|
||||
result.append = result.write;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
58
src/ldp/permissions/SparqlPatchPermissionsExtractor.ts
Normal file
58
src/ldp/permissions/SparqlPatchPermissionsExtractor.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Algebra } from 'sparqlalgebrajs';
|
||||
import { Operation } from '../operations/Operation';
|
||||
import { PermissionSet } from './PermissionSet';
|
||||
import { PermissionsExtractor } from './PermissionsExtractor';
|
||||
import { Representation } from '../representation/Representation';
|
||||
import { SparqlUpdatePatch } from '../http/SparqlUpdatePatch';
|
||||
import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError';
|
||||
|
||||
/**
|
||||
* Generates permissions for a SPARQL DELETE/INSERT patch.
|
||||
* Updates with only an INSERT can be done with just append permissions,
|
||||
* while DELETEs require write permissions as well.
|
||||
*/
|
||||
export class SparqlPatchPermissionsExtractor extends PermissionsExtractor {
|
||||
public async canHandle(input: Operation): Promise<void> {
|
||||
if (input.method !== 'PATCH') {
|
||||
throw new UnsupportedHttpError('Only PATCH operations are supported.');
|
||||
}
|
||||
if (!input.body) {
|
||||
throw new UnsupportedHttpError('PATCH body is required to determine permissions.');
|
||||
}
|
||||
if (!this.isSparql(input.body)) {
|
||||
throw new UnsupportedHttpError('Only SPARQL update PATCHes are supported.');
|
||||
}
|
||||
if (!this.isDeleteInsert(input.body.algebra)) {
|
||||
throw new UnsupportedHttpError('Only DELETE/INSERT SPARQL update operations are supported.');
|
||||
}
|
||||
}
|
||||
|
||||
public async handle(input: Operation): Promise<PermissionSet> {
|
||||
// Verified in `canHandle` call
|
||||
const op = (input.body as SparqlUpdatePatch).algebra as Algebra.DeleteInsert;
|
||||
|
||||
const read = false;
|
||||
const write = this.needsWrite(op);
|
||||
|
||||
// Since `append` is a specific type of write, it is true if `write` is true.
|
||||
const append = write || this.needsAppend(op);
|
||||
|
||||
return { read, write, append };
|
||||
}
|
||||
|
||||
private isSparql(data: Representation): data is SparqlUpdatePatch {
|
||||
return Boolean((data as SparqlUpdatePatch).algebra);
|
||||
}
|
||||
|
||||
private isDeleteInsert(op: Algebra.Operation): op is Algebra.DeleteInsert {
|
||||
return op.type === Algebra.types.DELETE_INSERT;
|
||||
}
|
||||
|
||||
private needsAppend(update: Algebra.DeleteInsert): boolean {
|
||||
return Boolean(update.insert && update.insert.length > 0);
|
||||
}
|
||||
|
||||
private needsWrite(update: Algebra.DeleteInsert): boolean {
|
||||
return Boolean(update.delete && update.delete.length > 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user