diff --git a/README.md b/README.md index 673d73e..f1d33ed 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,6 @@ An authorization library based in [Casbin](https://casbin.org/) [Rust library](h
app_auth/
-├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
@@ -70,8 +69,9 @@ Dedicated to load configuration, enviroment settings, profiles, collections, etc
app_env/
-├── Cargo.lock
├── Cargo.toml
+├── README.md
+├── TODO.md
└── src
├── appdata.rs
├── appenv.rs
@@ -88,7 +88,6 @@ Define common applications errors
app_errors/
-├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
@@ -102,7 +101,6 @@ To handle common application files and storages.
app_file/
-├── Cargo.lock
├── Cargo.toml
├── README.md
├── TODO.md
@@ -115,17 +113,17 @@ app_file/
Basic definitions and utilities
-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
## Author
@@ -134,4 +132,4 @@ kloud/
## License
-MIT
\ No newline at end of file
+MIT
diff --git a/app_file/.gitignore b/app_file/.gitignore
new file mode 100644
index 0000000..c3a29c2
--- /dev/null
+++ b/app_file/.gitignore
@@ -0,0 +1,10 @@
+/target
+target
+Cargo.lock
+.cache
+.temp
+.env
+*.log
+.DS_Store
+logs
+tmp
diff --git a/app_file/Cargo.toml b/app_file/Cargo.toml
new file mode 100644
index 0000000..7cd6e89
--- /dev/null
+++ b/app_file/Cargo.toml
@@ -0,0 +1,55 @@
+[package]
+name = "app_file"
+version = "0.1.0"
+authors = ["JesusPerez "]
+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"
diff --git a/app_file/README.md b/app_file/README.md
new file mode 100644
index 0000000..b32f69a
--- /dev/null
+++ b/app_file/README.md
@@ -0,0 +1,5 @@
+# App File library
+
+This is **types** collection library
+
+## app_file
diff --git a/app_file/TODO.md b/app_file/TODO.md
new file mode 100644
index 0000000..bbb1e0e
--- /dev/null
+++ b/app_file/TODO.md
@@ -0,0 +1,3 @@
+# App File library
+
+- [ ]
\ No newline at end of file
diff --git a/app_file/src/lib.rs b/app_file/src/lib.rs
new file mode 100644
index 0000000..cd00ac6
--- /dev/null
+++ b/app_file/src/lib.rs
@@ -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 = std::result::Result;
+
+#[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) -> warp::Rejection {
+pub fn custom_reject(error: impl Into) -> warp::Rejection {
+ warp::reject::custom(CustomReject(error.into()))
+}
+
+pub type UserMap = Arc>>;
+pub type UserShadowMap = Arc>>;
+pub type Sessions = Arc>>;
+pub type SharedEnforcer = Arc;
+
+#[derive(Clone)]
+pub struct AuthStore {
+ pub users: UserMap,
+ pub shadows: UserShadowMap,
+ pub sessions: Sessions,
+ pub enforcer: Arc, // 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 {
+ 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 = 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 {
+ 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 = 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 {
+ // 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 {
+ // 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,
+}