fix: Prevent parent containers from storing generated metadata

This commit is contained in:
Joachim Van Herwegen 2021-09-03 15:39:57 +02:00
parent 1e1edd5c67
commit 7f3eab0b20
2 changed files with 32 additions and 10 deletions

View File

@ -268,9 +268,7 @@ export class DataAccessorBasedStore implements ResourceStore {
deleted.push(container);
// Update modified date of parent
const parentMetadata = await this.accessor.getMetadata(container);
updateModifiedDate(parentMetadata);
await this.accessor.writeContainer(container, parentMetadata);
await this.updateContainerModifiedDate(container);
}
await this.accessor.deleteResource(identifier);
@ -386,15 +384,11 @@ export class DataAccessorBasedStore implements ResourceStore {
}
// Parent container is also modified
const parentMetadata = await this.accessor.getMetadata(container);
updateModifiedDate(parentMetadata);
await this.accessor.writeContainer(container, parentMetadata);
await this.updateContainerModifiedDate(container);
}
// Remove all generated metadata to prevent it from being stored permanently
representation.metadata.removeQuads(
representation.metadata.quads(null, null, null, SOLID_META.terms.ResponseMetadata),
);
this.removeResponseMetadata(representation.metadata);
await (isContainer ?
this.accessor.writeContainer(identifier, representation.metadata) :
@ -438,6 +432,25 @@ export class DataAccessorBasedStore implements ResourceStore {
representation.metadata.addQuads(quads);
}
/**
* Removes all generated data from metadata to prevent it from being stored permanently.
*/
protected removeResponseMetadata(metadata: RepresentationMetadata): void {
metadata.removeQuads(
metadata.quads(null, null, null, SOLID_META.terms.ResponseMetadata),
);
}
/**
* Updates the last modified date of the given container
*/
protected async updateContainerModifiedDate(container: ResourceIdentifier): Promise<void> {
const parentMetadata = await this.accessor.getMetadata(container);
updateModifiedDate(parentMetadata);
this.removeResponseMetadata(parentMetadata);
await this.accessor.writeContainer(container, parentMetadata);
}
/**
* Generates a new URI for a resource in the given container, potentially using the given slug.
*

View File

@ -26,6 +26,8 @@ import { guardedStreamFrom } from '../../../src/util/StreamUtil';
import { CONTENT_TYPE, SOLID_HTTP, LDP, PIM, RDF, SOLID_META, DC } from '../../../src/util/Vocabularies';
const { namedNode, quad } = DataFactory;
const GENERATED_PREDICATE = namedNode('generated');
class SimpleDataAccessor implements DataAccessor {
public readonly data: Record<string, Representation> = {};
@ -54,7 +56,9 @@ class SimpleDataAccessor implements DataAccessor {
public async getMetadata(identifier: ResourceIdentifier): Promise<RepresentationMetadata> {
this.checkExists(identifier);
return this.data[identifier.path].metadata;
const metadata = new RepresentationMetadata(this.data[identifier.path].metadata);
metadata.add(GENERATED_PREDICATE, 'data', SOLID_META.terms.ResponseMetadata);
return metadata;
}
public async* getChildren(identifier: ResourceIdentifier): AsyncIterableIterator<RepresentationMetadata> {
@ -180,6 +184,8 @@ describe('A DataAccessorBasedStore', (): void => {
containerMetadata.identifier = namedNode(resourceID.path);
accessor.data[resourceID.path] = { metadata: containerMetadata } as Representation;
const metaMirror = new RepresentationMetadata(containerMetadata);
// Generated metadata will have its graph removed
metaMirror.add(GENERATED_PREDICATE, 'data');
await auxiliaryStrategy.addMetadata(metaMirror);
const result = await store.getRepresentation(resourceID);
expect(result).toMatchObject({ binary: false });
@ -407,6 +413,7 @@ describe('A DataAccessorBasedStore', (): void => {
await expect(arrayifyStream(accessor.data[resourceID.path].data)).resolves.toEqual([ resourceData ]);
expect(accessor.data[resourceID.path].metadata.get(DC.terms.modified)?.value).toBe(now.toISOString());
expect(accessor.data[root].metadata.get(DC.terms.modified)?.value).toBe(now.toISOString());
expect(accessor.data[root].metadata.get(GENERATED_PREDICATE)).toBeUndefined();
});
it('can write containers.', async(): Promise<void> => {
@ -424,6 +431,7 @@ describe('A DataAccessorBasedStore', (): void => {
expect(accessor.data[resourceID.path].metadata.contentType).toBeUndefined();
expect(accessor.data[resourceID.path].metadata.get(DC.terms.modified)?.value).toBe(now.toISOString());
expect(accessor.data[root].metadata.get(DC.terms.modified)?.value).toBe(now.toISOString());
expect(accessor.data[root].metadata.get(GENERATED_PREDICATE)).toBeUndefined();
});
it('can overwrite resources which does not update parent metadata.', async(): Promise<void> => {
@ -625,6 +633,7 @@ describe('A DataAccessorBasedStore', (): void => {
]);
expect(accessor.data[`${root}resource`]).toBeUndefined();
expect(accessor.data[root].metadata.get(DC.terms.modified)?.value).toBe(now.toISOString());
expect(accessor.data[root].metadata.get(GENERATED_PREDICATE)).toBeUndefined();
});
it('will delete root non-storage containers.', async(): Promise<void> => {