Ruben Verborgh 2020-12-07 17:25:55 +01:00 committed by Joachim Van Herwegen
parent c182d252b1
commit 038d5728e3
3 changed files with 87 additions and 1 deletions

View File

@ -148,14 +148,15 @@ export * from './src/storage/routing/RouterRule';
export * from './src/storage/AtomicResourceStore'; export * from './src/storage/AtomicResourceStore';
export * from './src/storage/Conditions'; export * from './src/storage/Conditions';
export * from './src/storage/DataAccessorBasedStore'; export * from './src/storage/DataAccessorBasedStore';
export * from './src/storage/mapping/FileIdentifierMapper';
export * from './src/storage/LockingResourceStore'; export * from './src/storage/LockingResourceStore';
export * from './src/storage/MonitoringStore'; export * from './src/storage/MonitoringStore';
export * from './src/storage/PassthroughStore'; export * from './src/storage/PassthroughStore';
export * from './src/storage/PatchingStore'; export * from './src/storage/PatchingStore';
export * from './src/storage/ReadOnlyStore';
export * from './src/storage/RepresentationConvertingStore'; export * from './src/storage/RepresentationConvertingStore';
export * from './src/storage/ResourceStore'; export * from './src/storage/ResourceStore';
export * from './src/storage/RoutingResourceStore'; export * from './src/storage/RoutingResourceStore';
export * from './src/storage/mapping/FileIdentifierMapper';
// Util/Errors // Util/Errors
export * from './src/util/errors/BadRequestHttpError'; export * from './src/util/errors/BadRequestHttpError';

View File

@ -0,0 +1,35 @@
import type { Patch } from '../ldp/http/Patch';
import type { Representation } from '../ldp/representation/Representation';
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
import { ForbiddenHttpError } from '../util/errors/ForbiddenHttpError';
import type { Conditions } from './Conditions';
import { PassthroughStore } from './PassthroughStore';
import type { ResourceStore } from './ResourceStore';
/**
* Store that only allow read operations on the underlying source.
*/
/* eslint-disable @typescript-eslint/no-unused-vars */
export class ReadOnlyStore<T extends ResourceStore = ResourceStore> extends PassthroughStore<T> {
public constructor(source: T) {
super(source);
}
public async addResource(container: ResourceIdentifier, representation: Representation,
conditions?: Conditions): Promise<ResourceIdentifier> {
throw new ForbiddenHttpError();
}
public async deleteResource(identifier: ResourceIdentifier, conditions?: Conditions): Promise<void> {
throw new ForbiddenHttpError();
}
public async modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<void> {
throw new ForbiddenHttpError();
}
public async setRepresentation(identifier: ResourceIdentifier, representation: Representation,
conditions?: Conditions): Promise<void> {
throw new ForbiddenHttpError();
}
}

View File

@ -0,0 +1,50 @@
import type { Patch } from '../../../src/ldp/http/Patch';
import type { Representation } from '../../../src/ldp/representation/Representation';
import { ReadOnlyStore } from '../../../src/storage/ReadOnlyStore';
import type { ResourceStore } from '../../../src/storage/ResourceStore';
import { ForbiddenHttpError } from '../../../src/util/errors/ForbiddenHttpError';
describe('A ReadOnlyStore', (): void => {
const source: jest.Mocked<ResourceStore> = {
getRepresentation: jest.fn(async(): Promise<any> => 'get'),
addResource: jest.fn(),
setRepresentation: jest.fn(),
deleteResource: jest.fn(),
modifyResource: jest.fn(),
} as any;
let store: ReadOnlyStore;
beforeAll((): void => {
store = new ReadOnlyStore(source);
});
it('calls getRepresentation directly from the source.', async(): Promise<void> => {
await expect(store.getRepresentation({ path: 'getPath' }, {})).resolves.toBe('get');
expect(source.getRepresentation).toHaveBeenCalledTimes(1);
expect(source.getRepresentation).toHaveBeenLastCalledWith({ path: 'getPath' }, {}, undefined);
});
it('throws an error when calling addResource.', async(): Promise<void> => {
await expect(store.addResource({ path: 'addPath' }, {} as Representation))
.rejects.toThrow(ForbiddenHttpError);
expect(source.addResource).toHaveBeenCalledTimes(0);
});
it('throws an error when calling setRepresentation.', async(): Promise<void> => {
await expect(store.setRepresentation({ path: 'setPath' }, {} as Representation))
.rejects.toThrow(ForbiddenHttpError);
expect(source.setRepresentation).toHaveBeenCalledTimes(0);
});
it('throws an error when calling deleteResource.', async(): Promise<void> => {
await expect(store.deleteResource({ path: 'deletePath' }))
.rejects.toThrow(ForbiddenHttpError);
expect(source.deleteResource).toHaveBeenCalledTimes(0);
});
it('throws an error when calling modifyResource.', async(): Promise<void> => {
await expect(store.modifyResource({ path: 'modifyPath' }, {} as Patch))
.rejects.toThrow(ForbiddenHttpError);
expect(source.modifyResource).toHaveBeenCalledTimes(0);
});
});