Add getRoles method and return ttl for tokens

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

@ -3,15 +3,15 @@ use crate::database::role_permissions::RolePermissions;
use crate::database::roles::Roles; use crate::database::roles::Roles;
use crate::database::user_roles::UserRoles; use crate::database::user_roles::UserRoles;
use crate::database::users::Users; use crate::database::users::Users;
use crate::utils::error::{
DBError, DatabaseClient, DatabaseResult, PostgresError, RedisClient, RedisConnection,
};
use dotenv; use dotenv;
use postgres::{Client, NoTls}; use postgres::{Client, NoTls};
use redis::{RedisError, RedisResult}; use redis::RedisResult;
use serde::export::Formatter;
use std::error;
use std::fmt;
use std::fmt::Display;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
pub mod database_error;
pub mod models; pub mod models;
pub mod permissions; pub mod permissions;
pub mod redis_operations; pub mod redis_operations;
@ -26,11 +26,6 @@ const DEFAULT_CONNECTION: &str = "postgres://postgres:postgres@localhost/postgre
const REDIS_CONNECTION_URL: &str = "REDIS_CONNECTION_URL"; const REDIS_CONNECTION_URL: &str = "REDIS_CONNECTION_URL";
const DEFAULT_REDIS_CONNECTION: &str = "redis:://127.0.0.1/"; const DEFAULT_REDIS_CONNECTION: &str = "redis:://127.0.0.1/";
pub type DatabaseClient = postgres::Client;
pub type RedisClient = redis::Client;
pub type RedisConnection = redis::Connection;
pub type PostgresError = postgres::Error;
pub trait Table { pub trait Table {
fn new( fn new(
database_connection: Arc<Mutex<DatabaseClient>>, database_connection: Arc<Mutex<DatabaseClient>>,
@ -39,27 +34,6 @@ pub trait Table {
fn init(&self) -> DatabaseResult<()>; fn init(&self) -> DatabaseResult<()>;
} }
#[derive(Debug)]
pub enum Error {
Redis(RedisError),
Postgres(PostgresError),
RecordExists,
ScryptError,
DeserializeError(serde_postgres::DeError),
GenericError(String),
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_string())
}
}
impl error::Error for Error {}
pub type DatabaseError = Error;
pub type DatabaseResult<T> = Result<T, Error>;
#[derive(Clone)] #[derive(Clone)]
pub struct Database { pub struct Database {
database_connection: Arc<Mutex<Client>>, database_connection: Arc<Mutex<Client>>,
@ -74,10 +48,10 @@ pub struct Database {
impl Database { impl Database {
pub fn new() -> DatabaseResult<Self> { pub fn new() -> DatabaseResult<Self> {
let database_connection = Arc::new(Mutex::new( let database_connection = Arc::new(Mutex::new(
get_database_connection().map_err(|e| Error::Postgres(e))?, get_database_connection().map_err(|e| DBError::Postgres(e))?,
)); ));
let redis_connection = Arc::new(Mutex::new( let redis_connection = Arc::new(Mutex::new(
get_redis_connection().map_err(|e| Error::Redis(e))?, get_redis_connection().map_err(|e| DBError::Redis(e))?,
)); ));
Ok(Self { Ok(Self {
users: Users::new( users: Users::new(

@ -30,3 +30,10 @@ pub struct Permission {
pub name: String, pub name: String,
pub description: String, pub description: String,
} }
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Role {
pub id: i32,
pub name: String,
pub description: String,
}

@ -1,4 +1,5 @@
use crate::database::{DatabaseClient, DatabaseError, DatabaseResult, RedisConnection, Table}; use crate::database::{DatabaseClient, DatabaseResult, RedisConnection, Table};
use crate::utils::error::DBError;
use postgres::Client; use postgres::Client;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -30,6 +31,6 @@ impl Table for Permissions {
description VARCHAR(512) description VARCHAR(512)
);", );",
) )
.map_err(|e| DatabaseError::Postgres(e)) .map_err(DBError::from)
} }
} }

@ -1,5 +1,6 @@
use crate::database::models::Permission; use crate::database::models::Permission;
use crate::database::{DatabaseClient, DatabaseError, DatabaseResult, RedisConnection, Table}; use crate::database::{DatabaseClient, DatabaseResult, RedisConnection, Table};
use crate::utils::error::DBError;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
#[derive(Clone)] #[derive(Clone)]
@ -31,14 +32,17 @@ impl Table for RolePermissions {
PRIMARY KEY (role_id, permission_id) PRIMARY KEY (role_id, permission_id)
);", );",
) )
.map_err(|e| DatabaseError::Postgres(e)) .map_err(DBError::from)
} }
} }
impl RolePermissions { impl RolePermissions {
pub fn by_role(&self, role_id: i32) -> DatabaseResult<Vec<Permission>> { pub fn by_role(&self, role_id: i32) -> DatabaseResult<Vec<Permission>> {
let mut connection = self.database_connection.lock().unwrap(); let mut connection = self.database_connection.lock().unwrap();
let rows = connection.query("SELECT * FROM role_permissions, permissions WHERE role_id = $1 AND role_permissions.permission_id = permissions.id", &[&role_id]).map_err(|e|DatabaseError::Postgres(e))?; let rows = connection.query(
serde_postgres::from_rows(&rows).map_err(|e| DatabaseError::DeserializeError(e)) "SELECT * FROM role_permissions, permissions WHERE role_id = $1 AND role_permissions.permission_id = permissions.id",
&[&role_id])?;
serde_postgres::from_rows(&rows).map_err(DBError::from)
} }
} }

@ -1,5 +1,6 @@
use crate::database::role_permissions::RolePermissions; use crate::database::role_permissions::RolePermissions;
use crate::database::{DatabaseError, DatabaseResult, RedisConnection, Table}; use crate::database::{DatabaseResult, RedisConnection, Table};
use crate::utils::error::DBError;
use postgres::Client; use postgres::Client;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -37,6 +38,6 @@ impl Table for Roles {
description VARCHAR(512) description VARCHAR(512)
);", );",
) )
.map_err(|e| DatabaseError::Postgres(e)) .map_err(DBError::from)
} }
} }

@ -1,8 +1,8 @@
use crate::database::redis_operations::{EX, GET, SET}; use crate::database::redis_operations::{EX, GET, SET, TTL};
use crate::database::RedisConnection;
use crate::utils::create_user_token; use crate::utils::create_user_token;
use crate::utils::error::RedisConnection;
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use redis::RedisResult; use redis::{ErrorKind, RedisError, RedisResult};
use zeroize::Zeroize; use zeroize::Zeroize;
const REQUEST_TOKEN_EXPIRE_SECONDS: usize = 60 * 10; const REQUEST_TOKEN_EXPIRE_SECONDS: usize = 60 * 10;
@ -13,6 +13,8 @@ const REFRESH_TOKEN_EXPIRE_SECONDS: usize = 60 * 60 * 24;
pub struct SessionTokens { pub struct SessionTokens {
pub request_token: [u8; 32], pub request_token: [u8; 32],
pub refresh_token: [u8; 32], pub refresh_token: [u8; 32],
pub request_ttl: i32,
pub refresh_ttl: i32,
} }
impl SessionTokens { impl SessionTokens {
@ -20,6 +22,8 @@ impl SessionTokens {
Self { Self {
request_token: create_user_token(user_id), request_token: create_user_token(user_id),
refresh_token: create_user_token(user_id), refresh_token: create_user_token(user_id),
request_ttl: -1,
refresh_ttl: -1,
} }
} }
@ -27,31 +31,51 @@ impl SessionTokens {
Self { Self {
request_token, request_token,
refresh_token, refresh_token,
request_ttl: -1,
refresh_ttl: -1,
} }
} }
pub fn retrieve(user_id: i32, redis_connection: &mut RedisConnection) -> RedisResult<Self> { pub fn retrieve(user_id: i32, redis_connection: &mut RedisConnection) -> RedisResult<Self> {
let redis_request_key = format!("user-{}_request", user_id); let redis_request_key = format!("user-{}_request", user_id);
let request_token_vec: Vec<u8> = redis::cmd(GET) let request_token_vec: Vec<u8> = redis::cmd(GET)
.arg(redis_request_key) .arg(&redis_request_key)
.query(redis_connection)?; .query(redis_connection)?;
let redis_refresh_key = format!("user-{}_refresh", user_id); let redis_refresh_key = format!("user-{}_refresh", user_id);
let refresh_token_vec: Vec<u8> = redis::cmd(GET) let refresh_token_vec: Vec<u8> = redis::cmd(GET)
.arg(redis_refresh_key) .arg(&redis_refresh_key)
.query(redis_connection)?; .query(redis_connection)?;
let mut request_token = [0u8; 32]; let mut request_token = [0u8; 32];
let mut refresh_token = [0u8; 32]; let mut refresh_token = [0u8; 32];
if request_token_vec.len() == 32 { if request_token_vec.len() == 32 {
request_token.copy_from_slice(&request_token_vec); request_token.copy_from_slice(&request_token_vec);
} else {
return Err(RedisError::from((
ErrorKind::ResponseError,
"No refresh token available",
)));
} }
if refresh_token_vec.len() == 32 { if refresh_token_vec.len() == 32 {
refresh_token.copy_from_slice(&refresh_token_vec); refresh_token.copy_from_slice(&refresh_token_vec);
} else {
return Err(RedisError::from((
ErrorKind::ResponseError,
"No refresh token available",
)));
} }
let request_ttl: i32 = redis::cmd(TTL)
.arg(&redis_request_key)
.query(redis_connection)?;
let refresh_ttl: i32 = redis::cmd(TTL)
.arg(&redis_refresh_key)
.query(redis_connection)?;
Ok(Self { Ok(Self {
request_token, request_token,
refresh_token, refresh_token,
request_ttl,
refresh_ttl,
}) })
} }

@ -1,4 +1,6 @@
use crate::database::{DatabaseError, DatabaseResult, RedisConnection, Table}; use crate::database::models::Role;
use crate::database::{DatabaseResult, RedisConnection, Table};
use crate::utils::error::DBError;
use postgres::Client; use postgres::Client;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -31,6 +33,18 @@ impl Table for UserRoles {
PRIMARY KEY (user_id, role_id) PRIMARY KEY (user_id, role_id)
);", );",
) )
.map_err(|e| DatabaseError::Postgres(e)) .map_err(DBError::from)
}
}
impl UserRoles {
pub fn by_user(&self, user_id: i32) -> DatabaseResult<Vec<Role>> {
let mut connection = self.database_connection.lock().unwrap();
let rows = connection.query(
"SELECT * FROM user_roles, roles WHERE user_id = $1 AND roles.id = user_roles.role_id",
&[&user_id],
)?;
serde_postgres::from_rows(&rows).map_err(DBError::from)
} }
} }

@ -1,7 +1,8 @@
use crate::database::models::UserRecord; use crate::database::models::UserRecord;
use crate::database::tokens::SessionTokens; use crate::database::tokens::SessionTokens;
use crate::database::user_roles::UserRoles; use crate::database::user_roles::UserRoles;
use crate::database::{DatabaseError, DatabaseResult, RedisConnection, Table}; use crate::database::{DatabaseResult, RedisConnection, Table};
use crate::utils::error::DBError;
use crate::utils::{create_salt, get_user_id_from_token, TOKEN_LENGTH}; use crate::utils::{create_salt, get_user_id_from_token, TOKEN_LENGTH};
use postgres::Client; use postgres::Client;
use scrypt::ScryptParams; use scrypt::ScryptParams;
@ -43,7 +44,7 @@ impl Table for Users {
salt BYTEA NOT NULL salt BYTEA NOT NULL
);", );",
) )
.map_err(|e| DatabaseError::Postgres(e)) .map_err(DBError::from)
} }
} }
@ -58,11 +59,10 @@ impl Users {
let mut password = Zeroizing::new(password); let mut password = Zeroizing::new(password);
if !connection if !connection
.query("SELECT email FROM users WHERE email = $1", &[&email]) .query("SELECT email FROM users WHERE email = $1", &[&email])?
.map_err(|e| DatabaseError::Postgres(e))?
.is_empty() .is_empty()
{ {
return Err(DatabaseError::RecordExists); return Err(DBError::RecordExists);
} }
let salt = Zeroizing::new(create_salt()); let salt = Zeroizing::new(create_salt());
let mut pw_hash = Zeroizing::new([0u8; 32]); let mut pw_hash = Zeroizing::new([0u8; 32]);
@ -72,11 +72,11 @@ impl Users {
&ScryptParams::recommended(), &ScryptParams::recommended(),
&mut *pw_hash, &mut *pw_hash,
) )
.map_err(|_| DatabaseError::ScryptError)?; .map_err(|_| DBError::ScryptError)?;
password.zeroize(); password.zeroize();
let row = connection.query_one(" let row = connection.query_one("
INSERT INTO users (name, email, password_hash, salt) VALUES ($1, $2, $3, $4) RETURNING *; INSERT INTO users (name, email, password_hash, salt) VALUES ($1, $2, $3, $4) RETURNING *;
", &[&name, &email, &pw_hash.to_vec(), &salt.to_vec()]).map_err(|e|DatabaseError::Postgres(e))?; ", &[&name, &email, &pw_hash.to_vec(), &salt.to_vec()])?;
Ok(UserRecord::from_ordered_row(&row)) Ok(UserRecord::from_ordered_row(&row))
} }
@ -84,39 +84,39 @@ impl Users {
pub fn create_token(&self, email: String, password: String) -> DatabaseResult<SessionTokens> { pub fn create_token(&self, email: String, password: String) -> DatabaseResult<SessionTokens> {
if self.validate_login(&email, password)? { if self.validate_login(&email, password)? {
let mut connection = self.database_connection.lock().unwrap(); let mut connection = self.database_connection.lock().unwrap();
let row = connection let row = connection.query_one("SELECT id FROM users WHERE email = $1", &[&email])?;
.query_one("SELECT id FROM users WHERE email = $1", &[&email])
.map_err(|e| DatabaseError::Postgres(e))?;
let id: i32 = row.get(0); let id: i32 = row.get(0);
let mut redis_connection = self.redis_connection.lock().unwrap(); let mut redis_connection = self.redis_connection.lock().unwrap();
let tokens = SessionTokens::new(id); let tokens = SessionTokens::new(id);
tokens tokens.store(&mut redis_connection)?;
.store(&mut redis_connection)
.map_err(|e| DatabaseError::Redis(e))?;
Ok(tokens) Ok(tokens)
} else { } else {
Err(DatabaseError::GenericError("Invalid password".to_string())) Err(DBError::GenericError("Invalid password".to_string()))
} }
} }
pub fn validate_request_token(&self, token: &[u8; TOKEN_LENGTH]) -> DatabaseResult<bool> { pub fn validate_request_token(
&self,
token: &[u8; TOKEN_LENGTH],
) -> DatabaseResult<(bool, i32)> {
let id = get_user_id_from_token(token); let id = get_user_id_from_token(token);
let mut redis_connection = self.redis_connection.lock().unwrap(); let mut redis_connection = self.redis_connection.lock().unwrap();
let tokens = SessionTokens::retrieve(id, &mut redis_connection) let tokens = SessionTokens::retrieve(id, &mut redis_connection)?;
.map_err(|e| DatabaseError::Redis(e))?;
Ok(tokens.request_token == *token) Ok((tokens.request_token == *token, tokens.request_ttl))
} }
pub fn validate_refresh_token(&self, token: &[u8; TOKEN_LENGTH]) -> DatabaseResult<bool> { pub fn validate_refresh_token(
&self,
token: &[u8; TOKEN_LENGTH],
) -> DatabaseResult<(bool, i32)> {
let id = get_user_id_from_token(token); let id = get_user_id_from_token(token);
let mut redis_connection = self.redis_connection.lock().unwrap(); let mut redis_connection = self.redis_connection.lock().unwrap();
let tokens = SessionTokens::retrieve(id, &mut redis_connection) let tokens = SessionTokens::retrieve(id, &mut redis_connection)?;
.map_err(|e| DatabaseError::Redis(e))?;
Ok(tokens.refresh_token == *token) Ok((tokens.refresh_token == *token, tokens.refresh_ttl))
} }
pub fn refresh_tokens( pub fn refresh_tokens(
@ -125,32 +125,25 @@ impl Users {
) -> DatabaseResult<SessionTokens> { ) -> DatabaseResult<SessionTokens> {
let id = get_user_id_from_token(refresh_token); let id = get_user_id_from_token(refresh_token);
let mut redis_connection = self.redis_connection.lock().unwrap(); let mut redis_connection = self.redis_connection.lock().unwrap();
let mut tokens = SessionTokens::retrieve(id, &mut redis_connection) let mut tokens = SessionTokens::retrieve(id, &mut redis_connection)?;
.map_err(|e| DatabaseError::Redis(e))?;
if tokens.refresh_token == *refresh_token { if tokens.refresh_token == *refresh_token {
tokens.refresh(); tokens.refresh();
tokens tokens.store(&mut redis_connection)?;
.store(&mut redis_connection)
.map_err(|e| DatabaseError::Redis(e))?;
Ok(tokens) Ok(tokens)
} else { } else {
Err(DatabaseError::GenericError( Err(DBError::GenericError("Invalid refresh token!".to_string()))
"Invalid refresh token!".to_string(),
))
} }
} }
fn validate_login(&self, email: &String, password: String) -> DatabaseResult<bool> { fn validate_login(&self, email: &String, password: String) -> DatabaseResult<bool> {
let password = Zeroizing::new(password); let password = Zeroizing::new(password);
let mut connection = self.database_connection.lock().unwrap(); let mut connection = self.database_connection.lock().unwrap();
let row = connection let row = connection.query_one(
.query_one( "SELECT password_hash, salt FROM users WHERE email = $1",
"SELECT password_hash, salt FROM users WHERE email = $1", &[&email],
&[&email], )?;
)
.map_err(|e| DatabaseError::Postgres(e))?;
let original_pw_hash: Zeroizing<Vec<u8>> = Zeroizing::new(row.get(0)); let original_pw_hash: Zeroizing<Vec<u8>> = Zeroizing::new(row.get(0));
let salt: Zeroizing<Vec<u8>> = Zeroizing::new(row.get(1)); let salt: Zeroizing<Vec<u8>> = Zeroizing::new(row.get(1));
let mut pw_hash = Zeroizing::new([0u8; 32]); let mut pw_hash = Zeroizing::new([0u8; 32]);
@ -161,7 +154,7 @@ impl Users {
&ScryptParams::recommended(), &ScryptParams::recommended(),
&mut *pw_hash, &mut *pw_hash,
) )
.map_err(|_| DatabaseError::ScryptError)?; .map_err(|_| DBError::ScryptError)?;
Ok(*pw_hash == *original_pw_hash.as_slice()) Ok(*pw_hash == *original_pw_hash.as_slice())
} }

@ -1,3 +1,4 @@
use crate::utils::error::DBError;
use serde::export::Formatter; use serde::export::Formatter;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
@ -5,7 +6,7 @@ use std::fmt;
use std::fmt::Display; use std::fmt::Display;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct ValidateTokenRequest { pub struct TokenRequest {
pub token: [u8; 32], pub token: [u8; 32],
} }
@ -27,16 +28,26 @@ impl Display for ErrorMessage {
} }
impl Error for ErrorMessage {} impl Error for ErrorMessage {}
impl From<DBError> for ErrorMessage {
fn from(other: DBError) -> Self {
Self::new(other.to_string())
}
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct InfoEntry { pub struct InfoEntry {
name: String, name: String,
method: [u8; 4], method: String,
description: String, description: String,
data: String, data: String,
} }
impl InfoEntry { impl InfoEntry {
pub fn new(name: &str, method: [u8; 4], description: &str, data: &str) -> Self { pub fn new(name: &str, method: [u8; 4], description: &str, data: &str) -> Self {
let method = format!(
"0x{:x} 0x{:x} 0x{:x} 0x{:x}",
method[0], method[1], method[2], method[3]
);
Self { Self {
method, method,
name: name.to_string(), name: name.to_string(),

@ -1,8 +1,7 @@
use super::rpc_methods::*; use super::rpc_methods::*;
use crate::database::Database; use crate::database::Database;
use crate::server::messages::{ use crate::server::messages::{ErrorMessage, GetPermissionsRequest, InfoEntry, TokenRequest};
ErrorMessage, GetPermissionsRequest, InfoEntry, ValidateTokenRequest, use crate::utils::get_user_id_from_token;
};
use msgrpc::message::Message; use msgrpc::message::Message;
use msgrpc::server::RpcServer; use msgrpc::server::RpcServer;
use rmp_serde::Deserializer; use rmp_serde::Deserializer;
@ -39,7 +38,7 @@ impl UserRpcServer {
let mut handler = h.lock().unwrap(); let mut handler = h.lock().unwrap();
let response = match handler.message.method { let response = match handler.message.method {
INFO => self.handle_info(), INFO => self.handle_info(),
GET_ROLES => unimplemented!(), 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),
_ => Err(ErrorMessage::new("Invalid Method".to_string())), _ => Err(ErrorMessage::new("Invalid Method".to_string())),
@ -52,14 +51,13 @@ impl UserRpcServer {
fn handle_validate_token(&self, data: &Vec<u8>) -> RpcResult<Message> { fn handle_validate_token(&self, data: &Vec<u8>) -> RpcResult<Message> {
log::trace!("Validating token."); log::trace!("Validating token.");
let message = let message = TokenRequest::deserialize(&mut Deserializer::new(&mut data.as_slice()))
ValidateTokenRequest::deserialize(&mut Deserializer::new(&mut data.as_slice())) .map_err(|e| ErrorMessage::new(e.to_string()))?;
.map_err(|e| ErrorMessage::new(e.to_string()))?;
let valid = self let valid = self
.database .database
.users .users
.validate_request_token(&message.token) .validate_request_token(&message.token)
.unwrap_or(false); .unwrap_or((false, -1));
log::trace!("Serializing..."); log::trace!("Serializing...");
let data = rmp_serde::to_vec(&valid).map_err(|e| ErrorMessage::new(e.to_string()))?; let data = rmp_serde::to_vec(&valid).map_err(|e| ErrorMessage::new(e.to_string()))?;
@ -67,6 +65,7 @@ impl UserRpcServer {
} }
fn handle_info(&self) -> RpcResult<Message> { fn handle_info(&self) -> RpcResult<Message> {
log::trace!("Get Info");
Ok(Message::new_with_serialize( Ok(Message::new_with_serialize(
INFO, INFO,
vec![ vec![
@ -86,7 +85,7 @@ impl UserRpcServer {
InfoEntry::new( InfoEntry::new(
"get permissions", "get permissions",
GET_ROLE_PERMISSIONS, GET_ROLE_PERMISSIONS,
"Returns all permissions the givenroles are assigned to", "Returns all permissions the given roles are assigned to",
"{role_ids: [i32]}", "{role_ids: [i32]}",
), ),
], ],
@ -94,16 +93,13 @@ impl UserRpcServer {
} }
fn handle_get_permissions(&self, data: &Vec<u8>) -> RpcResult<Message> { fn handle_get_permissions(&self, data: &Vec<u8>) -> RpcResult<Message> {
log::trace!("Get Permissions");
let message = let message =
GetPermissionsRequest::deserialize(&mut Deserializer::new(&mut data.as_slice())) GetPermissionsRequest::deserialize(&mut Deserializer::new(&mut data.as_slice()))
.map_err(|e| ErrorMessage::new(e.to_string()))?; .map_err(|e| ErrorMessage::new(e.to_string()))?;
let mut response_data = HashMap::new(); let mut response_data = HashMap::new();
for role_id in message.role_ids { for role_id in message.role_ids {
let permissions = self let permissions = self.database.role_permission.by_role(role_id)?;
.database
.role_permission
.by_role(role_id)
.map_err(|e| ErrorMessage::new(e.to_string()))?;
response_data.insert(role_id.to_string(), permissions); response_data.insert(role_id.to_string(), permissions);
} }
@ -112,4 +108,23 @@ impl UserRpcServer {
response_data, response_data,
)) ))
} }
fn handle_get_roles(&self, data: &Vec<u8>) -> RpcResult<Message> {
log::trace!("Get Roles");
let message = TokenRequest::deserialize(&mut Deserializer::new(&mut data.as_slice()))
.map_err(|e| ErrorMessage::new(e.to_string()))?;
if !self
.database
.users
.validate_request_token(&message.token)
.unwrap_or((false, -1))
.0
{
return Err(ErrorMessage::new("Invalid request token".to_string()));
}
let user_id = get_user_id_from_token(&message.token);
let response_data = self.database.user_roles.by_user(user_id)?;
Ok(Message::new_with_serialize(GET_ROLES, response_data))
}
} }

@ -0,0 +1,47 @@
use redis::RedisError;
use serde_postgres::DeError;
use std::error;
use std::fmt::{self, Display, Formatter};
#[derive(Debug)]
pub enum DBError {
Redis(RedisError),
Postgres(PostgresError),
RecordExists,
ScryptError,
DeserializeError(serde_postgres::DeError),
GenericError(String),
}
impl Display for DBError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_string())
}
}
impl error::Error for DBError {}
pub type DatabaseResult<T> = Result<T, DBError>;
impl From<PostgresError> for DBError {
fn from(other: PostgresError) -> Self {
Self::Postgres(other)
}
}
impl From<RedisError> for DBError {
fn from(other: RedisError) -> Self {
Self::Redis(other)
}
}
impl From<serde_postgres::DeError> for DBError {
fn from(other: DeError) -> Self {
Self::DeserializeError(other)
}
}
pub type DatabaseClient = postgres::Client;
pub type RedisClient = redis::Client;
pub type RedisConnection = redis::Connection;
pub type PostgresError = postgres::Error;

@ -1,6 +1,8 @@
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use rand::Rng; use rand::Rng;
pub mod error;
pub const TOKEN_LENGTH: usize = 32; pub const TOKEN_LENGTH: usize = 32;
const SALT_LENGTH: usize = 16; const SALT_LENGTH: usize = 16;
Loading…
Cancel
Save