mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: Prevent POST requests from creating intermediate containers
This commit is contained in:
parent
867af28330
commit
a5bc8d22a9
@ -97,9 +97,9 @@ export class DataAccessorBasedStore implements ResourceStore {
|
|||||||
// Using the parent metadata as we can also use that later to check if the nested containers maybe need to be made
|
// Using the parent metadata as we can also use that later to check if the nested containers maybe need to be made
|
||||||
const parentMetadata = await this.getSafeNormalizedMetadata(container);
|
const parentMetadata = await this.getSafeNormalizedMetadata(container);
|
||||||
|
|
||||||
// When a POST method request targets a non-container resource without an existing representation,
|
// When a POST method request targets a resource without an existing representation,
|
||||||
// the server MUST respond with the 404 status code.
|
// the server MUST respond with the 404 status code.
|
||||||
if (!parentMetadata && !isContainerIdentifier(container)) {
|
if (!parentMetadata) {
|
||||||
throw new NotFoundHttpError();
|
throw new NotFoundHttpError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,10 +290,10 @@ export class DataAccessorBasedStore implements ResourceStore {
|
|||||||
*
|
*
|
||||||
* @param container - Identifier of the target container.
|
* @param container - Identifier of the target container.
|
||||||
* @param metadata - Metadata of the new resource.
|
* @param metadata - Metadata of the new resource.
|
||||||
* @param parentMetadata - Optional metadata of the parent container.
|
* @param parentMetadata - Metadata of the parent container.
|
||||||
*/
|
*/
|
||||||
protected createSafeUri(container: ResourceIdentifier, metadata: RepresentationMetadata,
|
protected createSafeUri(container: ResourceIdentifier, metadata: RepresentationMetadata,
|
||||||
parentMetadata?: RepresentationMetadata): ResourceIdentifier {
|
parentMetadata: RepresentationMetadata): ResourceIdentifier {
|
||||||
// Get all values needed for naming the resource
|
// Get all values needed for naming the resource
|
||||||
const isContainer = this.isNewContainer(metadata);
|
const isContainer = this.isNewContainer(metadata);
|
||||||
const slug = metadata.get(HTTP.slug)?.value;
|
const slug = metadata.get(HTTP.slug)?.value;
|
||||||
@ -302,14 +302,12 @@ export class DataAccessorBasedStore implements ResourceStore {
|
|||||||
let newID: ResourceIdentifier = this.createURI(container, isContainer, slug);
|
let newID: ResourceIdentifier = this.createURI(container, isContainer, slug);
|
||||||
|
|
||||||
// Make sure we don't already have a resource with this exact name (or with differing trailing slash)
|
// Make sure we don't already have a resource with this exact name (or with differing trailing slash)
|
||||||
if (parentMetadata) {
|
const withSlash = ensureTrailingSlash(newID.path);
|
||||||
const withSlash = ensureTrailingSlash(newID.path);
|
const withoutSlash = trimTrailingSlashes(newID.path);
|
||||||
const withoutSlash = trimTrailingSlashes(newID.path);
|
const exists = parentMetadata.getAll(LDP.contains).some((term): boolean =>
|
||||||
const exists = parentMetadata.getAll(LDP.contains).some((term): boolean =>
|
term.value === withSlash || term.value === withoutSlash);
|
||||||
term.value === withSlash || term.value === withoutSlash);
|
if (exists) {
|
||||||
if (exists) {
|
newID = this.createURI(container, isContainer);
|
||||||
newID = this.createURI(container, isContainer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newID;
|
return newID;
|
||||||
|
@ -137,8 +137,8 @@ describe('A DataAccessorBasedStore', (): void => {
|
|||||||
await expect(store.addResource(resourceID, representation)).rejects.toThrow(BadRequestHttpError);
|
await expect(store.addResource(resourceID, representation)).rejects.toThrow(BadRequestHttpError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will 404 if the target does not exist and does not end in a slash.', async(): Promise<void> => {
|
it('will 404 if the target does not exist.', async(): Promise<void> => {
|
||||||
const resourceID = { path: `${root}container` };
|
const resourceID = { path: `${root}container/` };
|
||||||
await expect(store.addResource(resourceID, representation)).rejects.toThrow(NotFoundHttpError);
|
await expect(store.addResource(resourceID, representation)).rejects.toThrow(NotFoundHttpError);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -219,27 +219,6 @@ describe('A DataAccessorBasedStore', (): void => {
|
|||||||
path: expect.stringMatching(new RegExp(`^${root}[^/]+/$`, 'u')),
|
path: expect.stringMatching(new RegExp(`^${root}[^/]+/$`, 'u')),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates recursive containers when needed.', async(): Promise<void> => {
|
|
||||||
const resourceID = { path: `${root}a/b/` };
|
|
||||||
const result = await store.addResource(resourceID, representation);
|
|
||||||
expect(result).toEqual({
|
|
||||||
path: expect.stringMatching(new RegExp(`^${root}a/b/[^/]+$`, 'u')),
|
|
||||||
});
|
|
||||||
await expect(arrayifyStream(accessor.data[result.path].data)).resolves.toEqual([ resourceData ]);
|
|
||||||
expect(accessor.data[`${root}a/`].metadata.getAll(RDF.type).map((type): string => type.value))
|
|
||||||
.toContain(LDP.Container);
|
|
||||||
expect(accessor.data[`${root}a/b/`].metadata.getAll(RDF.type).map((type): string => type.value))
|
|
||||||
.toContain(LDP.Container);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('errors when a recursive container overlaps with an existing resource.', async(): Promise<void> => {
|
|
||||||
const resourceID = { path: `${root}a/b/` };
|
|
||||||
accessor.data[`${root}a`] = representation;
|
|
||||||
await expect(store.addResource(resourceID, representation)).rejects.toThrow(
|
|
||||||
new ConflictHttpError(`Creating container ${root}a/ conflicts with an existing resource.`),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setting a Representation', (): void => {
|
describe('setting a Representation', (): void => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user