mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add contains function to IdentifierStrategy
This commit is contained in:
parent
18391ec414
commit
11c0d1d6cf
@ -1,12 +1,16 @@
|
|||||||
|
import { URL } from 'url';
|
||||||
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
|
||||||
import { InternalServerError } from '../errors/InternalServerError';
|
import { InternalServerError } from '../errors/InternalServerError';
|
||||||
import { ensureTrailingSlash } from '../PathUtil';
|
import { ensureTrailingSlash, isContainerIdentifier } from '../PathUtil';
|
||||||
import type { IdentifierStrategy } from './IdentifierStrategy';
|
import type { IdentifierStrategy } from './IdentifierStrategy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a default implementation for `getParentContainer`
|
* Provides a default implementation for `getParentContainer`
|
||||||
* which checks if the identifier is supported and not a root container.
|
* 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.
|
* If not, the last part before the first relevant slash will be removed to find the parent.
|
||||||
|
*
|
||||||
|
* Provides a default implementation for `contains`
|
||||||
|
* which does standard slash-semantics based string comparison.
|
||||||
*/
|
*/
|
||||||
export abstract class BaseIdentifierStrategy implements IdentifierStrategy {
|
export abstract class BaseIdentifierStrategy implements IdentifierStrategy {
|
||||||
public abstract supportsIdentifier(identifier: ResourceIdentifier): boolean;
|
public abstract supportsIdentifier(identifier: ResourceIdentifier): boolean;
|
||||||
@ -27,4 +31,22 @@ export abstract class BaseIdentifierStrategy implements IdentifierStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract isRootContainer(identifier: ResourceIdentifier): boolean;
|
public abstract isRootContainer(identifier: ResourceIdentifier): boolean;
|
||||||
|
|
||||||
|
public contains(container: ResourceIdentifier, identifier: ResourceIdentifier, transitive: boolean): boolean {
|
||||||
|
if (!isContainerIdentifier(container)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!identifier.path.startsWith(container.path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transitive) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tail = identifier.path.slice(container.path.length);
|
||||||
|
// If there is at least one `/` followed by a char this is not a direct parent container
|
||||||
|
return !/\/./u.test(tail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,14 @@ export interface IdentifierStrategy {
|
|||||||
* This does not check if this identifier actually exists.
|
* This does not check if this identifier actually exists.
|
||||||
*/
|
*/
|
||||||
isRootContainer: (identifier: ResourceIdentifier) => boolean;
|
isRootContainer: (identifier: ResourceIdentifier) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given container would contain the given identifier.
|
||||||
|
* This does not check that either of these identifiers actually exist.
|
||||||
|
* This is similar to calling {@link getParentContainer} on an identifier
|
||||||
|
* and comparing the result.
|
||||||
|
*
|
||||||
|
* If `transitive` is `false` this only checks if `container` is the direct parent container of `identifier`.
|
||||||
|
*/
|
||||||
|
contains: (container: ResourceIdentifier, identifier: ResourceIdentifier, transitive: boolean) => boolean;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,10 @@ class DummyStrategy extends BaseIdentifierStrategy {
|
|||||||
describe('A BaseIdentifierStrategy', (): void => {
|
describe('A BaseIdentifierStrategy', (): void => {
|
||||||
const strategy = new DummyStrategy();
|
const strategy = new DummyStrategy();
|
||||||
|
|
||||||
|
describe('getParentContainer', (): void => {
|
||||||
it('returns the parent identifier.', async(): Promise<void> => {
|
it('returns the parent identifier.', async(): Promise<void> => {
|
||||||
expect(strategy.getParentContainer({ path: 'http://test.com/foo/bar' })).toEqual({ path: 'http://test.com/foo/' });
|
expect(strategy.getParentContainer({ path: 'http://example.com/foo/bar' })).toEqual({ path: 'http://example.com/foo/' });
|
||||||
expect(strategy.getParentContainer({ path: 'http://test.com/foo/bar/' })).toEqual({ path: 'http://test.com/foo/' });
|
expect(strategy.getParentContainer({ path: 'http://example.com/foo/bar/' })).toEqual({ path: 'http://example.com/foo/' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors when attempting to get the parent of an unsupported identifier.', async(): Promise<void> => {
|
it('errors when attempting to get the parent of an unsupported identifier.', async(): Promise<void> => {
|
||||||
@ -27,7 +28,31 @@ describe('A BaseIdentifierStrategy', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('errors when attempting to get the parent of a root container.', async(): Promise<void> => {
|
it('errors when attempting to get the parent of a root container.', async(): Promise<void> => {
|
||||||
expect((): any => strategy.getParentContainer({ path: 'http://test.com/root' }))
|
expect((): any => strategy.getParentContainer({ path: 'http://example.com/root' }))
|
||||||
.toThrow('Cannot obtain the parent of http://test.com/root because it is a root container.');
|
.toThrow('Cannot obtain the parent of http://example.com/root because it is a root container.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('contains', (): void => {
|
||||||
|
it('returns false if container parameter is not a container identifier.', async(): Promise<void> => {
|
||||||
|
expect(strategy.contains({ path: 'http://example.com' }, { path: 'http://example.com/foo' }, false)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if container parameter is longer.', async(): Promise<void> => {
|
||||||
|
expect(strategy.contains({ path: 'http://example.com/foo/' }, { path: 'http://example.com' }, false)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if container parameter is not the direct container.', async(): Promise<void> => {
|
||||||
|
expect(strategy.contains({ path: 'http://example.com/' }, { path: 'http://example.com/foo/bar' }, false)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if the container parameter is the direct container.', async(): Promise<void> => {
|
||||||
|
expect(strategy.contains({ path: 'http://example.com/' }, { path: 'http://example.com/foo/' }, false)).toBe(true);
|
||||||
|
expect(strategy.contains({ path: 'http://example.com/' }, { path: 'http://example.com/foo' }, false)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true for transtive calls if container parameter is a grandparent.', async(): Promise<void> => {
|
||||||
|
expect(strategy.contains({ path: 'http://example.com/' }, { path: 'http://example.com/foo/bar' }, true)).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user