diff --git a/src/database/models.rs b/src/database/models.rs index 0736acb..d2bc72a 100644 --- a/src/database/models.rs +++ b/src/database/models.rs @@ -37,3 +37,9 @@ pub struct Role { pub name: String, pub description: String, } + +#[derive(Deserialize)] +pub struct CreatePermissionsEntry { + pub name: String, + pub description: String, +} diff --git a/src/database/permissions.rs b/src/database/permissions.rs index 13d3002..f7fc5fb 100644 --- a/src/database/permissions.rs +++ b/src/database/permissions.rs @@ -1,3 +1,4 @@ +use crate::database::models::{CreatePermissionsEntry, Permission}; use crate::database::{DatabaseClient, DatabaseResult, RedisConnection, Table}; use crate::utils::error::DBError; use postgres::Client; @@ -34,3 +35,34 @@ impl Table for Permissions { .map_err(DBError::from) } } + +impl Permissions { + pub fn create_permissions( + &self, + permissions: Vec, + ) -> DatabaseResult> { + let mut connection = self.database_connection.lock().unwrap(); + let mut transaction = connection.transaction()?; + let mut created_permissions = Vec::new(); + let _: Vec> = permissions + .iter() + .map(|CreatePermissionsEntry { name, description }| { + let exists = transaction + .query_opt("SELECT id FROM permissions WHERE name = $1", &[&name])?; + + if exists.is_none() { + let row = transaction.query_one( + "INSERT INTO permissions (name, description) VALUES ($1, $2) RETURNING *;", + &[&name, &description], + )?; + + created_permissions.push(serde_postgres::from_row(&row)?); + } + + Ok(()) + }) + .collect(); + transaction.commit()?; + Ok(created_permissions) + } +} diff --git a/src/server/messages.rs b/src/server/messages.rs index 7263a8d..94d67be 100644 --- a/src/server/messages.rs +++ b/src/server/messages.rs @@ -1,3 +1,4 @@ +use crate::database::models::CreatePermissionsEntry; use crate::utils::error::DBError; use serde::export::Formatter; use serde::{Deserialize, Serialize}; @@ -68,3 +69,8 @@ pub struct CreateRoleRequest { pub description: Option, pub permission: Vec, } + +#[derive(Deserialize)] +pub struct CreatePermissionsRequest { + pub permissions: Vec, +} diff --git a/src/server/rpc_methods.rs b/src/server/rpc_methods.rs index c1f49e8..31ce42f 100644 --- a/src/server/rpc_methods.rs +++ b/src/server/rpc_methods.rs @@ -6,3 +6,4 @@ 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]; pub(crate) const CREATE_ROLE: [u8; 4] = [0x43, 0x52, 0x4f, 0x4c]; +pub(crate) const CREATE_PERMISSION: [u8; 4] = [0x43, 0x50, 0x45, 0x52]; diff --git a/src/server/user_rpc.rs b/src/server/user_rpc.rs index 07df352..2965836 100644 --- a/src/server/user_rpc.rs +++ b/src/server/user_rpc.rs @@ -1,7 +1,8 @@ use super::rpc_methods::*; use crate::database::Database; use crate::server::messages::{ - CreateRoleRequest, ErrorMessage, GetPermissionsRequest, InfoEntry, TokenRequest, + CreatePermissionsRequest, CreateRoleRequest, ErrorMessage, GetPermissionsRequest, InfoEntry, + TokenRequest, }; use crate::utils::get_user_id_from_token; use msgrpc::message::Message; @@ -44,6 +45,7 @@ impl UserRpcServer { VALIDATE_TOKEN => self.handle_validate_token(&handler.message.data), GET_ROLE_PERMISSIONS => self.handle_get_permissions(&handler.message.data), CREATE_ROLE => self.handle_create_role(&handler.message.data), + CREATE_PERMISSION => self.handle_create_permissions(&handler.message.data), _ => Err(ErrorMessage::new("Invalid Method".to_string())), } .unwrap_or_else(|e| Message::new_with_serialize(ERROR, e)); @@ -97,6 +99,12 @@ impl UserRpcServer { "Creates a new role with the given permissions", "{name: String, description: String, permissions: [i32]}", ), + InfoEntry::new( + "create permissions", + CREATE_PERMISSION, + "Creates all given permissions if they don't exist.", + "{permissions: [{name: String, description: String}]}", + ), ], )) } @@ -149,4 +157,17 @@ impl UserRpcServer { Ok(Message::new_with_serialize(CREATE_ROLE, role)) } + + fn handle_create_permissions(&self, data: &Vec) -> RpcResult { + log::trace!("Create Permission"); + let message = + CreatePermissionsRequest::deserialize(&mut Deserializer::new(&mut data.as_slice())) + .map_err(|e| ErrorMessage::new(e.to_string()))?; + let permissions = self + .database + .permissions + .create_permissions(message.permissions)?; + + Ok(Message::new_with_serialize(CREATE_PERMISSION, permissions)) + } }