Add method to create roles

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/1/head
trivernis 4 years ago
parent a6119b04bf
commit 926a2d2334
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,3 +1,4 @@
use crate::database::models::Role;
use crate::database::role_permissions::RolePermissions; use crate::database::role_permissions::RolePermissions;
use crate::database::{DatabaseResult, RedisConnection, Table}; use crate::database::{DatabaseResult, RedisConnection, Table};
use crate::utils::error::DBError; use crate::utils::error::DBError;
@ -41,3 +42,45 @@ impl Table for Roles {
.map_err(DBError::from) .map_err(DBError::from)
} }
} }
impl Roles {
pub fn create_role(
&self,
name: String,
description: Option<String>,
permissions: Vec<i32>,
) -> DatabaseResult<Role> {
let mut connection = self.database_connection.lock().unwrap();
let exists = connection.query_opt("SELECT id FROM roles WHERE name = $1", &[&name])?;
if exists.is_some() {
return Err(DBError::RecordExists);
}
log::trace!("Preparing transaction");
let mut transaction = connection.transaction()?;
let result: DatabaseResult<Role> = {
let row = transaction.query_one(
"INSERT INTO roles (name, description) VALUES ($1, $2) RETURNING *",
&[&name, &description],
)?;
let role: Role = serde_postgres::from_row(&row)?;
for permission in permissions {
transaction.execute(
"INSERT INTO role_permissions (role_id, permission_id) VALUES ($1, $2);",
&[&role.id, &permission],
)?;
}
Ok(role)
};
if let Err(_) = result {
log::trace!("Rollback");
transaction.rollback()?;
} else {
log::trace!("Commit");
transaction.commit()?;
}
result
}
}

@ -61,3 +61,10 @@ impl InfoEntry {
pub struct GetPermissionsRequest { pub struct GetPermissionsRequest {
pub role_ids: Vec<i32>, pub role_ids: Vec<i32>,
} }
#[derive(Deserialize)]
pub struct CreateRoleRequest {
pub name: String,
pub description: Option<String>,
pub permission: Vec<i32>,
}

@ -5,3 +5,4 @@ pub(crate) const INFO: [u8; 4] = [0x49, 0x4e, 0x46, 0x4f];
pub(crate) const VALIDATE_TOKEN: [u8; 4] = [0x56, 0x41, 0x4c, 0x49]; 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_ROLES: [u8; 4] = [0x52, 0x4f, 0x4c, 0x45];
pub(crate) const GET_ROLE_PERMISSIONS: [u8; 4] = [0x50, 0x45, 0x52, 0x4d]; pub(crate) const GET_ROLE_PERMISSIONS: [u8; 4] = [0x50, 0x45, 0x52, 0x4d];
pub(crate) const CREATE_ROLE: [u8; 4] = [0x43, 0x52, 0x4f, 0x4c];

@ -1,6 +1,8 @@
use super::rpc_methods::*; use super::rpc_methods::*;
use crate::database::Database; use crate::database::Database;
use crate::server::messages::{ErrorMessage, GetPermissionsRequest, InfoEntry, TokenRequest}; use crate::server::messages::{
CreateRoleRequest, ErrorMessage, GetPermissionsRequest, InfoEntry, TokenRequest,
};
use crate::utils::get_user_id_from_token; use crate::utils::get_user_id_from_token;
use msgrpc::message::Message; use msgrpc::message::Message;
use msgrpc::server::RpcServer; use msgrpc::server::RpcServer;
@ -41,6 +43,7 @@ impl UserRpcServer {
GET_ROLES => self.handle_get_roles(&handler.message.data), GET_ROLES => self.handle_get_roles(&handler.message.data),
VALIDATE_TOKEN => self.handle_validate_token(&handler.message.data), VALIDATE_TOKEN => self.handle_validate_token(&handler.message.data),
GET_ROLE_PERMISSIONS => self.handle_get_permissions(&handler.message.data), GET_ROLE_PERMISSIONS => self.handle_get_permissions(&handler.message.data),
CREATE_ROLE => self.handle_create_role(&handler.message.data),
_ => Err(ErrorMessage::new("Invalid Method".to_string())), _ => Err(ErrorMessage::new("Invalid Method".to_string())),
} }
.unwrap_or_else(|e| Message::new_with_serialize(ERROR, e)); .unwrap_or_else(|e| Message::new_with_serialize(ERROR, e));
@ -88,6 +91,12 @@ impl UserRpcServer {
"Returns all permissions the given roles are assigned to", "Returns all permissions the given roles are assigned to",
"{role_ids: [i32]}", "{role_ids: [i32]}",
), ),
InfoEntry::new(
"create role",
CREATE_ROLE,
"Creates a new role with the given permissions",
"{name: String, description: String, permissions: [i32]}",
),
], ],
)) ))
} }
@ -127,4 +136,17 @@ impl UserRpcServer {
Ok(Message::new_with_serialize(GET_ROLES, response_data)) Ok(Message::new_with_serialize(GET_ROLES, response_data))
} }
fn handle_create_role(&self, data: &Vec<u8>) -> RpcResult<Message> {
log::trace!("Create Role");
let message = CreateRoleRequest::deserialize(&mut Deserializer::new(&mut data.as_slice()))
.map_err(|e| ErrorMessage::new(e.to_string()))?;
let role = self.database.roles.create_role(
message.name,
message.description,
message.permission,
)?;
Ok(Message::new_with_serialize(CREATE_ROLE, role))
}
} }

@ -21,6 +21,19 @@ impl Display for DBError {
impl error::Error for DBError {} impl error::Error for DBError {}
impl DBError {
pub fn to_string(&self) -> String {
match self {
DBError::GenericError(g) => g.clone(),
DBError::RecordExists => "Record Exists".to_string(),
DBError::Postgres(p) => p.to_string(),
DBError::Redis(r) => r.to_string(),
DBError::DeserializeError(de) => de.to_string(),
DBError::ScryptError => "sCrypt Hash creation error".to_string(),
}
}
}
pub type DatabaseResult<T> = Result<T, DBError>; pub type DatabaseResult<T> = Result<T, DBError>;
impl From<PostgresError> for DBError { impl From<PostgresError> for DBError {

Loading…
Cancel
Save