diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..6d68aeaf --- /dev/null +++ b/.dockerignore @@ -0,0 +1,24 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md diff --git a/.gitignore b/.gitignore index b3c11572..257bbd16 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,4 @@ tmp # Misc .DS_Store +.vscode/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..912b5550 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM node:20.0.0 +ENV NODE_ENV=production +WORKDIR /usr/src/app +# COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"] +# RUN npm install -g yarn + +COPY . . + +ENV YARN_VERSION 4.0.0 +RUN yarn policies set-version $YARN_VERSION + +RUN corepack enable yarn +RUN yarn install +# COPY . . + +RUN yarn build +RUN yarn install:demo +RUN yarn build:demo + +EXPOSE 3000 +EXPOSE 4000 +EXPOSE 4444 +EXPOSE 5123 +EXPOSE 8201 +EXPOSE 8202 +EXPOSE 8203 + +RUN chown -R node /usr/src/app +USER node +CMD ["yarn", "start:demo"] diff --git a/README.md b/README.md index 67ab303b..53c196dd 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,179 @@ # SolidLab's User Managed Access -This repository contains SolidLab research artefacts on use of UMA in the Solid ecosystem. +This repository contains a demonstrator for the [SolidLab project](https://solidlab.be/) on managing trust-flows in decentralized data storage systems such as Solid. -## Packages +## Cloning the repository -- [`@solidlab/uma`](packages/uma): Experimental and opinionated implementation of [UMA Grants](https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html) and [UMA Federation](https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-federated-authz-2.0.html). - -- [`@solidlab/uma-css`](packages/css): UMA modules for the [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer/). - -- [`@solidlab/ucp`](packages/ucp): Usage Control Policy decision/enforcement component. +To run the demonstrator, you will have to clone the repository. +``` +git clone -b e2e/setup git@github.com:SolidLabResearch/user-managed-access.git +cd user-managed-access/ +``` ## Getting started -In order to run this project you need to perform the following steps. - -1. Ensure that you are using Node.js 20 or higher, e.g. by running `nvm use`. (see [.nvmrc](./.nvmrc)) -1. Enable Node.js Corepack with `corepack enable`. -1. Run `yarn install` in the project root (this will automatically call `yarn build:all`). -1. Run `yarn start:all`. - -This will boot up a UMA server and compatible Community Solid Server instance. - -You can then execute the following flows: - -- `yarn script:public`: `GET` the public `/alice/profile/card` without redirection to the UMA server; -- `yarn script:private`: `PUT` some text to the private `/alice/private/resource.txt`, protected by a simple WebID check; -- `yarn script:uma-ucp`: `PUT` some text to the private `/alice/other/resource.txt`, protected by a UCP enforcer checking WebIDs according to policies in `packages/uma/config/rules/policy/`. -- `yarn script:registration`: `POST`, `GET` and `DELETE` some text to/from `/alice/public/resource.txt` to test the correct creation and deletion of resource registrations on the UNA server. -- `yarn script:ucp-enforcement`: Run the UCP enforcer in a script (`scripts/test-ucp-enforcement.ts`). This does not need the servers to be started. +### Setting up the project yourself -`yarn script:flow` runs all flows in sequence. +Before starting, make sure you are on the correct branch (e2e/setup). +See the above command to clone only the relevant branch for the demonstrator. +In order to run the demonstrator you need to perform the following steps. -## Demonstration - -A more extensive example of a real life use case has been implemented as described in [./demo/README.md](./demo/README.md). +1. Ensure that you are using Node.js 20 or higher, e.g. by running `nvm use`. (see [.nvmrc](./.nvmrc)) +2. Enable Node.js Corepack with `corepack enable`. +3. Run `yarn install` in the project root to install the requirements for the Solid server . +4. Run `yarn build` in the project root to build the Solid server. +5. Run `yarn install:demo` in the project root to install the requirements for the demonstrator sites and services . +6. Run `yarn build:demo` in the project root to build the demonstrator sites and services . +7. Run `yarn start:demo` to start both the Solid server and all demonstrator sites and services. + +This will boot up a UMA server and compatible Community Solid Server instance, as well as all sites and services for the demonstrator. + + +### Using docker +There is also a `docker` setup available, for which you need to have docker installed: +``` +docker pull raddecke/solidlab-trust-flows-demo +docker run -p 3000:3000 -p 4000:4000 -p 4444:4444 -p 5123:5123 -p 8201:8201 -p 8202:8202 -p 8203:8203 --net=host raddecke/solidlab-trust-flows-demo:latest +``` + +This will start up the same services as the above system installation. + + +## Screencast + +A screencast of the demonstrator can be found here: https://pod.rubendedecker.be/scholar/screencasts/trust-flows-demo.mp4 +or the video file can be found in the [github repository](https://github.com/SolidLabResearch/user-managed-access/tree/e2e/setup/screencast) + + + +# Demonstrator + +## The user data space with CSS and UMA + +- Ruben V., a.k.a. ``, has retrieved a credential containing their birth date from a government service at ``, and this credential has been stored at `` as a private resource. +- Additionally, an accompanying policy was also retrieved and stored in the policy directory at ``. This ODRL policy governs the access and usage requirements for the age credential resource. +- This can be checked on the companion app at ``. +- Using the login email `ruben@example.org` with the password `abc123`, the companion app shows an overview of the available credentials (the birth date credential) en policies in the data space (one policy managing read access for the user, and another one providing access to the age credential for the purpose of age-verification). + +- Access to Ruben's data is based on policies, which he manages through his Authz Companion app, and which are stored in ``. (This is, of course, not publicly known.) To request access to Ruben's data, an agent will need to negotiate with Ruben's UMA Authorization Server, which his WebID document identifies as ``. Via the Well-Known endpoint ``, we can discover the Token Endpoint ``. + +- Having discovered both the location of the UMA server and of the desired data, an agent can request the former for access to the latter. We get different results depending on the situation: + + - Without a policy allowing the access, the access is denied. + + However, the UMA server enables multiple flows in which such a policy can be added, for example by notifying the resource owner. (This is out-of-scope for this demo.) Having been notified in some way of the access request, Ruben could go to his Authz Companion app, and add a policy allowing the requested access.` + + - If a policy has been set (and perhaps the agent has been notified in some way to retry the access request), the UMA server will request the following claims from the agent, based on that policy: `http://www.w3.org/ns/odrl/2/purpose` and `urn:solidlab:uma:claims:types:webid`. + + - When the agent has gathered the necessary claims (the manner in which is out-of-scope for this demo), it can send them to the UMA server as a JWT: + + ``` + { + "http://www.w3.org/ns/odrl/2/purpose": "urn:solidlab:uma:claims:purpose:age-verification", + "urn:solidlab:uma:claims:types:webid": "http://localhost:5123/id" + } + ``` + +- Only when a policy is in place and the agent provides the UMA server with the relevant claims, an access token is produced, with which the agent can access the desired data at the Resource Server. + +## The web store + +- The store use-case starts out with the user navigating to a webshop 'The Drinks Center' located at `http://localhost:8202`. +- In here, the user decides to buy a mix of alcoholic and non-alcoholic drinks. +- Before checkout, the user has to first verify their age when alcoholic drinks were added to the cart. +- The list of options here is currently limited to only WebID. +- Upon continuing, we can provide a new WebID, or continue with Ruben's WebID that was stored from some previous interaction. Note that this does not authenticate the user, but only links their WebID to allow the store to negotiate with their system. +- Here, the web store calls their backend service with the WebID value to try and negotiate with the WebID system to find a valid age-credential. + +- In the store backend, a negotiation is setup with the UMA authorization server indicated by the WebID at ``. +- The location of the target resource `` is assumed to be known as an agreed well known path. +- Having discovered both the location of the UMA server and the target resource, the store agent requests access to the latter. + +- As an policy is set for the credential, the UMA server will request the following claims from the agent, based on that policy: `http://www.w3.org/ns/odrl/2/purpose` and `urn:solidlab:uma:claims:types:webid`. +- The store now re-sends the request, passing the following claims as a JWT: + ``` + { + "http://www.w3.org/ns/odrl/2/purpose": "urn:solidlab:uma:claims:purpose:age-verification", + "urn:solidlab:uma:claims:types:webid": "http://localhost:5123/id" + } + ``` +- The UMA server responds on this request by providing an signed JWT containing both an access token that the store agent can use to go retrieve the age credential resource, as well as a usage agreement for what can be done with the data in the following format: + ``` + { + "permissions": [ + { + "resource_id": "http://localhost:3000/ruben/credentials/age-credential", + "resource_scopes": [ "read", "use" ] + } + ], + "contract": { + "@context": [ + "http://www.w3.org/ns/odrl.jsonld", + { + "prov": "http://www.w3.org/ns/prov#" + } + ], + "@type": "Agreement", + "target": "http://localhost:3000/ruben/credentials/age-credential", + "uid": "urn:solidlab:uma:contract:55cfc913-24a3-4134-9895-2fa969a07181", + "assigner": "http://localhost:3000/ruben/profile/card#me", + "assignee": "http://localhost:5123/id", + "permission": [ + { + "action": [ "read", "use" ], + "constraint": [ + { + "leftOperand": "dateTime", + "operator": "gt", + "rightOperand": "2024-05-22T13:42:45.397Z" + }, + { + "leftOperand": "dateTime", + "operator": "lt", + "rightOperand": "2024-05-28T22:00:00.000Z" + }, + { + "leftOperand": "purpose", + "operator": "eq", + "rightOperand": "urn:solidlab:uma:claims:purpose:age-verification" + } + ] + } + ] + } + } + ``` + +- Using the provided token, the store can now retrieve the age credential using this token, after which the age is verified to be over 18, and both the data and contract are stored for auditing purposes. (this storage for auditing purposes is currently not yet negotiated) +- Based on the OK from the back-end, the store allows the user to go forward to the payment screen, where the transaction can be completed. + +## The auditing platform +To complete our trust interaction, we now need a way to check how the web store uses our data in their back-end. +Here, the auditing process can make use of the usage agreement that was obtained by the store backend during the negotiation for the age credential resource. + +- The auditor navigates to the auditing platform located at `` +- Here, 'The Drinks Central' is registered as a store audited by the platform. +- The platform retrieves all auditing information from the store from the store backend via ``. +- For each entry, the auditing platform can automatically verify: + - the signature of the token containing the usage agreement coming from the user data space. + - the signature of the age credential coming form a trusted government instance. + - the provided age in the credential being over 18 years old. +- For each entry, both the retrieved resource and the usage agreement are displayed on the interface. ## Implemented features +The demonstrator contains a demonstration that partially or fully includes the following features. + +### The Solid Server +The demonstrator uses the [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer) to represent a user data storage location and to host the user WebID. -The packages in this project currently only support a fixed UMA AS per CSS RS, and contain only the trivial [AllAuthorizer](packages/uma/src/models/AllAuthorizer.ts) that allows all access. More useful features are coming soon ... +### UMA Redirects for Solid +This codebase makes use of a Solid Server that can redirect to an Authorization server based on an adaptation of the [UMA protocol](https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html). ### Usage control policy enforcement @@ -57,9 +187,18 @@ For more information, you can check out its [own repository](https://github.com/ A test script is provided for a CRUD ODRL engine: `yarn script:ucp-enforcement`. In the [script](./scripts/test-ucp-enforcement.ts) a read Usage Control Rule (in ODRL) is present together with N3 interpretation rules. -Then a read request is performed using the engine, which results in a list of grants. This list is then printed to the console. +Then a read request is performed using the engine, which results in a list of grants. +These are then used as the basis of an agreement that is exchanged with the access token, that represents the usage agreement for the data exchange. + +### Verifiable Credential issuing and verification + +The demonstrator provides a mock government service that can issue a credential (currently manually copied in place), and allows the verification of this credential using their WebID. + +### Auditing +The demonstrator presents an auditing platform, that can read and automatically partially verify the grounds of data exchanges happening in the network. ## Next steps -Have a look at the [milestones](https://github.com/SolidLabResearch/user-managed-access/milestones) we set for ourselves, and other [issues](https://github.com/SolidLabResearch/user-managed-access/issues) we would like to solve. +The next step for the demonstrator is going in the direction of [Europe's Digital Identity Wallets](https://ec.europa.eu/digital-building-blocks/sites/display/EUDIGITALIDENTITYWALLET/EU+Digital+Identity+Wallet+Home) +where we will try to demonstrate how decentralized storage such as Solid can form a strong basis for the storage and sharing of digital crendentials. diff --git a/Requirements.md b/Requirements.md new file mode 100644 index 00000000..fdff2758 --- /dev/null +++ b/Requirements.md @@ -0,0 +1,119 @@ +# TODOs for end-to-end requirements: + +## Final sprint + +- [ ] load generic and instantiated policies in auth frontend +- [ ] update continuation screens in the shop frontend +- [ ] MAKE THE VIDEO + - [ ] show credential, policies -> buy item -> show instantiation that has been added for the user -> show auditing trail +- [ ] Write setup requirements +- [ ] Create new SolidLabResearch repository that links to the e2e/setup branch + +### To Fix By Demo + +- [ ] Add Policy Screen update +- [ ] Final fixes generic policy +- [ ] Change trust display on auditing screen + - [ ] Change contract to "Instantiated Policy" + - [ ] Instantiated Policy -> Trusted instead of verified, age keep verified +- [ ] Auth app -> My pod app + - [ ] My Data + - [ ] My Policies + - [ ] Relevant linking? +- [X] Login information on every App: + - [X] Green -> You are logged in\ + - [X] Red -> You are not logged in + - [X] Blue -> Auditer 3 is logged in +- [ ] Store login buttons: + - [ ] Remove its'me option + - [ ] Continue as Ruben -> Share WebID link (with profile avatar) (This is not a Login!) + + + + + +### HAS TO HAPPEN +- [X] VC and token validation on the auditing frontend + - [X] Represent this with green checkmarks in the frontend +- [ ] Check policy models + +### If there is time +- [ ] Check policy evaluation system + - [ ] Do time related policies work? + - [ ] Can we include wrong purposes that fail? + - [ ] Can we do a check on store registration +- [ ] Store decision to give purchase access or not in the audit entry? + +### If there is a lot of time +- [ ] Pod-based logging (not super necessary atm?) +- [ ] Can we model accesses by 2 different people? + +## Assignment minimum requirements +- [X] The system needs to facilitate the exchange of the data (date of birth). + - [X] A date of birth must be available at some location in the dataspace +- [X] The system needs to provide the store with the trust that the data is correct. + - [X] The stored DOB must be a verifiable credential + - [X] The stored credential must be verifiable on the store backend +- [X] The system needs to provide the person with the trust that their data will only be used for age checking. + - [X] The policy system must be able to handle a purpose +- [ ] The system allows the person to specify in advance the generic policy that “all Belgian stores are allowed to read my date of birth”. + - [X] The system needs to be able to store a generic policy + - [X] An interface needs to be available to store this policy + - [ ] The policy must be modeled in an appropriate way +- [X] The system automatically instantiates the above generic policy into the concrete case that “MyBelgianWineStore is allowed to use my date of birth from 2024-03-01 to 2024-03-15 for the purpose of age verification for purchases” + - [ ] MOCKED -> double check though +- [X] The system allows the above interaction to take place without the person having to click on any dialogs. + - [X] The interaction is automatic after a WebID button is clicked to show what is happening. +- [ ] The system allows the store to prove that they were allowed to perform the age verification. + - [X] A backend storage must be in place for the store + - [X] The store website must forward data storage and checks to the backend +- [X] The system allows the person to check that their data was used correctly. + - [X] An auditing routine must be built in the store backend + - [X] An auditing routine must be built as a frontend interface +- [ ] The Government VC Service + - [X] Must be able to create a VC + - [X] VC must be transfered to demo pod storage -> Not required for Demo because of fixed keypair seed + - [ ] VCs can be validated on the backend of the store +- [ ] The Auditing use-case + - [X] The store backend provides the option to retrieve all required data to audit + - [ ] This can be represented in an auditing browser app that shows colors when verified (token + VC) + + +Small note with using the UMA server token signature as the contract signature. +We can only trace this back to the UMA Server, and cannot reliably check the connection between the WebID and the UMA Server + +Another idea: preemptive auditing: +- The store has to advertise who is auditing them +- The contract has to be signed both ways +- upon agreement, the data is sent to the store AND to the auditing service. +- on auditing, the service can check if the store is withholding information + + + +## Demonstrator requirements +- [ ] Protocol message modelling + - [ ] claim request messages + - [ ] claim provision messages +- [ ] Logging system (no hard requirement) + - [X] Create logging interface + - [ ] Log Instantiated Policies + - [ ] Log Access Grants + - [ ] Log Operations +- [ ] Authorization system + - [ ] include logging endpoint + - [ ] include authorization endpoint + - [ ] include policy management endpoint +- [X] Mock Policy instantiation + - [ ] Write out policy model that works for demo + - [X] ??? Discover existing policies to instantly grant some access + - [ ] Link generic - instantiated - grant - operation +- [x] Negotiation implementations + - [X] Return instantiated policy requirements from ticket resolving function to create a signed instantiated policy to return +- [ ] Signatures + - [ ] Create a VC form an instantiated policy - I use the return JWT as a free signature + - [ ] Create verification endpoint for issued VCs +- [ ] Government mockup + - [ ] Create verification endpoint for issued VCs (can be mocked) +- [ ] Client + - [ ] Make some mock-up of how storage could be handled in a way that allows for auditing + - [ ] Recurring requests make use of the same grant? \ No newline at end of file diff --git a/demo/README.md b/demo/README.md deleted file mode 100644 index 48f916d4..00000000 --- a/demo/README.md +++ /dev/null @@ -1,36 +0,0 @@ - -# Demonstration - -Using the UMA server implemented in this repository, we set up an extensive demonstration of a real life use case: age verification for online shops selling age-restricted goods, such as alcoholic beverages. - -To experiment with the demo, first build the necessary extra code with `build:demo`, then start the demo by running `start:demo`. This starts the CSS and UMA servers with the right configurations, and spins up two websites: an online shop on `http://localhost:5001`, and a policy manager on `http://localhost:5002`. - -The context "story" of the demonstration is the following. This "story" can be either run through via the graphical interfaces of the websites, or by running the script `yarn script:demo`. - -- Ruben V., a.k.a. ``, has some private data in ``. Of course, he does not want everyone to be able to see all of his private data when they need just one aspect of it. Therefore, Ruben has installed two **Views** on his data, based on SPARQL filters from a public **Catalog**. (When and how this is done is out-of-scope for now.) - -- Discovery of views is currently a very crude mechanism based on a public index in the WebID document. (A cleaner mechanism using the UMA server as central hub is underway.) Using this discovery mechanism, we can find the following views on Ruben's private data: - - 1. `` filters out his birth date, according to the `` filter; - 2. `` derives his age, according to the `` filter. - -- Access to Ruben's data is based on policies, which he manages through his Authz Companion app, and which are stored in ``. (This is, of course, not publicly known.) To request access to Ruben's data, an agent will need to negotiate with Ruben's UMA Authorization Server, which his WebID document identifies as ``. Via the Well-Known endpoint ``, we can discover the Token Endpoint ``. - -- Having discovered both the location of the UMA server and of the desired data, an agent can request the former for access to the latter. We get different results depending on the situation: - - - Without a policy allowing the access, the access is denied. - - However, the UMA server enables multiple flows in which such a policy can be added, for example by notifying the resource owner. (This is out-of-scope for this demo.) Having been notified in some way of the access request, Ruben could go to his Authz Companion app, and add a policy allowing the requested access.` - - - If a policy has been set (and perhaps the agent has been notified in some way to retry the access request), the UMA server will request the following claims from the agent, based on that policy: `http://www.w3.org/ns/odrl/2/purpose` and `urn:solidlab:uma:claims:types:webid`. - - - When the agent has gathered the necessary claims (the manner in which is out-of-scope for this demo), it can send them to the UMA server as a JWT: - - ``` - { - "http://www.w3.org/ns/odrl/2/purpose": "urn:solidlab:uma:claims:purpose:age-verification", - "urn:solidlab:uma:claims:types:webid": "http://localhost:3000/demo/public/vendor" - } - ``` - -- Only when a policy is in place and the agent provides the UMA server with the relevant claims, an access token is produced, with which the agent can access the desired data at the Resource Server. diff --git a/demo/data/.internal/accounts/data/c5b28411-2340-4820-8f4f-62c209c20172$.json b/demo/data/.internal/accounts/data/c5b28411-2340-4820-8f4f-62c209c20172$.json deleted file mode 100644 index b57d48d4..00000000 --- a/demo/data/.internal/accounts/data/c5b28411-2340-4820-8f4f-62c209c20172$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/data/c5b28411-2340-4820-8f4f-62c209c20172","payload":{"linkedLoginsCount":1,"id":"c5b28411-2340-4820-8f4f-62c209c20172","authzServer":"http://localhost:4000/uma","**password**":{"934434d8-d44e-49c2-9618-694594059554":{"accountId":"c5b28411-2340-4820-8f4f-62c209c20172","email":"catalog@example.org","password":"$2a$10$8El17QwKSx3XaHjm.puBiOiNdNQv5t6JHPOVSvPnl8meQFE63CWo6","verified":true,"id":"934434d8-d44e-49c2-9618-694594059554"}},"**clientCredentials**":{},"**pod**":{"f1d42d48-8b96-4122-9e5d-f5803863a243":{"baseUrl":"http://localhost:3000/catalog/","accountId":"c5b28411-2340-4820-8f4f-62c209c20172","id":"f1d42d48-8b96-4122-9e5d-f5803863a243","**owner**":{"6bf4fe03-20c1-419d-9934-2b7533296edf":{"podId":"f1d42d48-8b96-4122-9e5d-f5803863a243","webId":"http://localhost:3000/catalog/profile/card#me","visible":false,"id":"6bf4fe03-20c1-419d-9934-2b7533296edf"}}}},"**webIdLink**":{"0c9522ea-b362-4991-bc72-fd1516834770":{"webId":"http://localhost:3000/catalog/profile/card#me","accountId":"c5b28411-2340-4820-8f4f-62c209c20172","id":"0c9522ea-b362-4991-bc72-fd1516834770"}}}} diff --git a/demo/data/.internal/accounts/data/d3156f11-ffb2-42f3-b928-b9752a9873ce$.json b/demo/data/.internal/accounts/data/d3156f11-ffb2-42f3-b928-b9752a9873ce$.json deleted file mode 100644 index ca7bad89..00000000 --- a/demo/data/.internal/accounts/data/d3156f11-ffb2-42f3-b928-b9752a9873ce$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/data/d3156f11-ffb2-42f3-b928-b9752a9873ce","payload":{"linkedLoginsCount":1,"id":"d3156f11-ffb2-42f3-b928-b9752a9873ce","authzServer":"http://localhost:4000/uma","**password**":{"084fd63e-faf3-4169-a917-0cdeb768710d":{"accountId":"d3156f11-ffb2-42f3-b928-b9752a9873ce","email":"demo@example.org","password":"$2a$10$CRQGngKyURJztvqyDIdXfOuZMiE43z1kuV7BDwAJCmi/gL4TCcPJ2","verified":true,"id":"084fd63e-faf3-4169-a917-0cdeb768710d"}},"**clientCredentials**":{},"**pod**":{"eb3898e1-d409-41d7-b928-f11a2116f218":{"baseUrl":"http://localhost:3000/demo/","accountId":"d3156f11-ffb2-42f3-b928-b9752a9873ce","id":"eb3898e1-d409-41d7-b928-f11a2116f218","**owner**":{"63f475ea-e87c-472c-a224-1b918a9ae059":{"podId":"eb3898e1-d409-41d7-b928-f11a2116f218","webId":"http://localhost:3000/demo/profile/card#me","visible":false,"id":"63f475ea-e87c-472c-a224-1b918a9ae059"}}}},"**webIdLink**":{"ccd6dcae-8e4c-4e43-9888-cc3bdf49acbd":{"webId":"http://localhost:3000/demo/profile/card#me","accountId":"d3156f11-ffb2-42f3-b928-b9752a9873ce","id":"ccd6dcae-8e4c-4e43-9888-cc3bdf49acbd"}}}} \ No newline at end of file diff --git a/demo/data/.internal/accounts/data/f644f883-ef0f-4986-b5ff-df6866707cf6$.json b/demo/data/.internal/accounts/data/f644f883-ef0f-4986-b5ff-df6866707cf6$.json deleted file mode 100644 index b79da7e9..00000000 --- a/demo/data/.internal/accounts/data/f644f883-ef0f-4986-b5ff-df6866707cf6$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/data/f644f883-ef0f-4986-b5ff-df6866707cf6","payload":{"linkedLoginsCount":1,"id":"f644f883-ef0f-4986-b5ff-df6866707cf6","authzServer":"http://localhost:4000/uma","**password**":{"126fe0d0-8189-4a51-954a-79e09ff88e18":{"accountId":"f644f883-ef0f-4986-b5ff-df6866707cf6","email":"ruben@example.org","password":"$2a$10$76sVaHi0nDwl46jKtXZR1uxwwIg8hp6gcfzgT7GCzEdKaOVZSnd1e","verified":true,"id":"126fe0d0-8189-4a51-954a-79e09ff88e18"}},"**clientCredentials**":{},"**pod**":{"b79c41e7-a00d-421d-9b57-009c99e7b0d5":{"baseUrl":"http://localhost:3000/ruben/","accountId":"f644f883-ef0f-4986-b5ff-df6866707cf6","id":"b79c41e7-a00d-421d-9b57-009c99e7b0d5","**owner**":{"173cb7a2-2b22-4b25-b4fb-6f61e0adbd35":{"podId":"b79c41e7-a00d-421d-9b57-009c99e7b0d5","webId":"http://localhost:3000/ruben/profile/card#me","visible":false,"id":"173cb7a2-2b22-4b25-b4fb-6f61e0adbd35"}}}},"**webIdLink**":{"fd6d91cf-4b8c-4769-962f-d9f667ee6ee9":{"webId":"http://localhost:3000/ruben/profile/card#me","accountId":"f644f883-ef0f-4986-b5ff-df6866707cf6","id":"fd6d91cf-4b8c-4769-962f-d9f667ee6ee9"}}}} diff --git a/demo/data/.internal/accounts/index/owner/173cb7a2-2b22-4b25-b4fb-6f61e0adbd35$.json b/demo/data/.internal/accounts/index/owner/173cb7a2-2b22-4b25-b4fb-6f61e0adbd35$.json deleted file mode 100644 index 5957f410..00000000 --- a/demo/data/.internal/accounts/index/owner/173cb7a2-2b22-4b25-b4fb-6f61e0adbd35$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/owner/173cb7a2-2b22-4b25-b4fb-6f61e0adbd35","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/owner/63f475ea-e87c-472c-a224-1b918a9ae059$.json b/demo/data/.internal/accounts/index/owner/63f475ea-e87c-472c-a224-1b918a9ae059$.json deleted file mode 100644 index b1768574..00000000 --- a/demo/data/.internal/accounts/index/owner/63f475ea-e87c-472c-a224-1b918a9ae059$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/owner/63f475ea-e87c-472c-a224-1b918a9ae059","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/owner/6bf4fe03-20c1-419d-9934-2b7533296edf$.json b/demo/data/.internal/accounts/index/owner/6bf4fe03-20c1-419d-9934-2b7533296edf$.json deleted file mode 100644 index 45d09cb0..00000000 --- a/demo/data/.internal/accounts/index/owner/6bf4fe03-20c1-419d-9934-2b7533296edf$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/owner/6bf4fe03-20c1-419d-9934-2b7533296edf","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/password/084fd63e-faf3-4169-a917-0cdeb768710d$.json b/demo/data/.internal/accounts/index/password/084fd63e-faf3-4169-a917-0cdeb768710d$.json deleted file mode 100644 index 4caef5d5..00000000 --- a/demo/data/.internal/accounts/index/password/084fd63e-faf3-4169-a917-0cdeb768710d$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/password/084fd63e-faf3-4169-a917-0cdeb768710d","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/password/126fe0d0-8189-4a51-954a-79e09ff88e18$.json b/demo/data/.internal/accounts/index/password/126fe0d0-8189-4a51-954a-79e09ff88e18$.json deleted file mode 100644 index 8a46d2c9..00000000 --- a/demo/data/.internal/accounts/index/password/126fe0d0-8189-4a51-954a-79e09ff88e18$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/password/126fe0d0-8189-4a51-954a-79e09ff88e18","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/password/934434d8-d44e-49c2-9618-694594059554$.json b/demo/data/.internal/accounts/index/password/934434d8-d44e-49c2-9618-694594059554$.json deleted file mode 100644 index 9ecc6a52..00000000 --- a/demo/data/.internal/accounts/index/password/934434d8-d44e-49c2-9618-694594059554$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/password/934434d8-d44e-49c2-9618-694594059554","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/password/email/catalog@example.org$.json b/demo/data/.internal/accounts/index/password/email/catalog@example.org$.json deleted file mode 100644 index 286ddd5b..00000000 --- a/demo/data/.internal/accounts/index/password/email/catalog@example.org$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/password/email/catalog%40example.org","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} diff --git a/demo/data/.internal/accounts/index/password/email/demo@example.org$.json b/demo/data/.internal/accounts/index/password/email/demo@example.org$.json deleted file mode 100644 index 5a421050..00000000 --- a/demo/data/.internal/accounts/index/password/email/demo@example.org$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/password/email/demo%40example.org","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/password/email/ruben@example.org$.json b/demo/data/.internal/accounts/index/password/email/ruben@example.org$.json deleted file mode 100644 index 4a1aa393..00000000 --- a/demo/data/.internal/accounts/index/password/email/ruben@example.org$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/password/email/ruben%40example.org","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} diff --git a/demo/data/.internal/accounts/index/pod/b79c41e7-a00d-421d-9b57-009c99e7b0d5$.json b/demo/data/.internal/accounts/index/pod/b79c41e7-a00d-421d-9b57-009c99e7b0d5$.json deleted file mode 100644 index e103f676..00000000 --- a/demo/data/.internal/accounts/index/pod/b79c41e7-a00d-421d-9b57-009c99e7b0d5$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/pod/b79c41e7-a00d-421d-9b57-009c99e7b0d5","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2F$.json b/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2F$.json deleted file mode 100644 index 0d660bc7..00000000 --- a/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2F$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2F","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} diff --git a/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2F$.json b/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2F$.json deleted file mode 100644 index 62c3a104..00000000 --- a/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2F$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2F","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fruben%2F$.json b/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fruben%2F$.json deleted file mode 100644 index ab4619d9..00000000 --- a/demo/data/.internal/accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fruben%2F$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3000%2Fruben%2F","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} diff --git a/demo/data/.internal/accounts/index/pod/eb3898e1-d409-41d7-b928-f11a2116f218$.json b/demo/data/.internal/accounts/index/pod/eb3898e1-d409-41d7-b928-f11a2116f218$.json deleted file mode 100644 index 7cab2026..00000000 --- a/demo/data/.internal/accounts/index/pod/eb3898e1-d409-41d7-b928-f11a2116f218$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/pod/eb3898e1-d409-41d7-b928-f11a2116f218","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/pod/f1d42d48-8b96-4122-9e5d-f5803863a243$.json b/demo/data/.internal/accounts/index/pod/f1d42d48-8b96-4122-9e5d-f5803863a243$.json deleted file mode 100644 index 31a1b104..00000000 --- a/demo/data/.internal/accounts/index/pod/f1d42d48-8b96-4122-9e5d-f5803863a243$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/pod/f1d42d48-8b96-4122-9e5d-f5803863a243","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/webIdLink/0c9522ea-b362-4991-bc72-fd1516834770$.json b/demo/data/.internal/accounts/index/webIdLink/0c9522ea-b362-4991-bc72-fd1516834770$.json deleted file mode 100644 index 3492d1b3..00000000 --- a/demo/data/.internal/accounts/index/webIdLink/0c9522ea-b362-4991-bc72-fd1516834770$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/webIdLink/0c9522ea-b362-4991-bc72-fd1516834770","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/webIdLink/ccd6dcae-8e4c-4e43-9888-cc3bdf49acbd$.json b/demo/data/.internal/accounts/index/webIdLink/ccd6dcae-8e4c-4e43-9888-cc3bdf49acbd$.json deleted file mode 100644 index 0abedfbc..00000000 --- a/demo/data/.internal/accounts/index/webIdLink/ccd6dcae-8e4c-4e43-9888-cc3bdf49acbd$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/webIdLink/ccd6dcae-8e4c-4e43-9888-cc3bdf49acbd","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/webIdLink/fd6d91cf-4b8c-4769-962f-d9f667ee6ee9$.json b/demo/data/.internal/accounts/index/webIdLink/fd6d91cf-4b8c-4769-962f-d9f667ee6ee9$.json deleted file mode 100644 index c3b3703c..00000000 --- a/demo/data/.internal/accounts/index/webIdLink/fd6d91cf-4b8c-4769-962f-d9f667ee6ee9$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/webIdLink/fd6d91cf-4b8c-4769-962f-d9f667ee6ee9","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2Fprofile%2Fcard#me$.json b/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2Fprofile%2Fcard#me$.json deleted file mode 100644 index 43f90ca5..00000000 --- a/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2Fprofile%2Fcard#me$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fcatalog%2Fprofile%2Fcard%23me","payload":["c5b28411-2340-4820-8f4f-62c209c20172"]} diff --git a/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2Fprofile%2Fcard#me$.json b/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2Fprofile%2Fcard#me$.json deleted file mode 100644 index 46e79bfd..00000000 --- a/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2Fprofile%2Fcard#me$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fdemo%2Fprofile%2Fcard%23me","payload":["d3156f11-ffb2-42f3-b928-b9752a9873ce"]} \ No newline at end of file diff --git a/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fruben%2Fprofile%2Fcard#me$.json b/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fruben%2Fprofile%2Fcard#me$.json deleted file mode 100644 index f1c210d9..00000000 --- a/demo/data/.internal/accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fruben%2Fprofile%2Fcard#me$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3000%2Fruben%2Fprofile%2Fcard%23me","payload":["f644f883-ef0f-4986-b5ff-df6866707cf6"]} diff --git a/demo/data/.internal/idp/keys/jwks$.json b/demo/data/.internal/idp/keys/jwks$.json deleted file mode 100644 index 355c6ef7..00000000 --- a/demo/data/.internal/idp/keys/jwks$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"idp/keys/jwks","payload":{"keys":[{"kty":"EC","x":"jmoT4I178SCHrtwUu2bFWG0my0o5zQkPhZyDPEyLE6g","y":"nDlReyfF7eyba7XmHXWTs_4Tlzs4ZL94WPaJii7gE90","crv":"P-256","d":"EdprrF79V4LHd5XkO8MHeFyYcXFAgZ_aXmFcuR6lNeU","alg":"ES256"}]}} \ No newline at end of file diff --git a/demo/data/.internal/setup/current-base-url$.json b/demo/data/.internal/setup/current-base-url$.json deleted file mode 100644 index bc4ad5af..00000000 --- a/demo/data/.internal/setup/current-base-url$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"setup/current-base-url","payload":"http://localhost:3000/"} \ No newline at end of file diff --git a/demo/data/.internal/setup/current-server-version$.json b/demo/data/.internal/setup/current-server-version$.json deleted file mode 100644 index 13e62be5..00000000 --- a/demo/data/.internal/setup/current-server-version$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"setup/current-server-version","payload":"7.0.2"} \ No newline at end of file diff --git a/demo/data/.internal/setup/rootInitialized$.json b/demo/data/.internal/setup/rootInitialized$.json deleted file mode 100644 index 6658e134..00000000 --- a/demo/data/.internal/setup/rootInitialized$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"setup/rootInitialized","payload":true} \ No newline at end of file diff --git a/demo/data/.internal/setup/v6-migration$.json b/demo/data/.internal/setup/v6-migration$.json deleted file mode 100644 index a7768a28..00000000 --- a/demo/data/.internal/setup/v6-migration$.json +++ /dev/null @@ -1 +0,0 @@ -{"key":"setup/v6-migration","payload":true} \ No newline at end of file diff --git a/demo/data/.meta b/demo/data/.meta deleted file mode 100644 index d1372b07..00000000 --- a/demo/data/.meta +++ /dev/null @@ -1 +0,0 @@ - a . diff --git a/demo/data/catalog/.meta b/demo/data/catalog/.meta deleted file mode 100644 index c65fdc62..00000000 --- a/demo/data/catalog/.meta +++ /dev/null @@ -1 +0,0 @@ - a . diff --git a/demo/data/catalog/public/filters/age$.sparql b/demo/data/catalog/public/filters/age$.sparql deleted file mode 100644 index 0daf0ec9..00000000 --- a/demo/data/catalog/public/filters/age$.sparql +++ /dev/null @@ -1,18 +0,0 @@ -PREFIX dbo: -PREFIX foaf: - -CONSTRUCT { - ?s foaf:age ?age . -} WHERE { - ?s dbo:birthDate ?bday . - BIND(now() AS ?now) - BIND(year(?bday) AS ?bday_year) - BIND(month(?bday) AS ?bday_month) - BIND(day(?bday) AS ?bday_day) - BIND(year(?now) AS ?now_year) - BIND(month(?now) AS ?now_month) - BIND(day(?now) AS ?now_day) - BIND(IF (?now_day - ?bday_day < 0, 1, 0) AS ?extra_month) - BIND(IF (?now_month - ?bday_month - ?extra_month < 0, 1, 0) AS ?extra_year) - BIND(?now_year - ?bday_year - ?extra_year AS ?age) -} diff --git a/demo/data/catalog/public/filters/bday$.sparql b/demo/data/catalog/public/filters/bday$.sparql deleted file mode 100644 index 9ae526dd..00000000 --- a/demo/data/catalog/public/filters/bday$.sparql +++ /dev/null @@ -1,7 +0,0 @@ -PREFIX dbo: - -CONSTRUCT { - ?s dbo:birthDate ?bday . -} WHERE { - ?s dbo:birthDate ?bday . -} diff --git a/demo/data/index.html b/demo/data/index.html deleted file mode 100644 index b74cf1c7..00000000 --- a/demo/data/index.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Community Solid Server - - - -
- [Solid logo] -

Community Solid Server

-
-
-

Welcome to Solid

-

- This server implements - the Solid protocol - so you can create your own Solid Pod - and identity. -

- -

Getting started as a user

-

- Sign up for an account - to get started with your own Pod and WebID. -

-

- The default configuration stores data only in memory. - If you want to keep data permanently, - choose a configuration that saves data to disk instead. -

-

- To learn more about how this server can be used, - have a look at the - getting started tutorial. -

- -

Getting started as a developer

-

- The default configuration includes - the ready-to-use root Pod you're currently looking at. -
- You can use any of the configurations in the config folder of the server - to set up an instance of this server with different features. - Besides the provided configurations, - you can also fine-tune your own custom configuration using the - configuration generator. -

-

- You can easily choose any folder on your disk - to expose as the root Pod with file-based configurations. -
- Use the --help switch to learn more. -

-

- Due to certain restrictions in the Solid specification it is usually not allowed - to both allow data to be written to the root of the server, - and to enable the creation of new pods. - This configuration does allow both these options to allow a quick exploration of Solid, - but other configurations provided will only allow one of those two to be enabled. -

- -

Have a wonderful Solid experience

-

- Learn more about Solid - at solidproject.org. -

-

- You are warmly invited - to share your experiences - and to report any bugs you encounter. -

-
- - - - - diff --git a/demo/data/ruben/.meta b/demo/data/ruben/.meta deleted file mode 100644 index 2ae477cb..00000000 --- a/demo/data/ruben/.meta +++ /dev/null @@ -1 +0,0 @@ - a . diff --git a/demo/data/ruben/private/.meta b/demo/data/ruben/private/.meta deleted file mode 100644 index 536a6faf..00000000 --- a/demo/data/ruben/private/.meta +++ /dev/null @@ -1,13 +0,0 @@ -@prefix derived: . - -<> derived:derivedResource [ - derived:template "derived/bday"; - derived:selector <./data>; - derived:filter - ]. - -<> derived:derivedResource [ - derived:template "derived/age"; - derived:selector <./data>; - derived:filter - ]. diff --git a/demo/data/ruben/private/data$.ttl b/demo/data/ruben/private/data$.ttl deleted file mode 100644 index 4eef87e2..00000000 --- a/demo/data/ruben/private/data$.ttl +++ /dev/null @@ -1,14 +0,0 @@ -@prefix ruben: . -@prefix con: . -@prefix dbo: . -@prefix dbp: . -@prefix foaf: . -@prefix xsd: . - -ruben: a foaf:Person; - con:preferredURI "https://ruben.verborgh.org/profile/#me"; - foaf:familyName "Verborgh"@en, "Verborgh"@nl ; - foaf:givenName "Ruben"@en, "Ruben"@nl ; - dbo:birthDate "1987-02-28"^^xsd:date ; - dbo:birthPlace dbp:Ostend ; - foaf:gender "male"@en . diff --git a/demo/data/ruben/profile/card$.ttl b/demo/data/ruben/profile/card$.ttl deleted file mode 100644 index 54f84452..00000000 --- a/demo/data/ruben/profile/card$.ttl +++ /dev/null @@ -1,27 +0,0 @@ -@prefix rdfs: . -@prefix foaf: . -@prefix solid: . -@prefix filters: . -@prefix views: . -@prefix ruben: . - -<> a foaf:PersonalProfileDocument; - foaf:maker ruben:; - foaf:primaryTopic ruben:. - -ruben: a foaf:Person ; - foaf:name "Ruben Verborgh"@en, "Ruben Verborgh"@nl; - rdfs:label "Ruben Verborgh"@en, "Ruben Verborgh"@nl; - solid:umaServer "http://localhost:4000/uma/" ; - solid:oidcIssuer ; - solid:viewIndex <#index> . - -<#index> a solid:ViewIndex ; - solid:entry [ - solid:filter filters:bday ; - solid:location views:bday - ] ; - solid:entry [ - solid:filter filters:age ; - solid:location views:age - ] . diff --git a/demo/data/ruben/settings/policies/.meta b/demo/data/ruben/settings/policies/.meta deleted file mode 100644 index e69de29b..00000000 diff --git a/demo/flow.ts b/demo/flow.ts deleted file mode 100644 index 41d06353..00000000 --- a/demo/flow.ts +++ /dev/null @@ -1,187 +0,0 @@ -/* eslint-disable max-len */ - -import { fetch } from 'cross-fetch'; -import { Parser, Writer, Store } from 'n3'; -import { demoPolicy } from "./policyCreation"; - -const parser = new Parser(); -const writer = new Writer(); - -const terms = { - solid: { - umaServer: 'http://www.w3.org/ns/solid/terms#umaServer', - viewIndex: 'http://www.w3.org/ns/solid/terms#viewIndex', - entry: 'http://www.w3.org/ns/solid/terms#entry', - filter: 'http://www.w3.org/ns/solid/terms#filter', - location: 'http://www.w3.org/ns/solid/terms#location', - }, - filters: { - bday: 'http://localhost:3000/catalog/public/filters/bday', - age: 'http://localhost:3000/catalog/public/filters/age', - }, - views: { - bday: 'http://localhost:3000/ruben/private/derived/bday', - age: 'http://localhost:3000/ruben/private/derived/age', - }, - agents: { - ruben: 'http://localhost:3000/ruben/profile/card#me', - vendor: 'http://localhost:3000/demo/public/vendor', - present: 'http://localhost:3000/demo/public/bday-app', - }, - scopes: { - read: 'urn:example:css:modes:read', - } -} - -async function main() { - - log(`Alright, so, for the demo ...`); - - log(`Ruben V., a.k.a. <${terms.agents.ruben}>, has some private data in .`); - - log(`Of course, he does not want everyone to be able to see all of his private data when they need just one aspect of it. Therefore, Ruben has installed two Views on his data, based on SPARQL filters from a public Catalog. (When and how this is done is out-of-scope for now.)`); - - const webIdData = new Store(parser.parse(await (await fetch(terms.agents.ruben)).text())); - const viewIndex = webIdData.getObjects(terms.agents.ruben, terms.solid.viewIndex, null)[0].value; - const views = Object.fromEntries(webIdData.getObjects(viewIndex, terms.solid.entry, null).map(entry => { - const filter = webIdData.getObjects(entry, terms.solid.filter, null)[0].value; - const location = webIdData.getObjects(entry, terms.solid.location, null)[0].value; - return [filter, location]; - })); - - log(`Discovery of views is currently a very crude mechanism based on a public index in the WebID document. (A cleaner mechanism using the UMA server as central hub is being devised.) Using the discovery mechanism, we find the following views on Ruben's private data.`) - - log(`(1) <${views[terms.filters.bday]}> filters out his birth date, according to the <${terms.filters.bday}> filter`); - log(`(2) <${views[terms.filters.age]}> derives his age, according to the <${terms.filters.bday}> filter`); - - const policyContainer = 'http://localhost:3000/ruben/settings/policies/'; - - log(`Access to Ruben's data is based on policies he manages through his Authz Companion app, and which are stored in <${policyContainer}>. (This is, of course, not publicly known.)`); - - const umaServer = webIdData.getObjects(terms.agents.ruben, terms.solid.umaServer, null)[0].value; - const configUrl = new URL('.well-known/uma2-configuration', umaServer); - const umaConfig = await (await fetch(configUrl)).json(); - const tokenEndpoint = umaConfig.token_endpoint; - - log(`To request access to Ruben's data, an agent will need to negotiate with Ruben's Authorization Server, which his WebID document identifies as <${umaServer}>.`); - log(`Via the Well-Known endpoint <${configUrl.href}>, we can discover the Token Endpoint <${tokenEndpoint}>.`); - - log(`Now, having discovered both the location of the UMA server and of the desired data, an agent can request the former for access to the latter.`); - - const accessRequest = { - permissions: [{ - resource_id: terms.views.age, - resource_scopes: [ terms.scopes.read ], - }] - }; - - const accessDeniedResponse = await fetch(tokenEndpoint, { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify(accessRequest), - }); - - if (accessDeniedResponse.status !== 403) { log('Access request succeeded without policy...'); throw 0; } - - log(`Without a policy allowing the access, the access is denied.`); - log(`However, the UMA server enables multiple flows in which such a policy can be added, for example by notifying the resource owner. (This is out-of-scope for this demo.)`); - - log(`...`); - - log(`Having been notified in some way of the access request, Ruben could go to his Authz Companion app, and add a policy allowing the requested access.`); - - const startDate = new Date(); - const endDate = new Date(startDate.valueOf() + 14 * 24 * 60 * 60 * 1000); - const purpose = 'urn:solidlab:uma:claims:purpose:age-verification' - const policy = demoPolicy(terms.views.age, terms.agents.vendor, { startDate, endDate, purpose }) - - // create container if it does not exist yet - await initContainer(policyContainer) - const policyCreationResponse = await fetch(policyContainer, { - method: 'POST', - headers: { 'content-type': 'text/turtle' }, - body: writer.quadsToString(policy.representation.getQuads(null, null, null, null)) - }); - - if (policyCreationResponse.status !== 201) { log('Adding a policy did not succeed...'); throw 0; } - - log(`Now that the policy has been set, and the agent has possibly been notified in some way, the agent can try the access request again.`); - - const needInfoResponse = await fetch(tokenEndpoint, { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify(accessRequest), - }); - - if (needInfoResponse.status !== 403) { log('Access request succeeded without claims...'); throw 0; } - - const { ticket, required_claims } = await needInfoResponse.json(); - - log(`Based on the policy, the UMA server requests the following claims from the agent:`); - required_claims.claim_token_format[0].forEach((format: string) => log(` - ${format}`)) - - // JWT (HS256; secret: "ceci n'est pas un secret") - // { - // "http://www.w3.org/ns/odrl/2/purpose": "urn:solidlab:uma:claims:purpose:age-verification", - // "urn:solidlab:uma:claims:types:webid": "http://localhost:3000/demo/public/vendor" - // } - const claim_token = "eyJhbGciOiJIUzI1NiJ9.eyJodHRwOi8vd3d3LnczLm9yZy9ucy9vZHJsLzIvcHVycG9zZSI6InVybjpzb2xpZGxhYjp1bWE6Y2xhaW1zOnB1cnBvc2U6YWdlLXZlcmlmaWNhdGlvbiIsInVybjpzb2xpZGxhYjp1bWE6Y2xhaW1zOnR5cGVzOndlYmlkIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwL2RlbW8vcHVibGljL3ZlbmRvciJ9.Px7G3zl1ZpTy1lk7ziRMvNv12Enb0uhup9kiVI6Ot3s" - - log(`The agent gathers the necessary claims (the manner in which is out-of-scope for this demo), and sends them to the UMA server as a JWT.`) - - const accessGrantedResponse = await fetch(tokenEndpoint, { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ - ...accessRequest, - ticket, - claim_token_format: 'urn:solidlab:uma:claims:formats:jwt', - claim_token, - }) - }); - - if (accessGrantedResponse.status !== 200) { log('Access request failed despite policy...'); throw 0; } - - log(`The UMA server checks the claims with the relevant policy, and returns the agent an access token with the requested permissions.`); - - const tokenParams = await accessGrantedResponse.json(); - const accessWithTokenResponse = await fetch(terms.views.age, { - headers: { 'Authorization': `${tokenParams.token_type} ${tokenParams.access_token}` } - }); - - if (accessWithTokenResponse.status !== 200) { log('Access with token failed...'); throw 0; } - - log(`The agent can then use this access token at the Resource Server to perform the desired action.`); -} - -main(); - - -/* Helper functions */ - -function parseJwt (token:string) { - return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); -} - -function log(msg: string, obj?: any) { - console.log(''); - console.log(msg); - if (obj) { - console.log('\n'); - console.log(obj); - } -} - -// creates the container if it does not exist yet (only when access is there) -async function initContainer(policyContainer: string): Promise { - const res = await fetch(policyContainer) - if (res.status === 404) { - const res = await fetch(policyContainer, { - method: 'PUT' - }) - if (res.status !== 201) { - log('Creating container at ' + policyContainer + ' not successful'); throw 0; - } - } -} - diff --git a/demo/package.json b/demo/package.json deleted file mode 100644 index 9b56caa4..00000000 --- a/demo/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@solidlab/uma-demos", - "version": "0.1.0", - "private": true, - "devDependencies": { - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", - "@mui/material": "^5.15.14", - "@types/react-dom": "^18.2.18", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.10.0", - "react-scripts": "5.0.1", - "serve": "^14.2.1" - }, - "workspaces": [ - "sites/*" - ], - "scripts": { - "build:demo": "yarn workspaces foreach --include 'sites/*' -A -pi run build", - "start:demo": "yarn workspaces foreach --include 'sites/*' -A -pi run start" - } -} diff --git a/demo/policyCreation.ts b/demo/policyCreation.ts deleted file mode 100644 index 0bf8d21c..00000000 --- a/demo/policyCreation.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { SimplePolicy, UCPPolicy, basicPolicy } from '@solidlab/ucp' - -/** - * Create demo ODRL policy: - * - * Read access for requestingparty to target under constraints (temporal + purpose) - * @param targetIRI - an IRI representing the target -> the resource - * @param requestingPartyIRI - an IRI representing the entity requesting access - * @param constraints - the temporal and purpuse constraints on the usage of the data - */ -export function demoPolicy( - targetIRI: string, - requestingPartyIRI: string, - constraints?: { - startDate?: Date, - endDate?: Date, - purpose?: string - } -): SimplePolicy { - const constraintList: any[] = []; - - if (constraints?.startDate) constraintList.push({ - type: 'temporal', - operator: 'http://www.w3.org/ns/odrl/2/gt', - value: constraints?.startDate, - }); - - if (constraints?.endDate) constraintList.push({ - type: 'temporal', - operator: 'http://www.w3.org/ns/odrl/2/lt', - value: constraints?.endDate, - }); - - if (constraints?.purpose) constraintList.push({ - type: 'purpose', - operator: 'http://www.w3.org/ns/odrl/2/eq', - value: constraints?.purpose, - }); - - const policy: UCPPolicy = { - rules: [{ - resource: targetIRI, - action: "http://www.w3.org/ns/odrl/2/read", // ODRL action - requestingParty: requestingPartyIRI, - // owner: "https://pod.woutslabbinck.com/profile/card#me", // might error - constraints: constraintList - }] - } - - const policyObject = basicPolicy(policy); - - return policyObject -} diff --git a/demo/problem/context.ttl b/demo/problem/context.ttl deleted file mode 100644 index c7657d4d..00000000 --- a/demo/problem/context.ttl +++ /dev/null @@ -1,4 +0,0 @@ - - ; - ; - . diff --git a/demo/problem/policy1.ttl b/demo/problem/policy1.ttl deleted file mode 100644 index 665fde13..00000000 --- a/demo/problem/policy1.ttl +++ /dev/null @@ -1,19 +0,0 @@ -@prefix odrl: . -@prefix xsd: . - - a odrl:Agreement; - odrl:permission . - a odrl:Permission; - odrl:action odrl:read; - odrl:target ; - odrl:assignee ; - odrl:constraint , , . - odrl:leftOperand odrl:dateTime; - odrl:operator odrl:gt; - odrl:rightOperand "2024-03-15T14:52:09.755Z"^^xsd:dateTime. - odrl:leftOperand odrl:dateTime; - odrl:operator odrl:lt; - odrl:rightOperand "2024-03-29T14:52:09.755Z"^^xsd:dateTime. - odrl:leftOperand odrl:purpose; - odrl:operator odrl:eq; - odrl:rightOperand "age-verification". diff --git a/demo/problem/policy2.ttl b/demo/problem/policy2.ttl deleted file mode 100644 index 19ff91ff..00000000 --- a/demo/problem/policy2.ttl +++ /dev/null @@ -1,19 +0,0 @@ -@prefix odrl: . -@prefix xsd: . - - a odrl:Agreement; - odrl:permission . - a odrl:Permission; - odrl:action odrl:read; - odrl:target ; - odrl:assignee ; - odrl:constraint , , . - odrl:leftOperand odrl:dateTime; - odrl:operator odrl:gt; - odrl:rightOperand "2024-03-15T14:52:09.755Z"^^xsd:dateTime. - odrl:leftOperand odrl:dateTime; - odrl:operator odrl:lt; - odrl:rightOperand "2024-03-29T14:52:09.755Z"^^xsd:dateTime. - odrl:leftOperand odrl:purpose; - odrl:operator odrl:eq; - odrl:rightOperand "age-verification". diff --git a/demo/problem/policy3.ttl b/demo/problem/policy3.ttl deleted file mode 100644 index 9e03bab2..00000000 --- a/demo/problem/policy3.ttl +++ /dev/null @@ -1,19 +0,0 @@ -@prefix odrl: . -@prefix xsd: . - - a odrl:Agreement; - odrl:permission . - a odrl:Permission; - odrl:action odrl:read; - odrl:target ; - odrl:assignee ; - odrl:constraint , , . - odrl:leftOperand odrl:dateTime; - odrl:operator odrl:gt; - odrl:rightOperand "2024-03-15T14:52:09.755Z"^^xsd:dateTime. - odrl:leftOperand odrl:dateTime; - odrl:operator odrl:lt; - odrl:rightOperand "2024-03-29T14:52:09.755Z"^^xsd:dateTime. - odrl:leftOperand odrl:purpose; - odrl:operator odrl:eq; - odrl:rightOperand "age-verification". diff --git a/demo/problem/rules_crud.n3 b/demo/problem/rules_crud.n3 deleted file mode 100644 index 2c240210..00000000 --- a/demo/problem/rules_crud.n3 +++ /dev/null @@ -1,163 +0,0 @@ -@prefix odrl: . -@prefix : . -@prefix acl: . -@prefix fno: . -@prefix log: . -@prefix string: . -@prefix list: . - -# Read ODRL rule -{ - ?permission a odrl:Permission; - odrl:action ?action ; - odrl:target ?targetResource ; - # odrl:assigner ?resourceOwner ; - odrl:assignee ?requestedParty. - - ?action list:in (odrl:use odrl:read) . # multiple options - - - # context of a request - ?context - # :resourceOwner ?resourceOwner; - :requestingParty ?requestedParty; - :target ?targetResource; - :requestPermission . - - :uuid5 log:uuid ?uuidStringdataUsagePolicyExecution. - ( "urn:uuid:" ?uuidStringdataUsagePolicyExecution) string:concatenation ?urnUuidStringdataUsagePolicyExecution. - ?dataUsagePolicyExecution log:uri ?urnUuidStringdataUsagePolicyExecution . - - # Constraint checking - # No odrl:constraints may be present - ?SCOPE log:notIncludes { ?permission odrl:constraint ?anything }. -} => -{ - ?dataUsagePolicyExecution a fno:Execution; - fno:executes ; - :accessModesAllowed . -}. - -# Append ODRL Rule -{ - ?permission a odrl:Permission; - odrl:action ?action ; - odrl:target ?targetResource ; - # odrl:assigner ?resourceOwner ; - odrl:assignee ?requestedParty. - - ?action list:in (odrl:use odrl:modify). # multiple options - - # context of a request - ?context - # :resourceOwner ?resourceOwner; - :requestingParty ?requestedParty; - :target ?targetResource; - :requestPermission . - - :uuid6 log:uuid ?uuidStringdataUsagePolicyExecution. - ( "urn:uuid:" ?uuidStringdataUsagePolicyExecution) string:concatenation ?urnUuidStringdataUsagePolicyExecution. - ?dataUsagePolicyExecution log:uri ?urnUuidStringdataUsagePolicyExecution . - - # Constraint checking - # No odrl:constraints may be present - ?SCOPE log:notIncludes { ?permission odrl:constraint ?anything }. -} => -{ - ?dataUsagePolicyExecution a fno:Execution; - fno:executes ; - :accessModesAllowed . -}. - -# Write ODRL Rule -{ - ?permission a odrl:Permission; - odrl:action ?action ; - odrl:target ?targetResource ; - # odrl:assigner ?resourceOwner ; - odrl:assignee ?requestedParty. - - ?action list:in (odrl:use odrl:modify). # multiple options - - # context of a request - ?context - # :resourceOwner ?resourceOwner; - :requestingParty ?requestedParty; - :target ?targetResource; - :requestPermission . - - :uuid6 log:uuid ?uuidStringdataUsagePolicyExecution. - ( "urn:uuid:" ?uuidStringdataUsagePolicyExecution) string:concatenation ?urnUuidStringdataUsagePolicyExecution. - ?dataUsagePolicyExecution log:uri ?urnUuidStringdataUsagePolicyExecution . - - # Constraint checking - # No odrl:constraints may be present - ?SCOPE log:notIncludes { ?permission odrl:constraint ?anything }. -} => -{ - ?dataUsagePolicyExecution a fno:Execution; - fno:executes ; - :accessModesAllowed . -}. - -# Create ODRL Rule -{ - ?permission a odrl:Permission; - odrl:action ?action ; - odrl:target ?targetResource ; - # odrl:assigner ?resourceOwner ; - odrl:assignee ?requestedParty . - - ?action list:in (odrl:use odrl:modify). # multiple options - - # context of a request - ?context - # :resourceOwner ?resourceOwner; - :requestingParty ?requestedParty; - :target ?targetResource; - :requestPermission . - - :uuid6 log:uuid ?uuidStringdataUsagePolicyExecution. - ( "urn:uuid:" ?uuidStringdataUsagePolicyExecution) string:concatenation ?urnUuidStringdataUsagePolicyExecution. - ?dataUsagePolicyExecution log:uri ?urnUuidStringdataUsagePolicyExecution . - - # Constraint checking - # No odrl:constraints may be present - ?SCOPE log:notIncludes { ?permission odrl:constraint ?anything }. -} => -{ - ?dataUsagePolicyExecution a fno:Execution; - fno:executes ; - :accessModesAllowed . -}. - -# Delete ODRL Rule -{ - ?permission a odrl:Permission; - odrl:action ?action ; - odrl:target ?targetResource ; - # odrl:assigner ?resourceOwner ; - odrl:assignee ?requestedParty. - - ?action list:in (odrl:use odrl:delete). # multiple options - - # context of a request - ?context - # :resourceOwner ?resourceOwner; - :requestingParty ?requestedParty; - :target ?targetResource; - :requestPermission . - - :uuid6 log:uuid ?uuidStringdataUsagePolicyExecution. - ( "urn:uuid:" ?uuidStringdataUsagePolicyExecution) string:concatenation ?urnUuidStringdataUsagePolicyExecution. - ?dataUsagePolicyExecution log:uri ?urnUuidStringdataUsagePolicyExecution . - - # Constraint checking - # No odrl:constraints may be present - ?SCOPE log:notIncludes { ?permission odrl:constraint ?anything }. -} => -{ - ?dataUsagePolicyExecution a fno:Execution; - fno:executes ; - :accessModesAllowed . -}. diff --git a/demo/problem/rules_purpose.n3 b/demo/problem/rules_purpose.n3 deleted file mode 100644 index d6e08fa2..00000000 --- a/demo/problem/rules_purpose.n3 +++ /dev/null @@ -1,79 +0,0 @@ - -@prefix xsd: . -@prefix odrl: . -@prefix : . -@prefix acl: . -@prefix fno: . -@prefix log: . -@prefix string: . -@prefix list: . -@prefix time: . -@prefix math: . - -# ... -{ :currentTime :is ?currentTime } <= { "" time:localTime ?currentTime }. - -# Read ODRL rule -{ - ?permission a odrl:Permission; - odrl:action ?action ; - odrl:target ?targetResource ; - # odrl:assigner ?resourceOwner ; - odrl:assignee ?requestedParty. - - ?action list:in (odrl:use odrl:read) . # multiple options - - # context of a request - ?context - # :resourceOwner ?resourceOwner; - :requestingParty ?requestedParty; - :target ?targetResource; - :requestPermission . - - :uuid5 log:uuid ?uuidStringdataUsagePolicyExecution. - ( "urn:uuid:" ?uuidStringdataUsagePolicyExecution) string:concatenation ?urnUuidStringdataUsagePolicyExecution. - ?dataUsagePolicyExecution log:uri ?urnUuidStringdataUsagePolicyExecution . - - # Constraint checking - - # number of constraints must be two (temporal needs lower and upper bound) - (?template {?permission odrl:constraint _:s} ?L) log:collectAllIn ?SCOPE. - ?L list:length 3 . - - :currentTime :is ?currentTime . - - # lower bound - ?permission odrl:constraint ?lowerBoundIRI . - ?lowerBoundIRI - odrl:leftOperand odrl:dateTime ; - odrl:operator odrl:gt ; - odrl:rightOperand ?lowerBound . - - # greater bound - ?permission odrl:constraint ?upperBoundIRI . - ?upperBoundIRI - odrl:leftOperand odrl:dateTime ; - odrl:operator odrl:lt ; - odrl:rightOperand ?upperBound . - - # ?lowerBound < ?currentTime < ?upperBound - ?currentTime math:greaterThan ?lowerBound . - ?currentTime math:lessThan ?upperBound . - - # purpose constraint - ?permission odrl:constraint ?purposeConstraint . - ?purposeConstraint - odrl:leftOperand odrl:purpose ; - odrl:operator odrl:eq ; - odrl:rightOperand ?purposeValue . - # Note: nothing is done with the purpose right now TODO: needs checking -} => -{ - ?dataUsagePolicyExecution a fno:Execution; - fno:executes ; - :accessModesAllowed ; - ?currentTime . - -}. - -# No ODRL rules for other access modes (`odrl:write` and `odrl:append` are deprecated) diff --git a/demo/problem/test.ts b/demo/problem/test.ts deleted file mode 100644 index 111a7280..00000000 --- a/demo/problem/test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { readFileSync } from "fs"; -import { EyeJsReasoner } from "koreografeye"; -import { Store, Parser, Writer } from "n3"; -import path from "path"; - -const parser = new Parser(); -const rules = new Array(); -const facts = new Store(); - -facts.addQuads(parser.parse(readFileSync(path.join(__dirname, 'context.ttl')).toString())) -facts.addQuads(parser.parse(readFileSync(path.join(__dirname, 'policy1.ttl')).toString())) -// facts.addQuads(parser.parse(readFileSync(path.join(__dirname, 'policy2.ttl')).toString())) -// facts.addQuads(parser.parse(readFileSync(path.join(__dirname, 'policy3.ttl')).toString())) - -rules.push(readFileSync(path.join(__dirname, 'rules_purpose.n3')).toString()); -rules.push(readFileSync(path.join(__dirname, 'rules_crud.n3')).toString()); - -(async () => { - - console.log('>>>>> BEFORE'); - const reasoner1 = new EyeJsReasoner(["--quiet", "--nope", "--pass"]); - await reasoner1.reason(facts, rules); - console.log('>>>>> BETWEEN'); - const reasoner2 = new EyeJsReasoner(["--quiet", "--nope", "--pass"]); - await reasoner2.reason(facts, rules); - console.log('>>>>> AFTER'); - -})(); diff --git a/demo/sites/authorizationsite/package.json b/demo/sites/authorizationsite/package.json deleted file mode 100644 index 1193845d..00000000 --- a/demo/sites/authorizationsite/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "@solidlab/uma-demo-authz", - "version": "0.1.0", - "private": true, - "dependencies": { - "@comunica/query-sparql": "^2.6.9", - "@inrupt/solid-client-authn-browser": "^1.14.0", - "n3": "^1.17.3", - "uuid": "^9.0.1" - }, - "scripts": { - "start": "yarn run -T serve -s build -l 5001", - "build": "yarn run -T react-scripts build" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/demo/sites/authorizationsite/public/index.html b/demo/sites/authorizationsite/public/index.html deleted file mode 100644 index 1aaf9e4c..00000000 --- a/demo/sites/authorizationsite/public/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Authorization Companion - - - -
- - diff --git a/demo/sites/authorizationsite/src/App.css b/demo/sites/authorizationsite/src/App.css deleted file mode 100644 index e247a5ff..00000000 --- a/demo/sites/authorizationsite/src/App.css +++ /dev/null @@ -1,39 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - diff --git a/demo/sites/authorizationsite/src/App.tsx b/demo/sites/authorizationsite/src/App.tsx deleted file mode 100644 index 236d3ee5..00000000 --- a/demo/sites/authorizationsite/src/App.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React from "react"; -import { handleIncomingRedirect, getDefaultSession } from '@inrupt/solid-client-authn-browser'; -import { BrowserRouter, Routes, Route } from 'react-router-dom'; -import { useEffect, useState} from 'react'; - -import './App.css'; - -import Home from './components/Home'; -import Navigate from './components/Navigate'; -import SolidAuth from './components/SolidAuth' - -const rubenWebID = 'http://localhost:3000/ruben/profile/card#me' - -export default function App() { - - // Ophalen van het Solid session object. - const session = getDefaultSession() - - // De loggedIn variabele houdt de login status bij, - // en update de pagina wanneer de status verandert. - const [loggedIn, setLoggedIn] = useState(session.info.isLoggedIn) - - // De checkingLogin variabele houdt bij of onze initiële - // check voor login informatie is afgerond. - const [checkingLogin, setCheckingLogin] = useState(true) - - // Deze functie voert uit bij het updaten van de component. - useEffect(() => { - // Forceer hernieuwen van de pagina bij het veranderen van de login status. - session.onLogin(() => setLoggedIn(true)) - session.onLogout(() => setLoggedIn(false)) - - // Deze functie gaat na of we teruggestuurd zijn - // naar de huidige pagina door de Solid login pagina. - handleIncomingRedirect({ restorePreviousSession: true }) - .then((info) => { - // Update de status van de component voor - // de login status en de login check status - // op basis van het resultaat van de functie. - // Voor meer informatie kan je de documentatie bekijken op - // https://docs.inrupt.com/developer-tools/api/javascript/solid-client-authn-browser/functions.html#handleincomingredirect - let status = info?.isLoggedIn || false - if (status !== loggedIn) setLoggedIn(status) - if (info) setCheckingLogin(false) - }) - .catch(console.error) - }) - - // return ( - //
- // { - // checkingLogin - // ? - //

Loading Session information ...

- // : ( - //
- // - // {loggedIn && - // - // - // - // } /> - // } /> - // - // - // } - //
- // ) - // } - //
- // ) - - return ( -
- - - - - } /> - - -
- ) -} \ No newline at end of file diff --git a/demo/sites/authorizationsite/src/components/DatePicker.tsx b/demo/sites/authorizationsite/src/components/DatePicker.tsx deleted file mode 100644 index e6171ae6..00000000 --- a/demo/sites/authorizationsite/src/components/DatePicker.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React, { useRef, useState } from 'react'; - -function getDateCompatString(date: Date) { - return date.toISOString().split('T')[0] -} - -const DatePicker = (props: any) => { - const [date, setDate] = useState(props.value) - const dateInputRef = useRef(null); - - const onChange = (e: any) => { - const date = new Date(e.target.value) - setDate(date); - props.onChange(date) - }; - - return ( -
- -
- ); -}; -export default DatePicker - - \ No newline at end of file diff --git a/demo/sites/authorizationsite/src/components/FormModal.tsx b/demo/sites/authorizationsite/src/components/FormModal.tsx deleted file mode 100644 index 3e7ae1a1..00000000 --- a/demo/sites/authorizationsite/src/components/FormModal.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { useState }from 'react'; -import Backdrop from '@mui/material/Backdrop'; -import Box from '@mui/material/Box'; -import Modal from '@mui/material/Modal'; -import Fade from '@mui/material/Fade'; -import DatePicker from './DatePicker'; -import { PolicyFormData, terms } from '../util/PolicyManagement'; - -const style = { - position: 'absolute' as 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - width: 600, - height: 600, - bgcolor: 'background.paper', - border: '2px solid #000', - boxShadow: 24, - p: 4, -}; - -const purposeValues: Map = new Map([ - ["age-verification", 'urn:solidlab:uma:claims:purpose:age-verification'], - ["some-random-purpose", 'urn:solidlab:uma:claims:purpose:some-random-purpose'] -]) - -const PolicyFormModal = (props: any) => { - const [open, setOpen] = useState(false); - - let now = new Date() - let end = new Date() - end.setDate(end.getDate() + 7) - - const [target, setTarget] = useState(terms.views.age); - const [assignee, setAssignee] = useState(terms.agents.vendor); - const [startDate, setStartDate] = useState(now); - const [endDate, setEndDate] = useState(end); - const [purpose, setPurpose] = useState('urn:solidlab:uma:claims:purpose:age-verification'); - const [description, setDescription] = useState('Age verification for food store'); - - const handleOpen = () => setOpen(true); - const handleClose = () => { - setOpen(false) - }; - - function commitPolicy(e: any) { - e.preventDefault(); - handleClose() - props.addPolicy({target, assignee, startDate, endDate, purpose, description} as PolicyFormData); - } - - return ( -
- - {/* */} - - - -

Add policy

-
- -
- -
- -
- -
- -
- - -
-
- -
-
-
-
-
- ); -} - -// targetIRI: string, -// requestingPartyIRI: string, -// constraints?: { -// startDate?: Date, -// endDate?: Date, -// purpose?: string -// } - - -export default PolicyFormModal; diff --git a/demo/sites/authorizationsite/src/components/Home.tsx b/demo/sites/authorizationsite/src/components/Home.tsx deleted file mode 100644 index 38349b7d..00000000 --- a/demo/sites/authorizationsite/src/components/Home.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { useEffect, useState } from "react"; -import { createAndSubmitPolicy, doPolicyFlowFromString, - readPolicy, readPolicyDirectory } from "../util/PolicyManagement"; -import PolicyFormModal from "./FormModal" -import { SimplePolicy } from "../util/policyCreation"; - -export default function Home() { - - const [policyList, setPolicyList] = useState([]) - const [selectedPolicy, setSelectedPolicy] = useState(null) - - useEffect(() => { - async function getPolicies() { - let policies = await readPolicyDirectory(); - setPolicyList(policies) - } - getPolicies() - }, []) - - async function addPolicyFromText(policyText: string) { - console.log('Adding the following policy:') - console.log(policyText) - await doPolicyFlowFromString(policyText) - const policyObject = await readPolicy(policyText) - if(policyObject) setPolicyList(policyList.concat(policyObject)) - } - - async function addPolicyFromFormdata(formdata: any) { - console.log('Adding the following policy:') - console.log(formdata) - const policyObject = await createAndSubmitPolicy(formdata) - if(policyObject) setPolicyList(policyList.concat(policyObject)) - } - - function renderPolicy(policy: SimplePolicy) { - return ( -
setSelectedPolicy(policy.policyIRI)}> -

id: {policy.policyIRI}

-

{policy.description}

-
- ) - } - - const selectedPolicyText = selectedPolicy - ? policyList.filter(p => p.policyIRI === selectedPolicy)[0]?.policyText || '' - : '' - - return ( -
-
-
-
- { - policyList.map(renderPolicy) - } -
- -
-
-