diff --git a/src/api_data/mod.rs b/src/api_data/mod.rs index 75d1494..17d2360 100644 --- a/src/api_data/mod.rs +++ b/src/api_data/mod.rs @@ -22,4 +22,5 @@ pub mod conversation_message_api; pub mod conversations_refresh_api; pub mod res_count_unread_conversations; pub mod list_unread_conversations_api; -pub mod global_search_result_api; \ No newline at end of file +pub mod global_search_result_api; +pub mod res_create_group; \ No newline at end of file diff --git a/src/api_data/res_create_group.rs b/src/api_data/res_create_group.rs new file mode 100644 index 0000000..5e1d7f4 --- /dev/null +++ b/src/api_data/res_create_group.rs @@ -0,0 +1,23 @@ +//! # Group creation result +//! +//! Result of the creation of a new group + +use serde::Serialize; + +use crate::data::group_id::GroupID; + +#[derive(Serialize)] +pub struct GroupCreationResult { + success: String, + id: u64, +} + +impl GroupCreationResult { + /// Construct a new instance of this object + pub fn new(id: &GroupID) -> GroupCreationResult { + GroupCreationResult { + success: "The group has been successfully created!".to_string(), + id: id.id(), + } + } +} \ No newline at end of file diff --git a/src/constants.rs b/src/constants.rs index 9a2a351..270759c 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -27,6 +27,9 @@ pub mod database_tables_names { /// Groups list table pub const GROUPS_LIST_TABLE: &str = "comunic_groups"; + /// Groups members table + pub const GROUPS_MEMBERS_TABLE: &str = "comunic_groups_members"; + /// Conversations tables pub const CONV_LIST_TABLE: &str = "comunic_conversations_list"; pub const CONV_USERS_TABLE: &str = "comunic_conversations_users"; diff --git a/src/controllers/groups_controller.rs b/src/controllers/groups_controller.rs index 61c3c2c..1921eb5 100644 --- a/src/controllers/groups_controller.rs +++ b/src/controllers/groups_controller.rs @@ -2,10 +2,20 @@ //! //! @author Pierre Hubert +use crate::api_data::res_create_group::GroupCreationResult; use crate::controllers::routes::RequestResult; use crate::data::http_request_handler::HttpRequestHandler; +use crate::data::new_group::NewGroup; +use crate::helpers::groups_helper; /// Create a new group pub fn create(r: &mut HttpRequestHandler) -> RequestResult { - r.success("implement me") + let new_group = NewGroup { + name: r.post_string_opt("name", 3, true)?, + owner_id: r.user_id()?, + }; + + let group_id = groups_helper::create(&new_group)?; + + r.set_response(GroupCreationResult::new(&group_id)) } \ No newline at end of file diff --git a/src/data/group_member.rs b/src/data/group_member.rs new file mode 100644 index 0000000..ceedcd5 --- /dev/null +++ b/src/data/group_member.rs @@ -0,0 +1,24 @@ +//! # Group membership information +//! +//! @author Pierre Hubert + +use crate::data::user::UserID; +use crate::data::group_id::GroupID; + +pub enum GroupMembershipLevel { + ADMINISTRATOR = 0, + MODERATOR = 1, + MEMBER = 2, + INVITED = 3, + PENDING = 4, //When the group membership has not been approved yet + VISITOR = 5, //Simple visit +} + +pub struct GroupMember { + pub id: u64, + pub user_id: UserID, + pub group_id: GroupID, + pub time_create: u64, + pub level: GroupMembershipLevel, + pub following: bool +} \ No newline at end of file diff --git a/src/data/mod.rs b/src/data/mod.rs index fd84e8e..b4e11b2 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -14,4 +14,6 @@ pub mod new_conversation_message; pub mod unread_conversation; pub mod group_id; pub mod group; +pub mod new_group; +pub mod group_member; pub mod global_search_result; \ No newline at end of file diff --git a/src/data/new_group.rs b/src/data/new_group.rs new file mode 100644 index 0000000..b71a212 --- /dev/null +++ b/src/data/new_group.rs @@ -0,0 +1,10 @@ +//! # New group information +//! +//! @author Pierre Hubert + +use crate::data::user::UserID; + +pub struct NewGroup { + pub name: String, + pub owner_id: UserID, +} \ No newline at end of file diff --git a/src/helpers/database.rs b/src/helpers/database.rs index 933c1da..ec5f472 100644 --- a/src/helpers/database.rs +++ b/src/helpers/database.rs @@ -10,8 +10,8 @@ use mysql::prelude::Queryable; use crate::data::config::DatabaseConfig; use crate::data::error::{ExecError, ResultBoxError}; -use crate::data::user::UserID; use crate::data::group_id::GroupID; +use crate::data::user::UserID; /// Database access helper /// @@ -498,6 +498,12 @@ impl InsertQuery { self } + pub fn add_group_id(mut self, key: &str, value: &GroupID) -> InsertQuery { + self.values.insert(key.to_string(), Value::from(value.id())); + self + } + + /// Legacy database boolean (1 = true / 0 = false) pub fn add_legacy_bool(mut self, key: &str, value: bool) -> InsertQuery { let num = match value { @@ -513,6 +519,12 @@ impl InsertQuery { pub fn insert(self) -> ResultBoxError> { insert(self) } + + /// Process insert, drop the result of the operation + pub fn insert_drop_result(self) -> ResultBoxError<()> { + insert(self)?; + Ok(()) + } } /// Insert a new entry into the database diff --git a/src/helpers/groups_helper.rs b/src/helpers/groups_helper.rs index e1acde0..c1fcc95 100644 --- a/src/helpers/groups_helper.rs +++ b/src/helpers/groups_helper.rs @@ -2,11 +2,14 @@ //! //! @author Pierre Hubert -use crate::constants::database_tables_names::GROUPS_LIST_TABLE; -use crate::data::error::ResultBoxError; +use crate::constants::database_tables_names::{GROUPS_LIST_TABLE, GROUPS_MEMBERS_TABLE}; +use crate::data::error::{ExecError, ResultBoxError}; use crate::data::group::GroupVisibilityLevel; use crate::data::group_id::GroupID; +use crate::data::group_member::{GroupMember, GroupMembershipLevel}; +use crate::data::new_group::NewGroup; use crate::helpers::database; +use crate::utils::date_utils::time; impl GroupVisibilityLevel { pub fn to_db(&self) -> u64 { @@ -18,6 +21,52 @@ impl GroupVisibilityLevel { } } +impl GroupMembershipLevel { + pub fn to_db(&self) -> u32 { + match self { + GroupMembershipLevel::ADMINISTRATOR => 0, + GroupMembershipLevel::MODERATOR => 1, + GroupMembershipLevel::MEMBER => 2, + GroupMembershipLevel::INVITED => 3, + GroupMembershipLevel::PENDING => 4, + GroupMembershipLevel::VISITOR => 5, + } + } +} + +/// Create a new group. Returns the ID of the new group +pub fn create(group: &NewGroup) -> ResultBoxError { + // First, create the group + let group_id = database::InsertQuery::new(GROUPS_LIST_TABLE) + .add_u64("time_create", time()) + .add_user_id("userid_create", group.owner_id) + .add_str("name", &group.name) + .insert()?.ok_or(ExecError::new("Could not get group ID!"))?; + let group_id = GroupID::new(group_id); + + // Insert first member + insert_member(&GroupMember { + id: 0, + user_id: group.owner_id, + group_id: group_id.clone(), + time_create: time(), + level: GroupMembershipLevel::ADMINISTRATOR, + following: true, + })?; + + Ok(group_id) +} + +/// Insert a new group into the database +pub fn insert_member(m: &GroupMember) -> ResultBoxError<()> { + database::InsertQuery::new(GROUPS_MEMBERS_TABLE) + .add_group_id("groups_id", &m.group_id) + .add_user_id("user_id", m.user_id) + .add_u64("time_create", m.time_create) + .add_u32("level", m.level.to_db()) + .insert_drop_result() +} + /// Find a group id by virtual directory pub fn find_by_virtual_directory(dir: &str) -> ResultBoxError { database::QueryInfo::new(GROUPS_LIST_TABLE)