Improve how users can access visible applications and files
Refactor `getVisibleAppsForUser` into a new file `appsVisibility.ts` and update existing imports. Add a new test case for app icon object authorization. Modify the `objectAuthz.ts` file to use a more precise JSONB path check for meeting attachments. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: d1d78e3b-ae14-4da2-b782-586269e0ef7e Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/jLdqQ2v Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -363,6 +363,75 @@ test("J: GET /executive-meetings/pdf-archives by executive_viewer → 200", asyn
|
||||
assert.ok(ours, "the seeded archive row must be visible to executive_viewer");
|
||||
});
|
||||
|
||||
// ---- L: app-icon authz mirrors launcher RBAC ----------------------
|
||||
test("L: app-icon object: user with app permission streams body, restricted user 404", async () => {
|
||||
// Upload a real icon, attach it to a freshly-created app, then
|
||||
// restrict the app via a unique permission. Only users granted
|
||||
// that permission (here: admin) should see the icon stream.
|
||||
const presignRes = await fetch(
|
||||
`${API_BASE}/api/storage/uploads/request-url`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", cookie: adminCookie },
|
||||
body: JSON.stringify({
|
||||
name: "app-icon.bin",
|
||||
size: 8,
|
||||
contentType: "application/octet-stream",
|
||||
}),
|
||||
},
|
||||
);
|
||||
assert.equal(presignRes.status, 200);
|
||||
const { uploadURL, objectPath } = await presignRes.json();
|
||||
const payload = "iconbyt";
|
||||
const putRes = await fetch(uploadURL, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/octet-stream" },
|
||||
body: payload,
|
||||
});
|
||||
assert.ok(putRes.status >= 200 && putRes.status < 300);
|
||||
|
||||
const appSlug = `obj_authz_app_${STAMP}`;
|
||||
const permName = `obj_authz_perm_${STAMP}`;
|
||||
const appRow = await pool.query(
|
||||
`INSERT INTO apps (slug, name_en, name_ar, route, image_url)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id`,
|
||||
[appSlug, appSlug, appSlug, `/${appSlug}`, objectPath],
|
||||
);
|
||||
const appId = appRow.rows[0].id;
|
||||
const permRow = await pool.query(
|
||||
`INSERT INTO permissions (name) VALUES ($1) RETURNING id`,
|
||||
[permName],
|
||||
);
|
||||
const permId = permRow.rows[0].id;
|
||||
await pool.query(
|
||||
`INSERT INTO app_permissions (app_id, permission_id) VALUES ($1, $2)`,
|
||||
[appId, permId],
|
||||
);
|
||||
|
||||
try {
|
||||
const tail = objectPath.replace("/objects/", "");
|
||||
|
||||
// Admin — sees every app via getVisibleAppsForUser short-circuit.
|
||||
const allow = await fetch(`${API_BASE}/api/storage/objects/${tail}`, {
|
||||
headers: { cookie: adminCookie },
|
||||
});
|
||||
assert.equal(allow.status, 200, `admin expected 200, got ${allow.status}`);
|
||||
assert.equal(await allow.text(), payload, "admin should stream the icon bytes");
|
||||
|
||||
// Receiver — has no role granting permName, no group_apps row.
|
||||
// Must be denied at authz → 404.
|
||||
const deny = await fetch(`${API_BASE}/api/storage/objects/${tail}`, {
|
||||
headers: { cookie: receiverCookie },
|
||||
});
|
||||
assert.equal(deny.status, 404, `receiver expected 404, got ${deny.status}`);
|
||||
} finally {
|
||||
await pool.query(`DELETE FROM app_permissions WHERE app_id = $1`, [appId]);
|
||||
await pool.query(`DELETE FROM permissions WHERE id = $1`, [permId]);
|
||||
await pool.query(`DELETE FROM apps WHERE id = $1`, [appId]);
|
||||
}
|
||||
});
|
||||
|
||||
// ---- K: positive + negative on the SAME real brand-logo object ----
|
||||
test("K: brand-logo object: executive_viewer streams body 200, non-executive 404", async () => {
|
||||
// Upload a real file as admin (any authed can presign), wire it to
|
||||
|
||||
Reference in New Issue
Block a user