fix(ui): подтверждать применение OSPF и согласовать права
This commit is contained in:
1 parent
bf2815b5a4
commit
c88e1400bf
8 files changed
+147
-35
No files matched your search
@@ -13,7 +13,7 @@
|
||||
"db:studio": "drizzle-kit studio",
|
||||
"db:migrate-from-sqlite": "tsx src/scripts/migrate-sqlite-to-pg.ts",
|
||||
"facts:rebuild": "tsx src/scripts/rebuild-flow-facts.ts",
|
||||
"test:auth": "tsx src/lib/permissions.test.ts && tsx src/plugins/auth.smoke.test.ts",
|
||||
"test:auth": "tsx src/lib/permissions.test.ts && tsx src/plugins/auth.smoke.test.ts && tsx src/plugins/auth.ospf-optimizer.test.ts",
|
||||
"test:wireguard": "npx tsx src/services/wireguard-config.test.ts",
|
||||
"test:traffic-rate": "tsx src/services/traffic-rate.test.ts",
|
||||
"test:traffic-flow": "tsx src/services/traffic-flow-parse.test.ts && tsx src/services/traffic-flow-map-exporter.test.ts && tsx src/services/traffic-flow-ifaces.test.ts && tsx src/services/traffic-flow-ifindex.test.ts && tsx src/services/traffic-flow-dedup.test.ts && tsx src/services/traffic-flow-planes.test.ts && tsx src/services/traffic-flow-ip.test.ts && tsx src/services/traffic-flow-dest.test.ts && tsx src/services/traffic-flow-classify.test.ts && tsx src/services/traffic-flow-ripe.test.ts && tsx src/services/traffic-flow-brands.test.ts && tsx src/services/traffic-flow-ingest.test.ts && tsx src/services/traffic-flow-analytics.test.ts && tsx src/services/traffic-flow-map-hops.test.ts && tsx src/services/traffic-flow-purge.test.ts && tsx src/services/traffic-flow-geoip.test.ts && tsx src/services/traffic-flow-facts.test.ts && tsx src/services/traffic-flow-facts-filter.test.ts && tsx src/services/traffic-flow-facts-rebuild.test.ts && tsx src/services/statistics-aggregate.test.ts",
|
||||
|
||||
@@ -61,4 +61,9 @@ assert.equal(hasPermission(["mm:settings:admin"], "mm:users:read"), true)
|
||||
assert.equal(hasPermission(["mm:settings:admin"], "mm:users:write"), true)
|
||||
assert.equal(hasPermission(["mm:dashboard:read"], "mm:users:write"), false)
|
||||
|
||||
assert.equal(permissionForRequest("GET","/api/servers/1/ospf"),"mm:network:read")
|
||||
assert.equal(permissionForRequest("POST","/api/servers/1/ospf/optimize/preview?x=1"),"mm:network:read")
|
||||
assert.equal(permissionForRequest("POST","/api/servers/1/ospf/optimize"),"mm:network:write")
|
||||
assert.equal(permissionForRequest("POST","/api/servers/1/ospf/optimize/preview/extra"),"mm:network:write")
|
||||
assert.equal(permissionForRequest("PUT","/api/servers/1"),"mm:servers:write")
|
||||
console.log("permissions.test.ts: ok")
|
||||
@@ -42,6 +42,22 @@ type Rule = {
|
||||
}
|
||||
|
||||
const RULES: Rule[] = [
|
||||
{
|
||||
methods: ["GET"],
|
||||
match: p => /^\/api\/servers\/\d+\/ospf(?:\/|$)/.test(p),
|
||||
permission: "mm:network:read",
|
||||
},
|
||||
{
|
||||
methods: ["POST"],
|
||||
match: p => /^\/api\/servers\/\d+\/ospf\/optimize\/preview$/.test(p),
|
||||
permission: "mm:network:read",
|
||||
},
|
||||
{
|
||||
methods: ["POST", "PUT", "PATCH", "DELETE"],
|
||||
match: p => /^\/api\/servers\/\d+\/ospf(?:\/|$)/.test(p),
|
||||
permission: "mm:network:write",
|
||||
},
|
||||
|
||||
{
|
||||
methods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
||||
match: (p) =>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import assert from "node:assert/strict"
|
||||
import Fastify from "fastify"
|
||||
import {SignJWT} from "jose"
|
||||
process.env.AUTH_REQUIRED="true"
|
||||
process.env.AUTH_JWT_SECRET="optimizer-test-secret"
|
||||
process.env.AUTH_ISSUER="https://auth.test.local"
|
||||
process.env.NODE_ENV="test"
|
||||
const {default:authPlugin,requireAuth}=await import("./auth.js")
|
||||
const app=Fastify()
|
||||
await app.register(authPlugin)
|
||||
app.addHook("preHandler",requireAuth)
|
||||
let reads=0,writes=0
|
||||
app.post("/api/servers/:id/ospf/optimize/preview",async()=>{reads++;return {ok:true}})
|
||||
app.post("/api/servers/:id/ospf/optimize",async()=>{writes++;return {ok:true}})
|
||||
const secret=new TextEncoder().encode("optimizer-test-secret")
|
||||
for(const permission of ["mm:network:read","mm:network:write","mm:servers:write"]){
|
||||
const token=await new SignJWT({sub:"reader",apps:["mm"],permissions:[permission]}).setProtectedHeader({alg:"HS256"}).setIssuer("https://auth.test.local").setExpirationTime("1h").sign(secret)
|
||||
const headers={authorization:"Bearer "+token}
|
||||
const preview=await app.inject({method:"POST",url:"/api/servers/1/ospf/optimize/preview",headers})
|
||||
const apply=await app.inject({method:"POST",url:"/api/servers/1/ospf/optimize",headers})
|
||||
assert.equal(preview.statusCode,permission==="mm:servers:write"?403:200)
|
||||
assert.equal(apply.statusCode,permission==="mm:network:write"?200:403)
|
||||
}
|
||||
assert.equal(reads,2);assert.equal(writes,1)
|
||||
assert.equal((await app.inject({method:"POST",url:"/api/servers/1/ospf/optimize"})).statusCode,401)
|
||||
await app.close()
|
||||
console.log("OSPF optimizer RBAC: signed JWT read/write/servers-only, no DB/RouterOS")
|
||||
Reference in new issue
Block a user