simple-authz 1.0.2 → 1.0.4
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/README.md +47 -2
- package/lib/core/authz.js +89 -0
- package/package.json +8 -4
- package/simple-authz-1.0.3.tgz +0 -0
- package/simple-authz-1.0.4.tgz +0 -0
package/README.md
CHANGED
|
@@ -153,7 +153,7 @@ const allowed = authz.can(user, "edit", "listing", listing)
|
|
|
153
153
|
Example usage:
|
|
154
154
|
|
|
155
155
|
```javascript
|
|
156
|
-
if(authz.can(user,"edit","listing",listing)){
|
|
156
|
+
if(authz.can(user,"edit", "listing", listing)){
|
|
157
157
|
updateListing()
|
|
158
158
|
}else{
|
|
159
159
|
throw new Error("Access denied")
|
|
@@ -162,6 +162,51 @@ if(authz.can(user,"edit","listing",listing)){
|
|
|
162
162
|
|
|
163
163
|
---
|
|
164
164
|
|
|
165
|
+
## 5. `authz.explain()` (Optional)
|
|
166
|
+
|
|
167
|
+
The `authz.explain()` method helps debug authorization decisions by returning detailed information about **why access was allowed or denied**.
|
|
168
|
+
|
|
169
|
+
Unlike `authz.can()`, which returns only `true` or `false`, this method returns an object explaining the result.
|
|
170
|
+
|
|
171
|
+
### Usage
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
authz.explain(user, "edit", "listing", listing)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Example
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
const result = authz.explain(user, "edit", "listing", listing)
|
|
181
|
+
|
|
182
|
+
console.log(result)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Example Output
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
{
|
|
189
|
+
allowed: true,
|
|
190
|
+
role: "user",
|
|
191
|
+
resource: "listing",
|
|
192
|
+
action: "edit",
|
|
193
|
+
reason: "condition passed"
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
If no rule matches:
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
{
|
|
201
|
+
allowed: false,
|
|
202
|
+
reason: "no matching rule"
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Use `authz.explain()` for **debugging and development**, and `authz.can()` for **regular authorization checks**.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
165
210
|
# Core Concepts
|
|
166
211
|
|
|
167
212
|
Simple Authz follows a common authorization model:
|
|
@@ -490,7 +535,7 @@ Steps:
|
|
|
490
535
|
|
|
491
536
|
# License
|
|
492
537
|
|
|
493
|
-
|
|
538
|
+
This project is licensed under the [Apache 2.0 license](LICENSE).
|
|
494
539
|
|
|
495
540
|
---
|
|
496
541
|
|
package/lib/core/authz.js
CHANGED
|
@@ -76,6 +76,95 @@ class Authz {
|
|
|
76
76
|
|
|
77
77
|
return false
|
|
78
78
|
}
|
|
79
|
+
|
|
80
|
+
explain(user, action, resourceType, data = {}) {
|
|
81
|
+
|
|
82
|
+
const roles = normalizeUser(user)
|
|
83
|
+
|
|
84
|
+
for (const role of roles) {
|
|
85
|
+
|
|
86
|
+
const rolePerm = this.permissions[role]
|
|
87
|
+
|
|
88
|
+
// ---------- Permission check ----------
|
|
89
|
+
if (rolePerm) {
|
|
90
|
+
|
|
91
|
+
const resourcePerm = rolePerm[resourceType]
|
|
92
|
+
|
|
93
|
+
if (resourcePerm) {
|
|
94
|
+
|
|
95
|
+
if (resourcePerm.has("*") || resourcePerm.has(action)) {
|
|
96
|
+
return {
|
|
97
|
+
allowed: true,
|
|
98
|
+
role,
|
|
99
|
+
resource: resourceType,
|
|
100
|
+
action,
|
|
101
|
+
reason: "direct permission match"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (rolePerm["*"]) {
|
|
107
|
+
if (rolePerm["*"].has("*") || rolePerm["*"].has(action)) {
|
|
108
|
+
return {
|
|
109
|
+
allowed: true,
|
|
110
|
+
role,
|
|
111
|
+
resource: "*",
|
|
112
|
+
action,
|
|
113
|
+
reason: "wildcard permission"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ---------- Condition check ----------
|
|
120
|
+
const roleCond = this.conditions[role]
|
|
121
|
+
|
|
122
|
+
if (!roleCond) continue
|
|
123
|
+
|
|
124
|
+
const resourceCond = roleCond[resourceType]
|
|
125
|
+
|
|
126
|
+
if (!resourceCond) continue
|
|
127
|
+
|
|
128
|
+
const actionCond = resourceCond[action]
|
|
129
|
+
|
|
130
|
+
if (!actionCond) continue
|
|
131
|
+
|
|
132
|
+
for (const cond of actionCond) {
|
|
133
|
+
|
|
134
|
+
const context = {
|
|
135
|
+
user,
|
|
136
|
+
[resourceType]: data
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const result = evaluateAST(cond, context)
|
|
140
|
+
|
|
141
|
+
if (result) {
|
|
142
|
+
return {
|
|
143
|
+
allowed: true,
|
|
144
|
+
role,
|
|
145
|
+
resource: resourceType,
|
|
146
|
+
action,
|
|
147
|
+
reason: "condition passed",
|
|
148
|
+
condition: cond
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
allowed: false,
|
|
155
|
+
role,
|
|
156
|
+
resource: resourceType,
|
|
157
|
+
action,
|
|
158
|
+
reason: "condition failed"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
allowed: false,
|
|
165
|
+
reason: "no matching rule"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
79
168
|
}
|
|
80
169
|
|
|
81
170
|
module.exports = Authz
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simple-authz",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "lib/
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "Lightweight policy-based authorization engine for Node.js using TOON policy language",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node bin/test.js",
|
|
8
8
|
"dev": "node lib/core/authz.js"
|
|
@@ -28,5 +28,9 @@
|
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
30
30
|
"url": "https://github.com/dhruvil05/simple-authz"
|
|
31
|
-
}
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/dhruvil05/simple-authz/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/dhruvil05/simple-authz#readme"
|
|
32
36
|
}
|
|
Binary file
|
|
Binary file
|