From 985ea1d68af608413c7db530fd5c15570f6f2be2 Mon Sep 17 00:00:00 2001 From: oxalica Date: Mon, 16 Sep 2024 06:19:53 -0400 Subject: [PATCH] remove(types)!: remove `members` from `CreateGroup` Now a group can only be created with the creator as the only initial member. This forbids group creator from adding other members without their consent. Additional members can join the group later at their own will. --- blah-types/src/lib.rs | 3 -- blahctl/src/main.rs | 10 ++---- blahd/src/lib.rs | 71 ++++++++++++++----------------------------- blahd/tests/webapi.rs | 8 ++--- docs/webapi.yaml | 10 ------ 5 files changed, 27 insertions(+), 75 deletions(-) diff --git a/blah-types/src/lib.rs b/blah-types/src/lib.rs index 496a82c..2f9f3c9 100644 --- a/blah-types/src/lib.rs +++ b/blah-types/src/lib.rs @@ -353,9 +353,6 @@ pub enum CreateRoomPayload { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct CreateGroup { pub attrs: RoomAttrs, - /// The initial member list. Besides invariants of `RoomMemberList`, this also must include the - /// room creator themselves, with the highest permission (-1). - pub members: RoomMemberList, pub title: String, } diff --git a/blahctl/src/main.rs b/blahctl/src/main.rs index 6761d67..b309f6f 100644 --- a/blahctl/src/main.rs +++ b/blahctl/src/main.rs @@ -4,8 +4,8 @@ use std::{fs, io}; use anyhow::{Context, Result}; use blah_types::{ - bitflags, get_timestamp, ChatPayload, CreateGroup, CreateRoomPayload, Id, MemberPermission, - RichText, RoomAttrs, RoomMember, RoomMemberList, ServerPermission, Signed, UserKey, + bitflags, get_timestamp, ChatPayload, CreateGroup, CreateRoomPayload, Id, RichText, RoomAttrs, + ServerPermission, Signed, UserKey, }; use ed25519_dalek::pkcs8::spki::der::pem::LineEnding; use ed25519_dalek::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey}; @@ -220,12 +220,6 @@ async fn main_api(api_url: Url, command: ApiCommand) -> Result<()> { let payload = CreateRoomPayload::Group(CreateGroup { attrs: attrs.unwrap_or_default(), title, - // The CLI does not support passing multiple members because `User` itself is a - // disjoint arg-group. - members: RoomMemberList(vec![RoomMember { - permission: MemberPermission::ALL, - user: UserKey(key.verifying_key().to_bytes()), - }]), }); let payload = Signed::sign(&key, get_timestamp(), &mut OsRng, payload)?; diff --git a/blahd/src/lib.rs b/blahd/src/lib.rs index 60f45fe..7368ec9 100644 --- a/blahd/src/lib.rs +++ b/blahd/src/lib.rs @@ -363,44 +363,34 @@ async fn room_create_group( )); } - let members = &op.members.0; - if !members - .iter() - .any(|m| m.user == user && m.permission == MemberPermission::ALL) - { - return Err(error_response!( - StatusCode::BAD_REQUEST, - "deserialization", - "invalid initial members", - )); - } - - let mut conn = st.db.get(); - let Some(true) = conn + let conn = st.db.get(); + let (uid, _perm) = conn .query_row( r" - SELECT `permission` + SELECT `uid`, `permission` FROM `user` WHERE `userkey` = ? ", params![user], |row| { - let perm = row.get::<_, ServerPermission>("permission")?; - Ok(perm.contains(ServerPermission::CREATE_ROOM)) + Ok(( + row.get::<_, i64>("uid")?, + row.get::<_, ServerPermission>("permission")?, + )) }, ) .optional()? - else { - return Err(error_response!( - StatusCode::FORBIDDEN, - "permission_denied", - "user does not have permission to create room", - )); - }; + .filter(|(_, perm)| perm.contains(ServerPermission::CREATE_ROOM)) + .ok_or_else(|| { + error_response!( + StatusCode::FORBIDDEN, + "permission_denied", + "the user does not exist or does not have permission to create room", + ) + })?; - let txn = conn.transaction()?; let rid = Id::gen(); - txn.execute( + conn.execute( r" INSERT INTO `room` (`rid`, `title`, `attrs`) VALUES (:rid, :title, :attrs) @@ -411,32 +401,17 @@ async fn room_create_group( ":attrs": op.attrs, }, )?; - let mut insert_user = txn.prepare( - r" - INSERT INTO `user` (`userkey`) - VALUES (?) - ON CONFLICT (`userkey`) DO NOTHING - ", - )?; - let mut insert_member = txn.prepare( + conn.execute( r" INSERT INTO `room_member` (`rid`, `uid`, `permission`) - SELECT :rid, `uid`, :permission - FROM `user` - WHERE `userkey` = :userkey + VALUES (:rid, :uid, :perm) ", - )?; - for member in members { - insert_user.execute(params![member.user])?; - insert_member.execute(named_params! { + named_params! { ":rid": rid, - ":userkey": member.user, - ":permission": member.permission, - })?; - } - drop(insert_member); - drop(insert_user); - txn.commit()?; + ":uid": uid, + ":perm": MemberPermission::ALL, + }, + )?; Ok(Json(rid)) } diff --git a/blahd/tests/webapi.rs b/blahd/tests/webapi.rs index 3d1602c..126a261 100644 --- a/blahd/tests/webapi.rs +++ b/blahd/tests/webapi.rs @@ -8,8 +8,8 @@ use std::sync::{Arc, LazyLock}; use anyhow::Result; use blah_types::{ get_timestamp, AuthPayload, ChatPayload, CreateGroup, CreatePeerChat, CreateRoomPayload, Id, - MemberPermission, RichText, RoomAdminOp, RoomAdminPayload, RoomAttrs, RoomMember, - RoomMemberList, RoomMetadata, ServerPermission, Signed, SignedChatMsg, UserKey, WithMsgId, + MemberPermission, RichText, RoomAdminOp, RoomAdminPayload, RoomAttrs, RoomMetadata, + ServerPermission, Signed, SignedChatMsg, UserKey, WithMsgId, }; use blahd::{ApiError, AppState, Database, RoomList, RoomMsgs}; use ed25519_dalek::SigningKey; @@ -120,10 +120,6 @@ impl Server { &mut *self.rng.borrow_mut(), CreateRoomPayload::Group(CreateGroup { attrs, - members: RoomMemberList(vec![RoomMember { - permission: MemberPermission::ALL, - user: UserKey(key.verifying_key().to_bytes()), - }]), title: title.to_string(), }), ); diff --git a/docs/webapi.yaml b/docs/webapi.yaml index 59c18ad..48caed3 100644 --- a/docs/webapi.yaml +++ b/docs/webapi.yaml @@ -612,16 +612,6 @@ components: const: 'create_room' title: type: string - members: - type: array - items: - type: object - properties: - user: - type: string - permission: - type: integer - format: int64 - type: object properties: typ: