security(music): ensure read permission via authz
This commit is contained in:
@@ -159,3 +159,77 @@ Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.items" count == 0
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Step 12 — Cross-tenant regression (post-Drive AuthZ audit,
|
||||
# Round 1 HIGH). Before this fix, `POST /api/favorites/…`
|
||||
# accepted any UUID and enrolled it; the listing endpoint
|
||||
# then JOINed back to storage.files/folders and returned
|
||||
# name/mime/size/drive_id for anything the caller had
|
||||
# managed to add — an information oracle over the whole
|
||||
# tenant. Now the write path calls `authz.require(Read, …)`
|
||||
# per item; a caller with no grant gets 404 (anti-enum)
|
||||
# + `authz.denied` audit line. See
|
||||
# `docs/plan/authz_audit/rest_storage.md`.
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
# Create a second, unprivileged user. Idempotent: `HTTP *` accepts
|
||||
# either 201 (first run) or 409 (subsequent runs). The login below
|
||||
# is the actual precondition — if it succeeds we know the user
|
||||
# exists with the expected password.
|
||||
POST {{base_url}}/api/admin/users
|
||||
Authorization: Bearer {{token}}
|
||||
Content-Type: application/json
|
||||
{ "username": "fav_mallory", "password": "FavMalloryPassword1!", "email": "fav_mallory@example.com", "role": "user" }
|
||||
|
||||
HTTP *
|
||||
|
||||
|
||||
POST {{base_url}}/api/auth/login
|
||||
Content-Type: application/json
|
||||
{ "username": "fav_mallory", "password": "FavMalloryPassword1!" }
|
||||
|
||||
HTTP 200
|
||||
[Captures]
|
||||
mallory_token: jsonpath "$.access_token"
|
||||
|
||||
|
||||
# Step 12a — Single-add on admin's file: 404 (anti-enum shape).
|
||||
POST {{base_url}}/api/favorites/file/{{file_id}}
|
||||
Authorization: Bearer {{mallory_token}}
|
||||
|
||||
HTTP 404
|
||||
|
||||
|
||||
# Step 12b — Single-add on admin's folder: 404.
|
||||
POST {{base_url}}/api/favorites/folder/{{test1_id}}
|
||||
Authorization: Bearer {{mallory_token}}
|
||||
|
||||
HTTP 404
|
||||
|
||||
|
||||
# Step 12c — Batch: must fail wholesale on the first denial. A partial
|
||||
# success would still leak "which items are valid" — the same
|
||||
# oracle we're closing.
|
||||
POST {{base_url}}/api/favorites/batch
|
||||
Authorization: Bearer {{mallory_token}}
|
||||
Content-Type: application/json
|
||||
{
|
||||
"items": [
|
||||
{ "item_id": "{{file_id}}", "item_type": "file" },
|
||||
{ "item_id": "{{test1_id}}", "item_type": "folder" }
|
||||
]
|
||||
}
|
||||
|
||||
HTTP 404
|
||||
|
||||
|
||||
# Step 12d — Mallory's favorites list is EMPTY — no partial success
|
||||
# slipped through.
|
||||
GET {{base_url}}/api/favorites/resources
|
||||
Authorization: Bearer {{mallory_token}}
|
||||
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.items" count == 0
|
||||
|
||||
Reference in New Issue
Block a user