mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
refactor: Restructure source code folder
This way the location of certain classes should make more sense
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import type { CredentialGroup } from '../authentication/Credentials';
|
||||
import type { Permission, PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import type { PermissionReaderInput } from './PermissionReader';
|
||||
import { PermissionReader } from './PermissionReader';
|
||||
import type { Permission, PermissionSet } from './permissions/Permissions';
|
||||
|
||||
/**
|
||||
* PermissionReader which sets all permissions to true or false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CredentialSet } from '../authentication/Credentials';
|
||||
import type { AccessMode, PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
|
||||
import type { ResourceIdentifier } from '../http/representation/ResourceIdentifier';
|
||||
import { AsyncHandler } from '../util/handlers/AsyncHandler';
|
||||
import type { AccessMode, PermissionSet } from './permissions/Permissions';
|
||||
|
||||
export interface AuthorizerInput {
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { AuxiliaryStrategy } from '../ldp/auxiliary/AuxiliaryStrategy';
|
||||
import type { PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import type { AuxiliaryStrategy } from '../http/auxiliary/AuxiliaryStrategy';
|
||||
import { getLoggerFor } from '../logging/LogUtil';
|
||||
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
|
||||
|
||||
import type { PermissionReaderInput } from './PermissionReader';
|
||||
import { PermissionReader } from './PermissionReader';
|
||||
import type { PermissionSet } from './permissions/Permissions';
|
||||
|
||||
/**
|
||||
* A PermissionReader for auxiliary resources such as acl or shape resources.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { CredentialGroup } from '../authentication/Credentials';
|
||||
import type { AuxiliaryIdentifierStrategy } from '../http/auxiliary/AuxiliaryIdentifierStrategy';
|
||||
import type { AccountSettings, AccountStore } from '../identity/interaction/email-password/storage/AccountStore';
|
||||
import type { AuxiliaryIdentifierStrategy } from '../ldp/auxiliary/AuxiliaryIdentifierStrategy';
|
||||
import type { AclPermission } from '../ldp/permissions/AclPermission';
|
||||
import type { PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import { getLoggerFor } from '../logging/LogUtil';
|
||||
import { createErrorMessage } from '../util/errors/ErrorUtil';
|
||||
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
|
||||
import type { PermissionReaderInput } from './PermissionReader';
|
||||
import { PermissionReader } from './PermissionReader';
|
||||
import type { AclPermission } from './permissions/AclPermission';
|
||||
import type { PermissionSet } from './permissions/Permissions';
|
||||
|
||||
/**
|
||||
* Allows control access if the request is being made by the owner of the pod containing the resource.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
|
||||
import { ensureTrailingSlash, trimTrailingSlashes } from '../util/PathUtil';
|
||||
|
||||
import type { PermissionReaderInput } from './PermissionReader';
|
||||
import { PermissionReader } from './PermissionReader';
|
||||
import type { PermissionSet } from './permissions/Permissions';
|
||||
|
||||
/**
|
||||
* Redirects requests to specific PermissionReaders based on their identifier.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { CredentialSet } from '../authentication/Credentials';
|
||||
import type { AccessMode, PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import { getLoggerFor } from '../logging/LogUtil';
|
||||
import { ForbiddenHttpError } from '../util/errors/ForbiddenHttpError';
|
||||
import { UnauthorizedHttpError } from '../util/errors/UnauthorizedHttpError';
|
||||
import type { AuthorizerInput } from './Authorizer';
|
||||
import { Authorizer } from './Authorizer';
|
||||
import type { AccessMode, PermissionSet } from './permissions/Permissions';
|
||||
|
||||
/**
|
||||
* Authorizer that bases its decision on the output it gets from its PermissionReader.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CredentialSet } from '../authentication/Credentials';
|
||||
import type { PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
|
||||
import type { ResourceIdentifier } from '../http/representation/ResourceIdentifier';
|
||||
import { AsyncHandler } from '../util/handlers/AsyncHandler';
|
||||
import type { PermissionSet } from './permissions/Permissions';
|
||||
|
||||
export interface PermissionReaderInput {
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CredentialGroup } from '../authentication/Credentials';
|
||||
import type { Permission, PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import { UnionHandler } from '../util/handlers/UnionHandler';
|
||||
import type { PermissionReader } from './PermissionReader';
|
||||
import type { Permission, PermissionSet } from './permissions/Permissions';
|
||||
|
||||
/**
|
||||
* Combines the results of multiple PermissionReaders.
|
||||
|
||||
@@ -2,13 +2,9 @@ import type { Quad, Term } from 'n3';
|
||||
import { Store } from 'n3';
|
||||
import { CredentialGroup } from '../authentication/Credentials';
|
||||
import type { Credential, CredentialSet } from '../authentication/Credentials';
|
||||
import type { AuxiliaryIdentifierStrategy } from '../ldp/auxiliary/AuxiliaryIdentifierStrategy';
|
||||
import { AclMode } from '../ldp/permissions/AclPermission';
|
||||
import type { AclPermission } from '../ldp/permissions/AclPermission';
|
||||
import type { PermissionSet } from '../ldp/permissions/Permissions';
|
||||
import { AccessMode } from '../ldp/permissions/Permissions';
|
||||
import type { Representation } from '../ldp/representation/Representation';
|
||||
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
|
||||
import type { AuxiliaryIdentifierStrategy } from '../http/auxiliary/AuxiliaryIdentifierStrategy';
|
||||
import type { Representation } from '../http/representation/Representation';
|
||||
import type { ResourceIdentifier } from '../http/representation/ResourceIdentifier';
|
||||
import { getLoggerFor } from '../logging/LogUtil';
|
||||
import type { ResourceStore } from '../storage/ResourceStore';
|
||||
import { INTERNAL_QUADS } from '../util/ContentTypes';
|
||||
@@ -19,9 +15,13 @@ import { NotFoundHttpError } from '../util/errors/NotFoundHttpError';
|
||||
import type { IdentifierStrategy } from '../util/identifiers/IdentifierStrategy';
|
||||
import { readableToQuads } from '../util/StreamUtil';
|
||||
import { ACL, RDF } from '../util/Vocabularies';
|
||||
import type { AccessChecker } from './access-checkers/AccessChecker';
|
||||
import type { AccessChecker } from './access/AccessChecker';
|
||||
import type { PermissionReaderInput } from './PermissionReader';
|
||||
import { PermissionReader } from './PermissionReader';
|
||||
import type { AclPermission } from './permissions/AclPermission';
|
||||
import { AclMode } from './permissions/AclPermission';
|
||||
import { AccessMode } from './permissions/Permissions';
|
||||
import type { PermissionSet } from './permissions/Permissions';
|
||||
|
||||
const modesMap: Record<string, keyof AclPermission> = {
|
||||
[ACL.Read]: AccessMode.read,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { Store, Term } from 'n3';
|
||||
|
||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
|
||||
import type { RepresentationConverter } from '../../storage/conversion/RepresentationConverter';
|
||||
import type { ExpiringStorage } from '../../storage/keyvalue/ExpiringStorage';
|
||||
import { fetchDataset } from '../../util/FetchUtil';
|
||||
10
src/authorization/permissions/AclPermission.ts
Normal file
10
src/authorization/permissions/AclPermission.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { Permission } from './Permissions';
|
||||
|
||||
export enum AclMode {
|
||||
control = 'control',
|
||||
}
|
||||
|
||||
// Adds a control field to the permissions to specify this WAC-specific value
|
||||
export type AclPermission = Permission & {
|
||||
[mode in AclMode]?: boolean;
|
||||
};
|
||||
37
src/authorization/permissions/MethodModesExtractor.ts
Normal file
37
src/authorization/permissions/MethodModesExtractor.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import type { Operation } from '../../http/Operation';
|
||||
import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError';
|
||||
import { ModesExtractor } from './ModesExtractor';
|
||||
import { AccessMode } from './Permissions';
|
||||
|
||||
const READ_METHODS = new Set([ 'GET', 'HEAD' ]);
|
||||
const WRITE_METHODS = new Set([ 'PUT', 'DELETE' ]);
|
||||
const APPEND_METHODS = new Set([ 'POST' ]);
|
||||
const SUPPORTED_METHODS = new Set([ ...READ_METHODS, ...WRITE_METHODS, ...APPEND_METHODS ]);
|
||||
|
||||
/**
|
||||
* Generates permissions for the base set of methods that always require the same permissions.
|
||||
* Specifically: GET, HEAD, POST, PUT and DELETE.
|
||||
*/
|
||||
export class MethodModesExtractor extends ModesExtractor {
|
||||
public async canHandle({ method }: Operation): Promise<void> {
|
||||
if (!SUPPORTED_METHODS.has(method)) {
|
||||
throw new NotImplementedHttpError(`Cannot determine permissions of ${method}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async handle({ method }: Operation): Promise<Set<AccessMode>> {
|
||||
const result = new Set<AccessMode>();
|
||||
if (READ_METHODS.has(method)) {
|
||||
result.add(AccessMode.read);
|
||||
}
|
||||
if (WRITE_METHODS.has(method)) {
|
||||
result.add(AccessMode.write);
|
||||
result.add(AccessMode.append);
|
||||
result.add(AccessMode.create);
|
||||
result.add(AccessMode.delete);
|
||||
} else if (APPEND_METHODS.has(method)) {
|
||||
result.add(AccessMode.append);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
5
src/authorization/permissions/ModesExtractor.ts
Normal file
5
src/authorization/permissions/ModesExtractor.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { Operation } from '../../http/Operation';
|
||||
import { AsyncHandler } from '../../util/handlers/AsyncHandler';
|
||||
import type { AccessMode } from './Permissions';
|
||||
|
||||
export abstract class ModesExtractor extends AsyncHandler<Operation, Set<AccessMode>> {}
|
||||
19
src/authorization/permissions/Permissions.ts
Normal file
19
src/authorization/permissions/Permissions.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { CredentialGroup } from '../../authentication/Credentials';
|
||||
|
||||
/**
|
||||
* Different modes that require permission.
|
||||
*/
|
||||
export enum AccessMode {
|
||||
read = 'read',
|
||||
append = 'append',
|
||||
write = 'write',
|
||||
create = 'create',
|
||||
delete = 'delete',
|
||||
}
|
||||
|
||||
/**
|
||||
* A data interface indicating which permissions are required (based on the context).
|
||||
*/
|
||||
export type Permission = Partial<Record<AccessMode, boolean>>;
|
||||
|
||||
export type PermissionSet = Partial<Record<CredentialGroup, Permission>>;
|
||||
85
src/authorization/permissions/SparqlPatchModesExtractor.ts
Normal file
85
src/authorization/permissions/SparqlPatchModesExtractor.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { Algebra } from 'sparqlalgebrajs';
|
||||
import type { Operation } from '../../http/Operation';
|
||||
import type { Representation } from '../../http/representation/Representation';
|
||||
import type { SparqlUpdatePatch } from '../../http/representation/SparqlUpdatePatch';
|
||||
import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError';
|
||||
import { ModesExtractor } from './ModesExtractor';
|
||||
import { AccessMode } from './Permissions';
|
||||
|
||||
export class SparqlPatchModesExtractor extends ModesExtractor {
|
||||
public async canHandle({ method, body }: Operation): Promise<void> {
|
||||
if (method !== 'PATCH') {
|
||||
throw new NotImplementedHttpError(`Cannot determine permissions of ${method}, only PATCH.`);
|
||||
}
|
||||
if (!body) {
|
||||
throw new NotImplementedHttpError('Cannot determine permissions of PATCH operations without a body.');
|
||||
}
|
||||
if (!this.isSparql(body)) {
|
||||
throw new NotImplementedHttpError('Cannot determine permissions of non-SPARQL patches.');
|
||||
}
|
||||
if (!this.isSupported(body.algebra)) {
|
||||
throw new NotImplementedHttpError('Can only determine permissions of a PATCH with DELETE/INSERT operations.');
|
||||
}
|
||||
}
|
||||
|
||||
public async handle({ body }: Operation): Promise<Set<AccessMode>> {
|
||||
// Verified in `canHandle` call
|
||||
const update = (body as SparqlUpdatePatch).algebra as Algebra.DeleteInsert;
|
||||
const result = new Set<AccessMode>();
|
||||
|
||||
// Since `append` is a specific type of write, it is true if `write` is true.
|
||||
if (this.needsWrite(update)) {
|
||||
result.add(AccessMode.write);
|
||||
result.add(AccessMode.append);
|
||||
result.add(AccessMode.create);
|
||||
result.add(AccessMode.delete);
|
||||
} else if (this.needsAppend(update)) {
|
||||
result.add(AccessMode.append);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private isSparql(data: Representation): data is SparqlUpdatePatch {
|
||||
return Boolean((data as SparqlUpdatePatch).algebra);
|
||||
}
|
||||
|
||||
private isSupported(op: Algebra.Operation): boolean {
|
||||
if (this.isDeleteInsert(op) || this.isNop(op)) {
|
||||
return true;
|
||||
}
|
||||
if (op.type === Algebra.types.COMPOSITE_UPDATE) {
|
||||
return (op as Algebra.CompositeUpdate).updates.every((update): boolean => this.isSupported(update));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private isDeleteInsert(op: Algebra.Operation): op is Algebra.DeleteInsert {
|
||||
return op.type === Algebra.types.DELETE_INSERT;
|
||||
}
|
||||
|
||||
private isNop(op: Algebra.Operation): op is Algebra.Nop {
|
||||
return op.type === Algebra.types.NOP;
|
||||
}
|
||||
|
||||
private needsAppend(update: Algebra.Operation): boolean {
|
||||
if (this.isNop(update)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isDeleteInsert(update)) {
|
||||
return Boolean(update.insert && update.insert.length > 0);
|
||||
}
|
||||
|
||||
return (update as Algebra.CompositeUpdate).updates.some((op): boolean => this.needsAppend(op));
|
||||
}
|
||||
|
||||
private needsWrite(update: Algebra.Operation): boolean {
|
||||
if (this.isNop(update)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isDeleteInsert(update)) {
|
||||
return Boolean(update.delete && update.delete.length > 0);
|
||||
}
|
||||
|
||||
return (update as Algebra.CompositeUpdate).updates.some((op): boolean => this.needsWrite(op));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user