diff --git a/src/database/mod.rs b/src/database/mod.rs index 4d12e16..f80ad3b 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -6,6 +6,10 @@ use crate::database::users::Users; use dotenv; use postgres::{Client, NoTls}; use redis::{RedisError, RedisResult}; +use serde::export::Formatter; +use std::error; +use std::fmt; +use std::fmt::Display; use std::sync::{Arc, Mutex}; pub mod models; @@ -45,6 +49,14 @@ pub enum Error { GenericError(String), } +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.to_string()) + } +} + +impl error::Error for Error {} + pub type DatabaseError = Error; pub type DatabaseResult = Result; @@ -55,8 +67,8 @@ pub struct Database { pub users: Users, pub roles: Roles, pub permissions: Permissions, - role_permission: RolePermissions, - user_roles: UserRoles, + pub role_permission: RolePermissions, + pub user_roles: UserRoles, } impl Database { diff --git a/src/database/models.rs b/src/database/models.rs index 2220f3d..7ccffba 100644 --- a/src/database/models.rs +++ b/src/database/models.rs @@ -1,4 +1,5 @@ use postgres::Row; +use serde::{Deserialize, Serialize}; use zeroize::Zeroize; #[derive(Clone, Debug, Zeroize)] @@ -22,3 +23,10 @@ impl UserRecord { } } } + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Permission { + pub id: i32, + pub name: String, + pub description: String, +} diff --git a/src/database/role_permissions.rs b/src/database/role_permissions.rs index feb21c2..5dc2c2b 100644 --- a/src/database/role_permissions.rs +++ b/src/database/role_permissions.rs @@ -1,3 +1,4 @@ +use crate::database::models::Permission; use crate::database::{DatabaseClient, DatabaseError, DatabaseResult, RedisConnection, Table}; use std::sync::{Arc, Mutex}; @@ -33,3 +34,11 @@ impl Table for RolePermissions { .map_err(|e| DatabaseError::Postgres(e)) } } + +impl RolePermissions { + pub fn by_role(&self, role_id: i32) -> DatabaseResult> { + let mut connection = self.database_connection.lock().unwrap(); + let rows = connection.query("SELECT * FROM role_permissions, permissions WHERE role_id = $1 AND role_permissions.permission_id = permissions.id", &[&role_id]).map_err(|e|DatabaseError::Postgres(e))?; + serde_postgres::from_rows(&rows).map_err(|e| DatabaseError::DeserializeError(e)) + } +} diff --git a/src/server/messages.rs b/src/server/messages.rs index 9c7bb09..853249d 100644 --- a/src/server/messages.rs +++ b/src/server/messages.rs @@ -45,3 +45,8 @@ impl InfoEntry { } } } + +#[derive(Deserialize)] +pub struct GetPermissionsRequest { + pub role_ids: Vec, +} diff --git a/src/server/rpc_methods.rs b/src/server/rpc_methods.rs index eccd169..71687be 100644 --- a/src/server/rpc_methods.rs +++ b/src/server/rpc_methods.rs @@ -4,3 +4,4 @@ pub(crate) const ERROR: [u8; 4] = [0x0F, 0x0F, 0x0F, 0x0F]; pub(crate) const INFO: [u8; 4] = [0x49, 0x4e, 0x46, 0x4f]; pub(crate) const VALIDATE_TOKEN: [u8; 4] = [0x56, 0x41, 0x4c, 0x49]; pub(crate) const GET_ROLES: [u8; 4] = [0x52, 0x4f, 0x4c, 0x45]; +pub(crate) const GET_ROLE_PERMISSIONS: [u8; 4] = [0x50, 0x45, 0x52, 0x4d]; diff --git a/src/server/user_rpc.rs b/src/server/user_rpc.rs index 322b971..c02e93c 100644 --- a/src/server/user_rpc.rs +++ b/src/server/user_rpc.rs @@ -1,10 +1,13 @@ use super::rpc_methods::*; use crate::database::Database; -use crate::server::messages::{ErrorMessage, InfoEntry, ValidateTokenRequest}; +use crate::server::messages::{ + ErrorMessage, GetPermissionsRequest, InfoEntry, ValidateTokenRequest, +}; use msgrpc::message::Message; use msgrpc::server::RpcServer; use rmp_serde::Deserializer; use serde::Deserialize; +use std::collections::HashMap; use std::sync::Arc; use std::thread; @@ -38,6 +41,7 @@ impl UserRpcServer { INFO => self.handle_info(), GET_ROLES => unimplemented!(), VALIDATE_TOKEN => self.handle_validate_token(&handler.message.data), + GET_ROLE_PERMISSIONS => self.handle_get_permissions(&handler.message.data), _ => Err(ErrorMessage::new("Invalid Method".to_string())), } .unwrap_or_else(|e| Message::new_with_serialize(ERROR, e)); @@ -79,7 +83,33 @@ impl UserRpcServer { "Returns the roles the user is assigned to", "{token: [u8; 32]}", ), + InfoEntry::new( + "get permissions", + GET_ROLE_PERMISSIONS, + "Returns all permissions the givenroles are assigned to", + "{role_ids: [i32]}", + ), ], )) } + + fn handle_get_permissions(&self, data: &Vec) -> RpcResult { + let message = + GetPermissionsRequest::deserialize(&mut Deserializer::new(&mut data.as_slice())) + .map_err(|e| ErrorMessage::new(e.to_string()))?; + let mut response_data = HashMap::new(); + for role_id in message.role_ids { + let permissions = self + .database + .role_permission + .by_role(role_id) + .map_err(|e| ErrorMessage::new(e.to_string()))?; + response_data.insert(role_id.to_string(), permissions); + } + + Ok(Message::new_with_serialize( + GET_ROLE_PERMISSIONS, + response_data, + )) + } }