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)