diff --git a/blah-types/src/msg.rs b/blah-types/src/msg.rs index c4bb1bd..f30d393 100644 --- a/blah-types/src/msg.rs +++ b/blah-types/src/msg.rs @@ -377,7 +377,6 @@ pub struct UpdateMemberPayload { pub enum RoomAdminOp { AddMember(AddMemberPayload), RemoveMember(RemoveMemberPayload), - // TODO: R } bitflags::bitflags! { diff --git a/blahd/src/lib.rs b/blahd/src/lib.rs index 7302c69..85c693f 100644 --- a/blahd/src/lib.rs +++ b/blahd/src/lib.rs @@ -149,7 +149,7 @@ impl AppState { type ArcState = State>; pub fn router(st: Arc) -> Router { - use axum::routing::{delete, get, post}; + use axum::routing::{get, post}; // NB. Use consistent handler naming: `_[_
]`. // Use prefix `list` for GET with pagination. @@ -171,7 +171,7 @@ pub fn router(st: Arc) -> Router { // TODO!: remove this. .route("/room/:rid/admin", post(post_room_admin)) .route("/room/:rid/member", get(list_room_member).post(post_room_member)) - .route("/room/:rid/member/:uid", delete(delete_room_member).patch(patch_room_member)) + .route("/room/:rid/member/:uid", get(get_room_member).delete(delete_room_member).patch(patch_room_member)) ; let router = router @@ -527,6 +527,23 @@ async fn post_room_member( }) } +async fn get_room_member( + st: ArcState, + R(Path((rid, id_key)), _): RE>, + Auth(user): Auth, +) -> Result, ApiError> { + st.db.with_read(|txn| { + // Check membership. + let _ = txn.get_room_member(rid, &user)?; + let (_uid, permission, last_seen_cid) = txn.get_room_member_by_id_key(rid, &id_key)?; + Ok(Json(RoomMember { + id_key, + permission, + last_seen_cid: (last_seen_cid != Id(0)).then_some(last_seen_cid), + })) + }) +} + async fn delete_room_member( st: ArcState, R(Path((rid, id_key)), _): RE>, diff --git a/blahd/tests/webapi.rs b/blahd/tests/webapi.rs index 415c659..165a6b1 100644 --- a/blahd/tests/webapi.rs +++ b/blahd/tests/webapi.rs @@ -1711,7 +1711,7 @@ async fn room_mgmt_remove(server: Server) { #[rstest] #[tokio::test] -async fn room_mgmt_update_perm(server: Server) { +async fn room_mgmt_perm(server: Server) { let rid = server .create_room(&ALICE, RoomAttrs::PUBLIC_JOINABLE, "public") .await @@ -1721,6 +1721,22 @@ async fn room_mgmt_update_perm(server: Server) { .await .unwrap(); + let get_bob = || { + server.get::( + &format!("/room/{rid}/member/{}", BOB.pubkeys.id_key), + Some(&auth(&BOB)), + ) + }; + // Initial permission. + assert_eq!( + get_bob().await.unwrap(), + RoomMember { + id_key: BOB.pubkeys.id_key.clone(), + permission: MemberPermission::MAX_SELF_ADD, + last_seen_cid: None, + } + ); + // OK, Alice grants Bob permission to change permission. server .update_member_perm( @@ -1731,6 +1747,10 @@ async fn room_mgmt_update_perm(server: Server) { ) .await .unwrap(); + assert_eq!( + get_bob().await.unwrap().permission, + MemberPermission::POST_CHAT | MemberPermission::UPDATE_MEMBER + ); // Cannot restrict a member with higher permission. server @@ -1743,6 +1763,10 @@ async fn room_mgmt_update_perm(server: Server) { .update_member_perm(rid, &BOB, &BOB, MemberPermission::empty()) .await .unwrap(); + assert_eq!( + get_bob().await.unwrap().permission, + MemberPermission::empty(), + ); // Cannot self-grant permission. server @@ -1761,6 +1785,10 @@ async fn room_mgmt_update_perm(server: Server) { .update_member_perm(rid, &ALICE, &BOB, MemberPermission::POST_CHAT) .await .unwrap(); + assert_eq!( + get_bob().await.unwrap().permission, + MemberPermission::POST_CHAT, + ); // Bob can chat again. server.post_chat(rid, &BOB, "yay").await.unwrap(); diff --git a/docs/webapi.yaml b/docs/webapi.yaml index 2b0137e..9b48a02 100644 --- a/docs/webapi.yaml +++ b/docs/webapi.yaml @@ -595,6 +595,32 @@ paths: $ref: '#/components/schemas/ApiError' /_blah/room/{rid}/member/{member_id_key}: + get: + summary: Get information of a room member + + parameters: + - name: Authorization + in: header + description: User authentication token. + schema: + $ref: '#/components/schemas/Signed-Auth' + + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/RoomMember' + + 404: + description: | + Room does not exist, the user does not have permission for the + operation, or the operand user is not a room member. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + patch: summary: Update permission of a room member