@chronark/access
Advanced tools
Comparing version 0.0.8 to 0.0.9
declare type SubArray<T extends unknown[]> = T[number][]; | ||
declare type Subset<K extends keyof R, R extends Record<string, string[]>> = { | ||
declare type Subset<K extends keyof R, R extends Record<string, unknown[]>> = { | ||
[P in K]: SubArray<R[P]>; | ||
}; | ||
declare type Statement = { | ||
action: string; | ||
}; | ||
declare type Statements = { | ||
[resource: string]: string[]; | ||
[resource: string]: Statement[]; | ||
}; | ||
@@ -13,3 +16,3 @@ | ||
} | ||
declare class AccessControl<TStatements extends Statements> { | ||
declare class AccessControl<TStatements extends Statements = Statements> { | ||
newRole<K extends keyof TStatements>( | ||
@@ -19,3 +22,3 @@ statements: Subset<K, TStatements>, | ||
} | ||
declare type VerifyResponse = { | ||
declare type AuthortizeResponse = { | ||
success: false; | ||
@@ -30,6 +33,3 @@ error: string; | ||
constructor(statements: TStatements); | ||
verify<TResource extends keyof TStatements>( | ||
resource: TResource, | ||
actions: SubArray<TStatements[TResource]>, | ||
): VerifyResponse; | ||
authorize(request: TStatements): AuthortizeResponse; | ||
static fromString<TStatements extends Statements = {}>( | ||
@@ -41,2 +41,2 @@ s: string, | ||
export { AccessControl, ParsingError, Role, Statements, VerifyResponse }; | ||
export { AccessControl, AuthortizeResponse, ParsingError, Role, Statements }; |
@@ -54,20 +54,40 @@ "use strict"; | ||
} | ||
verify(resource, actions) { | ||
for (const [r, as] of Object.entries(this.statements)) { | ||
if (resource === r) { | ||
for (const action of actions) { | ||
if (!(as == null ? void 0 : as.includes(action))) { | ||
return { | ||
success: false, | ||
error: | ||
`not authorized for action "${action}" on resource: "${r}"`, | ||
}; | ||
} | ||
authorize(request) { | ||
for ( | ||
const [requestedResource, requestedActions] of Object.entries(request) | ||
) { | ||
console.log( | ||
JSON.stringify( | ||
{ requestedResource, requestedActions, statements: this.statements }, | ||
null, | ||
2, | ||
), | ||
); | ||
const allowedActions = this.statements[requestedResource]; | ||
if (!allowedActions) { | ||
return { | ||
success: false, | ||
error: `You are not allowed to access resource: ${requestedResource}`, | ||
}; | ||
} | ||
console.log(JSON.stringify({ allowedActions }, null, 2)); | ||
const success = requestedActions.every((requestedAction) => { | ||
console.log(JSON.stringify({ requestedAction }, null, 2)); | ||
for (const allowedAction of allowedActions) { | ||
return allowedAction.action === requestedAction.action; | ||
} | ||
return { success: true }; | ||
return false; | ||
}); | ||
console.log({ success }); | ||
if (success) { | ||
return { success }; | ||
} | ||
return { | ||
success: false, | ||
error: `unauthorized to access resource "${requestedResource}"`, | ||
}; | ||
} | ||
return { | ||
success: false, | ||
error: `not authorized for resource "${resource.toString()}"`, | ||
error: `Not authorized`, | ||
}; | ||
@@ -74,0 +94,0 @@ } |
{ | ||
"name": "@chronark/access", | ||
"version": "0.0.8", | ||
"version": "0.0.9", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -73,3 +73,3 @@ <div align="center"> | ||
*/ | ||
const res = recovered.allow("team", ["read"]); | ||
const res = recovered.authorize({"team", ["read"]}); | ||
@@ -76,0 +76,0 @@ // res.success => boolean |
@@ -15,5 +15,8 @@ import assert from "node:assert"; | ||
const role = new Role({ | ||
"r1": ["a", "b"], | ||
"r1": [{ action: "a" }, { action: "b" }], | ||
}); | ||
assert.strictEqual(role.toString(), '{"r1":["a","b"]}'); | ||
assert.strictEqual( | ||
role.toString(), | ||
'{"r1":[{"action":"a"},{"action":"b"}]}', | ||
); | ||
}); | ||
@@ -38,17 +41,21 @@ }); | ||
describe("allow", () => { | ||
describe("authorize", () => { | ||
describe("without access", () => { | ||
it("denies the request", () => { | ||
const ac = new AccessControl<{ r: ["r", "w"] }>(); | ||
const role = ac.newRole({ r: ["r"] }); | ||
const { success, error } = role.allow("r", ["r", "w"]); | ||
const ac = new AccessControl<{ | ||
res1: [{ action: "r" }, { action: "w" }]; | ||
}>(); | ||
const role = ac.newRole({ res1: [{ action: "r" }] }); | ||
const { success, error } = role.authorize({ | ||
"res1": [{ action: "r" }, { action: "w" }], | ||
}); | ||
assert.equal(success, false); | ||
assert.equal(error, 'not authorized for action "w" on resource: "r"'); | ||
assert.equal(error, 'unauthorized to access resource "res1"'); | ||
}); | ||
}); | ||
describe("with access", () => { | ||
it("serializes correctly", () => { | ||
const ac = new AccessControl<{ r: ["r", "w"] }>(); | ||
const role = ac.newRole({ r: ["r"] }); | ||
const { success, error } = role.allow("r", ["r"]); | ||
it("allows the request", () => { | ||
const ac = new AccessControl<{ r: [{ action: "r" }, { action: "w" }] }>(); | ||
const role = ac.newRole({ r: [{ action: "r" }] }); | ||
const { success, error } = role.authorize({ "r": [{ action: "r" }] }); | ||
assert.equal(success, true); | ||
@@ -55,0 +62,0 @@ assert.equal(error, undefined); |
@@ -11,9 +11,3 @@ import type { Statements, SubArray, Subset } from "./types"; | ||
export class AccessControl<TStatements extends Statements> { | ||
// public readonly statements: TStatements | ||
// constructor(statements: TStatements) { | ||
// this.statements = statements | ||
// } | ||
export class AccessControl<TStatements extends Statements = Statements> { | ||
public newRole<K extends keyof TStatements>( | ||
@@ -26,3 +20,3 @@ statements: Subset<K, TStatements>, | ||
export type allowResponse = | ||
export type AuthortizeResponse = | ||
| { success: false; error: string } | ||
@@ -38,25 +32,45 @@ | { success: true; error?: never }; | ||
// public allow<TResource extends keyof TStatements>(req: { resource: TResource, actions: TStatements[TResource] }): allowResponse { | ||
public allow<TResource extends keyof TStatements>( | ||
resource: TResource, | ||
actions: SubArray<TStatements[TResource]>, | ||
): allowResponse { | ||
for (const [r, as] of Object.entries(this.statements)) { | ||
if (resource === r) { | ||
for (const action of (actions)) { | ||
if (!as?.includes(action)) { | ||
return { | ||
success: false, | ||
error: | ||
`not authorized for action "${action}" on resource: "${r}"`, | ||
}; | ||
} | ||
public authorize( | ||
request: TStatements, | ||
): AuthortizeResponse { | ||
for ( | ||
const [requestedResource, requestedActions] of Object.entries(request) | ||
) { | ||
console.log( | ||
JSON.stringify( | ||
{ requestedResource, requestedActions, statements: this.statements }, | ||
null, | ||
2, | ||
), | ||
); | ||
const allowedActions = this.statements[requestedResource]; | ||
if (!allowedActions) { | ||
return { | ||
success: false, | ||
error: `You are not allowed to access resource: ${requestedResource}`, | ||
}; | ||
} | ||
console.log(JSON.stringify({ allowedActions }, null, 2)); | ||
const success = requestedActions.every((requestedAction) => { | ||
console.log(JSON.stringify({ requestedAction }, null, 2)); | ||
for (const allowedAction of allowedActions) { | ||
// if (allowedAction.rid && allowedAction.rid !== requestedAction.rid){ | ||
// return false | ||
// } | ||
return allowedAction.action === requestedAction.action; | ||
} | ||
return { success: true }; | ||
return false; | ||
}); | ||
console.log({ success }); | ||
if (success) { | ||
return { success }; | ||
} | ||
return { | ||
success: false, | ||
error: `unauthorized to access resource "${requestedResource}"`, | ||
}; | ||
} | ||
return { | ||
success: false, | ||
error: `not authorized for resource "${resource.toString()}"`, | ||
error: `Not authorized`, | ||
}; | ||
@@ -63,0 +77,0 @@ } |
@@ -6,6 +6,17 @@ // Transforms an array into any combination of 0 or more of its members | ||
// instead they are either present or not | ||
export type Subset<K extends keyof R, R extends Record<string, string[]>> = { | ||
export type Subset<K extends keyof R, R extends Record<string, unknown[]>> = { | ||
[P in K]: SubArray<R[P]>; | ||
}; | ||
export type Statements = { [resource: string]: string[] }; | ||
export type Statement = { | ||
action: string; | ||
// /** | ||
// * A unique resource id | ||
// * This narrows down the scope of the resource to a single entity | ||
// */ | ||
// rid?: string | ||
}; | ||
export type Statements = { | ||
[resource: string]: Statement[]; | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36679
521