wac Get is done

main
jaxoncreed 2 years ago
parent e71db1ddb1
commit 59013086eb
  1. 1132
      package-lock.json
  2. 8
      packages/solid/src/resource/Leaf.ts
  3. 12
      packages/solid/src/resource/Resource.ts
  4. 200
      packages/solid/test/Integration.test.ts

1132
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -309,14 +309,14 @@ export class Leaf extends Resource {
* ```typescript * ```typescript
* const leaf = solidLdoDataset * const leaf = solidLdoDataset
* .getResource("https://example.com/container/resource.ttl"); * .getResource("https://example.com/container/resource.ttl");
* const leafParent = leaf.getParentContainer(); * const leafParent = await leaf.getParentContainer();
* if (!leafParent.isError) { * if (!leafParent.isError) {
* // Logs "https://example.com/container/" * // Logs "https://example.com/container/"
* console.log(leafParent.uri); * console.log(leafParent.uri);
* } * }
* ``` * ```
*/ */
getParentContainer(): Container { async getParentContainer(): Promise<Container> {
const parentUri = getParentUri(this.uri)!; const parentUri = getParentUri(this.uri)!;
return this.context.resourceStore.get(parentUri); return this.context.resourceStore.get(parentUri);
} }
@ -338,8 +338,8 @@ export class Leaf extends Resource {
* } * }
* ``` * ```
*/ */
getRootContainer(): Promise<Container | CheckRootResultError> { async getRootContainer(): Promise<Container | CheckRootResultError> {
const parent = this.getParentContainer(); const parent = await this.getParentContainer();
return parent.getRootContainer(); return parent.getRootContainer();
} }

@ -524,6 +524,10 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
*/ */
abstract getRootContainer(): Promise<Container | CheckRootResultError>; abstract getRootContainer(): Promise<Container | CheckRootResultError>;
abstract getParentContainer(): Promise<
Container | CheckRootResultError | undefined
>;
/** /**
* =========================================================================== * ===========================================================================
* WEB ACCESS CONTROL METHODS * WEB ACCESS CONTROL METHODS
@ -582,15 +586,15 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
} }
// If the WacRule is absent // If the WacRule is absent
const parentUri = getParentUri(this.uri); const parentResource = await this.getParentContainer();
if (!parentUri) { if (parentResource?.isError) return parentResource;
if (!parentResource) {
return new NoncompliantPodError( return new NoncompliantPodError(
this.uri, this.uri,
`Resource "${this.uri}" has no Effective ACL resource`, `Resource "${this.uri}" has no Effective ACL resource`,
); );
} }
const parent = this.context.resourceStore.get(parentUri); return parentResource.getWac();
return parent.getWac();
} }
// async setWac(wacRule: WacRule): Promise<> { // async setWac(wacRule: WacRule): Promise<> {

@ -95,7 +95,8 @@ const TEST_CONTAINER_ACL = `<#b30e3fd1-b5a8-4763-ad9d-e95de9cf7933> a <http://ww
<http://www.w3.org/ns/auth/acl#accessTo> <${TEST_CONTAINER_URI}>; <http://www.w3.org/ns/auth/acl#accessTo> <${TEST_CONTAINER_URI}>;
<http://www.w3.org/ns/auth/acl#default> <${TEST_CONTAINER_URI}>; <http://www.w3.org/ns/auth/acl#default> <${TEST_CONTAINER_URI}>;
<http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write>, <http://www.w3.org/ns/auth/acl#Append>, <http://www.w3.org/ns/auth/acl#Control>; <http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write>, <http://www.w3.org/ns/auth/acl#Append>, <http://www.w3.org/ns/auth/acl#Control>;
<http://www.w3.org/ns/auth/acl#agent> <${WEB_ID}>.`; <http://www.w3.org/ns/auth/acl#agent> <${WEB_ID}>;
<http://www.w3.org/ns/auth/acl#agentClass> <http://xmlns.com/foaf/0.1/Agent>, <http://www.w3.org/ns/auth/acl#AuthenticatedAgent>.`;
async function testRequestLoads<ReturnVal>( async function testRequestLoads<ReturnVal>(
request: () => Promise<ReturnVal>, request: () => Promise<ReturnVal>,
@ -305,6 +306,18 @@ describe("Integration", () => {
expect(result.type).toBe("serverError"); expect(result.type).toBe("serverError");
}); });
it("Returns an Unauthorized error if a 403 error is returned", async () => {
fetchMock.mockResolvedValueOnce(new Response("Error", { status: 403 }));
const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
const result = await testRequestLoads(() => resource.read(), resource, {
isLoading: true,
isReading: true,
isDoingInitialFetch: true,
});
expect(result.isError).toBe(true);
expect(result.type).toBe("unauthorizedError");
});
it("Returns an UnauthenticatedError on an 401 error is returned", async () => { it("Returns an UnauthenticatedError on an 401 error is returned", async () => {
fetchMock.mockResolvedValueOnce(new Response("Error", { status: 401 })); fetchMock.mockResolvedValueOnce(new Response("Error", { status: 401 }));
const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI); const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
@ -1626,16 +1639,16 @@ describe("Integration", () => {
expect(wacResult.isError).toBe(false); expect(wacResult.isError).toBe(false);
const wacSuccess = wacResult as GetWacRuleSuccess; const wacSuccess = wacResult as GetWacRuleSuccess;
expect(wacSuccess.wacRule.public).toEqual({ expect(wacSuccess.wacRule.public).toEqual({
read: false, read: true,
write: false, write: true,
append: false, append: true,
control: false, control: true,
}); });
expect(wacSuccess.wacRule.authenticated).toEqual({ expect(wacSuccess.wacRule.authenticated).toEqual({
read: false, read: true,
write: false, write: true,
append: false, append: true,
control: false, control: true,
}); });
expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({ expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({
read: true, read: true,
@ -1645,22 +1658,48 @@ describe("Integration", () => {
}); });
}); });
it("Gets wac rules for a resource that does not have a corresponding acl", async () => { it("Gets wac rules of a parent resource for a resource that does not have a corresponding acl", async () => {
const container = solidLdoDataset.getResource(SAMPLE_DATA_URI); const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
const wacResult = await container.getWac(); const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(false);
const wacSuccess = wacResult as GetWacRuleSuccess;
expect(wacSuccess.wacRule.public).toEqual({
read: true,
write: true,
append: true,
control: true,
});
expect(wacSuccess.wacRule.authenticated).toEqual({
read: true,
write: true,
append: true,
control: true,
});
expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({
read: true,
write: true,
append: true,
control: true,
});
});
it("uses cached values for a retrieved resource", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
await resource.getWac();
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(false); expect(wacResult.isError).toBe(false);
const wacSuccess = wacResult as GetWacRuleSuccess; const wacSuccess = wacResult as GetWacRuleSuccess;
expect(wacSuccess.wacRule.public).toEqual({ expect(wacSuccess.wacRule.public).toEqual({
read: false, read: true,
write: false, write: true,
append: false, append: true,
control: false, control: true,
}); });
expect(wacSuccess.wacRule.authenticated).toEqual({ expect(wacSuccess.wacRule.authenticated).toEqual({
read: false, read: true,
write: false, write: true,
append: false, append: true,
control: false, control: true,
}); });
expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({ expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({
read: true, read: true,
@ -1671,7 +1710,126 @@ describe("Integration", () => {
}); });
it("returns an error when an error is encountered fetching the aclUri", async () => { it("returns an error when an error is encountered fetching the aclUri", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("serverError");
});
it("returns an error when a document is not found", async () => {
const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("notFoundError");
});
it("returns a non-compliant error if a response is returned without a link header", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
fetchMock.mockResolvedValueOnce(
new Response("Error", {
status: 200,
}),
);
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("noncompliantPodError");
expect((wacResult as NoncompliantPodError).message).toBe(
"Response from http://localhost:3001/test_ldo/sample.ttl is not compliant with the Solid Specification: No link header present in request.",
);
});
it("returns a non-compliant error if a response is returned without an ACL link", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
fetchMock.mockResolvedValueOnce(
new Response("Error", {
status: 200,
headers: { link: `<card.meta>; rel="describedBy"` },
}),
);
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("noncompliantPodError");
expect((wacResult as NoncompliantPodError).message).toBe(
`Response from http://localhost:3001/test_ldo/sample.ttl is not compliant with the Solid Specification: There must be one link with a rel="acl"`,
);
});
it("Returns an UnexpectedResourceError if an unknown error is triggered while getting the wac URI", async () => {
fetchMock.mockRejectedValueOnce(new Error("Something happened."));
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
const result = await resource.getWac();
expect(result.isError).toBe(true);
if (!result.isError) return;
expect(result.type).toBe("unexpectedResourceError");
expect(result.message).toBe("Something happened.");
});
it("Returns an error if the request to get the ACL fails", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
fetchMock.mockResolvedValueOnce(
new Response("", {
status: 200,
headers: { link: `<card.acl>; rel="acl"` },
}),
);
fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("serverError");
});
it("Returns a non-compliant error if the root uri has no ACL", () => {});
it("Returns an error if the request to the ACL resource returns invalid turtle", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
fetchMock.mockResolvedValueOnce(
new Response("", {
status: 200,
headers: { link: `<card.acl>; rel="acl"` },
}),
);
fetchMock.mockResolvedValueOnce(
new Response("BAD TURTLE", { status: 200 }),
);
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("noncompliantPodError");
expect((wacResult as NoncompliantPodError).message).toBe(
`Response from card.acl is not compliant with the Solid Specification: Request returned noncompliant turtle: Unexpected "BAD" on line 1.\nBAD TURTLE`,
);
});
it("Returns an error if there was a problem getting the parent resource", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
fetchMock.mockResolvedValueOnce(
new Response("", {
status: 200,
headers: { link: `<card.acl>; rel="acl"` },
}),
);
fetchMock.mockResolvedValueOnce(new Response("", { status: 404 }));
fetchMock.mockResolvedValueOnce(new Response("", { status: 500 }));
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("serverError");
}); });
}); });
it("returns a NonCompliantPodError when this is the root resource and it doesn't have an ACL", async () => {
const resource = solidLdoDataset.getResource(ROOT_CONTAINER);
fetchMock.mockResolvedValueOnce(
new Response("", {
status: 200,
headers: { link: `<card.acl>; rel="acl"` },
}),
);
fetchMock.mockResolvedValueOnce(new Response("", { status: 404 }));
const wacResult = await resource.getWac();
expect(wacResult.isError).toBe(true);
expect(wacResult.type).toBe("noncompliantPodError");
expect((wacResult as NoncompliantPodError).message).toBe(
`Response from http://localhost:3001/ is not compliant with the Solid Specification: Resource "${ROOT_CONTAINER}" has no Effective ACL resource`,
);
});
}); });

Loading…
Cancel
Save