mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Return correct status codes for invalid requests
This commit is contained in:
@@ -2,4 +2,7 @@ import type { Operation } from '../../http/Operation';
|
||||
import { AsyncHandler } from '../../util/handlers/AsyncHandler';
|
||||
import type { AccessMode } from './Permissions';
|
||||
|
||||
/**
|
||||
* Extracts all {@link AccessMode}s that are necessary to execute the given {@link Operation}.
|
||||
*/
|
||||
export abstract class ModesExtractor extends AsyncHandler<Operation, Set<AccessMode>> {}
|
||||
|
||||
@@ -6,11 +6,13 @@ import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpErr
|
||||
import { ModesExtractor } from './ModesExtractor';
|
||||
import { AccessMode } from './Permissions';
|
||||
|
||||
export class SparqlPatchModesExtractor extends ModesExtractor {
|
||||
public async canHandle({ method, body }: Operation): Promise<void> {
|
||||
if (method !== 'PATCH') {
|
||||
throw new NotImplementedHttpError(`Cannot determine permissions of ${method}, only PATCH.`);
|
||||
}
|
||||
/**
|
||||
* Generates permissions for a SPARQL DELETE/INSERT body.
|
||||
* Updates with only an INSERT can be done with just append permissions,
|
||||
* while DELETEs require write permissions as well.
|
||||
*/
|
||||
export class SparqlUpdateModesExtractor extends ModesExtractor {
|
||||
public async canHandle({ body }: Operation): Promise<void> {
|
||||
if (!this.isSparql(body)) {
|
||||
throw new NotImplementedHttpError('Cannot determine permissions of non-SPARQL patches.');
|
||||
}
|
||||
@@ -18,7 +18,7 @@ export * from './authorization/access/AgentGroupAccessChecker';
|
||||
export * from './authorization/permissions/Permissions';
|
||||
export * from './authorization/permissions/ModesExtractor';
|
||||
export * from './authorization/permissions/MethodModesExtractor';
|
||||
export * from './authorization/permissions/SparqlPatchModesExtractor';
|
||||
export * from './authorization/permissions/SparqlUpdateModesExtractor';
|
||||
|
||||
// Authorization
|
||||
export * from './authorization/AllStaticReader';
|
||||
@@ -359,9 +359,12 @@ export * from './util/errors/UnsupportedMediaTypeHttpError';
|
||||
export * from './util/handlers/AsyncHandler';
|
||||
export * from './util/handlers/BooleanHandler';
|
||||
export * from './util/handlers/ConditionalHandler';
|
||||
export * from './util/handlers/HandlerUtil';
|
||||
export * from './util/handlers/MethodFilterHandler';
|
||||
export * from './util/handlers/ParallelHandler';
|
||||
export * from './util/handlers/SequenceHandler';
|
||||
export * from './util/handlers/StaticHandler';
|
||||
export * from './util/handlers/StaticThrowHandler';
|
||||
export * from './util/handlers/UnionHandler';
|
||||
export * from './util/handlers/UnsupportedAsyncHandler';
|
||||
export * from './util/handlers/WaterfallHandler';
|
||||
|
||||
30
src/util/handlers/MethodFilterHandler.ts
Normal file
30
src/util/handlers/MethodFilterHandler.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { NotImplementedHttpError } from '../errors/NotImplementedHttpError';
|
||||
import { AsyncHandler } from './AsyncHandler';
|
||||
|
||||
/**
|
||||
* Only accepts requests where the input has a `method` field that matches any one of the given methods.
|
||||
* In case of a match, the input will be sent to the source handler.
|
||||
*/
|
||||
export class MethodFilterHandler<TIn extends { method: string }, TOut> extends AsyncHandler<TIn, TOut> {
|
||||
private readonly methods: string[];
|
||||
private readonly source: AsyncHandler<TIn, TOut>;
|
||||
|
||||
public constructor(methods: string[], source: AsyncHandler<TIn, TOut>) {
|
||||
super();
|
||||
this.methods = methods;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public async canHandle(input: TIn): Promise<void> {
|
||||
if (!this.methods.includes(input.method)) {
|
||||
throw new NotImplementedHttpError(
|
||||
`Cannot determine permissions of ${input.method}, only ${this.methods.join(',')}.`,
|
||||
);
|
||||
}
|
||||
await this.source.canHandle(input);
|
||||
}
|
||||
|
||||
public async handle(input: TIn): Promise<TOut> {
|
||||
return this.source.handle(input);
|
||||
}
|
||||
}
|
||||
18
src/util/handlers/StaticThrowHandler.ts
Normal file
18
src/util/handlers/StaticThrowHandler.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { HttpError } from '../errors/HttpError';
|
||||
import { AsyncHandler } from './AsyncHandler';
|
||||
|
||||
/**
|
||||
* Utility handler that can handle all input and always throws the given error.
|
||||
*/
|
||||
export class StaticThrowHandler extends AsyncHandler<any, never> {
|
||||
private readonly error: HttpError;
|
||||
|
||||
public constructor(error: HttpError) {
|
||||
super();
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public async handle(): Promise<never> {
|
||||
throw this.error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user