Skip to content

Commit

Permalink
feat: add acl-cro
Browse files Browse the repository at this point in the history
  • Loading branch information
trungnotchung committed Nov 14, 2024
1 parent 2c21707 commit 74e9ebc
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
95 changes: 95 additions & 0 deletions packages/blueprints/src/AccessControlList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import {
ActionType,
type CRO,
type Operation,
type ResolveConflictsType,
SemanticsType,
type Vertex,
} from "@topology-foundation/object";
import { Role } from "@topology-foundation/object/src/constants.js";

export class ACL implements CRO {
operations: string[] = ["grant", "revoke"];
roles: Map<string, number>;
semanticsType = SemanticsType.pair;

constructor(nodeIds: string[] | undefined) {
this.roles = new Map<string, Role>();
if (nodeIds) {
for (const nodeId of nodeIds) {
this.roles.set(nodeId, Role.ADMIN);
}
}
}

private _grant(nodeId: string): void {
if (!this.roles.get(nodeId) || this.roles.get(nodeId) === Role.NONE) {
this.roles.set(nodeId, Role.ADMIN);
}
}

grant(nodeId: string): void {
this._grant(nodeId);
}

private _revoke(nodeId: string): void {
if (this.roles.get(nodeId) && this.roles.get(nodeId) !== Role.ADMIN) {
this.roles.set(nodeId, Role.NONE);
}
}

revoke(nodeId: string): void {
this._revoke(nodeId);
}

hasRole(nodeId: string, role: number): boolean {
return this.roles.get(nodeId) === role;
}

getNodesWithWritePermission(): string[] {
return Array.from(this.roles.entries())
.filter(([_, role]) => role !== Role.NONE)
.map(([value, _]) => value);
}

getNodesWithAdminPermission(): string[] {
return Array.from(this.roles.entries())
.filter(([_, role]) => role === Role.ADMIN)
.map(([value, _]) => value);
}

resolveConflicts(vertices: Vertex[]): ResolveConflictsType {
if (
vertices[0].operation &&
vertices[1].operation &&
vertices[0].operation?.type !== vertices[1].operation?.type &&
vertices[0].operation?.value === vertices[1].operation?.value
) {
return vertices[0].operation.type === "revoke"
? { action: ActionType.DropRight }
: { action: ActionType.DropLeft };
}
return { action: ActionType.Nop };
}

mergeCallback(operations: Operation[]): void {
const adminNodeIds = this.getNodesWithAdminPermission();
this.roles = new Map<string, Role>();
for (const nodeId of adminNodeIds) {
this.roles.set(nodeId, Role.ADMIN);
}

for (const op of operations) {
switch (op.type) {
case "grant":
if (op.value !== null) this._grant(op.value);
break;
case "revoke":
if (op.value !== null) this._revoke(op.value);
break;
default:
break;
}
}
}
}
2 changes: 1 addition & 1 deletion packages/blueprints/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"path": "../object"
}
],
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "../object/src/constants.ts"],
"exclude": ["src/**/*.asc.ts"]
}
5 changes: 5 additions & 0 deletions packages/object/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum Role {
NONE = 0,
GUEST = 1,
ADMIN = 2,
}

0 comments on commit 74e9ebc

Please sign in to comment.