mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add index signature to Credentials
* feat: abstract Credentials type for Authorizer * feat: abstract Credentials type in CredentialsExtractor & PermissionReader * chore: typegraphical corrections in documentation Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com> * fix: remove accidental .js extension * feat: also check for undefined credentials when deciding 401/404 * docs: corrections to code documentation Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com> * fix: revert abstraction & index signature to Credentials * chhore: fix linter issues --------- Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>
This commit is contained in:
parent
e7d8081aff
commit
86f45923ba
@ -5,4 +5,5 @@ export type Credentials = {
|
|||||||
agent?: { webId: string };
|
agent?: { webId: string };
|
||||||
client?: { clientId: string };
|
client?: { clientId: string };
|
||||||
issuer?: { url: string };
|
issuer?: { url: string };
|
||||||
|
[key: string]: unknown;
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,7 @@ export interface AuthorizerInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies if the credentials provide access with the given permissions on the resource.
|
* Verifies whether the credentials provide access with the given permissions on the resource.
|
||||||
* An {@link Error} with the necessary explanation will be thrown when permissions are not granted.
|
* An {@link Error} with the necessary explanation will be thrown if permissions are not granted.
|
||||||
*/
|
*/
|
||||||
export abstract class Authorizer extends AsyncHandler<AuthorizerInput> {}
|
export abstract class Authorizer extends AsyncHandler<AuthorizerInput> {}
|
||||||
|
@ -13,7 +13,7 @@ import { AccessMode } from './permissions/Permissions';
|
|||||||
/**
|
/**
|
||||||
* Authorizer that bases its decision on the output it gets from its PermissionReader.
|
* Authorizer that bases its decision on the output it gets from its PermissionReader.
|
||||||
* For each permission it checks if the reader allows that for at least one credential type,
|
* For each permission it checks if the reader allows that for at least one credential type,
|
||||||
* if yes authorization is granted.
|
* if yes, authorization is granted.
|
||||||
* `undefined` values for reader results are interpreted as `false`.
|
* `undefined` values for reader results are interpreted as `false`.
|
||||||
*/
|
*/
|
||||||
export class PermissionBasedAuthorizer extends Authorizer {
|
export class PermissionBasedAuthorizer extends Authorizer {
|
||||||
@ -37,7 +37,9 @@ export class PermissionBasedAuthorizer extends Authorizer {
|
|||||||
// Ensure all required modes are within the agent's permissions.
|
// Ensure all required modes are within the agent's permissions.
|
||||||
for (const [ identifier, modes ] of requestedModes.entrySets()) {
|
for (const [ identifier, modes ] of requestedModes.entrySets()) {
|
||||||
const modeString = [ ...modes ].join(',');
|
const modeString = [ ...modes ].join(',');
|
||||||
this.logger.debug(`Checking if ${credentials.agent?.webId} has ${modeString} permissions for ${identifier.path}`);
|
this.logger.debug(
|
||||||
|
`Checking if ${JSON.stringify(credentials)} has ${modeString} permissions for ${identifier.path}`,
|
||||||
|
);
|
||||||
const permissionSet = availablePermissions.get(identifier) ?? {};
|
const permissionSet = availablePermissions.get(identifier) ?? {};
|
||||||
for (const mode of modes) {
|
for (const mode of modes) {
|
||||||
try {
|
try {
|
||||||
@ -82,7 +84,7 @@ export class PermissionBasedAuthorizer extends Authorizer {
|
|||||||
private requireModePermission(credentials: Credentials, permissionSet: PermissionSet, mode: AccessMode): void {
|
private requireModePermission(credentials: Credentials, permissionSet: PermissionSet, mode: AccessMode): void {
|
||||||
if (!permissionSet[mode]) {
|
if (!permissionSet[mode]) {
|
||||||
if (this.isAuthenticated(credentials)) {
|
if (this.isAuthenticated(credentials)) {
|
||||||
this.logger.warn(`Agent ${credentials.agent!.webId} has no ${mode} permissions`);
|
this.logger.warn(`Agent ${JSON.stringify(credentials)} has no ${mode} permissions`);
|
||||||
throw new ForbiddenHttpError();
|
throw new ForbiddenHttpError();
|
||||||
} else {
|
} else {
|
||||||
// Solid, §2.1: "When a client does not provide valid credentials when requesting a resource that requires it,
|
// Solid, §2.1: "When a client does not provide valid credentials when requesting a resource that requires it,
|
||||||
@ -99,6 +101,6 @@ export class PermissionBasedAuthorizer extends Authorizer {
|
|||||||
* @param credentials - Credentials to check.
|
* @param credentials - Credentials to check.
|
||||||
*/
|
*/
|
||||||
private isAuthenticated(credentials: Credentials): boolean {
|
private isAuthenticated(credentials: Credentials): boolean {
|
||||||
return typeof credentials.agent?.webId === 'string';
|
return Object.values(credentials).some((cred): boolean => cred !== undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ export interface PermissionReaderInput {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Discovers the permissions of the given credentials on the given identifier.
|
* Discovers the permissions of the given credentials on the given identifier.
|
||||||
* In case the reader finds no permission for the requested identifiers and credentials
|
* If the reader finds no permission for the requested identifiers and credentials,
|
||||||
* it can return an empty or incomplete map.
|
* it can return an empty or incomplete map.
|
||||||
*/
|
*/
|
||||||
export abstract class PermissionReader extends AsyncHandler<PermissionReaderInput, PermissionMap> {}
|
export abstract class PermissionReader extends AsyncHandler<PermissionReaderInput, PermissionMap> {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user