From 0f4f1380be1fd067dcc73a757c1d7993822dccb8 Mon Sep 17 00:00:00 2001 From: HubertK05 Date: Fri, 27 Jan 2023 16:16:17 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=82invitation=20privilege=20verificati?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ~ first commit with that gitmoji --- backend/src/routes/chat.rs | 34 +++++++++++++++++++++++++++---- backend/src/utils/chat/socket.rs | 23 ++++++++++++++------- backend/src/utils/roles/models.rs | 13 ++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/backend/src/routes/chat.rs b/backend/src/routes/chat.rs index 57cd834..d7a0395 100644 --- a/backend/src/routes/chat.rs +++ b/backend/src/routes/chat.rs @@ -7,6 +7,7 @@ use crate::utils::chat::socket::{ use crate::utils::chat::*; use crate::utils::groups::*; use crate::utils::roles::models::{SocketGroupRolePrivileges, Gate, Role}; +use crate::utils::roles::privileges::{Privilege, CanInvite, CanSendMessages}; use crate::utils::roles::{get_group_role_privileges, get_user_role, single_set_group_role_privileges, single_set_group_user_role}; use axum::http::HeaderMap; use axum::{ @@ -16,6 +17,7 @@ use axum::{ Extension, Router, }; use sqlx::PgPool; +use std::cmp::Ordering; use std::sync::Arc; use tracing::{debug, error, info}; use uuid::Uuid; @@ -159,6 +161,18 @@ pub async fn chat_socket( } // todo: send group invites in chat ClientAction::GroupInvite { group_id } => { + match controller.verify_with_privilege(claims.user_id, Privilege::CanInvite(CanInvite::Yes)).await { + Ok(false) => { + info!("User does not have privileges to invite other users"); + continue; + }, + Err(e) => { + error!("Failed to verify with privilege: {:?}", e); + continue; + }, + _ => (), + } + let Ok(_is_member) = check_if_group_member(&pool, &claims.user_id, &group_id).await else { error!("Failed to check whether a user {} ({}) is a group {} member (during sending a group invite)", &claims.user_id, &claims.login, &group_id); continue; @@ -180,12 +194,24 @@ pub async fn chat_socket( _ => (), }; - // todo: check for user priviliges - let role_verified = gate.verify(Role::Admin, Role::Member, (Uuid::new_v4(), Uuid::new_v4())); + let Some(user_role) = controller.get_role(claims.user_id).await else { + error!("Failed to get the controller's role"); + continue; + }; + + let Some(target_user_role) = controller.get_role(user_id).await else { + error!("Failed to get the target user's role"); + continue; + }; + + if !gate.verify(user_role, target_user_role, (claims.user_id, user_id)) { + info!("User does not have privileges to kick another user"); + continue; + } // Remove user from group let Ok(_) = try_remove_user_from_group(&pool, user_id, group_id).await else { - error!("ws closed: Failed to remove user {} from a group {}", &user_id, &group_id); + error!("Failed to remove user {} from a group {}", &user_id, &group_id); continue; }; @@ -195,7 +221,7 @@ pub async fn chat_socket( // todo: disconnect group controllers } ClientAction::SingleChangePrivileges { mut data } => { - let Some(socket_privileges) = controller.get_privileges() else { + let Some(socket_privileges) = controller.get_group_privileges() else { debug!("User trying to change privileges not in group"); continue }; diff --git a/backend/src/utils/chat/socket.rs b/backend/src/utils/chat/socket.rs index 7ed784b..a4e6efe 100644 --- a/backend/src/utils/chat/socket.rs +++ b/backend/src/utils/chat/socket.rs @@ -1,6 +1,6 @@ use crate::utils::roles::errors::RoleError; use crate::utils::roles::models::{Role, SocketGroupRolePrivileges, PrivilegeChangeData, UserRoleChangeData}; -use crate::utils::roles::privileges::Privileges; +use crate::utils::roles::privileges::{Privileges, Privilege}; use super::models::{GroupUserMessage, KickMessage}; use anyhow::anyhow; @@ -246,21 +246,30 @@ impl UserController { Ok(user.connections.send_across_all(&ServerAction::SetPrivileges(privileges)).await) } - pub async fn get_role(&self) -> Option { + pub async fn get_role(&self, user_id: Uuid) -> Option { let Some(conn) = &self.group_conn else { return None }; - match conn.controller.users.0.read().await.get(&self.user_id) { - Some(user_data) => Some(user_data.role), - None => None, - } + conn.controller.users.0.read().await.get(&user_id) + .and_then(|x| Some(x.role)) } - pub fn get_privileges(&self) -> Option<&SocketGroupRolePrivileges> { + pub fn get_group_privileges(&self) -> Option<&SocketGroupRolePrivileges> { let connection = self.group_conn.as_ref()?; Some(&connection.controller.privileges) } + + pub async fn get_user_privilege(&self, user_id: Uuid, val: Privilege) -> Option { + let role = self.get_role(user_id).await?; + self.get_group_privileges()?.get_privilege(role, val).await + } + + pub async fn verify_with_privilege(&self, user_id: Uuid, min_val: Privilege) -> Result { + let role = self.get_role(user_id).await.ok_or(RoleError::Unexpected(anyhow!("No role found for user_id")))?; + let privileges = self.get_group_privileges().ok_or(RoleError::Unexpected(anyhow!("No socket privileges found")))?; + privileges.verify_with_privilege(role, min_val).await + } } pub struct UserChannelListener { diff --git a/backend/src/utils/roles/models.rs b/backend/src/utils/roles/models.rs index 2e8f118..6dc01c5 100644 --- a/backend/src/utils/roles/models.rs +++ b/backend/src/utils/roles/models.rs @@ -53,6 +53,19 @@ impl SocketGroupRolePrivileges { Some(self.0.get(&role)?.read().await.clone()) } } + + pub async fn get_privilege(&self, role: Role, val: Privilege) -> Option { + self.0.get(&role)?.read().await.0.get(&val).copied() + } + + pub async fn verify_with_privilege(&self, role: Role, min_val: Privilege) -> Result { + let cmp_res = self + .get_privilege(role, min_val) + .await + .ok_or(RoleError::Unexpected(anyhow!("No privilege found")))? + .partial_cmp(&min_val); + Ok(cmp_res == Some(Ordering::Greater) && cmp_res == Some(Ordering::Equal)) + } } impl GroupRolePrivileges {