UNPKG

@inrupt/solid-client

Version:

Make your web apps work with Solid Pods.

122 lines (119 loc) 6.49 kB
import 'jsonld-streaming-parser'; import 'jsonld-context-parser'; import { getSourceIri } from '../../resource/resource.mjs'; import 'n3'; import 'http-link-header'; import { rdf } from '../../constants.mjs'; import { asIri, createThing, setThing, getThing } from '../../thing/thing.mjs'; import { getIriAll } from '../../thing/get.mjs'; import { addIri } from '../../thing/add.mjs'; import { buildThing } from '../../thing/build.mjs'; import { ACP, VC_ACCESS_GRANT } from '../constants.mjs'; import { getAccessControlResourceThing } from '../internal/getAccessControlResourceThing.mjs'; import { internal_getAcr } from '../control.internal.mjs'; import { getModes } from '../internal/getModes.mjs'; import { getDefaultAccessControlThing } from '../internal/getDefaultAccessControlThing.mjs'; import { setModes } from '../internal/setModes.mjs'; import { setAcr } from '../internal/setAcr.mjs'; // Copyright 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. // const DEFAULT_VC_POLICY_NAME = "defaultVcPolicy"; const DEFAULT_VC_MATCHER_NAME = "defaultVcMatcher"; function createVcPolicy(acr, policyIri, matcherIri, access) { var _a; let vcPolicy = getThing(acr, policyIri); if (vcPolicy === null) { // If the policy does not exist, create it and link the default Access Control to it. vcPolicy = buildThing({ url: policyIri }) .addIri(rdf.type, ACP.Policy) .addIri(ACP.anyOf, matcherIri) .build(); } const vcMatcher = (_a = getThing(acr, matcherIri)) !== null && _a !== void 0 ? _a : buildThing({ url: matcherIri }) .addIri(rdf.type, ACP.Matcher) .addIri(ACP.vc, VC_ACCESS_GRANT) .build(); const currentModes = getModes(vcPolicy, ACP.allow); // Only change the modes which are set in `access`, and preserve the others. vcPolicy = setModes(vcPolicy, { ...currentModes, ...access }, ACP.allow); return { matcher: vcMatcher, policy: vcPolicy, }; } /** * ```{note} * The ACP specification is a draft. As such, this function is experimental and * subject to change, even in a non-major release. * See also: https://solid.github.io/authorization-panel/acp-specification/ * ``` * * Set the maximum access modes that are allowed for a VC holder for a given resource. * If the resource owner issued an Access Grant for the resource, the agent that * has been granted access will have at most the permissions set by this function. * The Access Grant may be more restrictive. * * Note that additional access may have been set if the ACR has been manipulated * not using this library, which is currently out of scope. In this case, the access * set by this function may not apply. * * @param resourceWithAcr The resource for which the access modes are being set for VC holders. * @param access The access modes to set. Setting a mode to `true` will enable it, to `false` * will disable it, and to `undefined` will leave it unchanged compared to what was previously * set. * @param options An option object to customize the function behavior: * - inherit: if set to `true`, the access set to the target resource cascades * to its contained resources. * @returns A copy of the resource and its attached ACR, updated to the new access modes. * @since 1.17.0 */ function setVcAccess(resourceWithAcr, access, options = { inherit: false }) { var _a; let acr = internal_getAcr(resourceWithAcr); const defaultVcPolicyIri = `${getSourceIri(acr)}#${DEFAULT_VC_POLICY_NAME}`; const defaultVcMatcherIri = `${getSourceIri(acr)}#${DEFAULT_VC_MATCHER_NAME}`; const { policy, matcher } = createVcPolicy(acr, defaultVcPolicyIri, defaultVcMatcherIri, access); let accessControl = getDefaultAccessControlThing(resourceWithAcr, "defaultAccessControl"); if (!getIriAll(accessControl, ACP.apply).includes(asIri(policy))) { // Case when the ACR Thing existed, but did not include a link to the default Access Control. accessControl = addIri(accessControl, ACP.apply, policy); } let memberAccessControl = getDefaultAccessControlThing(resourceWithAcr, "defaultMemberAccessControl"); let acrThing = (_a = getAccessControlResourceThing(resourceWithAcr)) !== null && _a !== void 0 ? _a : createThing({ url: getSourceIri(acr) }); if (!getIriAll(acrThing, ACP.accessControl).includes(asIri(accessControl))) { // Case when the ACR Thing existed, but did not include a link to the default Access Control. acrThing = addIri(acrThing, ACP.accessControl, accessControl); } // Write the changed access control, policy and matchers in the ACR acr = [acrThing, accessControl, policy, matcher].reduce(setThing, acr); if (options.inherit) { // Add triples to the member access control and link it to the ACR only // if the VC access is recursive if they don't exist already. if (!getIriAll(memberAccessControl, ACP.apply).includes(asIri(policy))) { memberAccessControl = addIri(memberAccessControl, ACP.apply, policy); } if (!getIriAll(acrThing, ACP.memberAccessControl).includes(asIri(memberAccessControl))) { acrThing = addIri(acrThing, ACP.memberAccessControl, memberAccessControl); } acr = [acrThing, memberAccessControl].reduce(setThing, acr); } return setAcr(resourceWithAcr, acr); } export { DEFAULT_VC_MATCHER_NAME, DEFAULT_VC_POLICY_NAME, setVcAccess };