mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Create PathBasedAuthorizer
This commit is contained in:
52
src/authorization/PathBasedAuthorizer.ts
Normal file
52
src/authorization/PathBasedAuthorizer.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
|
||||
import { ensureTrailingSlash, trimTrailingSlashes } from '../util/PathUtil';
|
||||
import type { Authorization } from './Authorization';
|
||||
import type { AuthorizerArgs } from './Authorizer';
|
||||
import { Authorizer } from './Authorizer';
|
||||
|
||||
/**
|
||||
* Redirects requests to specific authorizers based on their identifier.
|
||||
* The keys in the input map will be converted to regular expressions.
|
||||
* The regular expressions should all start with a slash
|
||||
* and will be evaluated relative to the base URL.
|
||||
*
|
||||
* Will error if no match is found.
|
||||
*/
|
||||
export class PathBasedAuthorizer extends Authorizer {
|
||||
private readonly baseUrl: string;
|
||||
private readonly paths: Map<RegExp, Authorizer>;
|
||||
|
||||
public constructor(baseUrl: string, paths: Record<string, Authorizer>) {
|
||||
super();
|
||||
this.baseUrl = ensureTrailingSlash(baseUrl);
|
||||
const entries = Object.entries(paths).map(([ key, val ]): [RegExp, Authorizer] => [ new RegExp(key, 'u'), val ]);
|
||||
this.paths = new Map(entries);
|
||||
}
|
||||
|
||||
public async canHandle(input: AuthorizerArgs): Promise<void> {
|
||||
const authorizer = this.findAuthorizer(input.identifier.path);
|
||||
await authorizer.canHandle(input);
|
||||
}
|
||||
|
||||
public async handle(input: AuthorizerArgs): Promise<Authorization> {
|
||||
const authorizer = this.findAuthorizer(input.identifier.path);
|
||||
return authorizer.handle(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the authorizer corresponding to the given path.
|
||||
* Errors if there is no match.
|
||||
*/
|
||||
private findAuthorizer(path: string): Authorizer {
|
||||
if (path.startsWith(this.baseUrl)) {
|
||||
// We want to keep the leading slash
|
||||
const relative = path.slice(trimTrailingSlashes(this.baseUrl).length);
|
||||
for (const [ regex, authorizer ] of this.paths) {
|
||||
if (regex.test(relative)) {
|
||||
return authorizer;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NotImplementedHttpError('No regex matches the given path.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user