ruby_ability_graph 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/ruby_ability_graph/html_report.rb +42 -8
- data/lib/ruby_ability_graph/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bd1d62067dae4acb3905ddcd4fc1b47833a4135dd6131cc91911098a28d46cb
|
|
4
|
+
data.tar.gz: 1d1d37df3d8ee78d1a08f850619ef08d7fc798eebac8680d40525c17f07dc432
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 44c8aa407082a81a668d572969e640395c564743e649aed7919fd8e03040451eb9836bfadda369281a426f7ac152cf48f7971eb3d05552a26683b69e67de7f73
|
|
7
|
+
data.tar.gz: 10260b71a1e46489661c61db10f0c4e7239df8201b74a2cc5b1bf9f2da84c6ad5068bb3c24cf5a37b1a82ab46f659a94f2f6245c4b6b0535928ad07373cd57b4
|
data/README.md
CHANGED
|
@@ -145,7 +145,7 @@ Note: a policy check is only as trustworthy as the underlying result's `confiden
|
|
|
145
145
|
ruby-ability-graph scan APP_PATH --html-report report.html
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
Writes a single, self-contained HTML file -- inlined CSS/JS, no server, no CDN assets, nothing fetched over the network -- showing an interactive role → action → resource graph. Hover a role to trace everything it can reach; hover an edge for the underlying condition and confidence.
|
|
148
|
+
Writes a single, self-contained HTML file -- inlined CSS/JS, no server, no CDN assets, nothing fetched over the network -- showing an interactive role → action → resource graph. Hover a role to trace everything it can reach; hover an edge for the underlying condition and confidence. Each edge bundles many underlying rows (a role→action edge spans every model that pair touches), so its color reflects the fraction resolved: solid green at 100%, solid amber-to-green gradient in between, dashed amber at 0% (`unsupported`), and solid red wherever a `--policy-file` check (if given) found a violation. A coverage line at the top mirrors the table's resolved/total summary. Only `allowed: true` results become edges -- it's a "who can access what" diagram, not a dump of every denial.
|
|
149
149
|
|
|
150
150
|

|
|
151
151
|
|
|
@@ -73,6 +73,7 @@ module RubyAbilityGraph
|
|
|
73
73
|
#legend span { display: inline-flex; align-items: center; gap: 6px; }
|
|
74
74
|
.swatch { display: inline-block; width: 22px; height: 0; border-top-width: 3px; border-top-style: solid; }
|
|
75
75
|
.swatch.resolved { border-color: var(--good); border-top-style: solid; }
|
|
76
|
+
.swatch.partial { height: 3px; border-top: none; background: linear-gradient(to right, var(--warning), var(--good)); }
|
|
76
77
|
.swatch.unsupported { border-color: var(--warning); border-top-style: dashed; }
|
|
77
78
|
.swatch.violation { border-color: var(--critical); border-top-style: solid; }
|
|
78
79
|
main {
|
|
@@ -123,6 +124,7 @@ module RubyAbilityGraph
|
|
|
123
124
|
</div>
|
|
124
125
|
<div id="legend">
|
|
125
126
|
<span><span class="swatch resolved"></span> Resolved</span>
|
|
127
|
+
<span><span class="swatch partial"></span> Bundled edge, partially resolved -- color shows % resolved</span>
|
|
126
128
|
<span><span class="swatch unsupported"></span> Unsupported -- not analyzed</span>
|
|
127
129
|
<span><span class="swatch violation"></span> Policy violation</span>
|
|
128
130
|
</div>
|
|
@@ -165,9 +167,30 @@ module RubyAbilityGraph
|
|
|
165
167
|
return map;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
// Aggregated edges bundle many rows (e.g. a role->action edge spans every
|
|
171
|
+
// model that pair touches). A single boolean verdict for the whole bundle
|
|
172
|
+
// is misleading at scale: one unsupported row among sixty resolved ones
|
|
173
|
+
// painted the entire edge amber. Color proportionally instead, so an
|
|
174
|
+
// edge that's mostly resolved reads as mostly green.
|
|
175
|
+
var COLOR_WARNING = [250, 178, 25]; // --warning, #fab219
|
|
176
|
+
var COLOR_GOOD = [12, 163, 12]; // --good, #0ca30c
|
|
177
|
+
|
|
178
|
+
function resolvedFraction(rows) {
|
|
179
|
+
var resolved = rows.filter(function (r) { return r.confidence === "resolved"; }).length;
|
|
180
|
+
return resolved / rows.length;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function mixColor(fraction) {
|
|
184
|
+
var rgb = COLOR_WARNING.map(function (c, i) { return Math.round(c + (COLOR_GOOD[i] - c) * fraction); });
|
|
185
|
+
return "rgb(" + rgb.join(",") + ")";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function edgeAppearance(rows) {
|
|
189
|
+
if (rows.some(function (r) { return r.violation; })) { return { cls: "violation" }; }
|
|
190
|
+
var fraction = resolvedFraction(rows);
|
|
191
|
+
if (fraction === 1) { return { cls: "resolved" }; }
|
|
192
|
+
if (fraction === 0) { return { cls: "unsupported" }; }
|
|
193
|
+
return { cls: "partial", style: "stroke:" + mixColor(fraction) + ";" };
|
|
171
194
|
}
|
|
172
195
|
|
|
173
196
|
function groupBy(rows, keyFn, shapeFn) {
|
|
@@ -240,10 +263,13 @@ module RubyAbilityGraph
|
|
|
240
263
|
|
|
241
264
|
function drawEdge(x1, y1, x2, y2, statusRows, store, key) {
|
|
242
265
|
var midX = (x1 + x2) / 2;
|
|
243
|
-
var
|
|
244
|
-
|
|
266
|
+
var appearance = edgeAppearance(statusRows);
|
|
267
|
+
var attrs = {
|
|
268
|
+
"class": "edge " + appearance.cls,
|
|
245
269
|
d: "M " + x1 + "," + y1 + " C " + midX + "," + y1 + " " + midX + "," + y2 + " " + x2 + "," + y2
|
|
246
|
-
}
|
|
270
|
+
};
|
|
271
|
+
if (appearance.style) { attrs.style = appearance.style; }
|
|
272
|
+
var path = svgEl("path", attrs);
|
|
247
273
|
svg.appendChild(path);
|
|
248
274
|
store[key] = path;
|
|
249
275
|
return path;
|
|
@@ -353,14 +379,22 @@ module RubyAbilityGraph
|
|
|
353
379
|
return bits.join(" ");
|
|
354
380
|
}
|
|
355
381
|
|
|
382
|
+
function edgeHeader(a, b, rows) {
|
|
383
|
+
var resolved = rows.filter(function (r) { return r.confidence === "resolved"; }).length;
|
|
384
|
+
var header = a + " → " + b + " -- " + resolved + "/" + rows.length + " resolved";
|
|
385
|
+
var violationCount = rows.filter(function (r) { return r.violation; }).length;
|
|
386
|
+
if (violationCount) { header += ", " + violationCount + " violation(s)"; }
|
|
387
|
+
return header;
|
|
388
|
+
}
|
|
389
|
+
|
|
356
390
|
function raTooltip(edge) {
|
|
357
|
-
return [edge.role
|
|
391
|
+
return [edgeHeader(edge.role, edge.action, edge.rows)]
|
|
358
392
|
.concat(edge.rows.map(function (r) { return rowLine(r.model, r); }))
|
|
359
393
|
.join("\n");
|
|
360
394
|
}
|
|
361
395
|
|
|
362
396
|
function amTooltip(edge) {
|
|
363
|
-
return [edge.action
|
|
397
|
+
return [edgeHeader(edge.action, edge.model, edge.rows)]
|
|
364
398
|
.concat(edge.rows.map(function (r) { return rowLine(r.role, r); }))
|
|
365
399
|
.join("\n");
|
|
366
400
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_ability_graph
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jessica Grider
|
|
@@ -25,8 +25,8 @@ dependencies:
|
|
|
25
25
|
version: '1.0'
|
|
26
26
|
description: |
|
|
27
27
|
ruby_ability_graph loads a Rails app's CanCanCan Ability class in isolation,
|
|
28
|
-
enumerates roles x actions x models, and reports resolved permissions
|
|
29
|
-
|
|
28
|
+
enumerates roles x actions x models, and reports resolved permissions.
|
|
29
|
+
Distinguishes patterns it can fully resolve from ones it doesn't support.
|
|
30
30
|
executables:
|
|
31
31
|
- ruby-ability-graph
|
|
32
32
|
extensions: []
|