mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
Merge branch 'main' into versions/6.0.0
This commit is contained in:
34
src/authorization/permissions/CreateModesExtractor.ts
Normal file
34
src/authorization/permissions/CreateModesExtractor.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Operation } from '../../http/Operation';
|
||||
import type { ResourceSet } from '../../storage/ResourceSet';
|
||||
import { ModesExtractor } from './ModesExtractor';
|
||||
import type { AccessMap } from './Permissions';
|
||||
import { AccessMode } from './Permissions';
|
||||
|
||||
/**
|
||||
* Adds the `create` access mode to the result of the source in case the target resource does not exist.
|
||||
*/
|
||||
export class CreateModesExtractor extends ModesExtractor {
|
||||
private readonly source: ModesExtractor;
|
||||
private readonly resourceSet: ResourceSet;
|
||||
|
||||
public constructor(source: ModesExtractor, resourceSet: ResourceSet) {
|
||||
super();
|
||||
this.source = source;
|
||||
this.resourceSet = resourceSet;
|
||||
}
|
||||
|
||||
public async canHandle(operation: Operation): Promise<void> {
|
||||
await this.source.canHandle(operation);
|
||||
}
|
||||
|
||||
public async handle(operation: Operation): Promise<AccessMap> {
|
||||
const accessMap = await this.source.handle(operation);
|
||||
|
||||
if (!accessMap.hasEntry(operation.target, AccessMode.create) &&
|
||||
!await this.resourceSet.hasResource(operation.target)) {
|
||||
accessMap.add(operation.target, AccessMode.create);
|
||||
}
|
||||
|
||||
return accessMap;
|
||||
}
|
||||
}
|
||||
44
src/authorization/permissions/DeleteParentExtractor.ts
Normal file
44
src/authorization/permissions/DeleteParentExtractor.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { Operation } from '../../http/Operation';
|
||||
import type { ResourceSet } from '../../storage/ResourceSet';
|
||||
import type { IdentifierStrategy } from '../../util/identifiers/IdentifierStrategy';
|
||||
import { ModesExtractor } from './ModesExtractor';
|
||||
import type { AccessMap } from './Permissions';
|
||||
import { AccessMode } from './Permissions';
|
||||
|
||||
/**
|
||||
* In case a resource is being deleted but does not exist,
|
||||
* the server response code depends on the access modes the agent has on the parent container.
|
||||
* In case the agent has read access on the parent container, a 404 should be returned,
|
||||
* otherwise it should be 401/403.
|
||||
*
|
||||
* This class adds support for this by requiring read access on the parent container
|
||||
* in case the target resource does not exist.
|
||||
*/
|
||||
export class DeleteParentExtractor extends ModesExtractor {
|
||||
private readonly source: ModesExtractor;
|
||||
private readonly resourceSet: ResourceSet;
|
||||
private readonly identifierStrategy: IdentifierStrategy;
|
||||
|
||||
public constructor(source: ModesExtractor, resourceSet: ResourceSet, identifierStrategy: IdentifierStrategy) {
|
||||
super();
|
||||
this.source = source;
|
||||
this.resourceSet = resourceSet;
|
||||
this.identifierStrategy = identifierStrategy;
|
||||
}
|
||||
|
||||
public async canHandle(operation: Operation): Promise<void> {
|
||||
await this.source.canHandle(operation);
|
||||
}
|
||||
|
||||
public async handle(operation: Operation): Promise<AccessMap> {
|
||||
const accessMap = await this.source.handle(operation);
|
||||
const { target } = operation;
|
||||
if (accessMap.get(target)?.has(AccessMode.delete) &&
|
||||
!this.identifierStrategy.isRootContainer(target) &&
|
||||
!await this.resourceSet.hasResource(target)) {
|
||||
const parent = this.identifierStrategy.getParentContainer(target);
|
||||
accessMap.add(parent, new Set([ AccessMode.read ]));
|
||||
}
|
||||
return accessMap;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user