diff --git a/src/database/permissions.rs b/src/database/permissions.rs index a003d04..4cdcb5b 100644 --- a/src/database/permissions.rs +++ b/src/database/permissions.rs @@ -1,6 +1,7 @@ use crate::database::models::{CreatePermissionsEntry, Permission}; use crate::database::{DatabaseResult, PostgresPool, Table, ADMIN_ROLE_NAME}; +pub(crate) const VIEW_ROLE_PERMISSION: &str = "ROLE_VIEW"; pub(crate) const CREATE_ROLE_PERMISSION: &str = "ROLE_CREATE"; pub(crate) const UPDATE_ROLE_PERMISSION: &str = "ROLE_UPDATE"; pub(crate) const DELETE_ROLE_PERMISSION: &str = "ROLE_DELETE"; @@ -8,6 +9,7 @@ pub(crate) const DEFAULT_PERMISSIONS: &[(&'static str, &'static str)] = &[ (CREATE_ROLE_PERMISSION, "Allows the user to create roles"), (UPDATE_ROLE_PERMISSION, "Allows the user to update roles"), (DELETE_ROLE_PERMISSION, "Allows the user to delete roles"), + (VIEW_ROLE_PERMISSION, "Allows to see information for roles"), ]; /// The permissions table that stores defined diff --git a/src/database/roles.rs b/src/database/roles.rs index c372b91..08ed5f1 100644 --- a/src/database/roles.rs +++ b/src/database/roles.rs @@ -107,4 +107,16 @@ impl Roles { } } } + + /// Returns information for a role + pub fn get_role(&self, name: String) -> DatabaseResult { + let mut connection = self.pool.get()?; + let result = connection.query_opt("SELECT * FROM roles WHERE roles.name = $1", &[&name])?; + + if let Some(row) = result { + Ok(serde_postgres::from_row::(&row)?) + } else { + Err(DBError::RecordDoesNotExist) + } + } } diff --git a/src/server/http_server.rs b/src/server/http_server.rs index 082debd..d5a421c 100644 --- a/src/server/http_server.rs +++ b/src/server/http_server.rs @@ -1,8 +1,7 @@ -use crate::database::permissions::CREATE_ROLE_PERMISSION; +use crate::database::permissions::{CREATE_ROLE_PERMISSION, VIEW_ROLE_PERMISSION}; use crate::database::Database; use crate::server::messages::{ - CreateRoleRequest, CreateRoleResponse, LoginMessage, LogoutConfirmation, LogoutMessage, - RefreshMessage, + CreateRoleRequest, FullRowData, LoginMessage, LogoutConfirmation, LogoutMessage, RefreshMessage, }; use crate::utils::error::DBError; use crate::utils::get_user_id_from_token; @@ -88,7 +87,10 @@ impl UserHttpServer { (POST) (/logout) => { Self::logout(&database, request).unwrap_or_else(HTTPError::into) }, - (POST)(/roles/create) => { + (GET) (/roles/{name: String}) => { + Self::get_role(&database, request, name).unwrap_or_else(HTTPError::into) + }, + (POST) (/roles/create) => { Self::create_role(&database, request).unwrap_or_else(HTTPError::into) }, _ => if request.method() == "OPTIONS" { @@ -153,6 +155,22 @@ impl UserHttpServer { Ok(Response::json(&LogoutConfirmation { success }).with_status_code(205)) } + /// Returns the data for a given role + fn get_role(database: &Database, request: &Request, name: String) -> HTTPResult { + let (_token, id) = validate_request_token(request, database)?; + if !database.users.has_permission(id, VIEW_ROLE_PERMISSION)? { + return Err(HTTPError::new("Insufficient permissions".to_string(), 403)); + } + let role = database.roles.get_role(name)?; + let permissions = database.role_permission.by_role(role.id)?; + + Ok(Response::json(&FullRowData { + id: role.id, + name: role.name, + permissions, + })) + } + fn create_role(database: &Database, request: &Request) -> HTTPResult { let (_token, id) = validate_request_token(request, database)?; if !database.users.has_permission(id, CREATE_ROLE_PERMISSION)? { @@ -166,7 +184,7 @@ impl UserHttpServer { .create_role(message.name, message.description, message.permissions)?; let permissions = database.role_permission.by_role(role.id)?; - Ok(Response::json(&CreateRoleResponse { + Ok(Response::json(&FullRowData { id: role.id, permissions, name: role.name, diff --git a/src/server/messages.rs b/src/server/messages.rs index ab79fb9..2fdcdea 100644 --- a/src/server/messages.rs +++ b/src/server/messages.rs @@ -101,7 +101,7 @@ pub struct LogoutConfirmation { } #[derive(Serialize)] -pub struct CreateRoleResponse { +pub struct FullRowData { pub id: i32, pub name: String, pub permissions: Vec, diff --git a/src/utils/error.rs b/src/utils/error.rs index fc84032..ad0e375 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -8,6 +8,7 @@ pub enum DBError { Postgres(PostgresError), Pool(r2d2::Error), RecordExists, + RecordDoesNotExist, BCryptError, DeserializeError(serde_postgres::DeError), GenericError(String), @@ -25,11 +26,12 @@ impl DBError { pub fn to_string(&self) -> String { match self { DBError::GenericError(g) => g.clone(), - DBError::RecordExists => "Record Exists".to_string(), + DBError::RecordExists => "Record exists".to_string(), DBError::Postgres(p) => p.to_string(), DBError::DeserializeError(de) => de.to_string(), DBError::BCryptError => "BCrypt Hash creation error".to_string(), DBError::Pool(p) => p.to_string(), + DBError::RecordDoesNotExist => "Record does not exist".to_string(), } } }