mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Create ContainerManager for containing container conventions
This commit is contained in:
parent
accfc2e58d
commit
9c080c2101
@ -172,6 +172,10 @@ export * from './util/errors/SystemError';
|
|||||||
export * from './util/errors/UnauthorizedHttpError';
|
export * from './util/errors/UnauthorizedHttpError';
|
||||||
export * from './util/errors/UnsupportedMediaTypeHttpError';
|
export * from './util/errors/UnsupportedMediaTypeHttpError';
|
||||||
|
|
||||||
|
// Util/Identifiers
|
||||||
|
export * from './util/identifiers/IdentifierStrategy';
|
||||||
|
export * from './util/identifiers/SingleRootIdentifierStrategy';
|
||||||
|
|
||||||
// Util/Locking
|
// Util/Locking
|
||||||
export * from './util/locking/ExpiringLock';
|
export * from './util/locking/ExpiringLock';
|
||||||
export * from './util/locking/ExpiringResourceLocker';
|
export * from './util/locking/ExpiringResourceLocker';
|
||||||
|
26
src/util/identifiers/IdentifierStrategy.ts
Normal file
26
src/util/identifiers/IdentifierStrategy.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures the behavior of container identifiers in a certain storage configuration.
|
||||||
|
*/
|
||||||
|
export interface IdentifierStrategy {
|
||||||
|
/**
|
||||||
|
* Verifies if this identifier is supported.
|
||||||
|
* This does not check if this identifier actually exists,
|
||||||
|
* but checks if the identifier is in scope for this class.
|
||||||
|
*/
|
||||||
|
supportsIdentifier: (identifier: ResourceIdentifier) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the identifier of the container this resource would be a member of.
|
||||||
|
* This does not check if that identifier actually exists.
|
||||||
|
* Will throw an error if the input identifier is a root container or is not supported.
|
||||||
|
*/
|
||||||
|
getParentContainer: (identifier: ResourceIdentifier) => ResourceIdentifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input corresponds to the identifier of a root container.
|
||||||
|
* This does not check if this identifier actually exists.
|
||||||
|
*/
|
||||||
|
isRootContainer: (identifier: ResourceIdentifier) => boolean;
|
||||||
|
}
|
37
src/util/identifiers/SingleRootIdentifierStrategy.ts
Normal file
37
src/util/identifiers/SingleRootIdentifierStrategy.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||||
|
import { InternalServerError } from '../errors/InternalServerError';
|
||||||
|
import { ensureTrailingSlash } from '../PathUtil';
|
||||||
|
import type { IdentifierStrategy } from './IdentifierStrategy';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
private readonly baseUrl: string;
|
||||||
|
|
||||||
|
public constructor(baseUrl: string) {
|
||||||
|
this.baseUrl = ensureTrailingSlash(baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public supportsIdentifier(identifier: ResourceIdentifier): boolean {
|
||||||
|
return identifier.path.startsWith(this.baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
import { SingleRootIdentifierStrategy } from '../../../../src/util/identifiers/SingleRootIdentifierStrategy';
|
||||||
|
|
||||||
|
describe('A SingleRootIdentifierStrategy', (): void => {
|
||||||
|
const baseUrl = 'http://test.com/';
|
||||||
|
const manager = new SingleRootIdentifierStrategy(baseUrl);
|
||||||
|
|
||||||
|
it('verifies if identifiers are in its domain.', async(): Promise<void> => {
|
||||||
|
expect(manager.supportsIdentifier({ path: 'http://notest.com/' })).toBe(false);
|
||||||
|
expect(manager.supportsIdentifier({ path: baseUrl })).toBe(true);
|
||||||
|
expect(manager.supportsIdentifier({ path: `${baseUrl}foo/bar` })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the parent identifier.', async(): Promise<void> => {
|
||||||
|
expect(manager.getParentContainer({ path: 'http://test.com/foo/bar' })).toEqual({ path: 'http://test.com/foo/' });
|
||||||
|
expect(manager.getParentContainer({ path: 'http://test.com/foo/bar/' })).toEqual({ path: 'http://test.com/foo/' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when attempting to get the parent of an unsupported identifier.', async(): Promise<void> => {
|
||||||
|
expect((): any => manager.getParentContainer({ path: 'http://nottest.com/' }))
|
||||||
|
.toThrow('http://nottest.com/ is not supported');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when attempting to get the parent of a root container.', async(): Promise<void> => {
|
||||||
|
expect((): any => manager.getParentContainer({ path: 'http://test.com/' }))
|
||||||
|
.toThrow('http://test.com/ is a root container and has no parent');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('checks for the root container by comparing with the base URL.', async(): Promise<void> => {
|
||||||
|
expect(manager.isRootContainer({ path: 'http://notest.com/' })).toBe(false);
|
||||||
|
expect(manager.isRootContainer({ path: baseUrl })).toBe(true);
|
||||||
|
expect(manager.isRootContainer({ path: `${baseUrl}foo/bar` })).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user