diff --git a/backend/src/luckperms/test_luckperms.py b/backend/src/luckperms/test_luckperms.py index 98607b12..b75e2950 100644 --- a/backend/src/luckperms/test_luckperms.py +++ b/backend/src/luckperms/test_luckperms.py @@ -230,6 +230,9 @@ def test_mods_see_everything_but_change_nothing(app, bridge, staff, env): assert [r["name"] for r in listing["rows"]] == ["Alice"] and listing["rows"][0]["rank"] == "commoner" members = mod.get("/admin/luckperms/players", params={"group": "staff"}).json() assert {r["name"] for r in members["rows"]} == {"AdminMC", "RootMC"} + staff_detail = mod.get("/admin/luckperms/groups/staff").json() + assert {r["name"]: r["rank"] for r in staff_detail["members"]["rows"]} == {"AdminMC": "staff", "RootMC": "staff"} + assert all("staff" in {g["name"] for g in r["groups"]} for r in staff_detail["members"]["rows"]) detail = mod.get("/admin/luckperms/groups/helper").json()["group"] assert detail["inherits"] == ["helper_inactive", "helper_player", "commoner", "default"] assert detail["tracks"] == ["helper"] and detail["children"] == [] diff --git a/backend/src/luckperms/views.py b/backend/src/luckperms/views.py index 61c8dc15..bfc1e9cb 100644 --- a/backend/src/luckperms/views.py +++ b/backend/src/luckperms/views.py @@ -87,6 +87,7 @@ def group_detail(viewer: dict, name: str) -> dict: counts = mirror.group_counts(conn) tracks = mirror.load_tracks(conn) members = mirror.search_users(conn, "", name, 1) + _add_ranks(conn, members, groups, now) status = mirror.status(conn) group = groups[name] editable = policy.may_edit_definitions(viewer["role"]) @@ -208,6 +209,17 @@ def user_detail(viewer: dict, raw_uuid: str) -> dict: } +def _add_ranks(conn, listing: dict, groups: dict[str, dict], now: int) -> None: + """Give each listed player their active groups and rank, as the player rows show them.""" + for row in listing["rows"]: + held = mirror.user_nodes(conn, row["uuid"]) + row["groups"] = [ + {"name": nodes.group_of(n["key"]), "contexts": n["contexts"], "expiry": n["expiry"]} + for n in held if nodes.group_of(n["key"]) and n["value"] and nodes.active(n, now) + ] + row["rank"] = mirror.rank_group(groups, held, now) + + def users(viewer: dict, q: str, group: str | None, page: int) -> dict: group = (group or "").strip().lower() or None if group is not None and not nodes.GROUP_NAME.match(group): @@ -218,12 +230,5 @@ def users(viewer: dict, q: str, group: str | None, page: int) -> dict: listing = mirror.search_users(conn, q, group, page) except mirror.SnapshotError as exc: raise AdminError(400, exc.code, "invalid") from None - groups = mirror.load_groups(conn) - for row in listing["rows"]: - held = mirror.user_nodes(conn, row["uuid"]) - row["groups"] = [ - {"name": nodes.group_of(n["key"]), "contexts": n["contexts"], "expiry": n["expiry"]} - for n in held if nodes.group_of(n["key"]) and n["value"] and nodes.active(n, now) - ] - row["rank"] = mirror.rank_group(groups, held, now) + _add_ranks(conn, listing, mirror.load_groups(conn), now) return listing diff --git a/frontend/app/components/admin/ranks/RanksOverview.test.tsx b/frontend/app/components/admin/ranks/RanksOverview.test.tsx index 0b371022..f5a11df0 100644 --- a/frontend/app/components/admin/ranks/RanksOverview.test.tsx +++ b/frontend/app/components/admin/ranks/RanksOverview.test.tsx @@ -90,7 +90,12 @@ it("edits a group's weight as a remove and an add", async () => { children: ["gilded"], tracks: [], }, - members: { total: 0, page: 1, page_size: 50, rows: [] }, + members: { + total: 1, + page: 1, + page_size: 50, + rows: [{ uuid: "u", name: "Bob", rank: "noble", groups: [{ name: "noble", contexts: {}, expiry: 0 }] }], + }, all_groups: ["noble", "commoner", "default"], rights: { read_only: false, change_players: true, edit_definitions: true }, changes: [], @@ -100,6 +105,7 @@ it("edits a group's weight as a remove and an add", async () => { vi.mocked(waitForChange).mockResolvedValue({ id: 4, status: "applied" } as LpChange); render(); const settings = await screen.findByRole("region", { name: "Settings" }); + expect(within(screen.getByRole("region", { name: "Members" })).getByText("Bob")).toBeTruthy(); fireEvent.change(within(settings).getByLabelText("Weight"), { target: { value: "25" } }); fireEvent.click(within(settings).getByRole("button", { name: "Save" })); fireEvent.change(within(settings).getByLabelText("Reason (recorded)"), { target: { value: "Reorder ranks" } });