mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
Merge branch 'main' into versions/5.0.0
This commit is contained in:
@@ -18,6 +18,13 @@ export class OidcHttpHandler extends HttpHandler {
|
||||
|
||||
public async handle({ request, response }: HttpHandlerInput): Promise<void> {
|
||||
const provider = await this.providerFactory.getProvider();
|
||||
|
||||
// Rewrite requests to allow hosting on root paths
|
||||
const path = new URL(provider.issuer).pathname;
|
||||
if (path.length > 1 && request.url!.startsWith(`${path}.well-known/openid-configuration`)) {
|
||||
request.url = request.url!.replace(path, '/');
|
||||
}
|
||||
|
||||
this.logger.debug(`Sending request to oidc-provider: ${request.url}`);
|
||||
// Even though the typings do not indicate this, this is a Promise that needs to be awaited.
|
||||
// Otherwise, the `BaseHttpServerFactory` will write a 404 before the OIDC library could handle the response.
|
||||
|
||||
@@ -51,9 +51,10 @@ export class WebIdAdapter extends PassthroughAdapter {
|
||||
let json: any | undefined;
|
||||
try {
|
||||
json = JSON.parse(data);
|
||||
const contexts = Array.isArray(json['@context']) ? json['@context'] : [ json['@context'] ];
|
||||
// We can only parse as simple JSON if the @context is correct
|
||||
if (json['@context'] !== 'https://www.w3.org/ns/solid/oidc-context.jsonld') {
|
||||
throw new Error('Invalid context');
|
||||
if (!contexts.includes('https://www.w3.org/ns/solid/oidc-context.jsonld')) {
|
||||
throw new Error('Missing context https://www.w3.org/ns/solid/oidc-context.jsonld');
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
json = undefined;
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { createHash } from 'crypto';
|
||||
import { parse } from 'path';
|
||||
import { BasicRepresentation } from '../../http/representation/BasicRepresentation';
|
||||
import type { Representation } from '../../http/representation/Representation';
|
||||
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
|
||||
import { NotFoundHttpError } from '../../util/errors/NotFoundHttpError';
|
||||
import { ensureLeadingSlash, ensureTrailingSlash, isContainerIdentifier, joinUrl } from '../../util/PathUtil';
|
||||
import { ensureLeadingSlash, ensureTrailingSlash, isContainerIdentifier, joinUrl,
|
||||
joinFilePath } from '../../util/PathUtil';
|
||||
import { readableToString } from '../../util/StreamUtil';
|
||||
import { LDP } from '../../util/Vocabularies';
|
||||
import type { ResourceStore } from '../ResourceStore';
|
||||
import type { KeyValueStorage } from './KeyValueStorage';
|
||||
|
||||
// Maximum allowed length for the keys, longer keys will be hashed.
|
||||
const KEY_LENGTH_LIMIT = 255;
|
||||
|
||||
/**
|
||||
* A {@link KeyValueStorage} for JSON-like objects using a {@link ResourceStore} as backend.
|
||||
*
|
||||
@@ -114,6 +120,15 @@ export class JsonResourceStorage<T> implements KeyValueStorage<string, T> {
|
||||
* Converts a key into an identifier for internal storage.
|
||||
*/
|
||||
private keyToIdentifier(key: string): ResourceIdentifier {
|
||||
// Parse the key as a file path
|
||||
const parsedPath = parse(key);
|
||||
// Hash long filenames to prevent issues with the underlying storage.
|
||||
// E.g. a UNIX a file name cannot exceed 255 bytes.
|
||||
// This is a temporary fix for https://github.com/CommunitySolidServer/CommunitySolidServer/issues/1013,
|
||||
// until we have a solution for data migration.
|
||||
if (parsedPath.base.length > KEY_LENGTH_LIMIT) {
|
||||
key = joinFilePath(parsedPath.dir, this.applyHash(parsedPath.base));
|
||||
}
|
||||
return { path: joinUrl(this.container, key) };
|
||||
}
|
||||
|
||||
@@ -127,4 +142,8 @@ export class JsonResourceStorage<T> implements KeyValueStorage<string, T> {
|
||||
// on the `entries` results matching a key that was sent before.
|
||||
return ensureLeadingSlash(identifier.path.slice(this.container.length));
|
||||
}
|
||||
|
||||
private applyHash(key: string): string {
|
||||
return createHash('sha256').update(key).digest('hex');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { getLoggerFor } from '../logging/LogUtil';
|
||||
import type { RepresentationConverter } from '../storage/conversion/RepresentationConverter';
|
||||
import { INTERNAL_QUADS } from './ContentTypes';
|
||||
import { BadRequestHttpError } from './errors/BadRequestHttpError';
|
||||
import { createErrorMessage } from './errors/ErrorUtil';
|
||||
|
||||
const logger = getLoggerFor('FetchUtil');
|
||||
|
||||
@@ -23,8 +24,8 @@ export async function fetchDataset(url: string): Promise<Representation> {
|
||||
const quadStream = (await rdfDereferencer.dereference(url)).data;
|
||||
const quadArray = await arrayifyStream<Quad>(quadStream);
|
||||
return new BasicRepresentation(quadArray, { path: url }, INTERNAL_QUADS, false);
|
||||
} catch {
|
||||
throw new BadRequestHttpError(`Could not parse resource at URL (${url})!`);
|
||||
} catch (error: unknown) {
|
||||
throw new BadRequestHttpError(`Could not parse resource at URL (${url})! ${createErrorMessage(error)}`);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user