Skip to content

Commit

Permalink
fix: Prevent parent containers from storing generated metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimvh committed Sep 3, 2021
1 parent 0b4e688 commit dfe17fc
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
31 changes: 22 additions & 9 deletions src/storage/DataAccessorBasedStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) :
Expand Down Expand Up @@ -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.
*
Expand Down
11 changes: 10 additions & 1 deletion test/unit/storage/DataAccessorBasedStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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> = {};

Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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 });
Expand Down Expand Up @@ -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> => {
Expand All @@ -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> => {
Expand Down Expand Up @@ -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> => {
Expand Down

0 comments on commit dfe17fc

Please sign in to comment.