@wxn0brp/gate-warden 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +11 -0
- package/.github/workflows/build.yml +14 -0
- package/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +89 -0
- package/dist/createDb.d.ts +4 -0
- package/dist/createDb.d.ts.map +1 -0
- package/dist/createDb.js +7 -0
- package/dist/createDb.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +8 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +8 -0
- package/dist/log.js.map +1 -0
- package/dist/mgr.d.ts +18 -0
- package/dist/mgr.d.ts.map +1 -0
- package/dist/mgr.js +42 -0
- package/dist/mgr.js.map +1 -0
- package/dist/test/ramStorage.d.ts +4 -0
- package/dist/test/ramStorage.d.ts.map +1 -0
- package/dist/test/ramStorage.js +13 -0
- package/dist/test/ramStorage.js.map +1 -0
- package/dist/test/test.d.ts +2 -0
- package/dist/test/test.d.ts.map +1 -0
- package/dist/test/test.js +49 -0
- package/dist/test/test.js.map +1 -0
- package/dist/types/system.d.ts +27 -0
- package/dist/types/system.d.ts.map +1 -0
- package/dist/types/system.js +2 -0
- package/dist/types/system.js.map +1 -0
- package/dist/user.d.ts +52 -0
- package/dist/user.d.ts.map +1 -0
- package/dist/user.js +89 -0
- package/dist/user.js.map +1 -0
- package/dist/warden.d.ts +10 -0
- package/dist/warden.d.ts.map +1 -0
- package/dist/warden.js +122 -0
- package/dist/warden.js.map +1 -0
- package/package.json +34 -0
- package/src/createDb.ts +7 -0
- package/src/index.ts +11 -0
- package/src/log.ts +7 -0
- package/src/mgr.ts +54 -0
- package/src/types/system.ts +32 -0
- package/src/user.ts +96 -0
- package/src/warden.ts +145 -0
- package/suglite.json +11 -0
- package/tsconfig.dev.json +6 -0
- package/tsconfig.json +26 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 (2025-05-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
* change result format
|
|
11
|
+
* make logic is logic
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* add GitHub Actions workflow for build process ([3d12dfe](https://github.com/wxn0brP/gate-warden/commit/3d12dfe739397c1b8b3a57e61425a40206779c1c))
|
|
16
|
+
* add README.md ([3b0f311](https://github.com/wxn0brP/gate-warden/commit/3b0f31115d740f63a0f3e94dc89bdacc30e95b63))
|
|
17
|
+
* add simple gui ([c1f4b27](https://github.com/wxn0brP/gate-warden/commit/c1f4b27004a6f07c949d37822d47a80d2b350f46))
|
|
18
|
+
* add user manager and organize files ([120277b](https://github.com/wxn0brP/gate-warden/commit/120277b18ffcff71afb1de7a893f0e82577ba43c))
|
|
19
|
+
* bump @wxn0brp/db version ([fc58a56](https://github.com/wxn0brP/gate-warden/commit/fc58a56947654baa69f9bacba412ac8130da6e2a))
|
|
20
|
+
* bump version to 0.0.3 and update @wxn0brp/db dependency to >=0.5.7; refactor database initialization to use createDb function ([053936e](https://github.com/wxn0brP/gate-warden/commit/053936e02e3af530ef07902bb31148b9f091ab36))
|
|
21
|
+
* change result format ([7948190](https://github.com/wxn0brP/gate-warden/commit/79481900193252c3ff6d52c9e3211fe822fbbc07))
|
|
22
|
+
* **core:** etch the first decrees of the Gatekeeper's will ([c0caa09](https://github.com/wxn0brP/gate-warden/commit/c0caa09f527adad97d3edbeaae180936eeced10c))
|
|
23
|
+
* make logic is logic ([6d4d466](https://github.com/wxn0brP/gate-warden/commit/6d4d466a35d142808fdbd3ec850a080b338b81a4))
|
|
24
|
+
* update ACLRule ([b9e78f2](https://github.com/wxn0brP/gate-warden/commit/b9e78f25da0467b5cb486d5709739a99a72017e7))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
* aclCheck function to include rules without uid ([0420a69](https://github.com/wxn0brP/gate-warden/commit/0420a6936874c1c0849379e07b912f1e3a11105c))
|
|
30
|
+
* update build workflow to include package.json in distribution files ([5de0f99](https://github.com/wxn0brP/gate-warden/commit/5de0f99b54ad211b08e31fbec0d9de80dfd6c809))
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 wxn0brP
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Gate Warden
|
|
2
|
+
|
|
3
|
+
Gate Warden is a lightweight access control library that supports ACL, RBAC, and ABAC models. It is designed to manage and enforce permissions for users and entities in a flexible and extensible way.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **ACL (Access Control List):** Define permissions for specific users on specific entities.
|
|
8
|
+
- **RBAC (Role-Based Access Control):** Assign roles to users and define permissions for roles on entities.
|
|
9
|
+
- **ABAC (Attribute-Based Access Control):** Use dynamic conditions based on user and entity attributes to determine access.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Install the library using npm or yarn:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
yarn add github:wxn0brp/gate-warden#dist
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### GateWarden
|
|
22
|
+
|
|
23
|
+
The `GateWarden` class is the main entry point for checking access permissions.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { GateWarden } from "@wxn0brp/gate-warden";
|
|
27
|
+
import { Valthera } from "@wxn0brp/db";
|
|
28
|
+
|
|
29
|
+
const wardenString = new GateWarden("dir");
|
|
30
|
+
// or
|
|
31
|
+
const wardenDB = new GateWarden(new Valthera("dir"));
|
|
32
|
+
|
|
33
|
+
const hasAccess = await warden.hasAccess("userId", "entityId", 0b001);
|
|
34
|
+
console.log(`Access granted: ${hasAccess}`);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### UserManager
|
|
38
|
+
|
|
39
|
+
The `UserManager` class provides methods to manage users.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { UserManager } from "@wxn0brp/gate-warden";
|
|
43
|
+
|
|
44
|
+
const userManager = new UserManager(db);
|
|
45
|
+
|
|
46
|
+
// Create a new user
|
|
47
|
+
await userManager.createUser({ _id: "userId", roles: ["roleId"] });
|
|
48
|
+
|
|
49
|
+
// Update user attributes
|
|
50
|
+
await userManager.updateAttributes("userId", { key: "value" });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### WardenManager
|
|
54
|
+
|
|
55
|
+
The `WardenManager` class provides methods to manage roles and rules.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { WardenManager } from "@wxn0brp/gate-warden";
|
|
59
|
+
|
|
60
|
+
const wardenManager = new WardenManager(db);
|
|
61
|
+
|
|
62
|
+
// Add a new role
|
|
63
|
+
await wardenManager.addRole({ _id: "roleId", name: "Admin" });
|
|
64
|
+
|
|
65
|
+
// Add an ACL rule
|
|
66
|
+
await wardenManager.addACLRule("entityId", 0b001, "userId");
|
|
67
|
+
|
|
68
|
+
// Add an ABAC rule
|
|
69
|
+
await wardenManager.addABACRule("entityId", 0b001, (user, entity) => user.attrib.isAdmin);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Debug Logging
|
|
73
|
+
|
|
74
|
+
Set the `debugLog` level in `GateWarden` to enable debug messages:
|
|
75
|
+
- `0`: No logs
|
|
76
|
+
- `1`: Basic logs
|
|
77
|
+
- `2`: Detailed logs
|
|
78
|
+
|
|
79
|
+
## Project Structure
|
|
80
|
+
|
|
81
|
+
- **src/warden.ts:** Core access control logic.
|
|
82
|
+
- **src/user.ts:** User management.
|
|
83
|
+
- **src/mgr.ts:** Role and rule management.
|
|
84
|
+
- **src/types/system.ts:** Type definitions for roles, rules, and users.
|
|
85
|
+
- **src/log.ts:** Logging utilities.
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDb.d.ts","sourceRoot":"","sources":["../src/createDb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAExD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAGvE"}
|
package/dist/createDb.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDb.js","sourceRoot":"","sources":["../src/createDb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG3D,MAAM,UAAU,QAAQ,CAAC,QAAoC;IACzD,IAAI,QAAQ,YAAY,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAClD,OAAO,kBAAkB,CAAC,QAAQ,CAAa,CAAC;AACpD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import GateWarden from "./warden.js";
|
|
2
|
+
import UserManager from "./user.js";
|
|
3
|
+
import WardenManager from "./mgr.js";
|
|
4
|
+
import { AccessResult } from "./types/system.js";
|
|
5
|
+
export { GateWarden, UserManager, WardenManager, AccessResult };
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,UAAU,CAAC;AAClC,OAAO,WAAW,MAAM,QAAQ,CAAC;AACjC,OAAO,aAAa,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EACH,UAAU,EACV,WAAW,EACX,aAAa,EACb,YAAY,EACf,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,UAAU,CAAC;AAClC,OAAO,WAAW,MAAM,QAAQ,CAAC;AACjC,OAAO,aAAa,MAAM,OAAO,CAAC;AAGlC,OAAO,EACH,UAAU,EACV,WAAW,EACX,aAAa,EAEhB,CAAC"}
|
package/dist/log.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;;;;CAMlB,CAAC"}
|
package/dist/log.js
ADDED
package/dist/log.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;IAClB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,UAAU;IACjB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,UAAU;IACf,IAAI,EAAE,UAAU;CACnB,CAAC"}
|
package/dist/mgr.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Id, Valthera } from "@wxn0brp/db";
|
|
2
|
+
import { ABACRule, Role } from "./types/system.js";
|
|
3
|
+
import { Remote } from "@wxn0brp/db/dist/client/remote";
|
|
4
|
+
declare class WardenManager<A = any> {
|
|
5
|
+
private db;
|
|
6
|
+
constructor(valthera: string | Valthera | Remote);
|
|
7
|
+
changeRoleNameToId(name: string): Promise<Id>;
|
|
8
|
+
addRole(role: Role): Promise<Role>;
|
|
9
|
+
addACLRule(entityId: string, p: number, uid?: Id): Promise<void>;
|
|
10
|
+
addRBACRule(role_id: string, entity_id: string, p: number): Promise<void>;
|
|
11
|
+
addABACRule(entity_id: string, flag: number, condition: ABACRule<A>["conditions"]): Promise<void>;
|
|
12
|
+
removeRole(roleId: string): Promise<boolean>;
|
|
13
|
+
removeACLRule(entityId: string, uid?: string): Promise<boolean>;
|
|
14
|
+
removeRBACRule(roleId: string, entityId: string): Promise<boolean>;
|
|
15
|
+
removeABACRule(entityId: string, flag: number): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
export default WardenManager;
|
|
18
|
+
//# sourceMappingURL=mgr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mgr.d.ts","sourceRoot":"","sources":["../src/mgr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAW,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAGxD,cAAM,aAAa,CAAC,CAAC,GAAG,GAAG;IACvB,OAAO,CAAC,EAAE,CAAW;gBACT,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM;IAI1C,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAK7C,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI5C,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK/D,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGzE;AAED,eAAe,aAAa,CAAC"}
|
package/dist/mgr.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createDb } from "./createDb.js";
|
|
2
|
+
class WardenManager {
|
|
3
|
+
db;
|
|
4
|
+
constructor(valthera) {
|
|
5
|
+
this.db = createDb(valthera);
|
|
6
|
+
}
|
|
7
|
+
async changeRoleNameToId(name) {
|
|
8
|
+
return await this.db.findOne("roles", { name });
|
|
9
|
+
}
|
|
10
|
+
// ADD
|
|
11
|
+
async addRole(role) {
|
|
12
|
+
return await this.db.add("roles", role);
|
|
13
|
+
}
|
|
14
|
+
async addACLRule(entityId, p, uid) {
|
|
15
|
+
const rule = { p };
|
|
16
|
+
if (uid)
|
|
17
|
+
rule.uid = uid;
|
|
18
|
+
return await this.db.add("acl/" + entityId, rule, false);
|
|
19
|
+
}
|
|
20
|
+
async addRBACRule(role_id, entity_id, p) {
|
|
21
|
+
return await this.db.add("role/" + role_id, { _id: entity_id, p }, false);
|
|
22
|
+
}
|
|
23
|
+
async addABACRule(entity_id, flag, condition) {
|
|
24
|
+
return await this.db.add("abac/" + entity_id, { flag, conditions: condition.toString() }, true);
|
|
25
|
+
}
|
|
26
|
+
// DELETE
|
|
27
|
+
async removeRole(roleId) {
|
|
28
|
+
return await this.db.removeOne("roles", { roleId });
|
|
29
|
+
}
|
|
30
|
+
async removeACLRule(entityId, uid) {
|
|
31
|
+
const q = uid ? { uid } : { $not: { $exists: { "uid": true } } };
|
|
32
|
+
return await this.db.removeOne("acl/" + entityId, q);
|
|
33
|
+
}
|
|
34
|
+
async removeRBACRule(roleId, entityId) {
|
|
35
|
+
return await this.db.removeOne("role/" + roleId, { _id: entityId });
|
|
36
|
+
}
|
|
37
|
+
async removeABACRule(entityId, flag) {
|
|
38
|
+
return await this.db.removeOne("abac/" + entityId, { flag });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export default WardenManager;
|
|
42
|
+
//# sourceMappingURL=mgr.js.map
|
package/dist/mgr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mgr.js","sourceRoot":"","sources":["../src/mgr.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,aAAa;IACP,EAAE,CAAW;IACrB,YAAY,QAAoC;QAC5C,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAY;QACjC,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM;IACN,KAAK,CAAC,OAAO,CAAC,IAAU;QACpB,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,CAAS,EAAE,GAAQ;QAClD,MAAM,IAAI,GAAY,EAAE,CAAC,EAAE,CAAC;QAC5B,IAAI,GAAG;YAAE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACxB,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,SAAiB,EAAE,CAAS;QAC3D,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,GAAG,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,SAAiB,EAAE,IAAY,EAAE,SAAoC;QACnF,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,GAAC,SAAS,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IAClG,CAAC;IAED,SAAS;IACT,KAAK,CAAC,UAAU,CAAC,MAAc;QAC3B,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,GAAY;QAC9C,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACjE,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,QAAgB;QACjD,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,GAAG,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,IAAY;QAC/C,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,GAAG,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;CACJ;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ramStorage.d.ts","sourceRoot":"","sources":["../../src/test/ramStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAa5C,QAAA,MAAM,IAAI,eAAmC,CAAC;AAC9C,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CustomFileCpu } from "@wxn0brp/db";
|
|
2
|
+
const temp = new Map();
|
|
3
|
+
async function _read(file) {
|
|
4
|
+
if (temp.has(file))
|
|
5
|
+
return temp.get(file) || [];
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
async function _write(file, data) {
|
|
9
|
+
temp.set(file, data);
|
|
10
|
+
}
|
|
11
|
+
const fCPU = new CustomFileCpu(_read, _write);
|
|
12
|
+
export default fCPU;
|
|
13
|
+
//# sourceMappingURL=ramStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ramStorage.js","sourceRoot":"","sources":["../../src/test/ramStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;AAEtC,KAAK,UAAU,KAAK,CAAC,IAAY;IAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAChD,OAAO,EAAE,CAAC;AACd,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAY,EAAE,IAAW;IAC3C,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,IAAI,GAAG,IAAI,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAC9C,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/test/test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { GateWarden, UserManager, WardenManager } from "../index.js";
|
|
2
|
+
import sourceMapSupport from "source-map-support";
|
|
3
|
+
import { Valthera } from "@wxn0brp/db";
|
|
4
|
+
import { rmSync } from "fs";
|
|
5
|
+
sourceMapSupport.install();
|
|
6
|
+
let total = 0;
|
|
7
|
+
let ok = 0;
|
|
8
|
+
var PermissionFlags;
|
|
9
|
+
(function (PermissionFlags) {
|
|
10
|
+
PermissionFlags[PermissionFlags["VIEW"] = 1] = "VIEW";
|
|
11
|
+
PermissionFlags[PermissionFlags["EDIT"] = 2] = "EDIT";
|
|
12
|
+
PermissionFlags[PermissionFlags["DELETE"] = 4] = "DELETE";
|
|
13
|
+
PermissionFlags[PermissionFlags["ADMIN"] = 8] = "ADMIN";
|
|
14
|
+
})(PermissionFlags || (PermissionFlags = {}));
|
|
15
|
+
rmSync("test.db", { recursive: true, force: true });
|
|
16
|
+
const db = new Valthera("test.db", {});
|
|
17
|
+
const gw = new GateWarden(db, 2);
|
|
18
|
+
const gwMgr = new WardenManager(db);
|
|
19
|
+
const userMgr = new UserManager(db);
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
db.add("test", "test", false);
|
|
22
|
+
// debugger
|
|
23
|
+
const admin = await gwMgr.addRole({ _id: "admin", name: "admin" });
|
|
24
|
+
const user = await gwMgr.addRole({ _id: "user", name: "user" });
|
|
25
|
+
const manager = await gwMgr.addRole({ _id: "manager", name: "manager" });
|
|
26
|
+
await gwMgr.addRBACRule(admin._id, "doc123", PermissionFlags.VIEW | PermissionFlags.EDIT | PermissionFlags.DELETE | PermissionFlags.ADMIN);
|
|
27
|
+
await gwMgr.addRBACRule(user._id, "doc123", PermissionFlags.VIEW);
|
|
28
|
+
await gwMgr.addRBACRule(manager._id, "doc123", PermissionFlags.VIEW | PermissionFlags.EDIT);
|
|
29
|
+
await userMgr.createUser({ _id: "alice", roles: [user._id], attrib: { dep: "HR", level: 1 } });
|
|
30
|
+
await userMgr.createUser({ _id: "bob", roles: [manager._id], attrib: { dep: "IT", level: 7 } });
|
|
31
|
+
await userMgr.createUser({ _id: "charlie", roles: [admin._id], attrib: { dep: "IT", level: 5 } });
|
|
32
|
+
await gwMgr.addACLRule("doc123", PermissionFlags.EDIT, "alice");
|
|
33
|
+
await gwMgr.addABACRule("doc123", PermissionFlags.DELETE, (user, entity) => user.attrib.level >= 4);
|
|
34
|
+
const log = (result, required = true) => {
|
|
35
|
+
total++;
|
|
36
|
+
ok += result.granted === required ? 1 : 0;
|
|
37
|
+
console.log(result.granted === required ? "OK" : "FAIL");
|
|
38
|
+
};
|
|
39
|
+
log(await gw.hasAccess("alice", "doc123", PermissionFlags.VIEW), true);
|
|
40
|
+
log(await gw.hasAccess("alice", "doc123", PermissionFlags.EDIT), true);
|
|
41
|
+
log(await gw.hasAccess("alice", "doc999", PermissionFlags.EDIT), false);
|
|
42
|
+
log(await gw.hasAccess("bob", "doc123", PermissionFlags.DELETE), true);
|
|
43
|
+
log(await gw.hasAccess("charlie", "doc123", PermissionFlags.DELETE), true);
|
|
44
|
+
log(await gw.hasAccess("alice", "doc123", PermissionFlags.DELETE), false);
|
|
45
|
+
const userManager = new UserManager(db);
|
|
46
|
+
await userManager.updateAttributes("bob", { level: 1 });
|
|
47
|
+
log(await gw.hasAccess("bob", "doc123", PermissionFlags.DELETE), false);
|
|
48
|
+
console.log(`\nOK: ${ok}/${total} (${(ok / total * 100).toFixed(2)}%)`);
|
|
49
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test/test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Id } from "@wxn0brp/db";
|
|
2
|
+
export interface Role {
|
|
3
|
+
_id: Id;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RoleEntity {
|
|
7
|
+
_id: Id;
|
|
8
|
+
p: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ACLRule {
|
|
11
|
+
uid?: Id;
|
|
12
|
+
p: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ABACRule<A> {
|
|
15
|
+
flag: number;
|
|
16
|
+
conditions: (user: User<A>, entity: any) => boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface User<A> {
|
|
19
|
+
_id: Id;
|
|
20
|
+
roles: Id[];
|
|
21
|
+
attrib: A;
|
|
22
|
+
}
|
|
23
|
+
export interface AccessResult {
|
|
24
|
+
granted: boolean;
|
|
25
|
+
via: "ACL" | "RBAC" | "ABAC" | "user-404" | "entity-404" | "not-permitted";
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/types/system.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,MAAM,WAAW,IAAI;IACjB,GAAG,EAAE,EAAE,CAAC;IACR,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACvB,GAAG,EAAE,EAAE,CAAC;IACR,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,OAAO;IACpB,GAAG,CAAC,EAAE,EAAE,CAAC;IACT,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC;CACvD;AAED,MAAM,WAAW,IAAI,CAAC,CAAC;IACnB,GAAG,EAAE,EAAE,CAAC;IACR,KAAK,EAAE,EAAE,EAAE,CAAC;IACZ,MAAM,EAAE,CAAC,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,eAAe,CAAC;CAC9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/types/system.ts"],"names":[],"mappings":""}
|
package/dist/user.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Id, Valthera } from "@wxn0brp/db";
|
|
2
|
+
import { User } from "./types/system.js";
|
|
3
|
+
declare class UserManager<A = any> {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(valthera: string | Valthera);
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new user
|
|
8
|
+
* @param userData User data (_id is required)
|
|
9
|
+
*/
|
|
10
|
+
createUser(userData: {
|
|
11
|
+
_id: Id;
|
|
12
|
+
roles?: Id[];
|
|
13
|
+
attrib?: A;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves a user by _id
|
|
17
|
+
* @param user_id User _id
|
|
18
|
+
* @returns User or null if it doesn't exist
|
|
19
|
+
*/
|
|
20
|
+
getUser(user_id: Id): Promise<User<A> | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Updates a user's data
|
|
23
|
+
* @param user_id User _id
|
|
24
|
+
* @param updates Object with fields to update
|
|
25
|
+
*/
|
|
26
|
+
updateUser(user_id: Id, updates: Partial<User<A>>): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Deletes a user
|
|
29
|
+
* @param user_id User _id
|
|
30
|
+
*/
|
|
31
|
+
deleteUser(user_id: Id): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Adds a role to a user
|
|
34
|
+
* @param user_id User _id
|
|
35
|
+
* @param role_id Role _id
|
|
36
|
+
*/
|
|
37
|
+
addRoleToUser(user_id: Id, role_id: Id): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Removes a role from a user
|
|
40
|
+
* @param user_id User _id
|
|
41
|
+
* @param role_id Role _id
|
|
42
|
+
*/
|
|
43
|
+
removeRoleFromUser(user_id: Id, role_id: Id): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Updates a user's attributes
|
|
46
|
+
* @param user_id User _id
|
|
47
|
+
* @param attributes New attributes to merge
|
|
48
|
+
*/
|
|
49
|
+
updateAttributes(user_id: Id, attributes: Partial<A>): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export default UserManager;
|
|
52
|
+
//# sourceMappingURL=user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAGtC,cAAM,WAAW,CAAC,CAAC,GAAG,GAAG;IACrB,OAAO,CAAC,EAAE,CAAW;gBAET,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAIvC;;;OAGG;IACG,UAAU,CAAC,QAAQ,EAAE;QAAE,GAAG,EAAE,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAShF;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAInD;;;;OAIG;IACG,UAAU,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE;;;OAGG;IACG,UAAU,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5D;;;;OAIG;IACG,kBAAkB,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjE;;;;OAIG;IACG,gBAAgB,CAAC,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAM7E;AAED,eAAe,WAAW,CAAC"}
|
package/dist/user.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createDb } from "./createDb.js";
|
|
2
|
+
class UserManager {
|
|
3
|
+
db;
|
|
4
|
+
constructor(valthera) {
|
|
5
|
+
this.db = createDb(valthera);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new user
|
|
9
|
+
* @param userData User data (_id is required)
|
|
10
|
+
*/
|
|
11
|
+
async createUser(userData) {
|
|
12
|
+
const newUser = {
|
|
13
|
+
_id: userData._id,
|
|
14
|
+
roles: userData.roles || [],
|
|
15
|
+
attrib: userData.attrib || {},
|
|
16
|
+
};
|
|
17
|
+
await this.db.add("users", newUser, false);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves a user by _id
|
|
21
|
+
* @param user_id User _id
|
|
22
|
+
* @returns User or null if it doesn't exist
|
|
23
|
+
*/
|
|
24
|
+
async getUser(user_id) {
|
|
25
|
+
return this.db.findOne("users", { _id: user_id });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Updates a user's data
|
|
29
|
+
* @param user_id User _id
|
|
30
|
+
* @param updates Object with fields to update
|
|
31
|
+
*/
|
|
32
|
+
async updateUser(user_id, updates) {
|
|
33
|
+
const existingUser = await this.getUser(user_id);
|
|
34
|
+
if (!existingUser)
|
|
35
|
+
throw new Error("User not found");
|
|
36
|
+
const updatedUser = { ...existingUser, ...updates };
|
|
37
|
+
await this.db.update("users", { _id: user_id }, updatedUser);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Deletes a user
|
|
41
|
+
* @param user_id User _id
|
|
42
|
+
*/
|
|
43
|
+
async deleteUser(user_id) {
|
|
44
|
+
await this.db.removeOne("users", { _id: user_id });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Adds a role to a user
|
|
48
|
+
* @param user_id User _id
|
|
49
|
+
* @param role_id Role _id
|
|
50
|
+
*/
|
|
51
|
+
async addRoleToUser(user_id, role_id) {
|
|
52
|
+
const user = await this.getUser(user_id);
|
|
53
|
+
if (!user)
|
|
54
|
+
throw new Error("User not found");
|
|
55
|
+
if (!user.roles.includes(role_id)) {
|
|
56
|
+
user.roles.push(role_id);
|
|
57
|
+
await this.db.update("users", { _id: user_id }, user);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Removes a role from a user
|
|
62
|
+
* @param user_id User _id
|
|
63
|
+
* @param role_id Role _id
|
|
64
|
+
*/
|
|
65
|
+
async removeRoleFromUser(user_id, role_id) {
|
|
66
|
+
const user = await this.getUser(user_id);
|
|
67
|
+
if (!user)
|
|
68
|
+
throw new Error("User not found");
|
|
69
|
+
const index = user.roles.indexOf(role_id);
|
|
70
|
+
if (index !== -1) {
|
|
71
|
+
user.roles.splice(index, 1);
|
|
72
|
+
await this.db.update("users", { _id: user_id }, user);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Updates a user's attributes
|
|
77
|
+
* @param user_id User _id
|
|
78
|
+
* @param attributes New attributes to merge
|
|
79
|
+
*/
|
|
80
|
+
async updateAttributes(user_id, attributes) {
|
|
81
|
+
const user = await this.getUser(user_id);
|
|
82
|
+
if (!user)
|
|
83
|
+
throw new Error("User not found");
|
|
84
|
+
user.attrib = { ...user.attrib, ...attributes };
|
|
85
|
+
await this.db.update("users", { _id: user_id }, user);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export default UserManager;
|
|
89
|
+
//# sourceMappingURL=user.js.map
|
package/dist/user.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"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"}
|
package/dist/warden.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Valthera } from "@wxn0brp/db";
|
|
2
|
+
import { AccessResult } from "./types/system.js";
|
|
3
|
+
declare class GateWarden<A = any> {
|
|
4
|
+
debugLog: number;
|
|
5
|
+
private db;
|
|
6
|
+
constructor(valthera: string | Valthera, debugLog?: number);
|
|
7
|
+
hasAccess(userId: string, entityId: string, flag: number): Promise<AccessResult>;
|
|
8
|
+
}
|
|
9
|
+
export default GateWarden;
|
|
10
|
+
//# sourceMappingURL=warden.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warden.d.ts","sourceRoot":"","sources":["../src/warden.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAY,YAAY,EAA6B,MAAM,gBAAgB,CAAC;AA0GnF,cAAM,UAAU,CAAC,CAAC,GAAG,GAAG;IAG4B,QAAQ,EAAE,MAAM;IAFhE,OAAO,CAAC,EAAE,CAAW;gBAET,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAS,QAAQ,GAAE,MAAU;IAI9D,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CA4BzF;AAED,eAAe,UAAU,CAAC"}
|
package/dist/warden.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { COLORS } from "./log.js";
|
|
2
|
+
import { createDb } from "./createDb.js";
|
|
3
|
+
function logAccess(userId, entityId, via, debugLog) {
|
|
4
|
+
if (debugLog < 1)
|
|
5
|
+
return;
|
|
6
|
+
console.log(`${COLORS.green}[GW] Access granted to ${COLORS.yellow}${entityId}${COLORS.green} via ` +
|
|
7
|
+
`${COLORS.yellow}${via}${COLORS.green} by ${COLORS.yellow}${userId}${COLORS.reset}`);
|
|
8
|
+
}
|
|
9
|
+
async function fetchUser(db, userId) {
|
|
10
|
+
const user = await db.findOne("users", { _id: userId });
|
|
11
|
+
if (!user)
|
|
12
|
+
throw new Error("User not found");
|
|
13
|
+
return user;
|
|
14
|
+
}
|
|
15
|
+
async function aclCheck({ db, entityId, flag, user }) {
|
|
16
|
+
if (!await db.issetCollection("acl/" + entityId))
|
|
17
|
+
return -1;
|
|
18
|
+
const rules = await db.find("acl/" + entityId, {
|
|
19
|
+
$or: [
|
|
20
|
+
{ uid: user._id },
|
|
21
|
+
{
|
|
22
|
+
$not: {
|
|
23
|
+
$exists: { "uid": true }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
if (rules.length === 0)
|
|
29
|
+
return -1;
|
|
30
|
+
for (const rule of rules) {
|
|
31
|
+
if (rule.p & flag)
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
async function rbacCheck({ db, flag, user, entityId }) {
|
|
37
|
+
for (const role of user.roles) {
|
|
38
|
+
const rolesEntity = await db.find("role/" + role, { _id: entityId });
|
|
39
|
+
for (const entity of rolesEntity) {
|
|
40
|
+
if (entity.p & flag)
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
async function abacCheck({ db, entityId, flag, user, debugLog }) {
|
|
47
|
+
if (!await db.issetCollection("abac/" + entityId))
|
|
48
|
+
return false;
|
|
49
|
+
const rules = await db.find("abac/" + entityId, { flag });
|
|
50
|
+
for (const rule of rules) {
|
|
51
|
+
try {
|
|
52
|
+
const conditions = new Function("user", "entity", `return ${rule.conditions}`)();
|
|
53
|
+
if (debugLog >= 1)
|
|
54
|
+
console.log(COLORS.blue + `[GW] ABAC rule: ${COLORS.yellow}${rule.conditions}${COLORS.blue} ` +
|
|
55
|
+
`-> ${COLORS.yellow}${conditions(user, entityId)}` + COLORS.reset);
|
|
56
|
+
if (conditions(user, entityId))
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
if (debugLog >= 1)
|
|
61
|
+
console.log(COLORS.red + `[GW] ABAC rule error: ${e}` + COLORS.reset);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
async function matchPermission(db, entityId, flag, user, debugLog) {
|
|
67
|
+
const checks = [
|
|
68
|
+
{ name: "ACL", method: aclCheck },
|
|
69
|
+
{ name: "RBAC", method: rbacCheck },
|
|
70
|
+
{ name: "ABAC", method: abacCheck },
|
|
71
|
+
];
|
|
72
|
+
const results = [];
|
|
73
|
+
const checkParams = { db, entityId, flag, user, debugLog };
|
|
74
|
+
for (const check of checks) {
|
|
75
|
+
const result = await check.method(checkParams);
|
|
76
|
+
results.push(result);
|
|
77
|
+
if (result === true || result === 1) {
|
|
78
|
+
return { granted: true, via: check.name };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (results[0] === -1) {
|
|
82
|
+
return { granted: false, via: "entity-404" };
|
|
83
|
+
}
|
|
84
|
+
return { granted: false, via: null };
|
|
85
|
+
}
|
|
86
|
+
class GateWarden {
|
|
87
|
+
debugLog;
|
|
88
|
+
db;
|
|
89
|
+
constructor(valthera, debugLog = 0) {
|
|
90
|
+
this.debugLog = debugLog;
|
|
91
|
+
this.db = createDb(valthera);
|
|
92
|
+
}
|
|
93
|
+
async hasAccess(userId, entityId, flag) {
|
|
94
|
+
const user = await fetchUser(this.db, userId);
|
|
95
|
+
if (!user) {
|
|
96
|
+
if (this.debugLog >= 1)
|
|
97
|
+
console.log(COLORS.red + "[GW] User not found." + COLORS.reset);
|
|
98
|
+
return {
|
|
99
|
+
granted: false,
|
|
100
|
+
via: "user-404"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const matched = await matchPermission(this.db, entityId, flag, user, this.debugLog);
|
|
104
|
+
if (matched.granted) {
|
|
105
|
+
logAccess(userId, entityId, matched.via, this.debugLog);
|
|
106
|
+
return matched;
|
|
107
|
+
}
|
|
108
|
+
if (!matched.granted && matched.via === "entity-404") {
|
|
109
|
+
if (this.debugLog >= 1)
|
|
110
|
+
console.log(COLORS.red + `[GW] Entity not found: ${entityId}` + COLORS.reset);
|
|
111
|
+
return matched;
|
|
112
|
+
}
|
|
113
|
+
if (this.debugLog >= 1)
|
|
114
|
+
console.log(COLORS.red + `[GW] Access denied to ${entityId} by ${userId}.` + COLORS.reset);
|
|
115
|
+
return {
|
|
116
|
+
granted: false,
|
|
117
|
+
via: "not-permitted"
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export default GateWarden;
|
|
122
|
+
//# sourceMappingURL=warden.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warden.js","sourceRoot":"","sources":["../src/warden.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wxn0brp/gate-warden",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"author": "wxn0brP",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && tsc-alias",
|
|
11
|
+
"build-dev": "tsc -p tsconfig.dev.json && tsc-alias",
|
|
12
|
+
"test": "node dist/test/test.js"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^22.13.11",
|
|
16
|
+
"@wxn0brp/db": ">=0.7.1",
|
|
17
|
+
"source-map-support": "^0.5.21",
|
|
18
|
+
"tsc-alias": "^1.8.10",
|
|
19
|
+
"typescript": "^5.7.3"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@wxn0brp/db": ">=0.7.1"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./*": {
|
|
30
|
+
"types": "./*",
|
|
31
|
+
"import": "./*"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
package/src/createDb.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Valthera, ValtheraAutoCreate } from "@wxn0brp/db";
|
|
2
|
+
import { Remote } from "@wxn0brp/db/dist/client/remote";
|
|
3
|
+
|
|
4
|
+
export function createDb(valthera: string | Valthera | Remote): Valthera {
|
|
5
|
+
if (valthera instanceof Valthera) return valthera;
|
|
6
|
+
return ValtheraAutoCreate(valthera) as Valthera;
|
|
7
|
+
}
|
package/src/index.ts
ADDED
package/src/log.ts
ADDED
package/src/mgr.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Id, Valthera } from "@wxn0brp/db";
|
|
2
|
+
import { ABACRule, ACLRule, Role } from "./types/system";
|
|
3
|
+
import { Remote } from "@wxn0brp/db/dist/client/remote";
|
|
4
|
+
import { createDb } from "./createDb";
|
|
5
|
+
|
|
6
|
+
class WardenManager<A = any> {
|
|
7
|
+
private db: Valthera;
|
|
8
|
+
constructor(valthera: string | Valthera | Remote) {
|
|
9
|
+
this.db = createDb(valthera);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async changeRoleNameToId(name: string): Promise<Id> {
|
|
13
|
+
return await this.db.findOne("roles", { name });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ADD
|
|
17
|
+
async addRole(role: Role): Promise<Role> {
|
|
18
|
+
return await this.db.add("roles", role);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async addACLRule(entityId: string, p: number, uid?: Id): Promise<void> {
|
|
22
|
+
const rule: ACLRule = { p };
|
|
23
|
+
if (uid) rule.uid = uid;
|
|
24
|
+
return await this.db.add("acl/"+entityId, rule, false);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async addRBACRule(role_id: string, entity_id: string, p: number): Promise<void> {
|
|
28
|
+
return await this.db.add("role/" + role_id, { _id: entity_id, p }, false);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async addABACRule(entity_id: string, flag: number, condition: ABACRule<A>["conditions"]): Promise<void> {
|
|
32
|
+
return await this.db.add("abac/"+entity_id, { flag, conditions: condition.toString() }, true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// DELETE
|
|
36
|
+
async removeRole(roleId: string): Promise<boolean> {
|
|
37
|
+
return await this.db.removeOne("roles", { roleId });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async removeACLRule(entityId: string, uid?: string): Promise<boolean> {
|
|
41
|
+
const q = uid ? { uid } : { $not: { $exists: { "uid": true } } };
|
|
42
|
+
return await this.db.removeOne("acl/" + entityId, q);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async removeRBACRule(roleId: string, entityId: string): Promise<boolean> {
|
|
46
|
+
return await this.db.removeOne("role/" + roleId, { _id: entityId });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async removeABACRule(entityId: string, flag: number): Promise<boolean> {
|
|
50
|
+
return await this.db.removeOne("abac/" + entityId, { flag });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default WardenManager;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Id } from "@wxn0brp/db";
|
|
2
|
+
|
|
3
|
+
export interface Role {
|
|
4
|
+
_id: Id;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface RoleEntity {
|
|
9
|
+
_id: Id;
|
|
10
|
+
p: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ACLRule {
|
|
14
|
+
uid?: Id;
|
|
15
|
+
p: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ABACRule<A> {
|
|
19
|
+
flag: number;
|
|
20
|
+
conditions: (user: User<A>, entity: any) => boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface User<A> {
|
|
24
|
+
_id: Id;
|
|
25
|
+
roles: Id[];
|
|
26
|
+
attrib: A;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AccessResult {
|
|
30
|
+
granted: boolean;
|
|
31
|
+
via: "ACL" | "RBAC" | "ABAC" | "user-404" | "entity-404" | "not-permitted";
|
|
32
|
+
}
|
package/src/user.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Id, Valthera } from "@wxn0brp/db";
|
|
2
|
+
import { User } from "./types/system";
|
|
3
|
+
import { createDb } from "./createDb";
|
|
4
|
+
|
|
5
|
+
class UserManager<A = any> {
|
|
6
|
+
private db: Valthera;
|
|
7
|
+
|
|
8
|
+
constructor(valthera: string | Valthera) {
|
|
9
|
+
this.db = createDb(valthera);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new user
|
|
14
|
+
* @param userData User data (_id is required)
|
|
15
|
+
*/
|
|
16
|
+
async createUser(userData: { _id: Id; roles?: Id[]; attrib?: A }): Promise<void> {
|
|
17
|
+
const newUser: User<A> = {
|
|
18
|
+
_id: userData._id,
|
|
19
|
+
roles: userData.roles || [],
|
|
20
|
+
attrib: userData.attrib || {} as A,
|
|
21
|
+
};
|
|
22
|
+
await this.db.add("users", newUser, false);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Retrieves a user by _id
|
|
27
|
+
* @param user_id User _id
|
|
28
|
+
* @returns User or null if it doesn't exist
|
|
29
|
+
*/
|
|
30
|
+
async getUser(user_id: Id): Promise<User<A> | null> {
|
|
31
|
+
return this.db.findOne<User<A>>("users", { _id: user_id });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Updates a user's data
|
|
36
|
+
* @param user_id User _id
|
|
37
|
+
* @param updates Object with fields to update
|
|
38
|
+
*/
|
|
39
|
+
async updateUser(user_id: Id, updates: Partial<User<A>>): Promise<void> {
|
|
40
|
+
const existingUser = await this.getUser(user_id);
|
|
41
|
+
if (!existingUser) throw new Error("User not found");
|
|
42
|
+
const updatedUser = { ...existingUser, ...updates };
|
|
43
|
+
await this.db.update("users", { _id: user_id }, updatedUser);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Deletes a user
|
|
48
|
+
* @param user_id User _id
|
|
49
|
+
*/
|
|
50
|
+
async deleteUser(user_id: Id): Promise<void> {
|
|
51
|
+
await this.db.removeOne("users", { _id: user_id });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Adds a role to a user
|
|
56
|
+
* @param user_id User _id
|
|
57
|
+
* @param role_id Role _id
|
|
58
|
+
*/
|
|
59
|
+
async addRoleToUser(user_id: Id, role_id: Id): Promise<void> {
|
|
60
|
+
const user = await this.getUser(user_id);
|
|
61
|
+
if (!user) throw new Error("User not found");
|
|
62
|
+
if (!user.roles.includes(role_id)) {
|
|
63
|
+
user.roles.push(role_id);
|
|
64
|
+
await this.db.update("users", { _id: user_id }, user);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Removes a role from a user
|
|
70
|
+
* @param user_id User _id
|
|
71
|
+
* @param role_id Role _id
|
|
72
|
+
*/
|
|
73
|
+
async removeRoleFromUser(user_id: Id, role_id: Id): Promise<void> {
|
|
74
|
+
const user = await this.getUser(user_id);
|
|
75
|
+
if (!user) throw new Error("User not found");
|
|
76
|
+
const index = user.roles.indexOf(role_id);
|
|
77
|
+
if (index !== -1) {
|
|
78
|
+
user.roles.splice(index, 1);
|
|
79
|
+
await this.db.update("users", { _id: user_id }, user);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Updates a user's attributes
|
|
85
|
+
* @param user_id User _id
|
|
86
|
+
* @param attributes New attributes to merge
|
|
87
|
+
*/
|
|
88
|
+
async updateAttributes(user_id: Id, attributes: Partial<A>): Promise<void> {
|
|
89
|
+
const user = await this.getUser(user_id);
|
|
90
|
+
if (!user) throw new Error("User not found");
|
|
91
|
+
user.attrib = { ...user.attrib, ...attributes };
|
|
92
|
+
await this.db.update("users", { _id: user_id }, user);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default UserManager;
|
package/src/warden.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Id, Valthera } from "@wxn0brp/db";
|
|
2
|
+
import { ABACRule, AccessResult, ACLRule, RoleEntity, User } from "./types/system";
|
|
3
|
+
import { COLORS } from "./log";
|
|
4
|
+
import { createDb } from "./createDb";
|
|
5
|
+
|
|
6
|
+
interface CheckParams<A> {
|
|
7
|
+
db: Valthera;
|
|
8
|
+
entityId: Id;
|
|
9
|
+
flag: number;
|
|
10
|
+
user: User<A>;
|
|
11
|
+
debugLog: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function logAccess(userId: Id, entityId: Id, via: string, debugLog: number) {
|
|
15
|
+
if (debugLog < 1) return;
|
|
16
|
+
console.log(
|
|
17
|
+
`${COLORS.green}[GW] Access granted to ${COLORS.yellow}${entityId}${COLORS.green} via ` +
|
|
18
|
+
`${COLORS.yellow}${via}${COLORS.green} by ${COLORS.yellow}${userId}${COLORS.reset}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function fetchUser<A>(db: Valthera, userId: Id): Promise<User<A>> {
|
|
23
|
+
const user = await db.findOne<User<A>>("users", { _id: userId });
|
|
24
|
+
if (!user) throw new Error("User not found");
|
|
25
|
+
return user;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function aclCheck<A>({ db, entityId, flag, user }: CheckParams<A>): Promise<number> {
|
|
29
|
+
if (!await db.issetCollection("acl/" + entityId)) return -1;
|
|
30
|
+
const rules = await db.find<ACLRule>("acl/" + entityId, {
|
|
31
|
+
$or: [
|
|
32
|
+
{ uid: user._id },
|
|
33
|
+
{
|
|
34
|
+
$not: {
|
|
35
|
+
$exists: { "uid": true }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
if (rules.length === 0) return -1;
|
|
41
|
+
for (const rule of rules) {
|
|
42
|
+
if (rule.p & flag) return 1;
|
|
43
|
+
}
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function rbacCheck<A>({ db, flag, user, entityId }: CheckParams<A>): Promise<boolean> {
|
|
48
|
+
for (const role of user.roles) {
|
|
49
|
+
const rolesEntity = await db.find<RoleEntity>("role/" + role, { _id: entityId });
|
|
50
|
+
for (const entity of rolesEntity) {
|
|
51
|
+
if (entity.p & flag) return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function abacCheck<A>({ db, entityId, flag, user, debugLog }: CheckParams<A>): Promise<boolean> {
|
|
58
|
+
if (!await db.issetCollection("abac/" + entityId)) return false;
|
|
59
|
+
const rules = await db.find<ABACRule<A>>("abac/" + entityId, { flag });
|
|
60
|
+
for (const rule of rules) {
|
|
61
|
+
try {
|
|
62
|
+
const conditions = new Function("user", "entity", `return ${rule.conditions}`)();
|
|
63
|
+
if (debugLog >= 1)
|
|
64
|
+
console.log(
|
|
65
|
+
COLORS.blue + `[GW] ABAC rule: ${COLORS.yellow}${rule.conditions}${COLORS.blue} ` +
|
|
66
|
+
`-> ${COLORS.yellow}${conditions(user, entityId)}` + COLORS.reset
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
if (conditions(user, entityId)) return true;
|
|
70
|
+
} catch (e) {
|
|
71
|
+
if (debugLog >= 1) console.log(COLORS.red + `[GW] ABAC rule error: ${e}` + COLORS.reset);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function matchPermission<A>(
|
|
78
|
+
db: Valthera,
|
|
79
|
+
entityId: Id,
|
|
80
|
+
flag: number,
|
|
81
|
+
user: User<A>,
|
|
82
|
+
debugLog: number
|
|
83
|
+
): Promise<AccessResult> {
|
|
84
|
+
const checks = [
|
|
85
|
+
{ name: "ACL", method: aclCheck },
|
|
86
|
+
{ name: "RBAC", method: rbacCheck },
|
|
87
|
+
{ name: "ABAC", method: abacCheck },
|
|
88
|
+
] as const;
|
|
89
|
+
|
|
90
|
+
const results = [];
|
|
91
|
+
|
|
92
|
+
const checkParams: CheckParams<A> = { db, entityId, flag, user, debugLog };
|
|
93
|
+
for (const check of checks) {
|
|
94
|
+
const result = await check.method(checkParams);
|
|
95
|
+
results.push(result);
|
|
96
|
+
if (result === true || result === 1) {
|
|
97
|
+
return { granted: true, via: check.name };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (results[0] === -1) {
|
|
102
|
+
return { granted: false, via: "entity-404" };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { granted: false, via: null };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class GateWarden<A = any> {
|
|
109
|
+
private db: Valthera;
|
|
110
|
+
|
|
111
|
+
constructor(valthera: string | Valthera, public debugLog: number = 0) {
|
|
112
|
+
this.db = createDb(valthera);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async hasAccess(userId: string, entityId: string, flag: number): Promise<AccessResult> {
|
|
116
|
+
const user = await fetchUser<A>(this.db, userId);
|
|
117
|
+
if (!user) {
|
|
118
|
+
if (this.debugLog >= 1) console.log(COLORS.red + "[GW] User not found." + COLORS.reset);
|
|
119
|
+
return {
|
|
120
|
+
granted: false,
|
|
121
|
+
via: "user-404"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const matched = await matchPermission(this.db, entityId, flag, user, this.debugLog);
|
|
126
|
+
|
|
127
|
+
if (matched.granted) {
|
|
128
|
+
logAccess(userId, entityId, matched.via, this.debugLog);
|
|
129
|
+
return matched;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!matched.granted && matched.via === "entity-404") {
|
|
133
|
+
if (this.debugLog >= 1) console.log(COLORS.red + `[GW] Entity not found: ${entityId}` + COLORS.reset);
|
|
134
|
+
return matched;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.debugLog >= 1) console.log(COLORS.red + `[GW] Access denied to ${entityId} by ${userId}.` + COLORS.reset);
|
|
138
|
+
return {
|
|
139
|
+
granted: false,
|
|
140
|
+
via: "not-permitted"
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export default GateWarden;
|
package/suglite.json
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "ES2022",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"paths": {},
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"inlineSourceMap": false,
|
|
11
|
+
"sourceMap": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"./src"
|
|
17
|
+
],
|
|
18
|
+
"exclude": [
|
|
19
|
+
"node_modules",
|
|
20
|
+
"src/test"
|
|
21
|
+
],
|
|
22
|
+
"tsc-alias": {
|
|
23
|
+
"resolveFullPaths": true,
|
|
24
|
+
"verbose": false
|
|
25
|
+
}
|
|
26
|
+
}
|