List and revoke portal members under Admin → Users
GET /cloud/members asks the portal who it admits to this instance and
marks those with a local user. DELETE /cloud/members/{portal_sub} takes a
membership back. Admin → Users lists the members who have not arrived
yet, with Revoke, which also surfaces a membership left standing when a
local user was deleted while the portal could not be told.
This commit is contained in:
@@ -717,3 +717,58 @@ def test_a_member_removed_at_the_portal_loses_their_user(db: Session) -> None:
|
||||
assert db.get(User, boss_id) is not None
|
||||
db.delete(boss)
|
||||
db.commit()
|
||||
|
||||
|
||||
def test_admin_lists_and_revokes_portal_members(
|
||||
client: TestClient,
|
||||
enrolled: User, # noqa: ARG001 (fixture installs the enrolment)
|
||||
superuser_token_headers: dict[str, str],
|
||||
normal_user_token_headers: dict[str, str],
|
||||
db: Session,
|
||||
) -> None:
|
||||
"""Who the portal admits, and which of them have arrived here."""
|
||||
arrived = create_random_user(db)
|
||||
arrived.portal_sub = str(uuid.uuid4())
|
||||
db.add(arrived)
|
||||
db.commit()
|
||||
waiting = str(uuid.uuid4())
|
||||
listed = Mock(
|
||||
status_code=200,
|
||||
json=Mock(
|
||||
return_value={
|
||||
"data": [
|
||||
{"user_id": arrived.portal_sub, "email": arrived.email},
|
||||
{"user_id": waiting, "email": "invited@example.com"},
|
||||
]
|
||||
}
|
||||
),
|
||||
)
|
||||
with patch("fluksio.api.routes.cloud.httpx.get", return_value=listed) as get:
|
||||
members = client.get(
|
||||
f"{settings.API_V1_STR}/cloud/members", headers=superuser_token_headers
|
||||
)
|
||||
assert members.status_code == 200, members.text
|
||||
assert get.call_args.args[0].endswith("/instance-members/")
|
||||
assert {row["user_id"]: row["local_user_id"] for row in members.json()} == {
|
||||
arrived.portal_sub: str(arrived.id),
|
||||
waiting: None,
|
||||
}
|
||||
|
||||
with patch(
|
||||
"fluksio.api.routes.cloud.httpx.delete", return_value=Mock(status_code=200)
|
||||
) as delete:
|
||||
revoked = client.delete(
|
||||
f"{settings.API_V1_STR}/cloud/members/{waiting}",
|
||||
headers=superuser_token_headers,
|
||||
)
|
||||
assert revoked.status_code == 200, revoked.text
|
||||
assert delete.call_args.args[0].endswith(f"/instance-members/{waiting}")
|
||||
|
||||
assert (
|
||||
client.get(
|
||||
f"{settings.API_V1_STR}/cloud/members", headers=normal_user_token_headers
|
||||
).status_code
|
||||
== 403
|
||||
)
|
||||
db.delete(arrived)
|
||||
db.commit()
|
||||
|
||||
Reference in New Issue
Block a user