chore: add app_file
This commit is contained in:
parent
82061f4a8d
commit
06846cc8f9
6 changed files with 285 additions and 13 deletions
201
app_file/src/lib.rs
Normal file
201
app_file/src/lib.rs
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use serde::{Deserialize,Serialize};
|
||||
use tokio::sync::RwLock;
|
||||
use casbin::prelude::*;
|
||||
use warp::{Rejection};
|
||||
|
||||
use app_env::{AppStore,config::Config};
|
||||
use app_tools::{trim_newline,from_base64};
|
||||
|
||||
pub const BEARER_PREFIX: &str = "Bearer ";
|
||||
|
||||
pub type WebResult<T> = std::result::Result<T, Rejection>;
|
||||
|
||||
#[derive(Deserialize,Serialize,Clone,Debug,Default)]
|
||||
pub struct UserCtx {
|
||||
pub user_id: String,
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize,Serialize,Clone,Debug,Default)]
|
||||
pub struct User {
|
||||
pub user_id: String,
|
||||
pub name: String,
|
||||
pub role: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize,Serialize,Clone,Debug,Default)]
|
||||
pub struct UserShadow {
|
||||
pub user_id: String,
|
||||
pub passwd: String,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug,Default)]
|
||||
pub struct LoginRequest {
|
||||
pub name: String,
|
||||
pub passwd: String,
|
||||
}
|
||||
|
||||
#[allow(clippy::pub_enum_variant_names)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AuthError {
|
||||
#[error("error")]
|
||||
SomeError(),
|
||||
#[error("no authorization header found")]
|
||||
NoAuthHeaderFoundError,
|
||||
#[error("wrong authorization header format")]
|
||||
InvalidAuthHeaderFormatError,
|
||||
#[error("no user found for this token")]
|
||||
InvalidTokenError,
|
||||
#[error("error during authorization")]
|
||||
AuthorizationError,
|
||||
#[error("user is not unauthorized")]
|
||||
UnauthorizedError,
|
||||
#[error("no user found with this name")]
|
||||
UserNotFoundError,
|
||||
}
|
||||
// impl warp::reject::Reject for anyhow::Error {}
|
||||
impl warp::reject::Reject for AuthError {}
|
||||
|
||||
// impl From<::Error> for warp::reject::Rejection {}
|
||||
|
||||
// https://github.com/seanmonstar/warp/issues/307
|
||||
#[derive(Debug)]
|
||||
pub struct CustomReject(anyhow::Error);
|
||||
impl warp::reject::Reject for CustomReject {}
|
||||
|
||||
#[must_use]
|
||||
// pub(crate) fn custom_reject(error: impl Into<anyhow::Error>) -> warp::Rejection {
|
||||
pub fn custom_reject(error: impl Into<anyhow::Error>) -> warp::Rejection {
|
||||
warp::reject::custom(CustomReject(error.into()))
|
||||
}
|
||||
|
||||
pub type UserMap = Arc<RwLock<HashMap<String, User>>>;
|
||||
pub type UserShadowMap = Arc<RwLock<HashMap<String, UserShadow>>>;
|
||||
pub type Sessions = Arc<RwLock<HashMap<String, String>>>;
|
||||
pub type SharedEnforcer = Arc<Enforcer>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AuthStore {
|
||||
pub users: UserMap,
|
||||
pub shadows: UserShadowMap,
|
||||
pub sessions: Sessions,
|
||||
pub enforcer: Arc<casbin::Enforcer>, // SharedEnforcer,
|
||||
}
|
||||
|
||||
impl AuthStore {
|
||||
#[must_use]
|
||||
pub fn new(config: &Config, enforcer: SharedEnforcer) -> Self {
|
||||
Self {
|
||||
users: Arc::new(RwLock::new(AuthStore::create_user_map(config))),
|
||||
shadows: Arc::new(RwLock::new(AuthStore::create_shadows_map(config))),
|
||||
sessions: Arc::new(RwLock::new(HashMap::new())),
|
||||
enforcer,
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn load_users_from_fs(store: &str,target: &str) -> HashMap<String, User> {
|
||||
let mut usrs_content = fs::read_to_string(target).unwrap_or_else(|_|String::from(""));
|
||||
trim_newline(&mut usrs_content);
|
||||
let data_content = from_base64(&usrs_content);
|
||||
if ! data_content.contains("role") {
|
||||
println!("Error no 'role' in users from store: {}", &store);
|
||||
return HashMap::new()
|
||||
}
|
||||
let usrs: HashMap<String, User> = toml::from_str(&data_content).unwrap_or_else(|e| {
|
||||
println!("Error loading users from store: {} error: {}", &store,e);
|
||||
HashMap::new()
|
||||
});
|
||||
usrs
|
||||
}
|
||||
#[must_use]
|
||||
pub fn load_shadows_from_fs(store: &str,target: &str) -> HashMap<String, UserShadow> {
|
||||
let mut shadow_content = fs::read_to_string(target).unwrap_or_else(|_|String::from(""));
|
||||
trim_newline(&mut shadow_content);
|
||||
let data_content = from_base64(&shadow_content);
|
||||
if ! data_content.contains("passwd") {
|
||||
println!("Error no 'passwd' in shadows from store: {}", &store);
|
||||
return HashMap::new()
|
||||
}
|
||||
let shadows: HashMap<String, UserShadow> = toml::from_str(&data_content).unwrap_or_else(|e| {
|
||||
println!("Error loading users shadows from store: {} error: {}", &store,e);
|
||||
HashMap::new()
|
||||
});
|
||||
shadows
|
||||
}
|
||||
#[must_use]
|
||||
pub fn create_user_map(config: &Config) -> HashMap<String, User> {
|
||||
// TODO load form YAML o CONFIG
|
||||
let mut usrs = HashMap::new();
|
||||
match config.usrs_store.as_str() {
|
||||
"fs" => {
|
||||
usrs = AuthStore::load_users_from_fs(&config.usrs_store,&config.usrs_store_target);
|
||||
if !usrs.is_empty() {
|
||||
println!("Users loaded successfully ({})", &usrs.len());
|
||||
}
|
||||
},
|
||||
_ => println!("Store {} not set for users store: ", config.usrs_store),
|
||||
}
|
||||
usrs
|
||||
}
|
||||
#[must_use]
|
||||
pub fn create_shadows_map(config: &Config) -> HashMap<String, UserShadow> {
|
||||
// TODO load form YAML o CONFIG
|
||||
let mut shadows = HashMap::new();
|
||||
match config.usrs_shadow_store.as_str() {
|
||||
"fs" => {
|
||||
shadows = AuthStore::load_shadows_from_fs(&config.usrs_shadow_store,&config.usrs_shadow_target);
|
||||
if !shadows.is_empty() {
|
||||
println!("Users info successfully ({})",&shadows.len());
|
||||
}
|
||||
},
|
||||
_ => println!("Store {} not set for shadow store: ", config.usrs_shadow_store),
|
||||
}
|
||||
shadows
|
||||
}
|
||||
// map.insert(
|
||||
// String::from("21"),
|
||||
// User {
|
||||
// user_id: String::from("21"),
|
||||
// name: String::from("herbert"),
|
||||
// role: String::from("member"),
|
||||
// },
|
||||
// );
|
||||
// map.insert(
|
||||
// String::from("100"),
|
||||
// User {
|
||||
// user_id: String::from("100"),
|
||||
// name: String::from("jesus"),
|
||||
// role: String::from("admin"),
|
||||
// },
|
||||
// );
|
||||
// map.insert(
|
||||
// String::from("1"),
|
||||
// User {
|
||||
// user_id: String::from("1"),
|
||||
// name: String::from("gordon"),
|
||||
// role: String::from("anonymous"),
|
||||
// },
|
||||
// );
|
||||
// map
|
||||
// }
|
||||
|
||||
pub async fn create_enforcer(model_path: &'static str, policy_path: &'static str) -> SharedEnforcer {
|
||||
// Arc::new(Enforcer::new(super::super::MODEL_PATH, super::super::POLICY_PATH)
|
||||
Arc::new(Enforcer::new(model_path, policy_path)
|
||||
.await
|
||||
.expect("can read casbin model and policy files")
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppAuthDBs {
|
||||
pub app: AppStore,
|
||||
pub auth: AuthStore,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue