UNPKG

@inrupt/solid-client

Version:
1,304 lines (1,162 loc) • 42.5 kB
/** * Copyright 2020 Inrupt Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the * Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import { jest, describe, it, expect } from "@jest/globals"; jest.mock("../fetcher.ts", () => ({ fetch: jest.fn().mockImplementation(() => Promise.resolve( new Response(undefined, { headers: { Location: "https://arbitrary.pod/resource" }, }) ) ), })); import { Response } from "cross-fetch"; import { DataFactory } from "n3"; import { rdf, acp } from "../constants"; import { mockSolidDatasetFrom } from "../resource/mock"; import { getSourceUrl } from "../resource/resource"; import { createSolidDataset } from "../resource/solidDataset"; import { addIri } from "../thing/add"; import { getIriAll, getUrl } from "../thing/get"; import { mockThingFrom } from "../thing/mock"; import { removeUrl } from "../thing/remove"; import { setUrl } from "../thing/set"; import { asUrl, createThing, getThing, getThingAll, setThing, } from "../thing/thing"; import { addAcrPolicyUrl, addPolicyUrl, getAcrPolicyUrlAll, getPolicyUrlAll, } from "./control"; import { internal_getAcr } from "./control.internal"; import { addMockAcrTo, mockAcrFor } from "./mock"; import { createPolicy, createResourcePolicyFor, getAllowModes, getDenyModes, getPolicy, getPolicyAll, getResourceAcrPolicy, getResourceAcrPolicyAll, getResourcePolicy, getResourcePolicyAll, policyAsMarkdown, removePolicy, removeResourceAcrPolicy, removeResourcePolicy, setAllowModes, setDenyModes, setPolicy, setResourceAcrPolicy, setResourcePolicy, } from "./policy"; import { addNoneOfRuleUrl, addAnyOfRuleUrl, addAllOfRuleUrl } from "./rule"; describe("createPolicy", () => { it("creates a Thing of type acp:AccessPolicy", () => { const newPolicy = createPolicy("https://some.pod/policy-resource#policy"); expect(getUrl(newPolicy, rdf.type)).toBe(acp.Policy); expect(asUrl(newPolicy)).toBe("https://some.pod/policy-resource#policy"); }); }); describe("getPolicy", () => { it("returns the Policy with the given URL", () => { let mockPolicy = createThing({ url: "https://some.pod/policy-resource#policy", }); mockPolicy = setUrl(mockPolicy, rdf.type, acp.Policy); const policyDataset = setThing(createSolidDataset(), mockPolicy); expect( getPolicy(policyDataset, "https://some.pod/policy-resource#policy") ).not.toBeNull(); }); it("returns null if the given URL identifies something that is not an Access Policy", () => { let notAPolicy = createThing({ url: "https://some.pod/policy-resource#not-a-policy", }); notAPolicy = setUrl( notAPolicy, rdf.type, "https://arbitrary.vocab/not-a-policy" ); const policyDataset = setThing(createSolidDataset(), notAPolicy); expect( getPolicy(policyDataset, "https://some.pod/policy-resource#not-a-policy") ).toBeNull(); }); it("returns null if there is no Thing at the given URL", () => { expect( getPolicy(createSolidDataset(), "https://some.pod/policy-resource#policy") ).toBeNull(); }); }); describe("getPolicyAll", () => { it("returns included Policies", () => { let mockPolicy = createThing({ url: "https://some.pod/policy-resource#policy", }); mockPolicy = setUrl(mockPolicy, rdf.type, acp.Policy); const policyDataset = setThing(createSolidDataset(), mockPolicy); expect(getPolicyAll(policyDataset)).toHaveLength(1); }); it("returns only those Things whose type is of acp:AccessPolicy", () => { let mockPolicy = createThing({ url: "https://some.pod/policy-resource#policy", }); mockPolicy = setUrl(mockPolicy, rdf.type, acp.Policy); let notAPolicy = createThing({ url: "https://some.pod/policy-resource#not-a-policy", }); notAPolicy = setUrl( notAPolicy, rdf.type, "https://arbitrary.vocab/not-a-policy" ); let policyDataset = setThing(createSolidDataset(), mockPolicy); policyDataset = setThing(policyDataset, notAPolicy); expect(getPolicyAll(policyDataset)).toHaveLength(1); }); it("returns an empty array if there are no Thing in the given PolicyDataset", () => { expect(getPolicyAll(createSolidDataset())).toHaveLength(0); }); }); describe("setPolicy", () => { it("replaces existing instances of the set Access Policy", () => { const somePredicate = "https://some.vocab/predicate"; let mockPolicy = createThing({ url: "https://some.pod/policy-resource#policy", }); mockPolicy = setUrl(mockPolicy, rdf.type, acp.Policy); mockPolicy = setUrl(mockPolicy, somePredicate, "https://example.test"); const policyDataset = setThing(createSolidDataset(), mockPolicy); const updatedPolicy = removeUrl( mockPolicy, somePredicate, "https://example.test" ); const updatedPolicyDataset = setPolicy(policyDataset, updatedPolicy); const policyAfterUpdate = getPolicy( updatedPolicyDataset, "https://some.pod/policy-resource#policy" ); expect(getUrl(policyAfterUpdate!, somePredicate)).toBeNull(); }); }); describe("removePolicy", () => { it("removes the given Access Policy from the Access Policy Resource", () => { let mockPolicy = createThing({ url: "https://some.pod/policy-resource#policy", }); mockPolicy = setUrl(mockPolicy, rdf.type, acp.Policy); const policyDataset = setThing(createSolidDataset(), mockPolicy); const updatedPolicyDataset = removePolicy(policyDataset, mockPolicy); expect(getThingAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a plain URL to remove an Access Policy", () => { let mockPolicy = createThing({ url: "https://some.pod/policy-resource#policy", }); mockPolicy = setUrl(mockPolicy, rdf.type, acp.Policy); const policyDataset = setThing(createSolidDataset(), mockPolicy); const updatedPolicyDataset = removePolicy( policyDataset, "https://some.pod/policy-resource#policy" ); expect(getThingAll(updatedPolicyDataset)).toHaveLength(0); }); it("does not remove unrelated policies", () => { let mockPolicy1 = createThing({ url: "https://some.pod/policy-resource#policy1", }); mockPolicy1 = setUrl(mockPolicy1, rdf.type, acp.Policy); let mockPolicy2 = createThing({ url: "https://some.pod/policy-resource#policy2", }); mockPolicy2 = setUrl(mockPolicy2, rdf.type, acp.Policy); let policyDataset = setThing(createSolidDataset(), mockPolicy1); policyDataset = setThing(policyDataset, mockPolicy2); const updatedPolicyDataset = removePolicy(policyDataset, mockPolicy1); expect(getThingAll(updatedPolicyDataset)).toHaveLength(1); }); }); describe("createResourcePolicyFor", () => { it("creates a Thing of type acp:AccessPolicy", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); const newPolicy = createResourcePolicyFor(mockedResourceWithAcr, "policy"); expect(getUrl(newPolicy, rdf.type)).toBe(acp.Policy); expect(asUrl(newPolicy)).toBe(`${getSourceUrl(mockedAcr)}#policy`); }); }); describe("getResourcePolicy", () => { it("returns the Policy with the given name", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourcePolicy(mockedResourceWithAcr, "policy")).not.toBeNull(); }); it("returns null if the Policy does not apply to the Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); expect(getResourcePolicy(mockedResourceWithAcr, "policy")).toBeNull(); }); it("returns null if the Policy applies to the ACR itself", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourcePolicy(mockedResourceWithAcr, "policy")).toBeNull(); }); it("returns null if the given URL identifies something that is not an Access Policy", () => { let notAPolicy = createThing({ url: "https://some.pod/resource?ext=acr#not-a-policy", }); notAPolicy = setUrl( notAPolicy, rdf.type, "https://arbitrary.vocab/not-a-policy" ); const mockedAcr = setThing( mockAcrFor("https://some.pod/resource"), notAPolicy ); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, "https://some.pod/resource?ext=acr#not-a-policy" ); expect(getResourcePolicy(mockedResourceWithAcr, "not-a-policy")).toBeNull(); }); it("returns null if there is no Thing at the given URL", () => { expect( getResourcePolicy( addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockAcrFor("https://some.pod/resource") ), "policy" ) ).toBeNull(); }); }); describe("getResourceAcrPolicy", () => { it("returns the Policy with the given name", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect( getResourceAcrPolicy(mockedResourceWithAcr, "policy") ).not.toBeNull(); }); it("returns null if the Policy does not apply to the Resource's ACR", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); expect(getResourceAcrPolicy(mockedResourceWithAcr, "policy")).toBeNull(); }); it("returns null if the Policy applies to the Resource itself", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourceAcrPolicy(mockedResourceWithAcr, "policy")).toBeNull(); }); it("returns null if the given URL identifies something that is not an Access Policy", () => { let notAPolicy = createThing({ url: "https://some.pod/resource?ext=acr#not-a-policy", }); notAPolicy = setUrl( notAPolicy, rdf.type, "https://arbitrary.vocab/not-a-policy" ); const mockedAcr = setThing( mockAcrFor("https://some.pod/resource"), notAPolicy ); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, "https://some.pod/resource?ext=acr#not-a-policy" ); expect( getResourceAcrPolicy(mockedResourceWithAcr, "not-a-policy") ).toBeNull(); }); it("returns null if there is no Thing at the given URL", () => { expect( getResourceAcrPolicy( addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockAcrFor("https://some.pod/resource") ), "policy" ) ).toBeNull(); }); }); describe("getResourcePolicyAll", () => { it("returns included Policies", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourcePolicyAll(mockedResourceWithAcr)).toHaveLength(1); }); it("returns only those Things whose type is of acp:AccessPolicy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); let notAPolicy = createThing({ url: "https://some.pod/policy-resource#not-a-policy", }); notAPolicy = setUrl( notAPolicy, rdf.type, "https://arbitrary.vocab/not-a-policy" ); mockedAcr = setThing(mockedAcr, mockedPolicy); mockedAcr = setThing(mockedAcr, notAPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, "https://some.pod/policy-resource#not-a-policy" ); expect(getResourcePolicyAll(mockedResourceWithAcr)).toHaveLength(1); }); it("returns only those Things that apply to the given Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let applicablePolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#applicable-policy`, }); applicablePolicy = setUrl(applicablePolicy, rdf.type, acp.Policy); let unapplicablePolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#unapplicable-policy`, }); unapplicablePolicy = setUrl(unapplicablePolicy, rdf.type, acp.Policy); let acrPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#acr-policy`, }); acrPolicy = setUrl(applicablePolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, applicablePolicy); mockedAcr = setThing(mockedAcr, unapplicablePolicy); mockedAcr = setThing(mockedAcr, acrPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#applicable-policy` ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#acr-policy` ); expect(getResourcePolicyAll(mockedResourceWithAcr)).toHaveLength(1); }); it("returns an empty array if there are no Things in the given Resource's ACR", () => { expect( getResourcePolicyAll( addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockAcrFor("https://some.pod/resource") ) ) ).toHaveLength(0); }); }); describe("getResourceAcrPolicyAll", () => { it("returns included ACR Policies", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourceAcrPolicyAll(mockedResourceWithAcr)).toHaveLength(1); }); it("returns only those Things whose type is of acp:AccessPolicy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); let notAPolicy = createThing({ url: "https://some.pod/policy-resource#not-a-policy", }); notAPolicy = setUrl( notAPolicy, rdf.type, "https://arbitrary.vocab/not-a-policy" ); mockedAcr = setThing(mockedAcr, mockedPolicy); mockedAcr = setThing(mockedAcr, notAPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, "https://some.pod/policy-resource#not-a-policy" ); expect(getResourceAcrPolicyAll(mockedResourceWithAcr)).toHaveLength(1); }); it("returns only those Things that apply to the given Resource's ACR", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let applicablePolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#applicable-policy`, }); applicablePolicy = setUrl(applicablePolicy, rdf.type, acp.Policy); let unapplicablePolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#unapplicable-policy`, }); unapplicablePolicy = setUrl(unapplicablePolicy, rdf.type, acp.Policy); let regularPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#regular-policy`, }); regularPolicy = setUrl(applicablePolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, applicablePolicy); mockedAcr = setThing(mockedAcr, unapplicablePolicy); mockedAcr = setThing(mockedAcr, regularPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#applicable-policy` ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#regular-policy` ); expect(getResourceAcrPolicyAll(mockedResourceWithAcr)).toHaveLength(1); }); it("returns an empty array if there are no Things in the given Resource's ACR", () => { expect( getResourceAcrPolicyAll( addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockAcrFor("https://some.pod/resource") ) ) ).toHaveLength(0); }); }); describe("setResourcePolicy", () => { it("replaces existing instances of the set Access Policy", () => { const somePredicate = "https://some.vocab/predicate"; let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedPolicy = setUrl(mockedPolicy, somePredicate, "https://example.test"); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicy = removeUrl( mockedPolicy, somePredicate, "https://example.test" ); const updatedResourceWithAcr = setResourcePolicy( mockedResourceWithAcr, updatedPolicy ); const policyAfterUpdate = getResourcePolicy( updatedResourceWithAcr, "policy" ); expect(getUrl(policyAfterUpdate!, somePredicate)).toBeNull(); }); it("applies the Policy to the Resource", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); const mockedPolicy = createResourcePolicyFor( mockedResourceWithAcr, "policy" ); const updatedResourceWithAcr = setResourcePolicy( mockedResourceWithAcr, mockedPolicy ); expect(getPolicyUrlAll(updatedResourceWithAcr)).toEqual([ `${getSourceUrl(mockedAcr)}#policy`, ]); }); }); describe("setResourceAcrPolicy", () => { it("replaces existing instances of the set Access Policy", () => { const somePredicate = "https://some.vocab/predicate"; let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedPolicy = setUrl(mockedPolicy, somePredicate, "https://example.test"); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicy = removeUrl( mockedPolicy, somePredicate, "https://example.test" ); const updatedResourceWithAcr = setResourceAcrPolicy( mockedResourceWithAcr, updatedPolicy ); const policyAfterUpdate = getResourceAcrPolicy( updatedResourceWithAcr, "policy" ); expect(getUrl(policyAfterUpdate!, somePredicate)).toBeNull(); }); it("applies the Policy to the Resource's ACR", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); const mockedPolicy = createResourcePolicyFor( mockedResourceWithAcr, "policy" ); const updatedResourceWithAcr = setResourceAcrPolicy( mockedResourceWithAcr, mockedPolicy ); expect(getAcrPolicyUrlAll(updatedResourceWithAcr)).toEqual([ `${getSourceUrl(mockedAcr)}#policy`, ]); }); }); describe("removeResourcePolicy", () => { it("removes the given Access Policy from the Access Policy Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, mockedPolicy ); expect(getResourcePolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("unapplies the Policy from the Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, mockedPolicy ); expect(getPolicyUrlAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a plain name to remove an Access Policy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, "policy" ); expect(getResourcePolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a full URL to remove an Access Policy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourcePolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a Named Node to remove an Access Policy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, DataFactory.namedNode(`${getSourceUrl(mockedAcr)}#policy`) ); expect(getResourcePolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("does not remove non-Policies", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl( mockedPolicy, rdf.type, "https://arbitrary.vocab/#not-a-policy" ); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, mockedPolicy ); const updatedAcr = internal_getAcr(updatedPolicyDataset); expect( getThing(updatedAcr, `${getSourceUrl(mockedAcr)}#policy`) ).not.toBeNull(); }); it("does not remove unrelated policies", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy1 = createThing({ url: `${getSourceUrl(mockedAcr)}#policy1`, }); mockedPolicy1 = setUrl(mockedPolicy1, rdf.type, acp.Policy); let mockedPolicy2 = createThing({ url: `${getSourceUrl(mockedAcr)}#policy2`, }); mockedPolicy2 = setUrl(mockedPolicy2, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy1); mockedAcr = setThing(mockedAcr, mockedPolicy2); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy1` ); mockedResourceWithAcr = addPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy2` ); const updatedPolicyDataset = removeResourcePolicy( mockedResourceWithAcr, mockedPolicy1 ); expect(getResourcePolicyAll(updatedPolicyDataset)).toHaveLength(1); }); }); describe("removeResourceAcrPolicy", () => { it("removes the given Access Policy from the Access Policy Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, mockedPolicy ); expect(getResourceAcrPolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("unapplies the Policy from the Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, mockedPolicy ); expect(getAcrPolicyUrlAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a plain name to remove an Access Policy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, "policy" ); expect(getResourceAcrPolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a full URL to remove an Access Policy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); expect(getResourceAcrPolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("accepts a Named Node to remove an Access Policy", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl(mockedPolicy, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, DataFactory.namedNode(`${getSourceUrl(mockedAcr)}#policy`) ); expect(getResourceAcrPolicyAll(updatedPolicyDataset)).toHaveLength(0); }); it("does not remove non-Policies", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy = createThing({ url: `${getSourceUrl(mockedAcr)}#policy`, }); mockedPolicy = setUrl( mockedPolicy, rdf.type, "https://arbitrary.vocab/#not-a-policy" ); mockedAcr = setThing(mockedAcr, mockedPolicy); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, mockedPolicy ); const updatedAcr = internal_getAcr(updatedPolicyDataset); expect( getThing(updatedAcr, `${getSourceUrl(mockedAcr)}#policy`) ).not.toBeNull(); }); it("does not remove unrelated policies", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedPolicy1 = createThing({ url: `${getSourceUrl(mockedAcr)}#policy1`, }); mockedPolicy1 = setUrl(mockedPolicy1, rdf.type, acp.Policy); let mockedPolicy2 = createThing({ url: `${getSourceUrl(mockedAcr)}#policy2`, }); mockedPolicy2 = setUrl(mockedPolicy2, rdf.type, acp.Policy); mockedAcr = setThing(mockedAcr, mockedPolicy1); mockedAcr = setThing(mockedAcr, mockedPolicy2); let mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy1` ); mockedResourceWithAcr = addAcrPolicyUrl( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#policy2` ); const updatedPolicyDataset = removeResourceAcrPolicy( mockedResourceWithAcr, mockedPolicy1 ); expect(getResourceAcrPolicyAll(updatedPolicyDataset)).toHaveLength(1); }); }); describe("setAllowModes", () => { it("sets the given modes on the Policy", () => { const policy = mockThingFrom( "https://arbitrary.pod/policy-resource#policy" ); const updatedPolicy = setAllowModes(policy, { read: false, append: true, write: true, }); expect(getIriAll(updatedPolicy, acp.allow)).toEqual([ acp.Append, acp.Write, ]); }); it("replaces existing modes set on the Policy", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.allow, acp.Append); const updatedPolicy = setAllowModes(policy, { read: true, append: false, write: false, }); expect(getIriAll(updatedPolicy, acp.allow)).toEqual([acp.Read]); }); it("does not affect denied modes", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.deny, acp.Append); const updatedPolicy = setAllowModes(policy, { read: true, append: false, write: false, }); expect(getIriAll(updatedPolicy, acp.deny)).toEqual([acp.Append]); }); }); describe("getAllowModes", () => { it("returns all modes that are allowed on the Policy", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.allow, acp.Append); const allowedModes = getAllowModes(policy); expect(allowedModes).toEqual({ read: false, append: true, write: false }); }); it("does not return modes that are denied on the Policy", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.deny, acp.Append); const allowedModes = getAllowModes(policy); expect(allowedModes).toEqual({ read: false, append: false, write: false }); }); }); describe("setDenyModes", () => { it("sets the given modes on the Policy", () => { const policy = mockThingFrom( "https://arbitrary.pod/policy-resource#policy" ); const updatedPolicy = setDenyModes(policy, { read: false, append: true, write: true, }); expect(getIriAll(updatedPolicy, acp.deny)).toEqual([acp.Append, acp.Write]); }); it("replaces existing modes set on the Policy", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.deny, acp.Append); const updatedPolicy = setDenyModes(policy, { read: true, append: false, write: false, }); expect(getIriAll(updatedPolicy, acp.deny)).toEqual([acp.Read]); }); it("does not affect allowed modes", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.allow, acp.Append); const updatedPolicy = setDenyModes(policy, { read: true, append: false, write: false, }); expect(getIriAll(updatedPolicy, acp.allow)).toEqual([acp.Append]); }); }); describe("getDenyModes", () => { it("returns all modes that are denied on the Policy", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.deny, acp.Append); const allowedModes = getDenyModes(policy); expect(allowedModes).toEqual({ read: false, append: true, write: false }); }); it("does not return modes that are allowed on the Policy", () => { let policy = mockThingFrom("https://arbitrary.pod/policy-resource#policy"); policy = addIri(policy, acp.allow, acp.Append); const allowedModes = getDenyModes(policy); expect(allowedModes).toEqual({ read: false, append: false, write: false }); }); }); describe("policyAsMarkdown", () => { it("lists which access modes are allowed, denied or unspecified", () => { let policy = createPolicy("https://some.pod/policyResource#policy"); policy = setAllowModes(policy, { read: true, append: false, write: false }); policy = setDenyModes(policy, { read: false, append: false, write: true }); expect(policyAsMarkdown(policy)).toBe( "## Policy: https://some.pod/policyResource#policy\n" + "\n" + "- Read: allowed\n" + "- Append: unspecified\n" + "- Write: denied\n" + "\n" + "<no rules specified yet>\n" ); }); it("can list individual rules without adding unused types of rules", () => { let policy = createPolicy("https://some.pod/policyResource#policy"); policy = addAllOfRuleUrl( policy, "https://some.pod/policyResource#allOfRule" ); expect(policyAsMarkdown(policy)).toBe( "## Policy: https://some.pod/policyResource#policy\n" + "\n" + "- Read: unspecified\n" + "- Append: unspecified\n" + "- Write: unspecified\n" + "\n" + "All of these rules should match:\n" + "- https://some.pod/policyResource#allOfRule\n" ); }); it("can list all applicable rules", () => { let policy = createPolicy("https://some.pod/policyResource#policy"); policy = addAllOfRuleUrl( policy, "https://some.pod/policyResource#allOfRule" ); policy = addAnyOfRuleUrl( policy, "https://some.pod/policyResource#anyOfRule" ); policy = addNoneOfRuleUrl( policy, "https://some.pod/policyResource#noneOfRule" ); expect(policyAsMarkdown(policy)).toBe( "## Policy: https://some.pod/policyResource#policy\n" + "\n" + "- Read: unspecified\n" + "- Append: unspecified\n" + "- Write: unspecified\n" + "\n" + "All of these rules should match:\n" + "- https://some.pod/policyResource#allOfRule\n" + "\n" + "At least one of these rules should match:\n" + "- https://some.pod/policyResource#anyOfRule\n" + "\n" + "None of these rules should match:\n" + "- https://some.pod/policyResource#noneOfRule\n" ); }); });