Add role delete and change update

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/13/head
trivernis 4 years ago
parent a0e6e4fb07
commit 7359c259eb
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -4,7 +4,9 @@
use crate::database::models::Role;
use crate::database::role_permissions::RolePermissions;
use crate::database::{DatabaseResult, PostgresPool, Table, DEFAULT_ADMIN_EMAIL, ENV_ADMIN_EMAIL};
use crate::database::{
DatabaseResult, PostgresPool, Table, ADMIN_ROLE_NAME, DEFAULT_ADMIN_EMAIL, ENV_ADMIN_EMAIL,
};
use crate::utils::error::DBError;
use std::collections::HashSet;
use std::iter::FromIterator;
@ -112,21 +114,35 @@ impl Roles {
pub fn update_role(
&self,
old_name: String,
name: String,
description: Option<String>,
permissions: Vec<i32>,
) -> DatabaseResult<Role> {
if old_name == ADMIN_ROLE_NAME {
return Err(DBError::GenericError(
"The admin role can't be altered!".to_string(),
));
}
let permissions = HashSet::from_iter(permissions.into_iter());
let mut connection = self.pool.get()?;
let mut transaction = connection.transaction()?;
let id: i32 = transaction
.query_opt("SELECT id FROM roles WHERE name = $1", &[&name])?
.query_opt("SELECT id FROM roles WHERE name = $1", &[&old_name])?
.ok_or(DBError::RecordDoesNotExist)?
.get(0);
let name_exists =
transaction.query_opt("SELECT id FROM roles WHERE name = $1", &[&name])?;
if name_exists.is_some() {
return Err(DBError::GenericError(format!(
"A role with the name {} already exists!",
name
)));
}
let update_result = transaction.query_one(
"UPDATE roles SET description = $2 WHERE id = $1 RETURNING *",
&[&id, &description],
"UPDATE roles SET name = $3, description = $2 WHERE id = $1 RETURNING *",
&[&id, &description, &name],
)?;
let current_permissions = transaction
.query(
@ -155,4 +171,23 @@ impl Roles {
Ok(serde_postgres::from_row::<Role>(&update_result)?)
}
/// Deletes a role if it exists
pub fn delete_role(&self, name: &String) -> DatabaseResult<()> {
if name == ADMIN_ROLE_NAME {
return Err(DBError::GenericError(
"The admin role can't be altered!".to_string(),
));
}
let mut connection = self.pool.get()?;
let result = connection.query_opt("SELECT id FROM roles WHERE name = $1", &[name])?;
if result.is_none() {
Err(DBError::RecordDoesNotExist)
} else {
connection.query("DELETE FROM roles WHERE name = $1", &[name])?;
Ok(())
}
}
}

@ -32,7 +32,9 @@ impl RESTDocumentation {
}
fn landing(&self) -> String {
let types = self.paths.keys().fold("".to_string(), |a, b| {
let mut keys = self.paths.keys().cloned().collect::<Vec<String>>();
keys.sort();
let types = keys.into_iter().fold("".to_string(), |a, b| {
format!("{}<br><a href='{}?path={2}'>{2}</a>", a, self.base_path, b)
});
@ -53,7 +55,7 @@ impl RESTDocumentation {
let content = format!(
"\
<a href={}>Back</a>
<h1>{}: {}</h1>
<h1><code>{}: {}</code></h1>
<p>{}</p>
<h2>Input</h2>
<code>{}</code>

@ -8,6 +8,10 @@ body {
font-family: "Fira Sans", "Noto Sans", sans-serif;
}
code {
font-family: "Fira Code", "DejaVu Sans Mono", monospace;
}
code > pre {
font-family: "Fira Code", "DejaVu Sans Mono", monospace;
max-width: 100%;

@ -13,14 +13,14 @@ use serde::Serialize;
use crate::database::models::Role;
use crate::database::permissions::{
CREATE_ROLE_PERMISSION, UPDATE_ROLE_PERMISSION, VIEW_ROLE_PERMISSION,
CREATE_ROLE_PERMISSION, DELETE_ROLE_PERMISSION, UPDATE_ROLE_PERMISSION, VIEW_ROLE_PERMISSION,
};
use crate::database::tokens::SessionTokens;
use crate::database::Database;
use crate::server::documentation::RESTDocumentation;
use crate::server::messages::{
ErrorMessage, FullRoleData, LoginMessage, LogoutConfirmation, LogoutMessage, ModifyRoleRequest,
RefreshMessage,
DeleteRoleResponse, ErrorMessage, FullRoleData, LoginMessage, LogoutConfirmation,
LogoutMessage, ModifyRoleRequest, RefreshMessage,
};
use crate::utils::error::DBError;
use crate::utils::get_user_id_from_token;
@ -121,8 +121,11 @@ impl UserHttpServer {
(POST) (/roles/create) => {
Self::create_role(&database, request).unwrap_or_else(HTTPError::into)
},
(POST) (/roles/update) => {
Self::update_role(&database, request).unwrap_or_else(HTTPError::into)
(POST) (/roles/{name:String}/update) => {
Self::update_role(&database, request, name).unwrap_or_else(HTTPError::into)
},
(POST) (/roles/{name: String}/delete) => {
Self::delete_role(&database, request, name).unwrap_or_else(HTTPError::into)
},
_ => if request.method() == "OPTIONS" {
Response::empty_204()
@ -184,10 +187,15 @@ impl UserHttpServer {
"Creates a new role",
)?;
doc.add_path::<ModifyRoleRequest, FullRoleData>(
"/roles/update",
"/roles/{name:String}/update",
"POST",
"Updates an existing role",
)?;
doc.add_path::<(), DeleteRoleResponse>(
"/roles/{name:String}/delete",
"POST",
"Deletes a role",
)?;
Ok(doc)
}
@ -280,7 +288,7 @@ impl UserHttpServer {
.with_status_code(201))
}
fn update_role(database: &Database, request: &Request) -> HTTPResult<Response> {
fn update_role(database: &Database, request: &Request, name: String) -> HTTPResult<Response> {
require_permission!(database, request, UPDATE_ROLE_PERMISSION);
let message: ModifyRoleRequest = serde_json::from_str(parse_string_body(request)?.as_str())
.map_err(|e| HTTPError::new(e.to_string(), 400))?;
@ -294,10 +302,12 @@ impl UserHttpServer {
)))
.with_status_code(400));
}
let role =
database
.roles
.update_role(message.name, message.description, message.permissions)?;
let role = database.roles.update_role(
name,
message.name,
message.description,
message.permissions,
)?;
let permissions = database.role_permission.by_role(role.id)?;
Ok(Response::json(&FullRoleData {
@ -306,6 +316,16 @@ impl UserHttpServer {
name: role.name,
}))
}
fn delete_role(database: &Database, request: &Request, role: String) -> HTTPResult<Response> {
require_permission!(database, request, DELETE_ROLE_PERMISSION);
database.roles.delete_role(&role)?;
Ok(Response::json(&DeleteRoleResponse {
success: true,
role,
}))
}
}
/// Parses the body of a http request into a string representation

@ -113,3 +113,9 @@ pub struct FullRoleData {
pub name: String,
pub permissions: Vec<Permission>,
}
#[derive(Serialize, JsonSchema)]
pub struct DeleteRoleResponse {
pub success: bool,
pub role: String,
}

Loading…
Cancel
Save