Merge branch 'main' into versions/2.0.0

This commit is contained in:
Joachim Van Herwegen
2021-09-03 10:09:03 +02:00
8 changed files with 122 additions and 34 deletions

View File

@@ -1,6 +1,20 @@
# Changelog
All notable changes to this project will be documented in this file.
<a name="v1.1.0"></a>
## [v1.1.0](https://github.com/solid/community-server/compare/v1.0.0...v1.1.0) - 2021-09-03
## Added
* [feat: Throw error when trying to complete interaction out of session](https://github.com/solid/community-server/commit/cb227d6431e8fe891752c7a52d216a0877f9d38e)
* [feat: Indicate to templates if this is part of an auth request](https://github.com/solid/community-server/commit/f71f8683fc0f4e40de2e1c64547397f32c0b6472)
* [feat: Allow filtering in ConstantConverter based on type](https://github.com/solid/community-server/commit/ab06dd30f3f8b0538b693fe50dd3d1f70c035b25)
## Fixed
* [fix: Allow clients to be remembered in the SessionHttpHandler](https://github.com/solid/community-server/commit/47b3a2d77f4a5b3fa5bab364ac19dc32d79a89c1)
* [fix: Convert data to SparqlDataAccessor in regex config](https://github.com/solid/community-server/commit/f34e124e1b88c59b4e456b3f69d9373e61550bd1)
* [fix(deps): update dependency @solid/access-token-verifier to ^0.12.0](https://github.com/solid/community-server/commit/7928f43f443f914c7850a968912f19a78212d266)
<a name="v1.0.0"></a>
## [v1.0.0](https://github.com/solid/community-server/compare/v1.0.0-beta.2...v1.0.0) - 2021-08-04

View File

@@ -71,6 +71,8 @@ npm start -- # add parameters if needed
### 📦 Running via Docker
Docker allows you to run the server without having Node.js installed:
```shell
git clone https://github.com/solid/community-server.git
cd community-server
# Build the Docker image
docker build --rm -f Dockerfile -t css:latest .
# Run the image, serving your `~/Solid` directory on `http://localhost:3000`

8
RELEASE_NOTES.md Normal file
View File

@@ -0,0 +1,8 @@
# Community Solid Server release notes
## v1.1.0
New features:
- The `ConstantConverter` can now filter on media type using the `enabledMediaRanges` and `disabledMediaRanges` options. That way, the server can be configured to bypass a default UI when accessing images or PDF documents. (https://github.com/solid/community-server/discussions/895, https://github.com/solid/community-server/pull/925)
## v1.0.0
First release of the Community Solid Server.

View File

@@ -56,11 +56,17 @@
"accessor": { "@id": "urn:solid-server:default:MemoryDataAccessor" }
},
{
"comment": "SparqlDataAccessor only accepts quad objects so data to that route needs to be converted",
"@id": "urn:solid-server:default:SparqlResourceStore",
"@type": "DataAccessorBasedStore",
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:SparqlDataAccessor" }
"@type": "RepresentationConvertingStore",
"options_inConverter": { "@id": "urn:solid-server:default:RepresentationConverter" },
"options_inType": "internal/quads",
"source": {
"@type": "DataAccessorBasedStore",
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:SparqlDataAccessor" }
}
}
]
}

66
package-lock.json generated
View File

@@ -1,24 +1,24 @@
{
"name": "@solid/community-server",
"version": "1.0.0",
"version": "1.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@solid/community-server",
"version": "1.0.0",
"version": "1.1.0",
"license": "MIT",
"dependencies": {
"@comunica/actor-init-sparql": "^1.21.3",
"@rdfjs/data-model": "^1.2.0",
"@solid/access-token-verifier": "^0.11.0",
"@solid/access-token-verifier": "^0.12.0",
"@types/arrayify-stream": "^1.0.0",
"@types/async-lock": "^1.1.2",
"@types/bcrypt": "^5.0.0",
"@types/cors": "^2.8.10",
"@types/end-of-stream": "^1.4.0",
"@types/lodash.orderby": "^4.6.6",
"@types/marked": "^2.0.3",
"@types/marked": "^3.0.0",
"@types/mime-types": "^2.1.0",
"@types/n3": "^1.10.0",
"@types/node": "^15.12.5",
@@ -45,7 +45,7 @@
"handlebars": "^4.7.7",
"jose": "^3.11.6",
"lodash.orderby": "^4.6.0",
"marked": "^2.1.3",
"marked": "^3.0.0",
"mime-types": "^2.1.32",
"n3": "^1.10.0",
"nodemailer": "^6.6.2",
@@ -4562,9 +4562,9 @@
}
},
"node_modules/@solid/access-token-verifier": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-0.11.0.tgz",
"integrity": "sha512-L5XG5qk77FfgfM9uGL16qe08MWt0u5IHz7NsmXEZy8P260RRyt99a2b+nJyb1siXsNC1Z25CtOn1OrPa4Mqjng==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-0.12.0.tgz",
"integrity": "sha512-Lx6bZv8JNSGDklx1vE2wFd2YzCM8GwZQaUSEFHb7Bl3zJqfaC8GabwUub+AmzZsGhwQZmcww3ipaIBhE1Oh0oA==",
"dependencies": {
"cross-fetch": "^3.1.4",
"jose": "^3.14.3",
@@ -4927,9 +4927,9 @@
"integrity": "sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w=="
},
"node_modules/@types/marked": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.3.tgz",
"integrity": "sha512-lbhSN1rht/tQ+dSWxawCzGgTfxe9DB31iLgiT1ZVT5lshpam/nyOA1m3tKHRoNPctB2ukSL22JZI5Fr+WI/zYg=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-3.0.0.tgz",
"integrity": "sha512-vof90OIWT+Tzq3MBRXgV9fsH8PC3WZ4OQg9Qa04vOtP0TcyiNfl7BTonYCmTapHZ5lRZh6ihUYkAy7St1hmk/A=="
},
"node_modules/@types/mime": {
"version": "1.3.2",
@@ -11805,14 +11805,14 @@
}
},
"node_modules/marked": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-3.0.1.tgz",
"integrity": "sha512-GQtec2MkSCp+ZecV2jBe7+J2fiDXeBFKUBr4981srZDjCaXg0WrtTo9eY2CVc2ZC5YQXkkc0Q8sTZ6c1DB1o2Q==",
"bin": {
"marked": "bin/marked"
},
"engines": {
"node": ">= 10"
"node": ">= 12"
}
},
"node_modules/media-typer": {
@@ -15391,6 +15391,18 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/typedoc/node_modules/marked": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==",
"dev": true,
"bin": {
"marked": "bin/marked"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/typescript": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz",
@@ -19580,9 +19592,9 @@
}
},
"@solid/access-token-verifier": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-0.11.0.tgz",
"integrity": "sha512-L5XG5qk77FfgfM9uGL16qe08MWt0u5IHz7NsmXEZy8P260RRyt99a2b+nJyb1siXsNC1Z25CtOn1OrPa4Mqjng==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@solid/access-token-verifier/-/access-token-verifier-0.12.0.tgz",
"integrity": "sha512-Lx6bZv8JNSGDklx1vE2wFd2YzCM8GwZQaUSEFHb7Bl3zJqfaC8GabwUub+AmzZsGhwQZmcww3ipaIBhE1Oh0oA==",
"requires": {
"cross-fetch": "^3.1.4",
"jose": "^3.14.3",
@@ -19939,9 +19951,9 @@
"integrity": "sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w=="
},
"@types/marked": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.3.tgz",
"integrity": "sha512-lbhSN1rht/tQ+dSWxawCzGgTfxe9DB31iLgiT1ZVT5lshpam/nyOA1m3tKHRoNPctB2ukSL22JZI5Fr+WI/zYg=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-3.0.0.tgz",
"integrity": "sha512-vof90OIWT+Tzq3MBRXgV9fsH8PC3WZ4OQg9Qa04vOtP0TcyiNfl7BTonYCmTapHZ5lRZh6ihUYkAy7St1hmk/A=="
},
"@types/mime": {
"version": "1.3.2",
@@ -25212,9 +25224,9 @@
"dev": true
},
"marked": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-3.0.1.tgz",
"integrity": "sha512-GQtec2MkSCp+ZecV2jBe7+J2fiDXeBFKUBr4981srZDjCaXg0WrtTo9eY2CVc2ZC5YQXkkc0Q8sTZ6c1DB1o2Q=="
},
"media-typer": {
"version": "0.3.0",
@@ -28001,6 +28013,12 @@
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"marked": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==",
"dev": true
}
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "@solid/community-server",
"version": "1.0.0",
"version": "1.1.0",
"description": "Community Solid Server: an open and modular implementation of the Solid specifications",
"keywords": [
"solid",
@@ -77,14 +77,14 @@
"dependencies": {
"@comunica/actor-init-sparql": "^1.21.3",
"@rdfjs/data-model": "^1.2.0",
"@solid/access-token-verifier": "^0.11.0",
"@solid/access-token-verifier": "^0.12.0",
"@types/arrayify-stream": "^1.0.0",
"@types/async-lock": "^1.1.2",
"@types/bcrypt": "^5.0.0",
"@types/cors": "^2.8.10",
"@types/end-of-stream": "^1.4.0",
"@types/lodash.orderby": "^4.6.6",
"@types/marked": "^2.0.3",
"@types/marked": "^3.0.0",
"@types/mime-types": "^2.1.0",
"@types/n3": "^1.10.0",
"@types/node": "^15.12.5",
@@ -111,7 +111,7 @@
"handlebars": "^4.7.7",
"jose": "^3.11.6",
"lodash.orderby": "^4.6.0",
"marked": "^2.1.3",
"marked": "^3.0.0",
"mime-types": "^2.1.32",
"n3": "^1.10.0",
"nodemailer": "^6.6.2",

View File

@@ -23,6 +23,14 @@ export interface ConstantConverterOptions {
* The minimum requested quality/preference before this should trigger.
*/
minQuality?: number;
/**
* Media ranges for which the conversion should happen.
*/
enabledMediaRanges?: string[];
/**
* Media ranges for which the conversion should not happen.
*/
disabledMediaRanges?: string[];
}
/**
@@ -57,6 +65,8 @@ export class ConstantConverter extends RepresentationConverter {
container: options.container ?? true,
document: options.document ?? true,
minQuality: options.minQuality ?? 0,
enabledMediaRanges: options.enabledMediaRanges ?? [ '*/*' ],
disabledMediaRanges: options.disabledMediaRanges ?? [],
};
}
@@ -83,10 +93,19 @@ export class ConstantConverter extends RepresentationConverter {
throw new NotImplementedHttpError(`Preference is lower than the specified minimum quality`);
}
const sourceContentType = representation.metadata.contentType ?? '';
// Do not replace the representation if it already has our content type
if (matchesMediaType(representation.metadata.contentType ?? '', this.contentType)) {
if (matchesMediaType(sourceContentType, this.contentType)) {
throw new NotImplementedHttpError(`Representation is already ${this.contentType}`);
}
// Only replace the representation if it matches the media range settings
if (!this.options.enabledMediaRanges.some((type): boolean => matchesMediaType(sourceContentType, type))) {
throw new NotImplementedHttpError(`${sourceContentType} is not one of the enabled media types.`);
}
if (this.options.disabledMediaRanges.some((type): boolean => matchesMediaType(sourceContentType, type))) {
throw new NotImplementedHttpError(`${sourceContentType} is one of the disabled media types.`);
}
}
public async handle({ representation }: RepresentationConverterArgs): Promise<Representation> {

View File

@@ -3,6 +3,7 @@ import arrayifyStream from 'arrayify-stream';
import { RepresentationMetadata } from '../../../../src/ldp/representation/RepresentationMetadata';
import type { ConstantConverterOptions } from '../../../../src/storage/conversion/ConstantConverter';
import { ConstantConverter } from '../../../../src/storage/conversion/ConstantConverter';
import { CONTENT_TYPE } from '../../../../src/util/Vocabularies';
const createReadStream = jest.spyOn(fs, 'createReadStream').mockReturnValue('file contents' as any);
@@ -12,7 +13,7 @@ describe('A ConstantConverter', (): void => {
let converter: ConstantConverter;
beforeEach(async(): Promise<void> => {
options = { container: true, document: true, minQuality: 1 };
options = { container: true, document: true, minQuality: 1, enabledMediaRanges: [ '*/*' ], disabledMediaRanges: []};
converter = new ConstantConverter('abc/def/index.html', 'text/html', options);
});
@@ -69,6 +70,26 @@ describe('A ConstantConverter', (): void => {
await expect(converter.canHandle(args)).rejects.toThrow('Representation is already text/html');
});
it('does not support representations if their content-type is not enabled.', async(): Promise<void> => {
const preferences = { type: { 'text/html': 1 }};
const representation = { metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/plain' }) } as any;
const args = { identifier: { path: 'container/' }, representation, preferences };
converter = new ConstantConverter('abc/def/index.html', 'text/html', { enabledMediaRanges: [ 'text/turtle' ]});
await expect(converter.canHandle(args)).rejects.toThrow('text/plain is not one of the enabled media types.');
});
it('does not support representations if their content-type is disabled.', async(): Promise<void> => {
const preferences = { type: { 'text/html': 1 }};
const representation = { metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/plain' }) } as any;
const args = { identifier: { path: 'container/' }, representation, preferences };
converter = new ConstantConverter('abc/def/index.html', 'text/html', { disabledMediaRanges: [ 'text/*' ]});
await expect(converter.canHandle(args)).rejects.toThrow('text/plain is one of the disabled media types.');
});
it('supports representations with an unknown content type.', async(): Promise<void> => {
const preferences = { type: { 'text/html': 1 }};
const metadata = new RepresentationMetadata();