Manage Access to Data (ACP)

Access Control Policies (ACP) determine the access to Resources stored in Solid Pods:

  • Each Resource has an associated Access Control Resource (ACR).

  • The ACR specifies the Access Policies that apply to its associated Resource.

  • The Access Policies specifies the ACP Access Rules and ACP Access Modes for the Resource.

Solid Server Support

ACP is an alternative to Web Access Control and is being proposed for inclusion in the Solid specifications.

ACP Modules

Tip

The solid-client library provides universal access control APIs that can be used with either Access Control Policies (ACP) proposal or Web Access Control (WAC).

When possible, use the universal access control APIs instead of the ACP-specific APIs or WAC-specific APIs. For situations that require ACP-specific or WAC-specific APIs, see Mechanism-Specific Access Control APIs.

The solid-client library provides the following acp modules for ACP-specific functions:

@inrupt/solid-client/acp/acp

Functions to get various Resources with their associated Apply Policies to a Resource.

@inrupt/solid-client/acp/control

Functions to manage Access Control Resource (ACR).

@inrupt/solid-client/acp/policy

Functions to manage Policies.

@inrupt/solid-client/acp/rule

Functions to manage Rules.

For examples, see:

Access Policy

An Access Policy defines the agents’ access to a resource. Specifically, the Access Policy allows or denies the specified access modes to agents’ and client apps based on how they match the conditions in the listed access rules; i.e.,

If
< allOf | anyOf | noneOf > (RuleA1, RuleA2, …) evaluate to true, AND
< allOf | anyOf | noneOf > (RuleB1, RuleB2, …) evaluates to true, AND
Then
<allow> (AccessModeA, …), AND
<deny> (AccessMode1, …), AND

Note

Access Rules and Policies are identified by their URL. Specifically, Rules and Policies are Things in Structured Data terminology. As such, you save Rules and Policies inside a SolidDataset and refer to them using their URLs.

A Resource’s ACR can include policies that exist in other SolidDataset as well as policies defined and stored in the Resource’s ACR itself.

ACP Access Rules

Access Rules specify the conditions under which the Access Policy applies. Access Rules can specify the following conditions:

To manage Access Rules, you can use the functions in @inrupt/solid-client/acp/rule module.

Note

Access Rules and Policies are identified by their URL. Specifically, Rules and Policies are Things in Structured Data terminology. As such, you save Rules and Policies inside a SolidDataset and refer to them using their URLs.

A policy specifies its rules as part of allOf(), anyOf(), and noneOf() operator expressions

allOf(<rules>)

Evaluates to true if all of its listed rules evaluate to true; i.e., a logical AND of its listed rules.

anyOf(<rules>)

Evaluates to true if any(i.e., one or more) of its listed rules evaluate to true; i.e., a logical OR of its listed rules.

noneOf(<rules>)

Evaluates to true if none of its listed rules evaluate to true; i.e., a logical NOT of all its listed rules (i.e., an inverse of allOf()). For example, noneOf(RuleA, RuleB) is NOT RuleA and NOT RuleB (i.e., neither RuleA nor RuleB evaluates to true).

For examples, see:

ACP Access Modes

Access Modes describe the type of permissions (i.e., access) to a resource. The following Access Modes are available:

Access Mode

Description

Read

View data.

Append

Add data.

Write

Add, update, and delete data.

A policy specifies its access modes in allow(<Access Modes>) or deny(Access Modes) expressions. A policy can specify only an allow expression or only the deny expression or a combination of both allow and deny expressions.

The @inrupt/solid-client’s ACP APIs handle <Access Modes> specification as an object of the form:

{ read: <boolean>, append: <boolean>, write: <boolean> }

For example, see:

Access Control Resource (ACR)

Every Resource has an associated Access Control Resource (ACR). The ACR specifies which Access Policies apply to its associated Resource. That is the Policies in the ACR determines the access to the Resource. If the Resource is a Container, you can also specify Member Policies to the Resource’s ACR; the Member Policies gets propagated to the Resource’s children’s ACR.

For examples, see:

Examples

Note

The examples use a single SolidDataset as a repository for the rules and policies. There is no requirement for either the rules or the policies to be stored in a single SolidDataset.

Create a Rule for Matching an Agent

The following example creates a new SolidDataset to store your custom ACP rules to match the specified agents.

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { createSolidDataset, saveSolidDatasetAt } from "@inrupt/solid-client";
import { createRule, addAgent, setRule } from "@inrupt/solid-client/acp/rule";

// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

async function setupMyAgentMatchingRule() {
  try {
    // 1. Initialize a new SolidDataset for your rules and policies.
    let myRulesAndPoliciesSolidDataset = createSolidDataset();
 
    // 2. Initialize your new Rules.
    let colleaguesRule = createRule(`${MY_ACP_SOLID_DATASET}#colleagues-rule`);
    let roommateRule = createRule(`${MY_ACP_SOLID_DATASET}#roommate-rule`);
  
    // 3. For the rules, specify the Agent to match.
    colleaguesRule = addAgent(colleaguesRule, "https://mypod.example.com/busybee/profile/card#me");
    colleaguesRule = addAgent(colleaguesRule, "https://mypod.example.com/leapinglizard/profile/card#me");

    roommateRule = addAgent(roommateRule, "https://mypod.example.com/snoringsue/profile/card#me");

    // 4. Add your new rules to the SolidDataset.
    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, colleaguesRule);
    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, roommateRule);

    // 5. Save the SolidDataset.
    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }       // fetch from the authenticated session
    );
  } catch (error) {
      console.error(error.message);
  }
}

In particular, the example uses:

  1. createSolidDataset to initialize a new SolidDataset for storing your custom rules and policies.

    let myRulesAndPoliciesSolidDataset = createSolidDataset();
    
  2. createRule to initialize the new rule to save:

    let colleaguesRule = createRule(`${MY_ACP_SOLID_DATASET}#colleagues-rule`);
    let roommateRule = createRule(`${MY_ACP_SOLID_DATASET}#roommate-rule`);
    

    When creating the rule, pass in the target URL for the Rule.

  3. addAgent to specify the agent(s) to match with the rules:

    colleaguesRule = addAgent(colleaguesRule, "https://mypod.example.com/busybee/profile/card#me");
    colleaguesRule = addAgent(colleaguesRule, "https://mypod.example.com/leapinglizard/profile/card#me");
    
    roommateRule = addAgent(roommateRule, "https://mypod.example.com/snoringsue/profile/card#me");
    

    In this example, the colleaguesRule matches either the agent busybee or the agent leapinglizard (identified by their WebIDs), and roommateRule matches the agent snoringsue.

  4. setRule to add the new rules to a SolidDataset.

    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, colleaguesRule);
    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, roommateRule);
    
  5. saveSolidDatasetAt to save the SolidDataset.

    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }       // fetch from the authenticated session
    );
    

For additional functions to manage agent matching rules, see @inrupt/solid-client/acp/rule.

Create a Rule for the General Public

Note

The example uses a single SolidDataset as a repository for the rules and policies. There is no requirement for the rules or policies to be stored in a single SolidDataset.

The following example continues from the previous example and assumes the existence of the SolidDataset at https://mypod.example.com/acp/myrulesandpolicies. Specifically, the example creates a new rule for the general Public and adds it to the https://mypod.example.com/acp/myrulesandpolicies SolidDataset:

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDataset, setThing, saveSolidDatasetAt } from "@inrupt/solid-client";
import { createRule, addAgent, setRule } from "@inrupt/solid-client/acp/rule";

// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

async function setupMyPublicRule() {
  try {
    // 1. Fetch the SolidDataset for your rules and policies.
    let myRulesAndPoliciesSolidDataset = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }          // fetch from the authenticated session
    );
 
    // 2. Initialize your new Rule.
    let publicRule = createRule(`${MY_ACP_SOLID_DATASET}#public-rule`);
  
    // 3. For the rule, specify that it should match the public.
    publicRule = setPublic(publicRule);

    // 4. Add your new rule to the SolidDataset.
    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, publicRule);

    // 5. Save the SolidDataset.
    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }        // fetch from the authenticated session
    );
  } catch (error) {
    console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDataset to retrieve the SolidDataset for storing your custom rules and policies.

    let myRulesAndPoliciesSolidDataset = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }          // fetch from the authenticated session
    );
    
  2. createRule to initialize the new rule to save:

    let publicRule = createRule(`${MY_ACP_SOLID_DATASET}#public-rule`);
    

    When creating the rule, pass in the target URL for the Rule.

  3. setPublic to specify that the rule matches the public (i.e., everyone):

    publicRule = setPublic(publicRule);
    
  4. setRule to add the new rule to a SolidDataset.

    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, publicRule);
    
  5. saveSolidDatasetAt to save the SolidDataset.

    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }        // fetch from the authenticated session
    );
    

For additional functions (e.g., hasPublic, removePublic, setAuthenticated, setCreator) to manage rules, see @inrupt/solid-client/acp/rule.

Create Rule for a Specific Client Application

Note

The example uses a single SolidDataset as a repository for the rules and policies. There is no requirement for the rules or policies to be stored in a single SolidDataset.

With ACP, you can create a rule that specifies not only the Agent but the Client Application. A Client Application identifies itself using a its client identifier. To verify the Client Application, a user must be logged in.

The following example continues from the previous example and assumes the existence of the SolidDataset at https://mypod.example.com/acp/myrulesandpolicies.

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDataset, saveSolidDatasetAt } from "@inrupt/solid-client";
import { createRule, addAgent, addClient, setRule } from "@inrupt/solid-client/acp/rule";

// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

async function setupMyAgentApplicationMatchingRule() {
  try {
    // 1. Fetch the SolidDataset for your rules and policies.
    let myRulesAndPoliciesSolidDataset = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }          // fetch from the authenticated session
    );
 
    // 2. Initialize your new Rules.
    let chatFriendRule = createRule(`${MY_ACP_SOLID_DATASET}#chat-friend-rule`);
  
    // 3. For the rule, specify the Agent to match.
    chatFriendRule = addAgent(chatFriendRule, "https://mypod.example.com/chattypatty/profile/card#me");

    // 4. For the rule, specify the Client Application to match.
    chatFriendRule = addClient(chatFriendRule, "https://mychat.example.net/appid.jsonld");

    // 5. Add your new rules to the SolidDataset.
    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, chatFriendRule);

    // 6. Save the SolidDataset.
    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }       // fetch from the authenticated session
    );
  } catch (error) {
      console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDataset to retrieve the SolidDataset for storing your custom rules and policies.

    let myRulesAndPoliciesSolidDataset = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }          // fetch from the authenticated session
    );
    
  2. createRule to initialize the new rule to save:

    let chatFriendRule = createRule(`${MY_ACP_SOLID_DATASET}#chat-friend-rule`);
    

    When creating the rule, pass in the target URL for the Rule.

  3. addAgent to specify the agent(s) to match with the rule:

    chatFriendRule = addAgent(chatFriendRule, "https://mypod.example.com/chattypatty/profile/card#me");
    
  4. addClient to specify the client(s) to match with the rule:

    chatFriendRule = addClient(chatFriendRule, "https://mychat.example.net/appid.jsonld");
    

    With the addition of the client to the rule, this rule matches only when agent chattypatty (added in the previous step) uses the specified client application.

  5. setRule to add the new rule to a SolidDataset.

    myRulesAndPoliciesSolidDataset = setRule(myRulesAndPoliciesSolidDataset, chatFriendRule);
    
  6. saveSolidDatasetAt to save the SolidDataset.

    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }       // fetch from the authenticated session
    );
    

For information on client application identifiers, see Authenticate Client Applications (Browser & Node.JS).

For additional functions to manage rules, see @inrupt/solid-client/acp/rule.

Create Policies

Note

The example uses a single SolidDataset as a repository for the rules and policies. There is no requirement for the rules or policies to be stored in a single SolidDataset.

The Access Policies specifies the ACP Access Rules and ACP Access Modes for the Resource:

  • A policy specifies its rules as part of allOf(), anyOf(), and noneOf() operator expressions.

  • A policy specifies its access modes in allow(<Access Modes>) or deny(Access Modes) expressions.

The following example continues from the previous examples. Specifically, the example creates new policies using the rules saved from the previous examples.

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDataset, saveSolidDatasetAt } from "@inrupt/solid-client";
import { addAllOfRuleUrl, addAnyOfRuleUrl } from "@inrupt/solid-client/acp/rule";
import { createPolicy, setAllowModes, setPolicy } from "@inrupt/solid-client/acp/policy";

// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

async function setupMyPolicies() {
  try {
    // 1. Fetch the SolidDataset for your rules and policies.
    let myRulesAndPoliciesSolidDataset = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }      // fetch from the authenticated session
    );
 
    // 2. Initialize your new Policies.
    let roommateandcolleaguesPolicy = createPolicy(`${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`);
    let publicReadPolicy = createPolicy(`${MY_ACP_SOLID_DATASET}#public-read-policy`);
  
    // 3. Add the rules from previous examples as allOf() or anyOf() expressions to the Policies.
    roommateandcolleaguesPolicy = addAnyOfRuleUrl(
        roommateandcolleaguesPolicy,
        `${MY_ACP_SOLID_DATASET}#colleagues-rule`       
    );
    roommateandcolleaguesPolicy = addAnyOfRuleUrl(
        roommateandcolleaguesPolicy,
        `${MY_ACP_SOLID_DATASET}#roommate-rule`       
    );

    publicReadPolicy = addAllOfRuleUrl(
      publicReadPolicy,
      `${MY_ACP_SOLID_DATASET}#public-rule`   // Rule matches anyone
    );

    // 4. Specify the access modes for the policies.
    roommateandcolleaguesPolicy = setAllowModes(
      roommateandcolleaguesPolicy,
      { read: true, append: false, write: true },
    );

    publicReadPolicy = setAllowModes(
      publicReadPolicy,
      { read: true, append: false, write: false },
    );

    // 5. Add your new Policies to the SolidDataset.
    myRulesAndPoliciesSolidDataset = setPolicy(myRulesAndPoliciesSolidDataset, roommateandcolleaguesPolicy);
    myRulesAndPoliciesSolidDataset = setPolicy(myRulesAndPoliciesSolidDataset, publicReadPolicy);

    // 6. Save the SolidDataset.
    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }      // fetch from the authenticated session
    );
  } catch (error) {
    console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDataset to retrieve the SolidDataset for storing your custom rules and policies.

    let myRulesAndPoliciesSolidDataset = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }      // fetch from the authenticated session
    );
    
  2. createPolicy to initialize the new policies to save:

    let roommateandcolleaguesPolicy = createPolicy(`${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`);
    let publicReadPolicy = createPolicy(`${MY_ACP_SOLID_DATASET}#public-read-policy`);
    

    When creating the policy, pass in the target URL for the policy.

  3. addAnyOfRuleUrl and addAllOfRuleUrl to the rules for the policies:

    roommateandcolleaguesPolicy = addAnyOfRuleUrl(
        roommateandcolleaguesPolicy,
        `${MY_ACP_SOLID_DATASET}#colleagues-rule`       
    );
    roommateandcolleaguesPolicy = addAnyOfRuleUrl(
        roommateandcolleaguesPolicy,
        `${MY_ACP_SOLID_DATASET}#roommate-rule`       
    );
    
    publicReadPolicy = addAllOfRuleUrl(
      publicReadPolicy,
      `${MY_ACP_SOLID_DATASET}#public-rule`   // Rule matches anyone
    );
    

    The roomateandcollegauesPolicy applies if either the agent is matched by the colleagues-rule or the agent is matched by the roommate-rule.

    The publicReadPolicy applies if the agent is matched by the public-rule (i.e., any agent matches this rule).

  4. setAllowModes to specify the access modes for the policies:

    roommateandcolleaguesPolicy = setAllowModes(
      roommateandcolleaguesPolicy,
      { read: true, append: false, write: true },
    );
    
    publicReadPolicy = setAllowModes(
      publicReadPolicy,
      { read: true, append: false, write: false },
    );
    
  5. setPolicy to add the new policies to the SolidDataset.

    myRulesAndPoliciesSolidDataset = setPolicy(myRulesAndPoliciesSolidDataset, roommateandcolleaguesPolicy);
    myRulesAndPoliciesSolidDataset = setPolicy(myRulesAndPoliciesSolidDataset, publicReadPolicy);
    
  6. saveSolidDatasetAt to save the SolidDataset.

    const savedSolidDataset = await saveSolidDatasetAt(
      MY_ACP_SOLID_DATASET,
      myRulesAndPoliciesSolidDataset,
      { fetch: fetch }      // fetch from the authenticated session
    );
    

For additional functions to manage rules and policies, see @inrupt/solid-client/acp/rule and @inrupt/solid-client/acp/policy.

Apply Policies to a Resource

Every Resource has an associated Access Control Resource (ACR). The Access Control Resource specifies the Access Policies that apply to its associated Resource. If the Resource is a Container, you can also specify Member Policies to the Resource’s ACR; the Member Policies gets propagated to the Resource’s children’s ACR.

The following example continues from the previous examples. Specifically, the example modifies a Resource’s access policies by adding to the Resource’s ACR the policies saved from the previous example.

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDatasetWithAcr, saveAcrFor } from "@inrupt/solid-client/acp/acp";
import { addPolicyUrl } from "@inrupt/solid-client/acp/control";


// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

async function setupAccessToResource() {
  try {
    
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}schedule/holidays`,
      { fetch: fetch }            // fetch from the authenticated session
    );

    // 2. Add the policies from previous examples to the ACR.
    let changedResourceWithAcr = addPolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`
    );

    changedResourceWithAcr = addPolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#public-read-policy`
    );

    // 3. Save the Resource with its ACR.
    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }           // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDatasetWithAcr to retrieve the SolidDataset with its ACR.

    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}schedule/holidays`,
      { fetch: fetch }            // fetch from the authenticated session
    );
    
  2. addPolicyUrl to add policies (by their URLs) to the Resource’s ACR.

    let changedResourceWithAcr = addPolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`
    );
    
    changedResourceWithAcr = addPolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#public-read-policy`
    );
    
  3. saveAcrFor to the save the Resource with its ACR.

    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }           // fetch from the authenticated session
    );
    

You can control access to the Access Control Resource (ACR) itself. For example, if you want others to be able to modify access policies for the Resource, you would give them write access the Resource’s ACR.

For brevity, the following example omits the logic to create https://mypod.example.com/acp/myrulesandpolicies#family-can-modify-policy:

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDatasetWithAcr, saveAcrFor } from "@inrupt/solid-client/acp/acp";
import { addAcrPolicyUrl } from "@inrupt/solid-client/acp/control";


// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

// ... Logic to create the `${MY_ACP_SOLID_DATASET}#family-can-modify-policy` omitted for brevity.

async function setupAccessToResourceACR() {
  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}schedule/holidays`,
      { fetch: fetch }          // fetch from the authenticated session
    );

    // 2. Add the policy that determines access, not to the Resource itself, but to the Resource's ACR.
    let changedResourceWithAcr = addAcrPolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#family-can-modify-policy` 
    );

    // 3. Save the Resource with its ACR.
    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDatasetWithAcr to retrieve the SolidDataset with its ACR.

    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}schedule/holidays`,
      { fetch: fetch }          // fetch from the authenticated session
    );
    
  2. addAcrPolicyUrl (instead of addPolicyUrl) to specify the ACR policy:

    let changedResourceWithAcr = addAcrPolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#family-can-modify-policy` 
    );
    
  3. saveAcrFor to the save the Resource with its ACR.

    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }          // fetch from the authenticated session
    );
    

For additional functions to manage access to a resource, see @inrupt/solid-client/acp/acp and @inrupt/solid-client/acp/control.

Use Resource-specific Rules and Policies

Access Control Policies allow you to set up access configurations that can be applied to multiple Resources. However, in some instances, you may want to set up Policies and Rules that apply to a single Resource.

Tip

To set up Policies and Rules that apply to a single Resource, use the universal access control APIs when possible. When not possible, you can use the ACP API to store Rules and Policies directly in the single Resource’s Access Control Resource (ACR).

The following example creates a resource-specific rules and policies:

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDatasetWithAcr, saveAcrFor } from "@inrupt/solid-client/acp/acp";
import { createResourceRuleFor,  addAllOfRuleUrl, setResourceRule } from "@inrupt/solid-client/acp/rule";
import { createResourcePolicyFor, setAllowModes, setResourcePolicy } from "@inrupt/solid-client/acp/policy";


const MY_POD_URL = "https://mypod.example.com/docsteam/";

// ... Various logic, including login logic, omitted for brevity.

async function createResourceSpecificRulesPolicies() {
  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}reviews/someReview`,
      { fetch: fetch }          // fetch from the authenticated session
    );


    // 2. Create the Resource-specific Rule.
    let resourceRule = createResourceRuleFor(resourceWithAcr, "myrule-public")
    resourceRule = setPublic(resourceRule);

    // 3. Create the Resource-specific Policy.
    let resourcePolicy = createResourcePolicyFor(
      resourceWithAcr,
      "mypolicy-public",
    );

    // 4. Add the public matching rule as an allOf() expression.
    resourcePolicy = addAllOfRuleUrl(
      resourcePolicy,
      resourceRule
    );
    
    // 5. Specify the access modes for the policy.
    resourcePolicy = setAllowModes(
      resourcePolicy,
      { read: true, append: false, write: false },
    );

    // 6. Add the new Rule to the Access Control Resource.
    let changedResourceWithAcr = setResourceRule(
      resourceWithAcr,
      resourceRule,
    );

    // 7. Add the new Policy to the Access Control Resource.
    changedResourceWithAcr = setResourcePolicy(
      changedResourceWithAcr,
      resourcePolicy,
    );

    // 8. Save the Resource with its ACR.
    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDatasetWithAcr to retrieve the SolidDataset with its ACR.

    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}reviews/someReview`,
      { fetch: fetch }          // fetch from the authenticated session
    );
    
  2. createResourceRuleFor to initialize the Resource-specific Rule.

    let resourceRule = createResourceRuleFor(resourceWithAcr, "myrule-public")
    resourceRule = setPublic(resourceRule);
    
  3. createResourcePolicyFor to initialize the Resource-specific Policy.

    let resourceRule = createResourceRuleFor(resourceWithAcr, "myrule-public")
    resourceRule = setPublic(resourceRule);
    
  4. addAllOfRuleUrl to the rule for the policy:

    resourcePolicy = addAllOfRuleUrl(
      resourcePolicy,
      resourceRule
    );
    
  5. setAllowModes to specify the access modes for the policy:

    resourcePolicy = setAllowModes(
      resourcePolicy,
      { read: true, append: false, write: false },
    );
    
  6. setResourceRule to add the new rule directly to the Resource’s ACR.

    let changedResourceWithAcr = setResourceRule(
      resourceWithAcr,
      resourceRule,
    );
    
  7. setResourcePolicy to add the new policy directly to the Resource’s ACR. This not only stores the policy definition in the ACR, but also applies the policy to the Resource.

    changedResourceWithAcr = setResourcePolicy(
      changedResourceWithAcr,
      resourcePolicy,
    );
    

    Note

    With regular Policies, after saving them to a resource-agnostic SolidDataset (e.g., Create Policies), they have to be applied explicitly to a Resource using various functions (e.g., Apply Policies to a Resource). With Resource-specific Policies, they are applied automatically to their Resource.

  8. saveAcrFor to the save the Resource with its ACR.

    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }          // fetch from the authenticated session
    );
    

Modify Existing Access for a Resource

The following example continues from the previous example to modify a Resource’s existing access policies:

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDatasetWithAcr, saveAcrFor } from "@inrupt/solid-client/acp/acp";
import { getPolicyUrlAll, removePolicyUrl } from "@inrupt/solid-client/acp/control";


// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";

async function modifyResourceAccessPolicies() {

  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}schedule/holidays`,
      { fetch: fetch }            // fetch from the authenticated session
    );

    // 2. Get all Policies in the Resource's ACR
    const myResourceAccessPolicies = getPolicyUrlAll(resourceWithAcr);
    // ... Can loop through policies to view all policies. 

    // 3. Removes a specific Policy in the Resource's ACR (i.e., it no longer applies to the resource)
    
    let changedResourceWithAcr = removePolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`
    );
            
    // 4. Save the Resource with its ACR.
    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }           // fetch from the authenticated session
    );    

  } catch (error) {
      console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDatasetWithAcr to retrieve the SolidDataset with its ACR.

    const resourceWithAcr = await getSolidDatasetWithAcr(
      `${MY_POD_URL}schedule/holidays`,
      { fetch: fetch }            // fetch from the authenticated session
    );
    
  2. getPolicyUrlAll to get the Policies that applies to the Resource.

    const myResourceAccessPolicies = getPolicyUrlAll(resourceWithAcr);
    // ... Can loop through policies to view all policies. 
    
  3. removePolicyUrl to remove a specific Policy.

    let changedResourceWithAcr = removePolicyUrl(
      resourceWithAcr,
      `${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`
    );
            
    
  4. saveAcrFor to the save the Resource with its ACR.

    const updatedResourceWithAcr = await saveAcrFor(
      changedResourceWithAcr, 
      { fetch: fetch }           // fetch from the authenticated session
    );    
    

View Existing Policies and Rules

The following example continues from the previous examples. Specifically, it assumes the existence of the SolidDataset at https://mypod.example.com/acp/myrulesandpolicies that acts as a repository for the example rules and policies.

import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { getSolidDataset } from "@inrupt/solid-client";
import { getRule, getRuleAll } from "@inrupt/solid-client/acp/rule";
import { getPolicy, getPolicyAll } from "@inrupt/solid-client/acp/policy";


// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://mypod.example.com/docsteam/";
const MY_ACP_SOLID_DATASET = `${MY_POD_URL}acp/myrulesandpolicies`;

async function viewMyRulesAndPolicies() {

  try {
    // 1. Fetch the SolidDataset acting as a repository of my rules and policies.
    const myACPRespository = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }          // fetch from the authenticated session
    );

    // 2. Get all Policies stored in that SolidDataset.
    const myExamplePolicies = getPolicyAll(myACPRespository);

    myExamplePolicies.forEach(mypolicy => {
      // ... policy processing logic omitted, such as to update the policy, etc.
    });
  
    // 3. Get a specific Policy stored in that SolidDataset.
    const mySpecificPolicy = getPolicy(
      myACPRespository,
      `${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`
    );
  
    // ... policy processing logic omitted, such as to update the policy, etc.

    // 4. Get all Rules stored in that SolidDataset.
    const myExampleRules = getRuleAll(myACPRespository);

    myExampleRules.forEach(myrule => {
      // ... rule processing logic omitted, such as to update the rule, etc.
    });
  
    // 5. Get a specific Rule stored in that SolidDataset.
    const mySpecificRule = getRule(
      myACPRespository,
      `${MY_ACP_SOLID_DATASET}#colleagues-rule`
    );
  
    // ... rule processing logic omitted, such as to update the rule, etc.
  } catch (error) {
      console.error(error.message);
  }
}

In particular, the example uses:

  1. getSolidDataset to fetch the SolidDataset.

    const myACPRespository = await getSolidDataset(
      MY_ACP_SOLID_DATASET,
      { fetch: fetch }          // fetch from the authenticated session
    );
    
  2. getPolicyAll to access all policies stored in the SolidDataset.

    const myExamplePolicies = getPolicyAll(myACPRespository);
    
    myExamplePolicies.forEach(mypolicy => {
      // ... policy processing logic omitted, such as to update the policy, etc.
    });
    
  3. getPolicy to access a specific policy stored in the SolidDataset.

    const mySpecificPolicy = getPolicy(
      myACPRespository,
      `${MY_ACP_SOLID_DATASET}#roommates-colleagues-policy`
    );
    
    // ... policy processing logic omitted, such as to update the policy, etc.
    
  4. getRuleAll to access all rules stored in the SolidDataset.

    const myExampleRules = getRuleAll(myACPRespository);
    
    myExampleRules.forEach(myrule => {
      // ... rule processing logic omitted, such as to update the rule, etc.
    });
    
  5. getRule to access a specific rule stored in the SolidDataset.

    const mySpecificRule = getRule(
      myACPRespository,
      `${MY_ACP_SOLID_DATASET}#colleagues-rule`
    );
    
    // ... rule processing logic omitted, such as to update the rule, etc.
    

For additional functions to manage rules and policies (such as to modify existing rules and policies), see @inrupt/solid-client/acp/rule and @inrupt/solid-client/acp/policy.