chore: add app_file

This commit is contained in:
Jesús Pérez Lorenzo 2021-09-01 18:59:13 +01:00
parent 82061f4a8d
commit 06846cc8f9
6 changed files with 285 additions and 13 deletions

View File

@ -56,7 +56,6 @@ An authorization library based in [Casbin](https://casbin.org/) [Rust library](h
<pre>
app_auth/
├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
@ -70,8 +69,9 @@ Dedicated to load configuration, enviroment settings, profiles, collections, etc
<pre>
app_env/
├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
└── src
├── appdata.rs
├── appenv.rs
@ -88,7 +88,6 @@ Define common applications errors
<pre>
app_errors/
├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
@ -102,7 +101,6 @@ To handle common application files and storages.
<pre>
app_file/
├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
@ -115,17 +113,17 @@ app_file/
Basic definitions and utilities
<pre>
kloud/
├── Cargo.lock
kloud
├── Cargo.toml
├── README.md
├── TODO.md
└── src
├── datacontext.rs
├── defs.rs
├── lang.rs
├── lib.rs
└── utils.rs
├── src
│   ├── datacontext.rs
│   ├── defs.rs
│   ├── kloud.rs
│   ├── lang.rs
│   ├── lib.rs
│   └── utils.rs
</pre>
## Author
@ -134,4 +132,4 @@ kloud/
## License
MIT
MIT

10
app_file/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
/target
target
Cargo.lock
.cache
.temp
.env
*.log
.DS_Store
logs
tmp

55
app_file/Cargo.toml Normal file
View File

@ -0,0 +1,55 @@
[package]
name = "app_file"
version = "0.1.0"
authors = ["JesusPerez <jpl@jesusperez.pro>"]
edition = "2018"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.40"
##
base64 = "0.13.0"
casbin = "2.0.7"
chrono = "0.4"
dotenv = "0.15.0"
envmnt = "0.9.0"
error-chain = "0.12.4"
glob = "0.3.0"
json = "0.12.4"
once_cell = "1.7.2"
parking_lot = "0.11.1"
rand = "0.8.3"
regex = "1.4.3"
serde = { version = "1.0", features = ["derive"] }
serde_derive = "1.0.125"
serde_json = "1.0.64"
serde_yaml = "0.8.17"
slab = "0.4.3"
tempfile = "3.2.0"
tera = "1.8.0"
thiserror = "1.0.24"
toml = "0.5.8"
yaml-rust = "0.4"
tokio = { version = "1.5.0", features = ["full"] }
uuid = { version = "0.8", features = ["serde", "v4"] }
url = "2.2.1"
warp = { version = "0.3", features = ["default","websocket","tls","compression"] }
app_tools = { version = "0.1.0", path = "../../utils/app_tools" }
app_env = { version = "0.1.0", path = "../app_env" }
[dev-dependencies]
pretty_env_logger = "0.4"
tracing-subscriber = "0.2.15"
tracing-log = "0.1"
serde_derive = "1.0.125"
handlebars = "4.1.2"
tokio = { version = "1.5.0", features = ["macros", "rt-multi-thread"] }
tokio-stream = { version = "0.1.5", features = ["net"] }
listenfd = "0.3"
envmnt = "0.9.0"
[build-dependencies]
envmnt = "0.9.0"

5
app_file/README.md Normal file
View File

@ -0,0 +1,5 @@
# App File library
This is **types** collection library
## app_file

3
app_file/TODO.md Normal file
View File

@ -0,0 +1,3 @@
# App File library
- [ ]

201
app_file/src/lib.rs Normal file
View 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,
}