feat(learner): owner admin API for roles, groups, course access and library curation
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
668ae379bf
commit
a8a8e32bcb
@@ -0,0 +1,43 @@
|
||||
import { expect } from "bun:test";
|
||||
import { forEachDb } from "./helpers";
|
||||
import { makeApp } from "./app";
|
||||
|
||||
forEachDb("admin API is owner-only and manages roles, groups, access and library", async (db) => {
|
||||
const t = await makeApp(db);
|
||||
const owner = await t.signUp("[email protected]");
|
||||
const learner = await t.signUp("[email protected]");
|
||||
expect((await t.call("GET", "/api/admin/users")).status).toBe(401);
|
||||
expect((await t.call("GET", "/api/admin/users", { cookie: learner })).status).toBe(403);
|
||||
|
||||
const users = await (await t.call("GET", "/api/admin/users", { cookie: owner })).json();
|
||||
expect(users.map((u: { email: string }) => u.email)).toEqual(["[email protected]", "[email protected]"]);
|
||||
const [o, l] = users;
|
||||
|
||||
// the last owner keeps the role
|
||||
expect((await t.call("PUT", `/api/admin/users/${o.id}/roles`, { cookie: owner, body: { roles: ["learner"] } })).status).toBe(409);
|
||||
expect((await t.call("PUT", `/api/admin/users/${l.id}/roles`, { cookie: owner, body: { roles: ["bogus"] } })).status).toBe(400);
|
||||
const r = await t.call("PUT", `/api/admin/users/${l.id}/roles`, { cookie: owner, body: { roles: ["author", "learner"] } });
|
||||
expect((await r.json()).roles).toEqual(["author", "learner"]);
|
||||
expect((await (await t.call("GET", "/api/me", { cookie: learner })).json()).user.roles).toEqual(["author", "learner"]);
|
||||
|
||||
const g = await (await t.call("POST", "/api/admin/groups", { cookie: owner, body: { name: "DevOps Team" } })).json();
|
||||
expect(g.id).toBe("devops-team");
|
||||
await t.call("PUT", `/api/admin/groups/${g.id}/members`, { cookie: owner, body: { userIds: [l.id] } });
|
||||
const groups = await (await t.call("GET", "/api/admin/groups", { cookie: owner })).json();
|
||||
expect(groups).toEqual([{ id: "devops-team", name: "DevOps Team", members: [l.id] }]);
|
||||
expect((await (await t.call("GET", "/api/me", { cookie: learner })).json()).user.groups).toEqual(["devops-team"]);
|
||||
|
||||
await t.call("PUT", "/api/admin/courses/sample/access", { cookie: owner, body: { acl: [{ principal_type: "group", principal_id: g.id }], authors: [l.id] } });
|
||||
const access = await (await t.call("GET", "/api/admin/courses/sample/access", { cookie: owner })).json();
|
||||
expect(access).toEqual({ visibility: "public", acl: [{ principal_type: "group", principal_id: "devops-team" }], authors: [l.id] });
|
||||
expect((await t.call("GET", "/api/admin/courses/nope/access", { cookie: owner })).status).toBe(404);
|
||||
|
||||
const libr = await (await t.call("PUT", "/api/admin/library", { cookie: owner, body: { featured: "sample", collections: [{ title: "Getting started", courseIds: ["sample"] }] } })).json();
|
||||
expect(libr.featured).toBe("sample");
|
||||
expect(libr.collections).toEqual([{ id: "getting-started", title: "Getting started", sort: 0, courseIds: ["sample"] }]);
|
||||
const cleared = await (await t.call("PUT", "/api/admin/library", { cookie: owner, body: { collections: [] } })).json();
|
||||
expect(cleared.collections).toEqual([]);
|
||||
|
||||
await t.call("DELETE", `/api/admin/groups/${g.id}`, { cookie: owner });
|
||||
expect(await (await t.call("GET", "/api/admin/groups", { cookie: owner })).json()).toEqual([]);
|
||||
}, 30_000);
|
||||
Reference in New Issue
Block a user