diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5425118f9..97c57a0ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,35 @@
All notable changes to this project will be documented in this file.
+## [7.0.3](https://github.com/CommunitySolidServer/CommunitySolidServer/compare/v7.0.2...v7.0.3) (2024-01-05)
+
+### Features
+
+* Support default mainModulePath when creating App ([c6ec45c](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/c6ec45c7c0fb91a1c1365e9a0139e4fdaf8838d6))
+
+### Fixes
+
+* Encode WebID ownership tokens ([277a0d0](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/277a0d0ab724074ed96940836ecc973a8533c538))
+* Fix pod base URL in README template ([4e7929f](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/4e7929f6d2b72fbb0a03e8f6e64955239f41c837))
+* Only require append when creating with PUT ([a0b7ee4](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/a0b7ee42f3a39cdd8fe2dbf1470e53f57ea62aba))
+
+### Chores
+
+* Remove Docker arm builds ([648ce1f](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/648ce1fba8737dc7a008ff987de161e5902f9d09))
+* Update linting dependency ([3a9b0d6](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/3a9b0d69f01d6f0490983eda4ff8000798e10dcc))
+
+### Documentation
+
+* Explain how to use AppRunner to start a server instance ([716c3c3](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/716c3c308933a10382d6726a70b5b77a62cfb787))
+* Explain that users need to log in for client credentials ([dca71bc](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/dca71bc5b82a9790d861babdcb1dd231c99dd042))
+* Fix links ([1f88864](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/1f888645d6619e253082f4bf0ed20e7ae4e4c38b))
+* Describe server feature set ([c64a1a2](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/c64a1a241ddd975f22eb223d545c938dfc8cb63c))
+* Fix Typo `is -> if` ([355f7dd](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/355f7dd1c7b9be14c3e243acb5c4634f3a800442))
+
+### Testing
+
+* Run tests on Node 21 ([8f74fc8](https://github.com/CommunitySolidServer/CommunitySolidServer/commit/8f74fc82ad8a611bf96c293748bc5c01c859cdeb))
+
## [7.0.2](https://github.com/CommunitySolidServer/CommunitySolidServer/compare/v7.0.1...v7.0.2) (2023-11-20)
### Features
diff --git a/documentation/markdown/contributing/release.md b/documentation/markdown/contributing/release.md
index 80ecb6cf9..be9307fa4 100644
--- a/documentation/markdown/contributing/release.md
+++ b/documentation/markdown/contributing/release.md
@@ -1,22 +1,24 @@
-# Releasing a new major version
+# Releasing a new version
This is only relevant if you are a developer with push access responsible for doing a new release.
Steps to follow:
-* Merge `main` into `versions/next-major`.
+* **Major** releases only:
+ * Merge `main` into `versions/next-major`.
* Verify if there are issues when upgrading an existing installation to the new version.
* Can the data still be accessed?
* Does authentication still work?
* Is there an issue upgrading any of the dependent repositories (see below for links)?
* None of the above has to be blocking per se, but should be noted in the release notes if relevant.
-* Verify that the `RELEASE_NOTES.md` are correct.
-* `npm run release -- -r major`
- * Automatically updates Components.js references to the new version.
+* **Major** and **Minor** releases:
+ * Verify that the `RELEASE_NOTES.md` are correct.
+* `npm run release -- -r major/minor/patch`
+ * Automatically updates Components.js references to the new version in case of a major release.
Committed with `chore(release): Update configs to vx.0.0`.
* Updates the `package.json`, and generates the new entries in `CHANGELOG.md`.
- Commits with `chore(release): Release version vx.0.0 of the npm package`
- * Optionally run `npx commit-and-tag-version -r major --dry-run` to preview the commands that will be run
+ Commits with `chore(release): Release version vx.y.z of the npm package`
+ * Optionally run `npx commit-and-tag-version -r major/minor/patch --dry-run` to preview the commands that will be run
and the changes to `CHANGELOG.md`.
* The `postrelease` script will now prompt you to manually edit the `CHANGELOG.md`.
* All entries are added in separate sections of the new release according to their commit prefixes.
@@ -24,11 +26,12 @@ Steps to follow:
Documentation can be removed.
* Press any key in your terminal when your changes are ready.
* The `postrelease` script will amend the release commit, create an annotated tag and push changes to origin.
-* Merge `versions/next-major` into `main` and push.
+* **Major** releases only:
+ * Merge `versions/next-major` into `main` and push.
* Do a GitHub release.
* `npm publish`
- * `npm dist-tag add @solid/community-server@x.0.0 next`
-* Rename the `versions/x.0.0` branch to the next version.
+* If there is no **pre-release** of a higher version:
+ * `npm dist-tag add @solid/community-server@x.y.z next`
* Potentially upgrade dependent repositories:
* Recipes at
* Tutorials at
@@ -40,9 +43,3 @@ Steps to follow:
* Version with `npm run release -- -r major --prerelease alpha`
* Do not merge `versions/next-major` into `main`.
* Publish with `npm publish --tag next`.
-* Do not update the branch or anything related.
-
-## Changes when doing a minor release
-
-* Version with `npm run release -- -r minor`
-* Do not merge `versions/next-major` into `main`.
diff --git a/documentation/markdown/usage/client-credentials.md b/documentation/markdown/usage/client-credentials.md
index e2b9f5537..fc76c64ce 100644
--- a/documentation/markdown/usage/client-credentials.md
+++ b/documentation/markdown/usage/client-credentials.md
@@ -100,11 +100,10 @@ Once you have an Access token, you can use it for authenticated requests until i
```ts
import { buildAuthenticatedFetch } from '@inrupt/solid-client-authn-core';
-import fetch from 'node-fetch';
// The DPoP key needs to be the same key as the one used in the previous step.
// The Access token is the one generated in the previous step.
-const authFetch = await buildAuthenticatedFetch(fetch, accessToken, { dpopKey });
+const authFetch = await buildAuthenticatedFetch(accessToken, { dpopKey });
// authFetch can now be used as a standard fetch function that will authenticate as your WebID.
// This request will do a simple GET for example.
const response = await authFetch('http://localhost:3000/private');
diff --git a/documentation/markdown/usage/dev-configuration.md b/documentation/markdown/usage/dev-configuration.md
index a4c806939..03f2b0cad 100644
--- a/documentation/markdown/usage/dev-configuration.md
+++ b/documentation/markdown/usage/dev-configuration.md
@@ -1,6 +1,62 @@
# Configuring the CSS as a development server in another project
It can be useful to use the CSS as local server to develop Solid applications against.
+There are several ways to configure and run a server in your project.
+Note that starting up the server takes some time so set your timeout high enough if you are using this in your tests.
+
+## Starting the server through code
+
+You can create a server instance in your code, or tests, by calling the `create` function of a new `AppRunner` instance.
+The resulting object has `start` and `stop` functions.
+The `create` function takes as input an object with 5 optional parameters
+which can all be used to define the server configuration.
+None of these are mandatory, if you don't think you need one you can probably ignore it.
+These are discussed below.
+
+### loaderProperties
+
+These values are specifically to configure how Components.js handles starting the server.
+Most of these are generally not going to be relevant,
+but here are some of those you might want to change:
+
+* **mainModulePath**: Determines where Components.js will look for components.
+ Defaults to the folder where the server dependency is installed.
+ In case you are making a custom component,
+ this value needs to point to the directory of your project instead.
+* **logLevel**: The logging level of Components.js when building. Defaults to `warn`.
+
+### config
+
+The file path of the Components.js configuration that needs to be used.
+This can also be an array of configuration paths.
+The `@css:` prefix can be used for file paths to generate a path
+relative to the folder where the server dependency is installed.
+Defaults to `@css:config/default.json`.
+
+### variableBindings
+
+Allows you to assign values to the variables that are used in a Components.js configuration.
+For example, `{ 'urn:solid-server:default:variable:port': 3000 }` tells the server to use port 3000.
+
+### shorthand
+
+Allows you to assign values to parameters similarly as if you would call the server from the CLI.
+For example, `{ port: 3000 }` tells the server to use port 3000.
+
+This is very similar to the `variableBindings` field mentioned above,
+as CLI parameters all get translated into Components.js variables,
+although some get transformed before being put into a variable.
+If you are not sure which one to use, `shorthand` is the safer choice to use.
+
+### argv
+
+If used, this parameter expects a string array.
+Here you can provide the raw dump of CLI values,
+so you don't have to parse them yourself,
+should this be useful for your application.
+
+## Configuring the server in `package.json`
+
As an alternative to using CLI arguments, or environment variables, the CSS can be configured in the `package.json` as follows:
```json
@@ -24,7 +80,7 @@ As an alternative to using CLI arguments, or environment variables, the CSS can
```
These parameters will then be used when the `community-solid-server`
-command is executed as an npm script (as shown in the example above).
+command is executed as an `npm` script (as shown in the example above).
Or whenever the `community-solid-server` command is executed in the same
folder as the `package.json`.
diff --git a/package-lock.json b/package-lock.json
index 8728daa98..f771a2643 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,19 +1,19 @@
{
"name": "@solid/community-server",
- "version": "7.0.2",
+ "version": "7.0.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@solid/community-server",
- "version": "7.0.2",
+ "version": "7.0.3",
"license": "MIT",
"dependencies": {
"@comunica/context-entries": "^2.8.2",
"@comunica/query-sparql": "^2.9.0",
"@rdfjs/types": "^1.1.0",
"@solid/access-control-policy": "^0.1.3",
- "@solid/access-token-verifier": "^2.0.5",
+ "@solid/access-token-verifier": "^2.1.0",
"@types/async-lock": "^1.4.0",
"@types/bcryptjs": "^2.4.4",
"@types/cookie": "^0.5.2",
@@ -85,8 +85,8 @@
"@antfu/eslint-config": "2.3.4",
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^18.0.0",
- "@inrupt/solid-client-authn-core": "^1.17.3",
- "@inrupt/solid-client-authn-node": "^1.17.3",
+ "@inrupt/solid-client-authn-core": "^2.0.0",
+ "@inrupt/solid-client-authn-node": "^2.0.0",
"@tsconfig/node18": "^18.2.2",
"@types/jest": "^29.5.5",
"@types/set-cookie-parser": "^2.4.4",
@@ -4275,15 +4275,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
- "node_modules/@fastify/busboy": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
- "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
- "dev": true,
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
@@ -4330,62 +4321,32 @@
}
},
"node_modules/@inrupt/solid-client-authn-core": {
- "version": "1.17.3",
- "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-core/-/solid-client-authn-core-1.17.3.tgz",
- "integrity": "sha512-UuHLFChd+0155EwYgdQJN6mP7fpnT4UFnWZT0+gDAbudUkUI0dKp6HKisWkJAK+KY1wDZ5HCQmCKBpjtiPXuyA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-core/-/solid-client-authn-core-2.0.0.tgz",
+ "integrity": "sha512-qM+E9I5u2DFlsfyoXossx8w0vKv8p+rXH98K9RUauJImpygQ3I3Ra6hSB2bwA1PdPQd5ttNg236oKe1sTT6Hqw==",
"dev": true,
"dependencies": {
- "@inrupt/universal-fetch": "^1.0.1",
"events": "^3.3.0",
- "jose": "^4.14.6",
+ "jose": "^5.1.3",
"uuid": "^9.0.1"
},
"engines": {
- "node": "^16.0.0 || ^18.0.0 || ^20.0.0"
- }
- },
- "node_modules/@inrupt/solid-client-authn-core/node_modules/jose": {
- "version": "4.15.4",
- "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
- "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/panva"
+ "node": "^18.0.0 || ^20.0.0"
}
},
"node_modules/@inrupt/solid-client-authn-node": {
- "version": "1.17.3",
- "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-node/-/solid-client-authn-node-1.17.3.tgz",
- "integrity": "sha512-3lmSh7VNBUVFlBQZBQAtqyVz2B0bRTP8Zm4mkIxG519b2oJwLQtttP/cqQU1WutqADjLLB7Xx4zQTnf2E7yZkw==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-node/-/solid-client-authn-node-2.0.0.tgz",
+ "integrity": "sha512-S1vGRodX0MSAKR3B6tm4qUvMhGv0sMcFjYyhVil7isoRI/7ei5QTpm+081RTWe6/cv4WI6UiHER3YIG15uwhhg==",
"dev": true,
"dependencies": {
- "@inrupt/solid-client-authn-core": "^1.17.3",
- "@inrupt/universal-fetch": "^1.0.1",
- "jose": "^4.14.6",
- "openid-client": "~5.5.0",
+ "@inrupt/solid-client-authn-core": "^2.0.0",
+ "jose": "^5.1.3",
+ "openid-client": "~5.6.1",
"uuid": "^9.0.1"
},
"engines": {
- "node": "^16.0.0 || ^18.0.0 || ^20.0.0"
- }
- },
- "node_modules/@inrupt/solid-client-authn-node/node_modules/jose": {
- "version": "4.15.4",
- "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
- "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/panva"
- }
- },
- "node_modules/@inrupt/universal-fetch": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@inrupt/universal-fetch/-/universal-fetch-1.0.1.tgz",
- "integrity": "sha512-oqbG7jS1fa6hVkjSir+u5Ab3eSbyxFyOjsgjDICL27mAd5z8oImTSETnY2hYbkRaJQYKMBOXhtm7L5/+EbeVJg==",
- "dev": true,
- "dependencies": {
- "node-fetch": "^2.6.7",
- "undici": "^5.19.1"
+ "node": "^18.0.0 || ^20.0.0"
}
},
"node_modules/@ioredis/commands": {
@@ -4970,25 +4931,17 @@
"integrity": "sha512-LTxfN8N5hNBNYfuwJr0nyfxlp2P0+GeK+biCa1FQgIqska3wXpTgYaxjVgsw27mKx4N1FOlaGwG+nXdLnl9ykg=="
},
"node_modules/@solid/access-token-verifier": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-2.0.5.tgz",
- "integrity": "sha512-YsoMmEk7pN6tlCHcDm5iLa9ZYvTYvuk3SX5cz18XW1qYmM46znEGnXz94vm7DIa7DcTLGi9suMw7M5pRs2xOLw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-2.1.0.tgz",
+ "integrity": "sha512-79u92GD1SBTxjYghg2ta6cfoBNZ5ljz/9zE6RmXUypTXW7oI18DTWiSrEjWwI4njW+OMh+4ih+sAR6AkI1IFxg==",
"dependencies": {
- "jose": "^4.10.3",
+ "jose": "^5.1.3",
"lru-cache": "^6.0.0",
- "n3": "^1.16.2",
- "node-fetch": "^2.6.7",
+ "n3": "^1.17.1",
+ "node-fetch": "^2.7.0",
"ts-guards": "^0.5.1"
}
},
- "node_modules/@solid/access-token-verifier/node_modules/jose": {
- "version": "4.15.4",
- "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
- "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==",
- "funding": {
- "url": "https://github.com/sponsors/panva"
- }
- },
"node_modules/@stylistic/eslint-plugin": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.0.tgz",
@@ -12997,9 +12950,9 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
"node_modules/node-fetch": {
- "version": "2.6.12",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
- "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
@@ -13356,12 +13309,12 @@
}
},
"node_modules/openid-client": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.5.0.tgz",
- "integrity": "sha512-Y7Xl8BgsrkzWLHkVDYuroM67hi96xITyEDSkmWaGUiNX6CkcXC3XyQGdv5aWZ6dukVKBFVQCADi9gCavOmU14w==",
+ "version": "5.6.4",
+ "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.4.tgz",
+ "integrity": "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA==",
"dev": true,
"dependencies": {
- "jose": "^4.14.4",
+ "jose": "^4.15.4",
"lru-cache": "^6.0.0",
"object-hash": "^2.2.0",
"oidc-token-hash": "^5.0.3"
@@ -15531,18 +15484,6 @@
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
- "node_modules/undici": {
- "version": "5.26.3",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.3.tgz",
- "integrity": "sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==",
- "dev": true,
- "dependencies": {
- "@fastify/busboy": "^2.0.0"
- },
- "engines": {
- "node": ">=14.0"
- }
- },
"node_modules/unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
@@ -19709,12 +19650,6 @@
"dev": true,
"peer": true
},
- "@fastify/busboy": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
- "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
- "dev": true
- },
"@humanwhocodes/config-array": {
"version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
@@ -19748,54 +19683,26 @@
"dev": true
},
"@inrupt/solid-client-authn-core": {
- "version": "1.17.3",
- "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-core/-/solid-client-authn-core-1.17.3.tgz",
- "integrity": "sha512-UuHLFChd+0155EwYgdQJN6mP7fpnT4UFnWZT0+gDAbudUkUI0dKp6HKisWkJAK+KY1wDZ5HCQmCKBpjtiPXuyA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-core/-/solid-client-authn-core-2.0.0.tgz",
+ "integrity": "sha512-qM+E9I5u2DFlsfyoXossx8w0vKv8p+rXH98K9RUauJImpygQ3I3Ra6hSB2bwA1PdPQd5ttNg236oKe1sTT6Hqw==",
"dev": true,
"requires": {
- "@inrupt/universal-fetch": "^1.0.1",
"events": "^3.3.0",
- "jose": "^4.14.6",
+ "jose": "^5.1.3",
"uuid": "^9.0.1"
- },
- "dependencies": {
- "jose": {
- "version": "4.15.4",
- "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
- "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==",
- "dev": true
- }
}
},
"@inrupt/solid-client-authn-node": {
- "version": "1.17.3",
- "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-node/-/solid-client-authn-node-1.17.3.tgz",
- "integrity": "sha512-3lmSh7VNBUVFlBQZBQAtqyVz2B0bRTP8Zm4mkIxG519b2oJwLQtttP/cqQU1WutqADjLLB7Xx4zQTnf2E7yZkw==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-node/-/solid-client-authn-node-2.0.0.tgz",
+ "integrity": "sha512-S1vGRodX0MSAKR3B6tm4qUvMhGv0sMcFjYyhVil7isoRI/7ei5QTpm+081RTWe6/cv4WI6UiHER3YIG15uwhhg==",
"dev": true,
"requires": {
- "@inrupt/solid-client-authn-core": "^1.17.3",
- "@inrupt/universal-fetch": "^1.0.1",
- "jose": "^4.14.6",
- "openid-client": "~5.5.0",
+ "@inrupt/solid-client-authn-core": "^2.0.0",
+ "jose": "^5.1.3",
+ "openid-client": "~5.6.1",
"uuid": "^9.0.1"
- },
- "dependencies": {
- "jose": {
- "version": "4.15.4",
- "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
- "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==",
- "dev": true
- }
- }
- },
- "@inrupt/universal-fetch": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@inrupt/universal-fetch/-/universal-fetch-1.0.1.tgz",
- "integrity": "sha512-oqbG7jS1fa6hVkjSir+u5Ab3eSbyxFyOjsgjDICL27mAd5z8oImTSETnY2hYbkRaJQYKMBOXhtm7L5/+EbeVJg==",
- "dev": true,
- "requires": {
- "node-fetch": "^2.6.7",
- "undici": "^5.19.1"
}
},
"@ioredis/commands": {
@@ -20272,22 +20179,15 @@
"integrity": "sha512-LTxfN8N5hNBNYfuwJr0nyfxlp2P0+GeK+biCa1FQgIqska3wXpTgYaxjVgsw27mKx4N1FOlaGwG+nXdLnl9ykg=="
},
"@solid/access-token-verifier": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-2.0.5.tgz",
- "integrity": "sha512-YsoMmEk7pN6tlCHcDm5iLa9ZYvTYvuk3SX5cz18XW1qYmM46znEGnXz94vm7DIa7DcTLGi9suMw7M5pRs2xOLw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-2.1.0.tgz",
+ "integrity": "sha512-79u92GD1SBTxjYghg2ta6cfoBNZ5ljz/9zE6RmXUypTXW7oI18DTWiSrEjWwI4njW+OMh+4ih+sAR6AkI1IFxg==",
"requires": {
- "jose": "^4.10.3",
+ "jose": "^5.1.3",
"lru-cache": "^6.0.0",
- "n3": "^1.16.2",
- "node-fetch": "^2.6.7",
+ "n3": "^1.17.1",
+ "node-fetch": "^2.7.0",
"ts-guards": "^0.5.1"
- },
- "dependencies": {
- "jose": {
- "version": "4.15.4",
- "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
- "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ=="
- }
}
},
"@stylistic/eslint-plugin": {
@@ -26253,9 +26153,9 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
"node-fetch": {
- "version": "2.6.12",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
- "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"requires": {
"whatwg-url": "^5.0.0"
},
@@ -26521,12 +26421,12 @@
"dev": true
},
"openid-client": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.5.0.tgz",
- "integrity": "sha512-Y7Xl8BgsrkzWLHkVDYuroM67hi96xITyEDSkmWaGUiNX6CkcXC3XyQGdv5aWZ6dukVKBFVQCADi9gCavOmU14w==",
+ "version": "5.6.4",
+ "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.4.tgz",
+ "integrity": "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA==",
"dev": true,
"requires": {
- "jose": "^4.14.4",
+ "jose": "^4.15.4",
"lru-cache": "^6.0.0",
"object-hash": "^2.2.0",
"oidc-token-hash": "^5.0.3"
@@ -28199,15 +28099,6 @@
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
- "undici": {
- "version": "5.26.3",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.3.tgz",
- "integrity": "sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==",
- "dev": true,
- "requires": {
- "@fastify/busboy": "^2.0.0"
- }
- },
"unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
diff --git a/package.json b/package.json
index e84cd3ce9..0da7031d0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@solid/community-server",
- "version": "7.0.2",
+ "version": "7.0.3",
"description": "Community Solid Server: an open and modular implementation of the Solid specifications",
"license": "MIT",
"homepage": "https://github.com/CommunitySolidServer/CommunitySolidServer#readme",
@@ -77,7 +77,7 @@
"@comunica/query-sparql": "^2.9.0",
"@rdfjs/types": "^1.1.0",
"@solid/access-control-policy": "^0.1.3",
- "@solid/access-token-verifier": "^2.0.5",
+ "@solid/access-token-verifier": "^2.1.0",
"@types/async-lock": "^1.4.0",
"@types/bcryptjs": "^2.4.4",
"@types/cookie": "^0.5.2",
@@ -146,8 +146,8 @@
"@antfu/eslint-config": "2.3.4",
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^18.0.0",
- "@inrupt/solid-client-authn-core": "^1.17.3",
- "@inrupt/solid-client-authn-node": "^1.17.3",
+ "@inrupt/solid-client-authn-core": "^2.0.0",
+ "@inrupt/solid-client-authn-node": "^2.0.0",
"@tsconfig/node18": "^18.2.2",
"@types/jest": "^29.5.5",
"@types/set-cookie-parser": "^2.4.4",
diff --git a/src/authorization/permissions/MethodModesExtractor.ts b/src/authorization/permissions/MethodModesExtractor.ts
index 0d995ad35..5a581ca14 100644
--- a/src/authorization/permissions/MethodModesExtractor.ts
+++ b/src/authorization/permissions/MethodModesExtractor.ts
@@ -39,11 +39,13 @@ export class MethodModesExtractor extends ModesExtractor {
if (READ_METHODS.has(method)) {
requiredModes.add(target, AccessMode.read);
}
- // Setting a resource's representation requires Write permissions
if (method === 'PUT') {
- requiredModes.add(target, AccessMode.write);
- // …and, if the resource does not exist yet, Create permissions are required as well
- if (!await this.resourceSet.hasResource(target)) {
+ if (await this.resourceSet.hasResource(target)) {
+ // Replacing a resource's representation with PUT requires Write permissions
+ requiredModes.add(target, AccessMode.write);
+ } else {
+ // ... while creating a new resource with PUT requires Append and Create permissions.
+ requiredModes.add(target, AccessMode.append);
requiredModes.add(target, AccessMode.create);
}
}
diff --git a/src/identity/ownership/TokenOwnershipValidator.ts b/src/identity/ownership/TokenOwnershipValidator.ts
index c0c9c1050..db2dd1f55 100644
--- a/src/identity/ownership/TokenOwnershipValidator.ts
+++ b/src/identity/ownership/TokenOwnershipValidator.ts
@@ -51,7 +51,7 @@ export class TokenOwnershipValidator extends OwnershipValidator {
* Creates a key to use with the token storage.
*/
private getTokenKey(webId: string): string {
- return `ownershipToken${webId}`;
+ return encodeURIComponent(webId);
}
/**
diff --git a/src/init/AppRunner.ts b/src/init/AppRunner.ts
index a91d08c81..0f2f701c1 100644
--- a/src/init/AppRunner.ts
+++ b/src/init/AppRunner.ts
@@ -36,13 +36,17 @@ const ENV_VAR_PREFIX = 'CSS';
export interface AppRunnerInput {
/**
* Properties that will be used when building the Components.js manager.
- * Sets `typeChecking` to false by default as the server components will result in errors otherwise.
+ * Default values:
+ * - `typeChecking`: `false`, as the server components would otherwise error.
+ * - `mainModulePath`: `@css:`, which resolves to the directory of the CSS package.
+ * This is useful for packages that depend on the CSS
+ * but do not create any new modules themselves.
*/
- loaderProperties: IComponentsManagerBuilderOptions;
+ loaderProperties?: Partial>;
/**
- * Path to the server config file(s).
+ * Path to the server config file(s). Defaults to `@css:config/default.json`.
*/
- config: string | string[];
+ config?: string | string[];
/**
* Values to apply to the Components.js variables.
* These are the variables CLI values will be converted to.
@@ -87,14 +91,19 @@ export class AppRunner {
*
* @param input - All values necessary to configure the server.
*/
- public async create(input: AppRunnerInput): Promise {
+ public async create(input: AppRunnerInput = {}): Promise {
const loaderProperties = {
typeChecking: false,
+ mainModulePath: '@css:',
+ dumpErrorState: false,
...input.loaderProperties,
};
+ // Expand mainModulePath as needed
+ loaderProperties.mainModulePath = resolveAssetPath(loaderProperties.mainModulePath);
- // Potentially expand file paths as needed
- const configs = (Array.isArray(input.config) ? input.config : [ input.config ]).map(resolveAssetPath);
+ // Potentially expand config paths as needed
+ let configs = input.config ?? [ '@css:config/default.json' ];
+ configs = (Array.isArray(configs) ? configs : [ configs ]).map(resolveAssetPath);
let componentsManager: ComponentsManager;
try {
@@ -178,8 +187,8 @@ export class AppRunner {
const params = await yargv.parse();
- const loaderProperties: IComponentsManagerBuilderOptions = {
- mainModulePath: resolveAssetPath(params.mainModulePath),
+ const loaderProperties: AppRunnerInput['loaderProperties'] = {
+ mainModulePath: params.mainModulePath,
logLevel: params.loggingLevel,
};
diff --git a/templates/pod/base/README$.md.hbs b/templates/pod/base/README$.md.hbs
index 23e4064c2..370a09673 100644
--- a/templates/pod/base/README$.md.hbs
+++ b/templates/pod/base/README$.md.hbs
@@ -14,7 +14,7 @@ The easiest way to interact with pods
is through Solid apps.
For example,
-you can open your pod in [Databrowser](https://solidos.github.io/mashlib/dist/browse.html?uri={{podBaseUrl}}).
+you can open your pod in [Databrowser](https://solidos.github.io/mashlib/dist/browse.html?uri={{base.path}}).
## Accessing your account
To keep track of your pods, webIDs and any other resources,
diff --git a/test/integration/Accounts.test.ts b/test/integration/Accounts.test.ts
index 78e6f3760..9063a658d 100644
--- a/test/integration/Accounts.test.ts
+++ b/test/integration/Accounts.test.ts
@@ -6,15 +6,27 @@ import type { ResourceStore } from '../../src/storage/ResourceStore';
import { APPLICATION_X_WWW_FORM_URLENCODED } from '../../src/util/ContentTypes';
import { joinUrl } from '../../src/util/PathUtil';
import { getPort } from '../util/Util';
-import { getDefaultVariables, getTestConfigPath, instantiateFromConfig } from './Config';
+import { getDefaultVariables, getTestConfigPath, getTestFolder, instantiateFromConfig, removeFolder } from './Config';
const port = getPort('Accounts');
const baseUrl = `http://localhost:${port}/`;
+const rootFilePath = getTestFolder('Accounts');
+const stores: [string, any][] = [
+ [ 'in-memory storage', {
+ config: 'memory-pod.json',
+ teardown: jest.fn(),
+ }],
+ [ 'on-disk storage', {
+ config: 'file-pod.json',
+ teardown: async(): Promise => removeFolder(rootFilePath),
+ }],
+];
+
// Don't send actual e-mails
jest.mock('nodemailer');
-describe('A server with account management', (): void => {
+describe.each(stores)('A server with account management using %s', (name, { config, teardown }): void => {
let app: App;
let store: ResourceStore;
let sendMail: jest.Mock;
@@ -42,8 +54,11 @@ describe('A server with account management', (): void => {
const instances = await instantiateFromConfig(
'urn:solid-server:test:Instances',
- getTestConfigPath('memory-pod.json'),
- getDefaultVariables(port, baseUrl),
+ getTestConfigPath(config),
+ {
+ ...getDefaultVariables(port, baseUrl),
+ 'urn:solid-server:default:variable:rootFilePath': rootFilePath,
+ },
) as Record;
({ app, store } = instances);
await app.start();
@@ -68,6 +83,7 @@ describe('A server with account management', (): void => {
});
afterAll(async(): Promise => {
+ await teardown();
await app.stop();
});
diff --git a/test/integration/Identity.test.ts b/test/integration/Identity.test.ts
index b0f25a5f0..8fd6bbb99 100644
--- a/test/integration/Identity.test.ts
+++ b/test/integration/Identity.test.ts
@@ -392,7 +392,7 @@ describe.each(stores)('A Solid server with IDP using %s', (name, { config, teard
});
it('can use the generated access token to do an authenticated call.', async(): Promise => {
- const authFetch = await buildAuthenticatedFetch(fetch, accessToken!, { dpopKey });
+ const authFetch = await buildAuthenticatedFetch(accessToken!, { dpopKey });
let res = await fetch(container);
expect(res.status).toBe(401);
res = await authFetch(container);
diff --git a/test/integration/PermissionTable.test.ts b/test/integration/PermissionTable.test.ts
index 0d1f93ea2..c81c85a41 100644
--- a/test/integration/PermissionTable.test.ts
+++ b/test/integration/PermissionTable.test.ts
@@ -83,7 +83,7 @@ const table: [string, string, AM[], AM[] | undefined, string, string, number, nu
[ 'PUT', 'C/R', [], [ AM.append ], '', TXT, 401, 401 ],
[ 'PUT', 'C/R', [], [ AM.write ], '', TXT, 205, 401 ],
[ 'PUT', 'C/R', [ AM.read ], undefined, '', TXT, 401, 401 ],
- [ 'PUT', 'C/R', [ AM.append ], undefined, '', TXT, 401, 401 ],
+ [ 'PUT', 'C/R', [ AM.append ], undefined, '', TXT, 401, 201 ],
[ 'PUT', 'C/R', [ AM.write ], undefined, '', TXT, 205, 201 ],
[ 'PUT', 'C/R', [ AM.append ], [ AM.write ], '', TXT, 205, 201 ],
diff --git a/test/unit/authorization/permissions/MethodModesExtractor.test.ts b/test/unit/authorization/permissions/MethodModesExtractor.test.ts
index 37ab0c6be..ad1e06acb 100644
--- a/test/unit/authorization/permissions/MethodModesExtractor.test.ts
+++ b/test/unit/authorization/permissions/MethodModesExtractor.test.ts
@@ -58,11 +58,11 @@ describe('A MethodModesExtractor', (): void => {
compareMaps(await extractor.handle({ ...operation, method: 'PUT' }), getMap([ AccessMode.write ]));
});
- it('requires create for PUT operations if the target does not exist.', async(): Promise => {
+ it('requires append/create for PUT operations if the target does not exist.', async(): Promise => {
resourceSet.hasResource.mockResolvedValueOnce(false);
compareMaps(
await extractor.handle({ ...operation, method: 'PUT' }),
- getMap([ AccessMode.write, AccessMode.create ]),
+ getMap([ AccessMode.append, AccessMode.create ]),
);
});
diff --git a/test/unit/init/AppRunner.test.ts b/test/unit/init/AppRunner.test.ts
index c99b0eea0..2013cd7d9 100644
--- a/test/unit/init/AppRunner.test.ts
+++ b/test/unit/init/AppRunner.test.ts
@@ -206,6 +206,30 @@ describe('AppRunner', (): void => {
expect(app.clusterManager.isSingleThreaded()).toBeFalsy();
});
+ it('has several defaults.', async(): Promise => {
+ const createdApp = await new AppRunner().create();
+ expect(createdApp).toBe(app);
+
+ expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
+ expect(ComponentsManager.build).toHaveBeenCalledWith({
+ mainModulePath: joinFilePath(__dirname, '../../../'),
+ typeChecking: false,
+ dumpErrorState: false,
+ });
+ expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
+ expect(manager.configRegistry.register)
+ .toHaveBeenCalledWith(joinFilePath(__dirname, '/../../../config/default.json'));
+ expect(manager.instantiate).toHaveBeenCalledTimes(2);
+ expect(manager.instantiate).toHaveBeenNthCalledWith(1, 'urn:solid-server-app-setup:default:CliResolver', {});
+ expect(manager.instantiate)
+ .toHaveBeenNthCalledWith(2, 'urn:solid-server:default:App', { variables: {}});
+ expect(shorthandResolver.handleSafe).toHaveBeenCalledTimes(1);
+ expect(shorthandResolver.handleSafe).toHaveBeenLastCalledWith({});
+ expect(cliExtractor.handleSafe).toHaveBeenCalledTimes(0);
+ expect(app.start).toHaveBeenCalledTimes(0);
+ expect(app.clusterManager.isSingleThreaded()).toBeFalsy();
+ });
+
it('throws an error if threading issues are detected with 1 class.', async(): Promise => {
listSingleThreadedComponentsMock.mockImplementationOnce((): string[] => [ 'ViolatingClass' ]);
const variables = {
@@ -344,6 +368,7 @@ describe('AppRunner', (): void => {
logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false,
+ dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register)
@@ -375,6 +400,7 @@ describe('AppRunner', (): void => {
logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false,
+ dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(2);
expect(manager.configRegistry.register).toHaveBeenNthCalledWith(1, '/var/cwd/config1.json');
@@ -419,6 +445,7 @@ describe('AppRunner', (): void => {
logLevel: 'debug',
mainModulePath: '/var/cwd/module/path',
typeChecking: false,
+ dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register).toHaveBeenCalledWith('/var/cwd/myconfig.json');
@@ -569,6 +596,7 @@ describe('AppRunner', (): void => {
logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false,
+ dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register)
@@ -600,6 +628,7 @@ describe('AppRunner', (): void => {
logLevel: 'debug',
mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false,
+ dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register)
@@ -760,6 +789,7 @@ describe('AppRunner', (): void => {
logLevel: 'info',
mainModulePath: joinFilePath(__dirname, '../../../'),
typeChecking: false,
+ dumpErrorState: false,
});
expect(manager.configRegistry.register).toHaveBeenCalledTimes(1);
expect(manager.configRegistry.register)