mirror of
https://github.com/Blah-IM/blahrs.git
synced 2025-06-30 19:45:34 +00:00
feat(blahd): impl non-self member removal
This commit is contained in:
parent
a8c29cb9b2
commit
ad4a38cf43
5 changed files with 101 additions and 12 deletions
|
@ -220,6 +220,26 @@ pub trait TransactionOps {
|
|||
.and_then(|row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))
|
||||
}
|
||||
|
||||
fn get_room_member_by_id_key(
|
||||
&self,
|
||||
rid: Id,
|
||||
id_key: &PubKey,
|
||||
) -> Result<(i64, MemberPermission, Id)> {
|
||||
prepare_cached_and_bind!(
|
||||
self.conn(),
|
||||
r"
|
||||
SELECT `uid`, `room_member`.`permission`, `last_seen_cid`
|
||||
FROM `room_member`
|
||||
JOIN `user` USING (`uid`)
|
||||
WHERE (`rid`, `id_key`) = (:rid, :id_key)
|
||||
"
|
||||
)
|
||||
.raw_query()
|
||||
.next()?
|
||||
.ok_or(ApiError::MemberNotFound)
|
||||
.and_then(|row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))
|
||||
}
|
||||
|
||||
fn get_room_having(&self, rid: Id, filter: RoomAttrs) -> Result<(RoomAttrs, Option<String>)> {
|
||||
prepare_cached_and_bind!(
|
||||
self.conn(),
|
||||
|
@ -527,7 +547,7 @@ pub trait TransactionOps {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_room_member(&self, rid: Id, uid: i64) -> Result<bool> {
|
||||
fn remove_room_member(&self, rid: Id, uid: i64) -> Result<()> {
|
||||
// TODO: Check if it is the last member?
|
||||
let updated = prepare_cached_and_bind!(
|
||||
self.conn(),
|
||||
|
@ -537,7 +557,10 @@ pub trait TransactionOps {
|
|||
"
|
||||
)
|
||||
.raw_execute()?;
|
||||
Ok(updated == 1)
|
||||
if updated != 1 {
|
||||
return Err(ApiError::UserNotFound);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_room_chat_msg(&self, rid: Id, uid: i64, cid: Id, chat: &SignedChatMsg) -> Result<()> {
|
||||
|
|
|
@ -539,17 +539,23 @@ async fn delete_room_member(
|
|||
);
|
||||
let tgt_user = op.signee.payload.user;
|
||||
api_ensure!(id_key == tgt_user, "user id mismatch with URI");
|
||||
api_ensure!(
|
||||
op.signee.user.id_key == tgt_user,
|
||||
ApiError::NotImplemented("only self-removal is implemented yet"),
|
||||
);
|
||||
let is_self_removal = op.signee.user.id_key == tgt_user;
|
||||
|
||||
st.db.with_write(|txn| {
|
||||
let (uid, ..) = txn.get_room_member(rid, &op.signee.user)?;
|
||||
let (uid, perm, _) = txn.get_room_member(rid, &op.signee.user)?;
|
||||
api_ensure!(
|
||||
is_self_removal || perm.contains(MemberPermission::REMOVE_MEMBER),
|
||||
ApiError::PermissionDenied("the user does not have permission to remove members")
|
||||
);
|
||||
let (attrs, _) = txn.get_room_having(rid, RoomAttrs::empty())?;
|
||||
// Sanity check.
|
||||
assert!(!attrs.contains(RoomAttrs::PEER_CHAT));
|
||||
txn.remove_room_member(rid, uid)?;
|
||||
let tgt_uid = if is_self_removal {
|
||||
uid
|
||||
} else {
|
||||
txn.get_room_member_by_id_key(rid, &tgt_user)?.0
|
||||
};
|
||||
txn.remove_room_member(rid, tgt_uid)?;
|
||||
Ok(NoContent)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ pub enum ApiError {
|
|||
UserNotFound = (StatusCode::NOT_FOUND, "the user does not exist"),
|
||||
RoomNotFound = (StatusCode::NOT_FOUND, "the room does not exist or the user is not a room member"),
|
||||
PeerUserNotFound = (StatusCode::NOT_FOUND, "peer user does not exist or disallows peer chat"),
|
||||
MemberNotFound = (StatusCode::NOT_FOUND, "the operand user is not a room member"),
|
||||
Conflict(&'static str) = (StatusCode::CONFLICT),
|
||||
Exists(&'static str) = (StatusCode::CONFLICT),
|
||||
FetchIdDescription(Box<str>) = (StatusCode::UNPROCESSABLE_ENTITY),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue