Add method to get a list of assigned permissions

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/15/head
trivernis 4 years ago
parent 26c8e38c86
commit e71bc70cd4
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -7,7 +7,7 @@ use std::sync::Arc;
use parking_lot::Mutex;
use zeroize::{Zeroize, Zeroizing};
use crate::database::models::{UserInformation, UserRecord};
use crate::database::models::{Permission, UserInformation, UserRecord};
use crate::database::tokens::{SessionTokens, TokenStore};
use crate::database::user_roles::UserRoles;
use crate::database::{DatabaseResult, PostgresPool, Table};
@ -242,6 +242,7 @@ impl Users {
pub fn delete_tokens(&self, request_token: &String) -> DatabaseResult<bool> {
let mut token_store = self.token_store.lock();
let tokens = token_store.get_by_request_token(request_token);
if let Some(tokens) = tokens {
tokens.invalidate();
@ -288,4 +289,22 @@ impl Users {
Ok(pw_hash == *original_pw_hash.as_slice())
}
pub fn get_permissions(&self, email: &String) -> DatabaseResult<Vec<Permission>> {
let mut connection = self.pool.get()?;
let results = connection.query(
"\
SELECT permissions.id, permissions.name, permissions.description
FROM permissions, role_permissions, user_roles, users
WHERE users.email = $1
AND users.id = user_roles.user_id
AND role_permissions.role_id = user_roles.role_id
AND permissions.id = role_permissions.permission_id
",
&[&email],
)?;
let permissions: Vec<Permission> = serde_postgres::from_rows(results.iter())?;
Ok(permissions)
}
}

@ -11,7 +11,7 @@ use rouille::{Request, Response, Server};
use serde::export::Formatter;
use serde::Serialize;
use crate::database::models::{Role, UserFullInformation, UserInformation};
use crate::database::models::{Permission, Role, UserFullInformation, UserInformation};
use crate::database::permissions::{
ROLE_CREATE_PERM, ROLE_DELETE_PERM, ROLE_UPDATE_PERM, ROLE_VIEW_PERM, USER_CREATE_PERM,
USER_DELETE_PERM, USER_UPDATE_PERM, USER_VIEW_PERM,
@ -133,6 +133,9 @@ impl UserHttpServer {
(GET) (/users/{email: String}) => {
Self::get_user(&database, request, email).unwrap_or_else(HTTPError::into)
},
(GET) (/users/{email: String}/permissions) => {
Self::get_user_permissions(&database, request, email).unwrap_or_else(HTTPError::into)
},
(GET) (/users) => {
Self::get_users(&database, request).unwrap_or_else(HTTPError::into)
},
@ -239,6 +242,11 @@ impl UserHttpServer {
"POST",
"Deletes a user",
)?;
doc.add_path::<(), Vec<Permission>>(
"/users/{email:String}/permissions",
"GET",
"Returns a list of permissions the user was granted",
)?;
Ok(doc)
}
@ -375,7 +383,7 @@ impl UserHttpServer {
/// Returns information for a single user
fn get_user(database: &Database, request: &Request, email: String) -> HTTPResult<Response> {
require_permission!(database, request, USER_VIEW_PERM);
check_user_permission_or_self(request, database, &email, USER_VIEW_PERM)?;
let user = database.users.get_user_by_email(&email)?;
let roles = database.user_roles.by_user(user.id)?;
@ -410,9 +418,10 @@ impl UserHttpServer {
/// Updates the information of a user. This requires the operating user to revalidate his password
fn update_user(database: &Database, request: &Request, email: String) -> HTTPResult<Response> {
let (_, id) = validate_request_token(request, database)?;
let logged_in_user =
check_user_permission_or_self(request, database, &email, USER_UPDATE_PERM)?;
let message = deserialize_body::<UpdateUserRequest>(&request)?;
let logged_in_user = database.users.get_user(id)?;
if !database
.users
.validate_login(&logged_in_user.email, &message.own_password)?
@ -423,9 +432,6 @@ impl UserHttpServer {
));
}
if logged_in_user.email != email {
require_permission!(database, request, USER_UPDATE_PERM);
}
let user_record = database.users.get_user_by_email(&email)?;
let record = database.users.update_user(
&email,
@ -439,9 +445,9 @@ impl UserHttpServer {
/// Deletes a user completely
fn delete_user(database: &Database, request: &Request, email: String) -> HTTPResult<Response> {
let (_, id) = validate_request_token(request, database)?;
let message = deserialize_body::<DeleteUserRequest>(&request)?;
let logged_in_user = database.users.get_user(id)?;
let logged_in_user =
check_user_permission_or_self(request, database, &email, USER_DELETE_PERM)?;
let message = deserialize_body::<DeleteUserRequest>(request)?;
if !database
.users
@ -452,9 +458,7 @@ impl UserHttpServer {
401,
));
}
if !database.users.has_permission(id, USER_DELETE_PERM)? {
return Err(HTTPError::new("Insufficient permissions".to_string(), 403));
}
database.users.delete_user(&email)?;
Ok(Response::json(&DeleteUserResponse {
@ -462,6 +466,18 @@ impl UserHttpServer {
email,
}))
}
/// Returns a list of permissions the user has
fn get_user_permissions(
database: &Database,
request: &Request,
email: String,
) -> HTTPResult<Response> {
check_user_permission_or_self(request, database, &email, USER_VIEW_PERM)?;
let permissions = database.users.get_permissions(&email)?;
Ok(Response::json(&permissions))
}
}
/// Parses the body of a http request into a string representation
@ -500,3 +516,20 @@ fn validate_request_token(request: &Request, database: &Database) -> HTTPResult<
))
}
}
/// Returns if the user has a certain permission or queries him/herself
fn check_user_permission_or_self(
request: &Request,
database: &Database,
email: &String,
permission: &str,
) -> HTTPResult<UserInformation> {
let (_, id) = validate_request_token(request, database)?;
let logged_in_user = database.users.get_user(id)?;
if &logged_in_user.email != email && !database.users.has_permission(id, permission)? {
Err(HTTPError::new("Insufficient permission".to_string(), 403))
} else {
Ok(logged_in_user)
}
}

Loading…
Cancel
Save