mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Create SubdomainIdentifierStrategy
This strategy interprets all subdomains of the base to also be root containers.
This commit is contained in:
@@ -216,8 +216,10 @@ export * from './util/handlers/UnsupportedAsyncHandler';
|
||||
export * from './util/handlers/WaterfallHandler';
|
||||
|
||||
// Util/Identifiers
|
||||
export * from './util/identifiers/BaseIdentifierStrategy';
|
||||
export * from './util/identifiers/IdentifierStrategy';
|
||||
export * from './util/identifiers/SingleRootIdentifierStrategy';
|
||||
export * from './util/identifiers/SubdomainIdentifierStrategy';
|
||||
|
||||
// Util/Locking
|
||||
export * from './util/locking/ExpiringReadWriteLocker';
|
||||
|
||||
29
src/util/identifiers/BaseIdentifierStrategy.ts
Normal file
29
src/util/identifiers/BaseIdentifierStrategy.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||
import { InternalServerError } from '../errors/InternalServerError';
|
||||
import { ensureTrailingSlash } from '../PathUtil';
|
||||
import type { IdentifierStrategy } from './IdentifierStrategy';
|
||||
|
||||
/**
|
||||
* Provides a default implementation for `getParentContainer`
|
||||
* which checks if the identifier is supported and not a root container.
|
||||
* If not, the last part before the first relevant slash will be removed to find the parent.
|
||||
*/
|
||||
export abstract class BaseIdentifierStrategy implements IdentifierStrategy {
|
||||
public abstract supportsIdentifier(identifier: ResourceIdentifier): boolean;
|
||||
|
||||
public getParentContainer(identifier: ResourceIdentifier): ResourceIdentifier {
|
||||
if (!this.supportsIdentifier(identifier)) {
|
||||
throw new InternalServerError(`${identifier.path} is not supported`);
|
||||
}
|
||||
if (this.isRootContainer(identifier)) {
|
||||
throw new InternalServerError(`${identifier.path} is a root container and has no parent`);
|
||||
}
|
||||
|
||||
// Trailing slash is necessary for URL library
|
||||
const parentPath = new URL('..', ensureTrailingSlash(identifier.path)).href;
|
||||
|
||||
return { path: parentPath };
|
||||
}
|
||||
|
||||
public abstract isRootContainer(identifier: ResourceIdentifier): boolean;
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||
import { getLoggerFor } from '../../logging/LogUtil';
|
||||
import { InternalServerError } from '../errors/InternalServerError';
|
||||
import { ensureTrailingSlash } from '../PathUtil';
|
||||
import type { IdentifierStrategy } from './IdentifierStrategy';
|
||||
import { BaseIdentifierStrategy } from './BaseIdentifierStrategy';
|
||||
|
||||
/**
|
||||
* An IdentifierStrategy that assumes there is only 1 root and all other identifiers are made by appending to that root.
|
||||
*/
|
||||
export class SingleRootIdentifierStrategy implements IdentifierStrategy {
|
||||
export class SingleRootIdentifierStrategy extends BaseIdentifierStrategy {
|
||||
private readonly baseUrl: string;
|
||||
protected readonly logger = getLoggerFor(this);
|
||||
|
||||
public constructor(baseUrl: string) {
|
||||
super();
|
||||
this.baseUrl = ensureTrailingSlash(baseUrl);
|
||||
}
|
||||
|
||||
@@ -23,20 +23,6 @@ export class SingleRootIdentifierStrategy implements IdentifierStrategy {
|
||||
return supported;
|
||||
}
|
||||
|
||||
public getParentContainer(identifier: ResourceIdentifier): ResourceIdentifier {
|
||||
if (!this.supportsIdentifier(identifier)) {
|
||||
throw new InternalServerError(`${identifier.path} is not supported`);
|
||||
}
|
||||
if (this.isRootContainer(identifier)) {
|
||||
throw new InternalServerError(`${identifier.path} is a root container and has no parent`);
|
||||
}
|
||||
|
||||
// Trailing slash is necessary for URL library
|
||||
const parentPath = new URL('..', ensureTrailingSlash(identifier.path)).href;
|
||||
|
||||
return { path: parentPath };
|
||||
}
|
||||
|
||||
public isRootContainer(identifier: ResourceIdentifier): boolean {
|
||||
return identifier.path === this.baseUrl;
|
||||
}
|
||||
|
||||
32
src/util/identifiers/SubdomainIdentifierStrategy.ts
Normal file
32
src/util/identifiers/SubdomainIdentifierStrategy.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||
import { getLoggerFor } from '../../logging/LogUtil';
|
||||
import { ensureTrailingSlash, createSubdomainRegexp } from '../PathUtil';
|
||||
import { BaseIdentifierStrategy } from './BaseIdentifierStrategy';
|
||||
|
||||
/**
|
||||
* An IdentifierStrategy that interprets all subdomains of the given base URL as roots.
|
||||
*/
|
||||
export class SubdomainIdentifierStrategy extends BaseIdentifierStrategy {
|
||||
private readonly baseUrl: string;
|
||||
private readonly regex: RegExp;
|
||||
protected readonly logger = getLoggerFor(this);
|
||||
|
||||
public constructor(baseUrl: string) {
|
||||
super();
|
||||
this.baseUrl = ensureTrailingSlash(baseUrl);
|
||||
this.regex = createSubdomainRegexp(this.baseUrl);
|
||||
}
|
||||
|
||||
public supportsIdentifier(identifier: ResourceIdentifier): boolean {
|
||||
const supported = this.regex.test(identifier.path);
|
||||
this.logger.debug(supported ?
|
||||
`Identifier ${identifier.path} is part of ${this.baseUrl}` :
|
||||
`Identifier ${identifier.path} is not part of ${this.baseUrl}`);
|
||||
return supported;
|
||||
}
|
||||
|
||||
public isRootContainer(identifier: ResourceIdentifier): boolean {
|
||||
const match = this.regex.exec(identifier.path);
|
||||
return Array.isArray(match) && match[0].length === identifier.path.length;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user