From e9a6e436c4bb147c16bb84dcafef3eead53fcc52 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Tue, 14 Jun 2022 20:43:16 +0530 Subject: [PATCH 01/18] upgraded dependencies in file adapter --- actix-fileadapter-rbac/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-fileadapter-rbac/Cargo.toml b/actix-fileadapter-rbac/Cargo.toml index 2a84227..024ba45 100644 --- a/actix-fileadapter-rbac/Cargo.toml +++ b/actix-fileadapter-rbac/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = "3.0" -actix-rt = "1.1" +actix-web = "4.1.0" +actix-rt = "2.7.0" casbin = "2.0" dotenv = "0.15" loge = {version = "0.4", default-features = false, features = ["colored", "chrono"]} From a5b22c2692213e02dcf080a2a5c5c1dde5ec244f Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Tue, 14 Jun 2022 20:44:48 +0530 Subject: [PATCH 02/18] upgraded rest dependencies --- actix-middleware-example/Cargo.toml | 18 +++++++++--------- actix-pgsql-simple/Cargo.toml | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/actix-middleware-example/Cargo.toml b/actix-middleware-example/Cargo.toml index 44699d9..df78c15 100644 --- a/actix-middleware-example/Cargo.toml +++ b/actix-middleware-example/Cargo.toml @@ -8,11 +8,11 @@ edition = "2018" [dependencies] http = "0.2.1" -actix = "0.11.0" -actix-web = "3.0.2" -actix-service = "1.0.6" -actix-rt = "1.1.1" -actix-cors = "0.5.0" +actix = "0.13.0" +actix-web = "4.1.0" +actix-service = "2.0.2" +actix-rt = "2.7.0" +actix-cors = "0.6.1" futures = "0.3.5" failure = "0.1.8" serde = "1.0.116" @@ -25,11 +25,11 @@ diesel_migrations = "1.4.0" dotenv = "0.15.0" env_logger = "0.9.0" log = "0.4.11" -jsonwebtoken = "7.2.0" -bcrypt = "0.10.0" +jsonwebtoken = "8.1.0" +bcrypt = "0.13.0" csv = "1.1.3" walkdir = "2.3.1" actix-casbin= {version = "0.4.2", default-features = false, features = [ "runtime-async-std" ]} actix-casbin-auth = {version = "0.4.4", default-features = false, features = [ "runtime-async-std" ]} -diesel-adapter = { version = "0.8.1", default-features = false, features = ["postgres","runtime-async-std"] } -uuid = {version = "0.8.1", features = ["v4"] } +diesel-adapter = { version = "0.9.0", default-features = false, features = ["postgres","runtime-async-std"] } +uuid = {version = "1.0.0", features = ["v4"] } diff --git a/actix-pgsql-simple/Cargo.toml b/actix-pgsql-simple/Cargo.toml index 3b85221..b2c4858 100644 --- a/actix-pgsql-simple/Cargo.toml +++ b/actix-pgsql-simple/Cargo.toml @@ -5,13 +5,13 @@ edition = "2018" [dependencies] casbin = "2.0" -diesel-adapter = { version = "0.8", features = ["postgres"] } +diesel-adapter = { version = "0.9.0", features = ["postgres"] } async-std = { version = "1.6", features = ["attributes"] } diesel = { version = "1.4", features = ["postgres", "serde_json", "r2d2"] } -actix-web = { version = "3.0" } -actix-rt = "1.1" +actix-web = { version = "4.1.0" } +actix-rt = "2.7.0" serde = "1.0" serde_derive = "1.0" From cb3a84cea79d31f885a1ccd6e45720d96445f71b Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sun, 19 Jun 2022 11:11:31 +0530 Subject: [PATCH 03/18] added pullrequest and cache in github actions --- .github/workflows/check.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index ac00021..add86d2 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,6 +1,7 @@ name: Check Code on: + pull_request: push: branches: - '*' @@ -15,7 +16,16 @@ jobs: steps: - name: "Checkout Repository" - uses: actions/checkout@v1 + uses: actions/checkout@v2 + + - name: "Use Rust stable" + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + + - name: "Check rust_cache" + uses: Swatinem/rust-cache@v1 - name: Generate test secret key shell: sh From bd7097eae46694238750bf4abddfa9de5caf8134 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sat, 9 Jul 2022 05:47:32 +0530 Subject: [PATCH 04/18] actix-fileadapter-rbac, actix-pgsql-simple, ntex-fileadapter-acl error resolved --- actix-middleware-example/Cargo.toml | 6 +-- actix-middleware-example/src/main.rs | 6 +-- .../src/middleware/authn.rs | 40 +++++++++---------- actix-middleware-example/src/models/user.rs | 2 +- .../src/services/account_service.rs | 6 +-- .../src/services/post_service.rs | 2 +- 6 files changed, 29 insertions(+), 33 deletions(-) diff --git a/actix-middleware-example/Cargo.toml b/actix-middleware-example/Cargo.toml index df78c15..4cc7f0b 100644 --- a/actix-middleware-example/Cargo.toml +++ b/actix-middleware-example/Cargo.toml @@ -8,10 +8,10 @@ edition = "2018" [dependencies] http = "0.2.1" -actix = "0.13.0" +actix = "0.10.0" +actix-rt = "2.7.0" actix-web = "4.1.0" actix-service = "2.0.2" -actix-rt = "2.7.0" actix-cors = "0.6.1" futures = "0.3.5" failure = "0.1.8" @@ -32,4 +32,4 @@ walkdir = "2.3.1" actix-casbin= {version = "0.4.2", default-features = false, features = [ "runtime-async-std" ]} actix-casbin-auth = {version = "0.4.4", default-features = false, features = [ "runtime-async-std" ]} diesel-adapter = { version = "0.9.0", default-features = false, features = ["postgres","runtime-async-std"] } -uuid = {version = "1.0.0", features = ["v4"] } +uuid = {version = "1.1.2", features = ["v4"] } \ No newline at end of file diff --git a/actix-middleware-example/src/main.rs b/actix-middleware-example/src/main.rs index b91a774..9706e15 100644 --- a/actix-middleware-example/src/main.rs +++ b/actix-middleware-example/src/main.rs @@ -62,7 +62,6 @@ async fn main() -> Result<()> { .await .get_role_manager() .write() - .unwrap() .matching_fn(Some(key_match2), None); let share_enforcer = casbin_middleware.get_enforcer(); @@ -100,7 +99,7 @@ async fn main() -> Result<()> { .data(pool.clone()) .data(started_actor.clone()) .wrap( - Cors::new() + Cors::default() .send_wildcard() .allowed_methods(vec!["GET", "POST", "DELETE"]) .allowed_headers(vec![ @@ -108,8 +107,7 @@ async fn main() -> Result<()> { http::header::ACCEPT, ]) .allowed_header(http::header::CONTENT_TYPE) - .max_age(3600) - .finish(), + .max_age(3600), ) .wrap(NormalizePath::new(TrailingSlash::Trim)) .wrap(Logger::default()) diff --git a/actix-middleware-example/src/middleware/authn.rs b/actix-middleware-example/src/middleware/authn.rs index 14993eb..779e092 100644 --- a/actix-middleware-example/src/middleware/authn.rs +++ b/actix-middleware-example/src/middleware/authn.rs @@ -6,8 +6,12 @@ use crate::{ use actix_casbin_auth::CasbinVals; use actix_service::{Service, Transform}; use actix_web::{ + body::{EitherBody, MessageBody}, dev::{ServiceRequest, ServiceResponse}, - http::{HeaderName, HeaderValue, Method}, + http::{ + header::{HeaderName, HeaderValue}, + Method, + }, web::Data, Error, HttpMessage, HttpResponse, }; @@ -24,15 +28,12 @@ use std::{ pub struct Authentication; -impl Transform for Authentication +impl Transform for Authentication where - S: Service, Error = Error> - + 'static, - S::Future: 'static, - B: 'static, +S: Service, Error = Error> + 'static, +B: MessageBody, { - type Request = ServiceRequest; - type Response = ServiceResponse; + type Response = ServiceResponse>; type Error = Error; type InitError = (); type Transform = AuthenticationMiddleware; @@ -48,23 +49,20 @@ pub struct AuthenticationMiddleware { service: Rc>, } -impl Service for AuthenticationMiddleware +impl Service for AuthenticationMiddleware where - S: Service, Error = Error> - + 'static, - S::Future: 'static, - B: 'static, + S: Service, Error = Error> + 'static, + B: MessageBody, { - type Request = ServiceRequest; - type Response = ServiceResponse; - type Error = Error; + type Response = ServiceResponse>; + type Error = S::Error; type Future = Pin>>>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + fn poll_ready(&self, cx: &mut Context<'_>) -> Poll> { self.service.poll_ready(cx) } - fn call(&mut self, mut req: ServiceRequest) -> Self::Future { + fn call(&self, mut req: ServiceRequest) -> Self::Future { let mut srv = self.service.clone(); let mut authenticate_pass: bool = false; let mut public_route: bool = false; @@ -125,14 +123,14 @@ where domain: None, }; req.extensions_mut().insert(vals); - Box::pin(async move { srv.call(req).await }) + Box::pin(async move { srv.call(req).await.map(|res| res.map_into_left_body()) }) } else { let vals = CasbinVals { subject: authenticate_username, domain: None, }; req.extensions_mut().insert(vals); - Box::pin(async move { srv.clone().call(req).await }) + Box::pin(async move { srv.clone().call(req).await.map(|res| res.map_into_left_body()) }) } } else { Box::pin(async move { @@ -142,7 +140,7 @@ where constants::MESSAGE_INVALID_TOKEN, constants::EMPTY, )) - .into_body(), + .map_into_right_body(), )) }) } diff --git a/actix-middleware-example/src/models/user.rs b/actix-middleware-example/src/models/user.rs index b9f201b..df0f996 100644 --- a/actix-middleware-example/src/models/user.rs +++ b/actix-middleware-example/src/models/user.rs @@ -130,7 +130,7 @@ impl User { } pub fn generate_login_session() -> String { - Uuid::new_v4().to_simple().to_string() + Uuid::new_v4().simple().to_string() } // pub fn get_user_role( diff --git a/actix-middleware-example/src/services/account_service.rs b/actix-middleware-example/src/services/account_service.rs index 20c0d24..26a61c3 100644 --- a/actix-middleware-example/src/services/account_service.rs +++ b/actix-middleware-example/src/services/account_service.rs @@ -6,11 +6,11 @@ use crate::{ models::user::{DeleteUser, LoginForm, NewUser, User}, models::user_token::UserToken, }; -use actix::Addr; +use actix::{Addr, dev::channel::AddressSender, Actor, Context}; use actix_casbin::{CasbinActor, CasbinCmd, CasbinResult}; -use actix_casbin_auth::casbin::CachedEnforcer; +use actix_casbin_auth::casbin::{CachedEnforcer, IEnforcer}; use actix_casbin_auth::CasbinVals; -use actix_web::{http::StatusCode, web, HttpRequest}; +use actix_web::{http::StatusCode, web, HttpRequest, HttpMessage}; #[derive(Serialize, Deserialize)] pub struct TokenBodyResponse { diff --git a/actix-middleware-example/src/services/post_service.rs b/actix-middleware-example/src/services/post_service.rs index 8a58f27..b449e4e 100644 --- a/actix-middleware-example/src/services/post_service.rs +++ b/actix-middleware-example/src/services/post_service.rs @@ -6,7 +6,7 @@ use crate::{ models::user::User, }; use actix_casbin_auth::CasbinVals; -use actix_web::{http::StatusCode, web, HttpRequest}; +use actix_web::{http::StatusCode, web, HttpRequest, HttpMessage}; pub fn find_all_public(pool: &web::Data) -> Result, ServiceError> { match Post::find_all(false, &pool.get().unwrap()) { From 10069e0ddcde004c0a0916d4cf4944b8e8552fb6 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sat, 9 Jul 2022 05:51:56 +0530 Subject: [PATCH 05/18] ntex-fileadapter-acl build success --- ntex-fileadapter-acl/Cargo.toml | 6 +++--- ntex-fileadapter-acl/src/main.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ntex-fileadapter-acl/Cargo.toml b/ntex-fileadapter-acl/Cargo.toml index efaffe1..761a3fe 100644 --- a/ntex-fileadapter-acl/Cargo.toml +++ b/ntex-fileadapter-acl/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" workspace = ".." [dependencies] -ntex = "0.5" -casbin = "2.0" +ntex = { version = "0.5", features = ["tokio"] } +casbin = "2.0.9" dotenv = "0.15" -loge = {version = "0.4", default-features = false, features = ["colored", "chrono"]} +loge = {version = "0.4.2", default-features = false, features = ["colored", "chrono"]} diff --git a/ntex-fileadapter-acl/src/main.rs b/ntex-fileadapter-acl/src/main.rs index 889adda..ddf107c 100644 --- a/ntex-fileadapter-acl/src/main.rs +++ b/ntex-fileadapter-acl/src/main.rs @@ -6,7 +6,7 @@ use ntex::web::{self, middleware, App, HttpRequest, HttpResponse}; /// simple handle async fn auth( - enforcer: web::types::Data>, + enforcer: web::types::State>, req: HttpRequest, ) -> HttpResponse { let e = enforcer.write().unwrap(); @@ -38,12 +38,12 @@ async fn main() -> io::Result<()> { let adapter = FileAdapter::new("acl/acl_policy.csv"); let e = Enforcer::new(model, adapter).await.unwrap(); - let e = web::types::Data::new(RwLock::new(e)); // wrap enforcer into actix-state + let e = web::types::State::new(RwLock::new(e)); // wrap enforcer into actix-state //move is necessary to give closure below ownership of counter web::server(move || { App::new() - .app_data(e.clone()) // <- create app with shared state + .app_state(e.clone()) // <- create app with shared state // enable logger .wrap(middleware::Logger::default()) // register simple handler, handle all methods From 9dc325b5867cb9bfda1948abdd14bccc67f926f7 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Fri, 15 Jul 2022 09:11:23 +0530 Subject: [PATCH 06/18] actix-middleware-example --- actix-middleware-example/Cargo.toml | 9 +++++---- actix-middleware-example/src/main.rs | 4 ++-- actix-middleware-example/src/middleware/authn.rs | 2 +- actix-middleware-example/src/services/account_service.rs | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/actix-middleware-example/Cargo.toml b/actix-middleware-example/Cargo.toml index 4cc7f0b..95385fe 100644 --- a/actix-middleware-example/Cargo.toml +++ b/actix-middleware-example/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] http = "0.2.1" -actix = "0.10.0" +actix = "0.13.0" actix-rt = "2.7.0" actix-web = "4.1.0" actix-service = "2.0.2" @@ -29,7 +29,8 @@ jsonwebtoken = "8.1.0" bcrypt = "0.13.0" csv = "1.1.3" walkdir = "2.3.1" -actix-casbin= {version = "0.4.2", default-features = false, features = [ "runtime-async-std" ]} -actix-casbin-auth = {version = "0.4.4", default-features = false, features = [ "runtime-async-std" ]} diesel-adapter = { version = "0.9.0", default-features = false, features = ["postgres","runtime-async-std"] } -uuid = {version = "1.1.2", features = ["v4"] } \ No newline at end of file +uuid = {version = "1.1.2", features = ["v4"] } +# UPDATE AFTER LATEST RELEASE OF actix-casbin and actix-casbin-auth to CRATE.IO +actix-casbin= {git = "https://github.com/casbin-rs/actix-casbin", default-features = false, features = [ "runtime-async-std" ]} +actix-casbin-auth = {git = "https://github.com/casbin-rs/actix-casbin-auth", default-features = false, features = [ "runtime-async-std" ]} \ No newline at end of file diff --git a/actix-middleware-example/src/main.rs b/actix-middleware-example/src/main.rs index 9706e15..43d492e 100644 --- a/actix-middleware-example/src/main.rs +++ b/actix-middleware-example/src/main.rs @@ -96,8 +96,8 @@ async fn main() -> Result<()> { HttpServer::new(move || { App::new() - .data(pool.clone()) - .data(started_actor.clone()) + .app_data(pool.clone()) + .app_data(started_actor.clone()) .wrap( Cors::default() .send_wildcard() diff --git a/actix-middleware-example/src/middleware/authn.rs b/actix-middleware-example/src/middleware/authn.rs index 779e092..81a308f 100644 --- a/actix-middleware-example/src/middleware/authn.rs +++ b/actix-middleware-example/src/middleware/authn.rs @@ -63,7 +63,7 @@ where } fn call(&self, mut req: ServiceRequest) -> Self::Future { - let mut srv = self.service.clone(); + let srv = self.service.clone(); let mut authenticate_pass: bool = false; let mut public_route: bool = false; let mut authenticate_username: String = String::from(""); diff --git a/actix-middleware-example/src/services/account_service.rs b/actix-middleware-example/src/services/account_service.rs index 26a61c3..57441d4 100644 --- a/actix-middleware-example/src/services/account_service.rs +++ b/actix-middleware-example/src/services/account_service.rs @@ -6,9 +6,9 @@ use crate::{ models::user::{DeleteUser, LoginForm, NewUser, User}, models::user_token::UserToken, }; -use actix::{Addr, dev::channel::AddressSender, Actor, Context}; +use actix::Addr; use actix_casbin::{CasbinActor, CasbinCmd, CasbinResult}; -use actix_casbin_auth::casbin::{CachedEnforcer, IEnforcer}; +use actix_casbin_auth::casbin::{CachedEnforcer}; use actix_casbin_auth::CasbinVals; use actix_web::{http::StatusCode, web, HttpRequest, HttpMessage}; From bcdc9ddd0f32af2b7c36e0267ffb45749e585239 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sat, 16 Jul 2022 19:33:59 +0530 Subject: [PATCH 07/18] filestructure and initial db implementation --- Cargo.toml | 1 + actix-fileadapter-rbac/Cargo.toml | 2 +- actix-middleware-example/.env.sample | 2 +- actix-pgsql-simple/Cargo.toml | 4 +- axum-middleware-example/.env.sample | 5 ++ axum-middleware-example/Cargo.toml | 27 ++++++++ axum-middleware-example/diesel.toml | 5 ++ axum-middleware-example/migrations/.gitkeep | 0 .../down.sql | 6 ++ .../up.sql | 36 +++++++++++ .../2022-07-16-125141_users/down.sql | 2 + .../migrations/2022-07-16-125141_users/up.sql | 14 ++++ .../src/config/rbac_model.conf | 14 ++++ axum-middleware-example/src/constants.rs | 10 +++ axum-middleware-example/src/errors.rs | 1 + axum-middleware-example/src/main.rs | 33 ++++++++++ .../src/middleware/authorizeJWT.rs | 1 + .../src/middleware/middleware.rs | 64 +++++++++++++++++++ axum-middleware-example/src/middleware/mod.rs | 1 + axum-middleware-example/src/model/db.rs | 1 + axum-middleware-example/src/model/mod.rs | 2 + axum-middleware-example/src/model/user.rs | 16 +++++ axum-middleware-example/src/schema.rs | 9 +++ axum-middleware-example/src/utils/bcrypt.rs | 11 ++++ 24 files changed, 263 insertions(+), 4 deletions(-) create mode 100644 axum-middleware-example/.env.sample create mode 100644 axum-middleware-example/Cargo.toml create mode 100644 axum-middleware-example/diesel.toml create mode 100644 axum-middleware-example/migrations/.gitkeep create mode 100644 axum-middleware-example/migrations/00000000000000_diesel_initial_setup/down.sql create mode 100644 axum-middleware-example/migrations/00000000000000_diesel_initial_setup/up.sql create mode 100644 axum-middleware-example/migrations/2022-07-16-125141_users/down.sql create mode 100644 axum-middleware-example/migrations/2022-07-16-125141_users/up.sql create mode 100644 axum-middleware-example/src/config/rbac_model.conf create mode 100644 axum-middleware-example/src/constants.rs create mode 100644 axum-middleware-example/src/errors.rs create mode 100644 axum-middleware-example/src/main.rs create mode 100644 axum-middleware-example/src/middleware/authorizeJWT.rs create mode 100644 axum-middleware-example/src/middleware/middleware.rs create mode 100644 axum-middleware-example/src/middleware/mod.rs create mode 100644 axum-middleware-example/src/model/db.rs create mode 100644 axum-middleware-example/src/model/mod.rs create mode 100644 axum-middleware-example/src/model/user.rs create mode 100644 axum-middleware-example/src/schema.rs create mode 100644 axum-middleware-example/src/utils/bcrypt.rs diff --git a/Cargo.toml b/Cargo.toml index 204515e..76e365d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ members = [ "actix-pgsql-simple", "ntex-fileadapter-acl", "actix-middleware-example", + "axum-middleware-example" ] diff --git a/actix-fileadapter-rbac/Cargo.toml b/actix-fileadapter-rbac/Cargo.toml index 024ba45..9ed91a3 100644 --- a/actix-fileadapter-rbac/Cargo.toml +++ b/actix-fileadapter-rbac/Cargo.toml @@ -8,6 +8,6 @@ workspace = ".." [dependencies] actix-web = "4.1.0" actix-rt = "2.7.0" -casbin = "2.0" +casbin = "2.0.9" dotenv = "0.15" loge = {version = "0.4", default-features = false, features = ["colored", "chrono"]} diff --git a/actix-middleware-example/.env.sample b/actix-middleware-example/.env.sample index 3384e7c..1793bd6 100644 --- a/actix-middleware-example/.env.sample +++ b/actix-middleware-example/.env.sample @@ -1,5 +1,5 @@ APP_HOST=127.0.0.1 APP_PORT=8080 -DATABASE_URL=postgres://casbin_rs:casbin_rs@127.0.0.1:5432/test +DATABASE_URL=postgres://postgres:postgresAdmin@127.0.0.1:5432/alpha POOL_SIZE=8 HASH_ROUNDS=12 \ No newline at end of file diff --git a/actix-pgsql-simple/Cargo.toml b/actix-pgsql-simple/Cargo.toml index b2c4858..48f6684 100644 --- a/actix-pgsql-simple/Cargo.toml +++ b/actix-pgsql-simple/Cargo.toml @@ -4,13 +4,13 @@ version = "0.1.0" edition = "2018" [dependencies] -casbin = "2.0" +casbin = "2.0.9" diesel-adapter = { version = "0.9.0", features = ["postgres"] } async-std = { version = "1.6", features = ["attributes"] } diesel = { version = "1.4", features = ["postgres", "serde_json", "r2d2"] } -actix-web = { version = "4.1.0" } +actix-web = "4.1.0" actix-rt = "2.7.0" serde = "1.0" serde_derive = "1.0" diff --git a/axum-middleware-example/.env.sample b/axum-middleware-example/.env.sample new file mode 100644 index 0000000..6403a4c --- /dev/null +++ b/axum-middleware-example/.env.sample @@ -0,0 +1,5 @@ +APP_HOST=127.0.0.1 +APP_PORT=8080 +DATABASE_URL=postgres://postgres:postgresAdmin@127.0.0.1:5432/casbintest +POOL_SIZE=8 +HASH_ROUNDS=12 \ No newline at end of file diff --git a/axum-middleware-example/Cargo.toml b/axum-middleware-example/Cargo.toml new file mode 100644 index 0000000..bc62eff --- /dev/null +++ b/axum-middleware-example/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "axum-middleware-example" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +axum = "0.5.7" +tokio = { version = "1.17.0", features = [ "full" ] } +futures = "0.3.5" +failure = "0.1.8" +serde = "1.0.116" +serde_derive = "1.0.116" +serde_json = "1.0.57" +derive_more = "0.99.10" +diesel = { version = "1.4.5", features = ["postgres","r2d2", "chrono"] } +diesel_migrations = "1.4.0" +dotenv = "0.15.0" +env_logger = "0.9.0" +log = "0.4.11" +jsonwebtoken = "8.1.0" +bcrypt = "0.13.0" +csv = "1.1.3" +walkdir = "2.3.1" +diesel-adapter = { version = "0.9.0", default-features = false, features = ["postgres","runtime-async-std"] } +uuid = {version = "1.1.2", features = ["v4"] } \ No newline at end of file diff --git a/axum-middleware-example/diesel.toml b/axum-middleware-example/diesel.toml new file mode 100644 index 0000000..92267c8 --- /dev/null +++ b/axum-middleware-example/diesel.toml @@ -0,0 +1,5 @@ +# For documentation on how to configure this file, +# see diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" diff --git a/axum-middleware-example/migrations/.gitkeep b/axum-middleware-example/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/axum-middleware-example/migrations/00000000000000_diesel_initial_setup/down.sql b/axum-middleware-example/migrations/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..a9f5260 --- /dev/null +++ b/axum-middleware-example/migrations/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,6 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/axum-middleware-example/migrations/00000000000000_diesel_initial_setup/up.sql b/axum-middleware-example/migrations/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..d68895b --- /dev/null +++ b/axum-middleware-example/migrations/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,36 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + + + + +-- Sets up a trigger for the given table to automatically set a column called +-- `updated_at` whenever the row is modified (unless `updated_at` was included +-- in the modified columns) +-- +-- # Example +-- +-- ```sql +-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); +-- +-- SELECT diesel_manage_updated_at('users'); +-- ``` +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; diff --git a/axum-middleware-example/migrations/2022-07-16-125141_users/down.sql b/axum-middleware-example/migrations/2022-07-16-125141_users/down.sql new file mode 100644 index 0000000..0172a87 --- /dev/null +++ b/axum-middleware-example/migrations/2022-07-16-125141_users/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE users; \ No newline at end of file diff --git a/axum-middleware-example/migrations/2022-07-16-125141_users/up.sql b/axum-middleware-example/migrations/2022-07-16-125141_users/up.sql new file mode 100644 index 0000000..7eb4f4a --- /dev/null +++ b/axum-middleware-example/migrations/2022-07-16-125141_users/up.sql @@ -0,0 +1,14 @@ +-- Your SQL goes here +CREATE TABLE users +( + id SERIAL PRIMARY KEY, + username VARCHAR(32) NOT NULL, + email VARCHAR(100) NOT NULL, + password VARCHAR(200) NOT NULL, + role VARCHAR(32) NOT NULL +); + +INSERT INTO users +VALUES (0, 'John', 'john@john.com', 'imjohn', 'doctor'); +INSERT INTO users +VALUES (1, 'Sam', 'sam@sam.com', 'imsam', 'patient'); \ No newline at end of file diff --git a/axum-middleware-example/src/config/rbac_model.conf b/axum-middleware-example/src/config/rbac_model.conf new file mode 100644 index 0000000..71159e3 --- /dev/null +++ b/axum-middleware-example/src/config/rbac_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[role_definition] +g = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act \ No newline at end of file diff --git a/axum-middleware-example/src/constants.rs b/axum-middleware-example/src/constants.rs new file mode 100644 index 0000000..d980ba0 --- /dev/null +++ b/axum-middleware-example/src/constants.rs @@ -0,0 +1,10 @@ +// Messages +pub const MESSAGE_OK: &str = "ok"; +pub const MESSAGE_CAN_NOT_FIND_USER: &str = "Can not find user, user not exist"; +pub const MESSAGE_CAN_NOT_FETCH_DATA: &str = "Can not fetch data"; +pub const MESSAGE_CAN_NOT_INSERT_DATA: &str = "Can not insert data"; +pub const MESSAGE_CAN_NOT_DELETE_DATA: &str = "Can not delete data"; +pub const MESSAGE_PROCESS_TOKEN_ERROR: &str = "Error while processing token"; +pub const MESSAGE_INVALID_TOKEN: &str = "Invalid token, please login again"; +pub const MESSAGE_INTERNAL_SERVER_ERROR: &str = "Internal Server Error"; +pub const MESSAGE_TOKEN_MISSING: &str = "Token is missing"; \ No newline at end of file diff --git a/axum-middleware-example/src/errors.rs b/axum-middleware-example/src/errors.rs new file mode 100644 index 0000000..210b3ae --- /dev/null +++ b/axum-middleware-example/src/errors.rs @@ -0,0 +1 @@ +// DEFINE ERROR HERE \ No newline at end of file diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs new file mode 100644 index 0000000..eaf88d8 --- /dev/null +++ b/axum-middleware-example/src/main.rs @@ -0,0 +1,33 @@ +#[macro_use] +extern crate diesel; + +mod model; +mod schema; + +use crate::model::*; +use crate::schema::*; +use crate::user::User; +use diesel::pg::PgConnection; +use diesel::prelude::*; +use dotenv::dotenv; +use std::env; + +fn establish_connection() -> PgConnection { + dotenv().ok(); + + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + PgConnection::establish(&database_url) + .expect(&format!("Error connecting to {}", database_url)) +} + +fn main() { + let mut connection = establish_connection(); + let results = users::table + .limit(5) + .load::(&mut connection) + .expect("Error loading posts"); + println!("Displaying {} users", results.len()); + for user in results { + println!("{} {} {} {} {}", user.id, user.username, user.email, user.password, user.role); + } +} diff --git a/axum-middleware-example/src/middleware/authorizeJWT.rs b/axum-middleware-example/src/middleware/authorizeJWT.rs new file mode 100644 index 0000000..a6f278d --- /dev/null +++ b/axum-middleware-example/src/middleware/authorizeJWT.rs @@ -0,0 +1 @@ +// JWT AUTHENTICATION \ No newline at end of file diff --git a/axum-middleware-example/src/middleware/middleware.rs b/axum-middleware-example/src/middleware/middleware.rs new file mode 100644 index 0000000..fa52467 --- /dev/null +++ b/axum-middleware-example/src/middleware/middleware.rs @@ -0,0 +1,64 @@ +use axum::{response::Response, routing::get, BoxError, Router}; +use axum_casbin_auth::{CasbinAxumLayer, CasbinVals}; +use axum_test_helper::TestClient; +use bytes::Bytes; +use casbin::function_map::key_match2; +use casbin::{CoreApi, DefaultModel, FileAdapter}; +use futures::future::BoxFuture; +use http::{self, Request, StatusCode}; +use http_body::Body as HttpBody; +use std::{ + boxed::Box, + convert::Infallible, + task::{Context, Poll}, +}; +use tower::{Layer, Service}; + +#[derive(Clone)] +struct AuthLayer; + +impl Layer for AuthLayer { + type Service = AuthMiddleware; + + fn layer(&self, inner: S) -> Self::Service { + AuthMiddleware { inner } + } +} + +#[derive(Clone)] +struct AuthMiddleware { + inner: S, +} + +impl Service> for AuthMiddleware +where + S: Service, Response = Response, Error = Infallible> + + Clone + + Send + + 'static, + S::Future: Send + 'static, + ReqBody: Send + 'static, + Infallible: From<>>::Error>, + ResBody: HttpBody + Send + 'static, + ResBody::Error: Into, +{ + type Response = S::Response; + type Error = S::Error; + // `BoxFuture` is a type alias for `Pin>` + type Future = BoxFuture<'static, Result>; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, mut req: Request) -> Self::Future { + let not_ready_inner = self.inner.clone(); + let mut inner = std::mem::replace(&mut self.inner, not_ready_inner); + + // IMPLEMENT LOGIC HERE + Box::pin(async move { + inner.call(req).await + }) + } +} + diff --git a/axum-middleware-example/src/middleware/mod.rs b/axum-middleware-example/src/middleware/mod.rs new file mode 100644 index 0000000..f35d8d4 --- /dev/null +++ b/axum-middleware-example/src/middleware/mod.rs @@ -0,0 +1 @@ +pub mod middleware; \ No newline at end of file diff --git a/axum-middleware-example/src/model/db.rs b/axum-middleware-example/src/model/db.rs new file mode 100644 index 0000000..6a0204f --- /dev/null +++ b/axum-middleware-example/src/model/db.rs @@ -0,0 +1 @@ +// SETUP DATABASE HERE \ No newline at end of file diff --git a/axum-middleware-example/src/model/mod.rs b/axum-middleware-example/src/model/mod.rs new file mode 100644 index 0000000..6fee132 --- /dev/null +++ b/axum-middleware-example/src/model/mod.rs @@ -0,0 +1,2 @@ +pub mod user; +pub mod db; \ No newline at end of file diff --git a/axum-middleware-example/src/model/user.rs b/axum-middleware-example/src/model/user.rs new file mode 100644 index 0000000..98356eb --- /dev/null +++ b/axum-middleware-example/src/model/user.rs @@ -0,0 +1,16 @@ +use crate::schema::*; +use diesel::prelude::*; +use diesel::QueryDsl; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Serialize, Deserialize, Queryable)] +// #[derive(Identifiable, Queryable, PartialEq, Debug)] +#[diesel(table_name = users)] +pub struct User { + pub id: i32, + pub username: String, + pub email: String, + pub password: String, + pub role: String, +} \ No newline at end of file diff --git a/axum-middleware-example/src/schema.rs b/axum-middleware-example/src/schema.rs new file mode 100644 index 0000000..8e5bdbd --- /dev/null +++ b/axum-middleware-example/src/schema.rs @@ -0,0 +1,9 @@ +table! { + users (id) { + id -> Int4, + username -> Varchar, + email -> Varchar, + password -> Varchar, + role -> Varchar, + } +} diff --git a/axum-middleware-example/src/utils/bcrypt.rs b/axum-middleware-example/src/utils/bcrypt.rs new file mode 100644 index 0000000..7b6340f --- /dev/null +++ b/axum-middleware-example/src/utils/bcrypt.rs @@ -0,0 +1,11 @@ +use crate::constants; +use bcrypt::{hash, verify, DEFAULT_COST}; +use std::env; + +pub fn hash_password() {} + +pub fn compare_password() {} + +pub fn generate_token() {} + +pub fn validate_token() {} From ca00c5c57858c03e6ba6ddcc35e14dbb8d6a2dcc Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sat, 16 Jul 2022 19:37:29 +0530 Subject: [PATCH 08/18] corrected database test url --- actix-middleware-example/.env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-middleware-example/.env.sample b/actix-middleware-example/.env.sample index 1793bd6..4bf0113 100644 --- a/actix-middleware-example/.env.sample +++ b/actix-middleware-example/.env.sample @@ -1,5 +1,5 @@ APP_HOST=127.0.0.1 APP_PORT=8080 -DATABASE_URL=postgres://postgres:postgresAdmin@127.0.0.1:5432/alpha +DATABASE_URL=//casbin_rs:casbin_rs@127.0.0.1:5432/test POOL_SIZE=8 HASH_ROUNDS=12 \ No newline at end of file From 2a3f49aa9040e44a28c016d902abf4b5b3c281a3 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Thu, 21 Jul 2022 17:41:45 +0530 Subject: [PATCH 09/18] utils, user model, user service --- axum-middleware-example/Cargo.toml | 11 +- .../2022-07-21-025537_users/down.sql | 1 + .../migrations/2022-07-21-025537_users/up.sql | 3 + axum-middleware-example/src/constants.rs | 3 +- axum-middleware-example/src/errors.rs | 26 +++- axum-middleware-example/src/main.rs | 13 ++ .../src/middleware/authorizeJWT.rs | 3 +- .../src/middleware/middleware.rs | 3 - axum-middleware-example/src/middleware/mod.rs | 3 +- axum-middleware-example/src/model/db.rs | 27 +++- axum-middleware-example/src/model/mod.rs | 4 +- axum-middleware-example/src/model/response.rs | 16 +++ axum-middleware-example/src/model/user.rs | 115 +++++++++++++++++- .../src/model/user_token.rs | 40 ++++++ axum-middleware-example/src/repository/mod.rs | 0 .../src/repository/user_repository.rs | 0 axum-middleware-example/src/route/mod.rs | 0 axum-middleware-example/src/schema.rs | 1 + axum-middleware-example/src/secret.key.sample | 1 + axum-middleware-example/src/service/mod.rs | 1 + axum-middleware-example/src/service/user.rs | 62 ++++++++++ axum-middleware-example/src/utils/bcrypt.rs | 28 ++++- axum-middleware-example/src/utils/mod.rs | 2 + .../src/utils/token_utils.rs | 29 +++++ 24 files changed, 374 insertions(+), 18 deletions(-) create mode 100644 axum-middleware-example/migrations/2022-07-21-025537_users/down.sql create mode 100644 axum-middleware-example/migrations/2022-07-21-025537_users/up.sql create mode 100644 axum-middleware-example/src/model/response.rs create mode 100644 axum-middleware-example/src/model/user_token.rs create mode 100644 axum-middleware-example/src/repository/mod.rs create mode 100644 axum-middleware-example/src/repository/user_repository.rs create mode 100644 axum-middleware-example/src/route/mod.rs create mode 100644 axum-middleware-example/src/secret.key.sample create mode 100644 axum-middleware-example/src/service/mod.rs create mode 100644 axum-middleware-example/src/service/user.rs create mode 100644 axum-middleware-example/src/utils/mod.rs create mode 100644 axum-middleware-example/src/utils/token_utils.rs diff --git a/axum-middleware-example/Cargo.toml b/axum-middleware-example/Cargo.toml index bc62eff..83c91b9 100644 --- a/axum-middleware-example/Cargo.toml +++ b/axum-middleware-example/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] axum = "0.5.7" -tokio = { version = "1.17.0", features = [ "full" ] } futures = "0.3.5" failure = "0.1.8" serde = "1.0.116" @@ -18,10 +17,16 @@ diesel = { version = "1.4.5", features = ["postgres","r2d2", "chrono"] } diesel_migrations = "1.4.0" dotenv = "0.15.0" env_logger = "0.9.0" +http = "0.2.8" +http-body = "0.4.5" log = "0.4.11" jsonwebtoken = "8.1.0" bcrypt = "0.13.0" csv = "1.1.3" walkdir = "2.3.1" -diesel-adapter = { version = "0.9.0", default-features = false, features = ["postgres","runtime-async-std"] } -uuid = {version = "1.1.2", features = ["v4"] } \ No newline at end of file +tower = { version = "0.4", features = ["full"] } +diesel-adapter = "0.9.0" +bytes = "1.1.0" +uuid = {version = "1.1.2", features = ["v4"] } +chrono = { version = "0.4.18", features = ["serde"] } +axum-casbin-auth = {git = "https://github.com/casbin-rs/axum-casbin-auth"} \ No newline at end of file diff --git a/axum-middleware-example/migrations/2022-07-21-025537_users/down.sql b/axum-middleware-example/migrations/2022-07-21-025537_users/down.sql new file mode 100644 index 0000000..291a97c --- /dev/null +++ b/axum-middleware-example/migrations/2022-07-21-025537_users/down.sql @@ -0,0 +1 @@ +-- This file should undo anything in `up.sql` \ No newline at end of file diff --git a/axum-middleware-example/migrations/2022-07-21-025537_users/up.sql b/axum-middleware-example/migrations/2022-07-21-025537_users/up.sql new file mode 100644 index 0000000..d952eca --- /dev/null +++ b/axum-middleware-example/migrations/2022-07-21-025537_users/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE users +ADD COLUMN login_session VARCHAR NOT NULL DEFAULT ''; \ No newline at end of file diff --git a/axum-middleware-example/src/constants.rs b/axum-middleware-example/src/constants.rs index d980ba0..22b1130 100644 --- a/axum-middleware-example/src/constants.rs +++ b/axum-middleware-example/src/constants.rs @@ -7,4 +7,5 @@ pub const MESSAGE_CAN_NOT_DELETE_DATA: &str = "Can not delete data"; pub const MESSAGE_PROCESS_TOKEN_ERROR: &str = "Error while processing token"; pub const MESSAGE_INVALID_TOKEN: &str = "Invalid token, please login again"; pub const MESSAGE_INTERNAL_SERVER_ERROR: &str = "Internal Server Error"; -pub const MESSAGE_TOKEN_MISSING: &str = "Token is missing"; \ No newline at end of file +pub const MESSAGE_TOKEN_MISSING: &str = "Token is missing"; +pub const MESSAGE_SIGNIN_FAILED: &str = "Wrong email or password, please try again"; \ No newline at end of file diff --git a/axum-middleware-example/src/errors.rs b/axum-middleware-example/src/errors.rs index 210b3ae..b13e8e0 100644 --- a/axum-middleware-example/src/errors.rs +++ b/axum-middleware-example/src/errors.rs @@ -1 +1,25 @@ -// DEFINE ERROR HERE \ No newline at end of file +// DEFINE ERROR HERE +use crate::model::response::ResponseBody; +use http::{StatusCode, Response}; + +#[derive(Debug)] +pub struct ServiceError { + pub http_status: StatusCode, + pub body: ResponseBody, +} + +impl ServiceError { + pub fn new(http_status: StatusCode, message: String) -> ServiceError { + ServiceError { + http_status, + body: ResponseBody { + message, + data: String::new(), + }, + } + } + + pub fn response(&self) -> http::Result>> { + Response::builder().status(self.http_status).body(&self.body) + } +} \ No newline at end of file diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs index eaf88d8..b26a4a8 100644 --- a/axum-middleware-example/src/main.rs +++ b/axum-middleware-example/src/main.rs @@ -1,8 +1,21 @@ #[macro_use] extern crate diesel; +#[macro_use] +extern crate diesel_migrations; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_json; mod model; mod schema; +mod utils; +mod errors; +mod service; +mod middleware; +mod repository; +mod route; +mod constants; use crate::model::*; use crate::schema::*; diff --git a/axum-middleware-example/src/middleware/authorizeJWT.rs b/axum-middleware-example/src/middleware/authorizeJWT.rs index a6f278d..059bec6 100644 --- a/axum-middleware-example/src/middleware/authorizeJWT.rs +++ b/axum-middleware-example/src/middleware/authorizeJWT.rs @@ -1 +1,2 @@ -// JWT AUTHENTICATION \ No newline at end of file +// JWT AUTHENTICATION +const BEARER: &str = "Bearer "; \ No newline at end of file diff --git a/axum-middleware-example/src/middleware/middleware.rs b/axum-middleware-example/src/middleware/middleware.rs index fa52467..8b5f975 100644 --- a/axum-middleware-example/src/middleware/middleware.rs +++ b/axum-middleware-example/src/middleware/middleware.rs @@ -1,9 +1,6 @@ use axum::{response::Response, routing::get, BoxError, Router}; use axum_casbin_auth::{CasbinAxumLayer, CasbinVals}; -use axum_test_helper::TestClient; use bytes::Bytes; -use casbin::function_map::key_match2; -use casbin::{CoreApi, DefaultModel, FileAdapter}; use futures::future::BoxFuture; use http::{self, Request, StatusCode}; use http_body::Body as HttpBody; diff --git a/axum-middleware-example/src/middleware/mod.rs b/axum-middleware-example/src/middleware/mod.rs index f35d8d4..ff093dc 100644 --- a/axum-middleware-example/src/middleware/mod.rs +++ b/axum-middleware-example/src/middleware/mod.rs @@ -1 +1,2 @@ -pub mod middleware; \ No newline at end of file +pub mod middleware; +pub mod authorizeJWT; \ No newline at end of file diff --git a/axum-middleware-example/src/model/db.rs b/axum-middleware-example/src/model/db.rs index 6a0204f..b925404 100644 --- a/axum-middleware-example/src/model/db.rs +++ b/axum-middleware-example/src/model/db.rs @@ -1 +1,26 @@ -// SETUP DATABASE HERE \ No newline at end of file +// SETUP DATABASE HERE +use diesel::{ + pg::PgConnection, + r2d2::{self, ConnectionManager}, +}; +use std::time::Duration; + +embed_migrations!(); + +pub type Connection = PgConnection; +pub type Pool = r2d2::Pool>; + +// THIS HAS TO BE CALLED TO SETUP THE DATABASE +pub fn migrate_and_config_db(url: &str, pool_size: u32) -> Pool { + info!("Migrating and configurating database..."); + let manager = ConnectionManager::::new(url); + let pool = r2d2::Pool::builder() + .connection_timeout(Duration::from_secs(10)) + .max_size(pool_size) + .build(manager) + .expect("Failed to create pool."); + embedded_migrations::run(&pool.get().expect("Failed to migrate.")) + .expect("Failed to migrate."); + + pool +} \ No newline at end of file diff --git a/axum-middleware-example/src/model/mod.rs b/axum-middleware-example/src/model/mod.rs index 6fee132..632ddb7 100644 --- a/axum-middleware-example/src/model/mod.rs +++ b/axum-middleware-example/src/model/mod.rs @@ -1,2 +1,4 @@ pub mod user; -pub mod db; \ No newline at end of file +pub mod db; +pub mod response; +pub mod user_token; \ No newline at end of file diff --git a/axum-middleware-example/src/model/response.rs b/axum-middleware-example/src/model/response.rs new file mode 100644 index 0000000..a86bcd1 --- /dev/null +++ b/axum-middleware-example/src/model/response.rs @@ -0,0 +1,16 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct ResponseBody { + pub message: String, + pub data: T, +} + +impl ResponseBody { + pub fn new(message: &str, data: T) -> ResponseBody { + ResponseBody { + message: message.to_string(), + data, + } + } +} \ No newline at end of file diff --git a/axum-middleware-example/src/model/user.rs b/axum-middleware-example/src/model/user.rs index 98356eb..7a411b6 100644 --- a/axum-middleware-example/src/model/user.rs +++ b/axum-middleware-example/src/model/user.rs @@ -1,4 +1,10 @@ -use crate::schema::*; +use crate::{ + model::{db::Connection, user_token::UserToken}, + schema::users::{self, dsl::*}, + utils::bcrypt::compare_password, +}; + +use chrono::Utc; use diesel::prelude::*; use diesel::QueryDsl; use serde::{Deserialize, Serialize}; @@ -13,4 +19,109 @@ pub struct User { pub email: String, pub password: String, pub role: String, -} \ No newline at end of file + pub login_session: String, +} + +#[derive(Insertable, Serialize, Deserialize, AsChangeset, Clone)] +#[table_name = "users"] +pub struct NewUser { + pub username: String, + pub email: String, + pub password: String, + // #[serde(default = "default_role")] + pub role: String, + pub login_session: String +} + +// fn default_role() -> String { +// DEFAULT_USER_ROLE +// } + +// pub const DEFAULT_USER_ROLE: String = "patient"; + +#[derive(Serialize, Deserialize)] +pub struct LoginForm { + pub email: String, + pub password: String, +} + +#[derive(Insertable)] +#[table_name = "users"] +pub struct LoginInfo { + // WILL GET UNIQUE USERNAME BY EMAIL + pub username: String, + pub role: String, + pub login_session: String, +} + +impl User { + pub fn add_user() {} + + pub fn get_user(i: i32, conn: &Connection) -> QueryResult { + users.find(i).get_result::(conn) + } + + pub fn get_all_user(conn: &Connection) -> QueryResult> { + users.order(id.asc()).load::(conn) + } + + pub fn signin(login: LoginForm, conn: &Connection) -> Option { + if let Ok(user_to_verify) = users + .filter(email.eq(&login.email)) + .get_result::(conn) + { + if !user_to_verify.password.is_empty() + && compare_password(&login.password, &user_to_verify.password).unwrap() + { + let login_session_str = User::generate_login_session(); + if User::update_login_session_to_db( + &user_to_verify.email, + &login_session_str, + conn, + ) { + return Some(LoginInfo { + username: user_to_verify.username, + role: user_to_verify.role, + login_session: login_session_str, + }); + } + } + } + None + } + + pub fn update_user() {} + + pub fn delete_user() {} + + pub fn update_login_session_to_db( + eml: &str, + login_session_str: &str, + conn: &Connection, + ) -> bool { + if let Ok(user) = User::get_user_by_email(eml, conn) { + diesel::update(users.find(user.id)) + .set(login_session.eq(login_session_str.to_string())) + .execute(conn) + .is_ok() + } else { + false + } + } + + pub fn is_valid_login_session(user_token: &UserToken, conn: &Connection) -> bool { + users + .filter(username.eq(&user_token.user_name)) + .filter(login_session.eq(&user_token.login_session)) + .get_result::(conn) + .is_ok() + } + + pub fn get_user_by_email(eml: &str, conn: &Connection) -> QueryResult { + users.filter(email.eq(eml)).get_result::(conn) + } + + pub fn generate_login_session() -> String { + Uuid::new_v4().simple().to_string() + } +} diff --git a/axum-middleware-example/src/model/user_token.rs b/axum-middleware-example/src/model/user_token.rs new file mode 100644 index 0000000..df4199f --- /dev/null +++ b/axum-middleware-example/src/model/user_token.rs @@ -0,0 +1,40 @@ +use crate::model::user::LoginInfo; + +use chrono::Utc; +use jsonwebtoken::{EncodingKey, Header}; +use serde::{Serialize, Deserialize}; + +static THREE_HOUR: i64 = 60 * 60 * 3; +pub static KEY: [u8; 16] = *include_bytes!("../secret.key"); + +#[derive(Serialize, Deserialize)] +pub struct UserToken { + // issued at + pub iat: i64, + // expiration + pub exp: i64, + // userID + pub user_name: String, + pub role: String, + pub login_session: String +} + +impl UserToken { + pub fn generate_token(login: LoginInfo) -> String{ + let now = Utc::now().timestamp_nanos() / 1_000_000_000; + let payload = UserToken { + iat: now, + exp: now + THREE_HOUR, + user_name: login.username, + role: login.role, + login_session:login.login_session + }; + + jsonwebtoken::encode( + &Header::default(), + &payload, + &EncodingKey::from_secret(&KEY), + ) + .unwrap() + } +} diff --git a/axum-middleware-example/src/repository/mod.rs b/axum-middleware-example/src/repository/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/axum-middleware-example/src/repository/user_repository.rs b/axum-middleware-example/src/repository/user_repository.rs new file mode 100644 index 0000000..e69de29 diff --git a/axum-middleware-example/src/route/mod.rs b/axum-middleware-example/src/route/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/axum-middleware-example/src/schema.rs b/axum-middleware-example/src/schema.rs index 8e5bdbd..91f2a13 100644 --- a/axum-middleware-example/src/schema.rs +++ b/axum-middleware-example/src/schema.rs @@ -5,5 +5,6 @@ table! { email -> Varchar, password -> Varchar, role -> Varchar, + login_session -> Varchar, } } diff --git a/axum-middleware-example/src/secret.key.sample b/axum-middleware-example/src/secret.key.sample new file mode 100644 index 0000000..4cbf8a5 --- /dev/null +++ b/axum-middleware-example/src/secret.key.sample @@ -0,0 +1 @@ +n ��<������C \ No newline at end of file diff --git a/axum-middleware-example/src/service/mod.rs b/axum-middleware-example/src/service/mod.rs new file mode 100644 index 0000000..018ff2e --- /dev/null +++ b/axum-middleware-example/src/service/mod.rs @@ -0,0 +1 @@ +pub mod user; \ No newline at end of file diff --git a/axum-middleware-example/src/service/user.rs b/axum-middleware-example/src/service/user.rs new file mode 100644 index 0000000..e8fc0ca --- /dev/null +++ b/axum-middleware-example/src/service/user.rs @@ -0,0 +1,62 @@ + +#![allow(clippy::if_same_then_else)] +use crate::{ + model::{db::Pool, user::LoginForm}, + constants, + errors::ServiceError, + model::user::{NewUser, User}, + model::user_token::UserToken, +}; + +use axum::extract::Extension; +use axum::http::StatusCode; +use axum_casbin_auth::casbin::{CachedEnforcer}; +use axum_casbin_auth::CasbinVals; +use serde::{Deserialize, Serialize}; +use http_body::Data; + +#[derive(Serialize, Deserialize)] +pub struct TokenBodyResponse { + pub token: String, + pub token_type: String, +} + +pub async fn add_user() {} + +pub fn get_all_user(Extension(pool): Extension) -> Result, ServiceError>{ + match User::get_all_user(&pool.get().unwrap()) { + Ok(user) => Ok(user), + Err(_) => Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(),)) + } +} + +pub fn get_user(user_id: i32, Extension(pool): Extension) -> Result { + match User::get_user(user_id, &pool.get().unwrap()) { + Ok(user) => Ok(user), + Err(_) => Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(),)) + } +} + +pub fn signin(login: LoginForm, Extension(pool): Extension) -> Result { + match User::signin(login, &pool.get().unwrap()) { + Some(logged_user) => { + match serde_json::from_value( + json!({ "token": UserToken::generate_token(logged_user), "token_type": "bearer" }), + ) { + Ok(token_res) => Ok(token_res), + Err(_) => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_INTERNAL_SERVER_ERROR.to_string(), + )), + } + } + None => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_SIGNIN_FAILED.to_string(), + )), + } +} + +pub fn update_user() {} + +pub fn delete_user() {} \ No newline at end of file diff --git a/axum-middleware-example/src/utils/bcrypt.rs b/axum-middleware-example/src/utils/bcrypt.rs index 7b6340f..41f0470 100644 --- a/axum-middleware-example/src/utils/bcrypt.rs +++ b/axum-middleware-example/src/utils/bcrypt.rs @@ -1,11 +1,31 @@ use crate::constants; +use crate::errors::ServiceError; +use axum::http::StatusCode; use bcrypt::{hash, verify, DEFAULT_COST}; use std::env; -pub fn hash_password() {} +pub fn hash_password(plain: &str) -> Result { + let hashing_cost: u32 = match env::var("HASH_ROUNDS") { + Ok(cost) => cost.parse().unwrap_or(DEFAULT_COST), + _ => DEFAULT_COST, + }; + hash(plain, hashing_cost).map_err(|_| { + ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_PROCESS_TOKEN_ERROR.to_string(), + ) + }) +} +// VERIFY PASSWORD +pub fn compare_password(plain: &str, hash: &str) -> Result{ + verify(plain, hash).map_err(|_| { + ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_PROCESS_TOKEN_ERROR.to_string(), + ) + }) +} + -pub fn compare_password() {} -pub fn generate_token() {} -pub fn validate_token() {} diff --git a/axum-middleware-example/src/utils/mod.rs b/axum-middleware-example/src/utils/mod.rs new file mode 100644 index 0000000..d5c3333 --- /dev/null +++ b/axum-middleware-example/src/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod bcrypt; +pub mod token_utils; \ No newline at end of file diff --git a/axum-middleware-example/src/utils/token_utils.rs b/axum-middleware-example/src/utils/token_utils.rs new file mode 100644 index 0000000..f1b3883 --- /dev/null +++ b/axum-middleware-example/src/utils/token_utils.rs @@ -0,0 +1,29 @@ +use crate::{ + model::{ + user::User, + user_token::{UserToken, KEY}, + db::Pool + }, +}; +use axum::extract::Extension; +use jsonwebtoken::{DecodingKey, TokenData, Validation}; + +// DECODE THE GOT TOKEN +pub fn decode_token( + token: String, +) -> jsonwebtoken::errors::Result> { + jsonwebtoken::decode::( + &token, + &DecodingKey::from_secret(&KEY), + &Validation::default(), + ) +} + +// VALIDATE TOKEN +pub fn validate_token(token_data: &TokenData, Extension(pool): Extension) -> Result { + if User::is_valid_login_session(&token_data.claims, &pool.get().unwrap()) { + Ok(token_data.claims.user_name.to_string()) + } else { + Err("Invalid token".to_string()) + } +} \ No newline at end of file From 565baf177a3961ff49f5b8135ad8d211418e7ac0 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sun, 24 Jul 2022 02:14:34 +0530 Subject: [PATCH 10/18] tokio and async-std conflict resolved --- actix-middleware-example/.env.sample | 2 +- actix-middleware-example/Cargo.toml | 6 +++--- actix-middleware-example/src/models/post.rs | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/actix-middleware-example/.env.sample b/actix-middleware-example/.env.sample index 4bf0113..3384e7c 100644 --- a/actix-middleware-example/.env.sample +++ b/actix-middleware-example/.env.sample @@ -1,5 +1,5 @@ APP_HOST=127.0.0.1 APP_PORT=8080 -DATABASE_URL=//casbin_rs:casbin_rs@127.0.0.1:5432/test +DATABASE_URL=postgres://casbin_rs:casbin_rs@127.0.0.1:5432/test POOL_SIZE=8 HASH_ROUNDS=12 \ No newline at end of file diff --git a/actix-middleware-example/Cargo.toml b/actix-middleware-example/Cargo.toml index 95385fe..71ff95d 100644 --- a/actix-middleware-example/Cargo.toml +++ b/actix-middleware-example/Cargo.toml @@ -29,8 +29,8 @@ jsonwebtoken = "8.1.0" bcrypt = "0.13.0" csv = "1.1.3" walkdir = "2.3.1" -diesel-adapter = { version = "0.9.0", default-features = false, features = ["postgres","runtime-async-std"] } +diesel-adapter ="0.9.0" uuid = {version = "1.1.2", features = ["v4"] } # UPDATE AFTER LATEST RELEASE OF actix-casbin and actix-casbin-auth to CRATE.IO -actix-casbin= {git = "https://github.com/casbin-rs/actix-casbin", default-features = false, features = [ "runtime-async-std" ]} -actix-casbin-auth = {git = "https://github.com/casbin-rs/actix-casbin-auth", default-features = false, features = [ "runtime-async-std" ]} \ No newline at end of file +actix-casbin-auth = {git = "https://github.com/casbin-rs/actix-casbin-auth", default-features = false, features = [ "runtime-tokio" ]} +actix-casbin= {git = "https://github.com/casbin-rs/actix-casbin", default-features = false, features = [ "runtime-tokio" ]} diff --git a/actix-middleware-example/src/models/post.rs b/actix-middleware-example/src/models/post.rs index 73f9c23..f18c8d5 100644 --- a/actix-middleware-example/src/models/post.rs +++ b/actix-middleware-example/src/models/post.rs @@ -37,24 +37,24 @@ pub struct DeletePost { } impl Post { - pub fn find_all(is_admin: bool, conn: &Connection) -> QueryResult> { + pub fn find_all(is_admin: bool, conn: &Connection) -> QueryResult> { if is_admin { - return posts::table.order(id.asc()).load::(conn); + return posts::table.order(id.asc()).load::(conn); } posts::table .filter(is_deleted.eq(false)) .order(id.asc()) - .load::(conn) + .load::(conn) } - pub fn find_by_id(is_admin: bool, i: i32, conn: &Connection) -> QueryResult { + pub fn find_by_id(is_admin: bool, i: i32, conn: &Connection) -> QueryResult { if is_admin { - return posts::table.find(i).get_result::(conn); + return posts::table.find(i).get_result::(conn); } posts::table .filter(is_deleted.eq(false)) .find(i) - .get_result::(conn) + .get_result::(conn) } pub fn insert(new_post: NewPost, conn: &Connection) -> QueryResult { From f9bfe55fe38cbfc1f1583f18141c622811dedf68 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Wed, 27 Jul 2022 16:46:05 +0530 Subject: [PATCH 11/18] api, middleware, routes --- axum-middleware-example/Cargo.toml | 2 +- axum-middleware-example/src/api/mod.rs | 1 + axum-middleware-example/src/api/user.rs | 69 +++++++++++++ axum-middleware-example/src/constants.rs | 20 +++- axum-middleware-example/src/errors.rs | 25 +++-- axum-middleware-example/src/main.rs | 1 + .../src/middleware/middleware.rs | 97 ++++++++++++++++--- axum-middleware-example/src/model/response.rs | 10 +- axum-middleware-example/src/model/user.rs | 31 ++++-- axum-middleware-example/src/route/mod.rs | 1 + axum-middleware-example/src/route/routes.rs | 20 ++++ axum-middleware-example/src/service/user.rs | 10 +- .../src/utils/token_utils.rs | 2 +- 13 files changed, 255 insertions(+), 34 deletions(-) create mode 100644 axum-middleware-example/src/api/mod.rs create mode 100644 axum-middleware-example/src/api/user.rs create mode 100644 axum-middleware-example/src/route/routes.rs diff --git a/axum-middleware-example/Cargo.toml b/axum-middleware-example/Cargo.toml index 83c91b9..ea7a27e 100644 --- a/axum-middleware-example/Cargo.toml +++ b/axum-middleware-example/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -axum = "0.5.7" +axum = "0.5.13" futures = "0.3.5" failure = "0.1.8" serde = "1.0.116" diff --git a/axum-middleware-example/src/api/mod.rs b/axum-middleware-example/src/api/mod.rs new file mode 100644 index 0000000..018ff2e --- /dev/null +++ b/axum-middleware-example/src/api/mod.rs @@ -0,0 +1 @@ +pub mod user; \ No newline at end of file diff --git a/axum-middleware-example/src/api/user.rs b/axum-middleware-example/src/api/user.rs new file mode 100644 index 0000000..36ccd30 --- /dev/null +++ b/axum-middleware-example/src/api/user.rs @@ -0,0 +1,69 @@ +// use crate::model::user::DeleteUser; +use crate::{ + constants, + model::db::Pool, + model::{ + response::ResponseBody, + user::{LoginForm, NewUser}, + }, + service::user::{self, TokenBodyResponse}, +}; +// use actix::Addr; +// use actix_casbin::CasbinActor; +// use actix_casbin_auth::casbin::CachedEnforcer; +// use actix_web::{web, HttpRequest, HttpResponse, Result}; +use axum::{ + extract::{Extension, Path}, + http::StatusCode, + response::{IntoResponse, Response}, + Json, +}; +use axum_casbin_auth::casbin::CachedEnforcer; +// use serde_json::json; +// use http::{StatusCode, Response}; +use chrono::{NaiveDateTime, Utc}; +use tower::balance::pool; + +// IMPLEMENT INTORESPONSE FOR SERVICE ERROR AND UPDATE ALL ERRORS OR MATCH THE ERROR WITH SERVICE ERROR (STATUSCODE, CONTANTSMSG).INTO_RESPONSE() +// POST(api/auth/signin) +pub async fn signin( + Json(login_form): Json, + pool: Extension, +) -> Response { + // output should be a json response + match user::signin(login_form, &pool) { + Ok(token_res) => Json(ResponseBody::new( + constants::MESSAGE_SIGNIN_SUCCESS, + token_res, + )) + .into_response(), + Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_INTERNAL_SERVER_ERROR.to_string()).into_response(), + } +} + +// POST(api/auth/register) +pub async fn register() {} + +// DELETE(api/admin/{:id}) +pub async fn delete_user() {} + +// GET(api/user/{:id}) +pub async fn get_user(Path(id): Path, pool: Extension) -> Response{ + match user::get_user(id.parse::().unwrap(), &pool){ + Ok(user) => {Json(ResponseBody::new(constants::MESSAGE_OK, user)).into_response()} + Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string()).into_response() + } +} + +// GET(api/users) +pub async fn get_all_user(pool: Extension) -> Response { + match user::get_all_user(&pool) { + Ok(users) => { + Json(ResponseBody::new(constants::MESSAGE_OK, users)).into_response() + } + Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string()).into_response(), + } +} + +// PUT(api/admin/{:id}) +pub async fn update_user() {} diff --git a/axum-middleware-example/src/constants.rs b/axum-middleware-example/src/constants.rs index 22b1130..fd2c5cb 100644 --- a/axum-middleware-example/src/constants.rs +++ b/axum-middleware-example/src/constants.rs @@ -7,5 +7,23 @@ pub const MESSAGE_CAN_NOT_DELETE_DATA: &str = "Can not delete data"; pub const MESSAGE_PROCESS_TOKEN_ERROR: &str = "Error while processing token"; pub const MESSAGE_INVALID_TOKEN: &str = "Invalid token, please login again"; pub const MESSAGE_INTERNAL_SERVER_ERROR: &str = "Internal Server Error"; +pub const MESSAGE_SIGNIN_FAILED: &str = "Wrong email or password, please try again"; +pub const MESSAGE_SIGNIN_SUCCESS: &str = "Signin successfully"; +pub const MESSAGE_SIGNUP_SUCCESS: &str = "Signup successfully"; + +// BAD REQUEST pub const MESSAGE_TOKEN_MISSING: &str = "Token is missing"; -pub const MESSAGE_SIGNIN_FAILED: &str = "Wrong email or password, please try again"; \ No newline at end of file + +// HEADERS +pub const AUTHORIZATION: &str = "Authorization"; + +// Misc +pub const EMPTY: &str = ""; + +// IGNORE ROUTES +pub const IGNORE_ROUTES: [&str; 4] = [ + "api/auth/register", + "api/auth/signin", + "api/users", + "api/user", +]; diff --git a/axum-middleware-example/src/errors.rs b/axum-middleware-example/src/errors.rs index b13e8e0..b87b7a9 100644 --- a/axum-middleware-example/src/errors.rs +++ b/axum-middleware-example/src/errors.rs @@ -1,6 +1,11 @@ // DEFINE ERROR HERE use crate::model::response::ResponseBody; -use http::{StatusCode, Response}; +use serde_json::json; +use axum::Json; +use axum::response::{IntoResponse, Response}; +use axum::http::{StatusCode}; +use axum::body::{self, BoxBody}; +use http_body::Full; #[derive(Debug)] pub struct ServiceError { @@ -14,12 +19,20 @@ impl ServiceError { http_status, body: ResponseBody { message, - data: String::new(), + data: String::new(), // try box body, in this see if you can implement HttpResponse like service, post on axum }, } } + + // pub fn response(&self) -> http::Result>> { + // Response::builder().status(self.http_status).body(&self.body) + // } - pub fn response(&self) -> http::Result>> { - Response::builder().status(self.http_status).body(&self.body) - } -} \ No newline at end of file + +} + +// impl IntoResponse for ServiceError { +// fn into_response(self) -> Response { + +// } +// } diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs index b26a4a8..ed55b0c 100644 --- a/axum-middleware-example/src/main.rs +++ b/axum-middleware-example/src/main.rs @@ -16,6 +16,7 @@ mod middleware; mod repository; mod route; mod constants; +mod api; use crate::model::*; use crate::schema::*; diff --git a/axum-middleware-example/src/middleware/middleware.rs b/axum-middleware-example/src/middleware/middleware.rs index 8b5f975..78f373c 100644 --- a/axum-middleware-example/src/middleware/middleware.rs +++ b/axum-middleware-example/src/middleware/middleware.rs @@ -1,9 +1,21 @@ -use axum::{response::Response, routing::get, BoxError, Router}; -use axum_casbin_auth::{CasbinAxumLayer, CasbinVals}; +use crate::{constants, model::{db::Pool, response::ResponseBody}, utils::token_utils}; + +use axum::{ + body::{self, BoxBody}, + extract::Extension, + http::{ + header::{HeaderName, HeaderValue}, + Method, + }, + Json, + response::{Response, IntoResponse}, + BoxError +}; +use axum_casbin_auth::CasbinVals; use bytes::Bytes; use futures::future::BoxFuture; -use http::{self, Request, StatusCode}; -use http_body::Body as HttpBody; +use http::{self, Request}; +use http_body::{Body as HttpBody}; use std::{ boxed::Box, convert::Infallible, @@ -39,8 +51,8 @@ where ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { - type Response = S::Response; - type Error = S::Error; + type Response = Response; + type Error = Infallible; // `BoxFuture` is a type alias for `Pin>` type Future = BoxFuture<'static, Result>; @@ -51,11 +63,74 @@ where fn call(&mut self, mut req: Request) -> Self::Future { let not_ready_inner = self.inner.clone(); let mut inner = std::mem::replace(&mut self.inner, not_ready_inner); + let mut authenticate_pass: bool = false; + let mut authenticate_username: String = String::from(""); + + // Bypass account routes + let headers = req.headers_mut(); + headers.append( + HeaderName::from_static("content-length"), + HeaderValue::from_static("true"), + ); + + if Method::OPTIONS == *req.method() { + authenticate_pass = true; + } else { + for ignore_route in constants::IGNORE_ROUTES.iter() { + if req.uri().path().starts_with(ignore_route) { + authenticate_pass = true; + break; + } + } + if !authenticate_pass { + if let Some(pool) = req.extensions().get::>() { + info!("Connecting to database..."); + if let Some(auth_header) = + req.headers().get(constants::AUTHORIZATION) + { + info!("Parsing authorization header..."); + if let Ok(auth_str) = auth_header.to_str() { + if auth_str.starts_with("bearer") + || auth_str.starts_with("Bearer") + { + info!("Parsing token..."); + let token = auth_str[6..auth_str.len()].trim(); + if let Ok(token_data) = + token_utils::decode_token(token.to_string()) + { + info!("Decoding token..."); + if token_utils::validate_token(&token_data, pool) + .is_ok() + { + info!("Valid token"); + authenticate_username = token_data.claims.user_name; + authenticate_pass = true; + } else { + error!("Invalid token"); + } + } + } + } + } + } + } + } + if authenticate_pass { + // UNDERSTAND POLICY GROUPING AND UPDATE CASBINBALS HERE + let vals = CasbinVals { + subject: authenticate_username, + domain: None, + }; + req.extensions_mut().insert(vals); + Box::pin(async move { + Ok(inner.call(req).await?.map(body::boxed)) + }) + } else{ + Box::pin(async move{ + Ok(Json(ResponseBody::new(constants::MESSAGE_TOKEN_MISSING, constants::EMPTY)).into_response()) + }) + + } - // IMPLEMENT LOGIC HERE - Box::pin(async move { - inner.call(req).await - }) } } - diff --git a/axum-middleware-example/src/model/response.rs b/axum-middleware-example/src/model/response.rs index a86bcd1..43d20f6 100644 --- a/axum-middleware-example/src/model/response.rs +++ b/axum-middleware-example/src/model/response.rs @@ -1,3 +1,5 @@ +use axum::response::{IntoResponse, Response}; +use axum::body; use serde::{Serialize, Deserialize}; #[derive(Debug, Serialize, Deserialize)] @@ -13,4 +15,10 @@ impl ResponseBody { data, } } -} \ No newline at end of file +} + +// impl IntoResponse for ResponseBody { +// fn into_response(self) -> Response { +// Response::new(ReponseBody) +// } +// } \ No newline at end of file diff --git a/axum-middleware-example/src/model/user.rs b/axum-middleware-example/src/model/user.rs index 7a411b6..580d76f 100644 --- a/axum-middleware-example/src/model/user.rs +++ b/axum-middleware-example/src/model/user.rs @@ -1,7 +1,8 @@ use crate::{ model::{db::Connection, user_token::UserToken}, schema::users::{self, dsl::*}, - utils::bcrypt::compare_password, + utils::bcrypt::{compare_password, hash_password}, + constants }; use chrono::Utc; @@ -28,16 +29,14 @@ pub struct NewUser { pub username: String, pub email: String, pub password: String, - // #[serde(default = "default_role")] + #[serde(default = "default_role")] pub role: String, pub login_session: String } -// fn default_role() -> String { -// DEFAULT_USER_ROLE -// } - -// pub const DEFAULT_USER_ROLE: String = "patient"; +fn default_role() -> String { + "patient".to_owned() +} #[derive(Serialize, Deserialize)] pub struct LoginForm { @@ -55,7 +54,23 @@ pub struct LoginInfo { } impl User { - pub fn add_user() {} + pub fn register(user: NewUser, conn: &Connection) -> Result { + if Self::get_user_by_email(&user.email, conn).is_err() { + let hashed_pwd = hash_password(&user.password).unwrap(); + let user_upd = NewUser { + password: hashed_pwd, + ..user + }; + diesel::insert_into(users) + .values(&user_upd) + .execute(conn) + .map_err(|e| e.to_string())?; + + Ok(constants::MESSAGE_SIGNUP_SUCCESS.to_string()) + } else { + Err(format!("User {} is already registered", &user.username)) + } + } pub fn get_user(i: i32, conn: &Connection) -> QueryResult { users.find(i).get_result::(conn) diff --git a/axum-middleware-example/src/route/mod.rs b/axum-middleware-example/src/route/mod.rs index e69de29..8b4ddc8 100644 --- a/axum-middleware-example/src/route/mod.rs +++ b/axum-middleware-example/src/route/mod.rs @@ -0,0 +1 @@ +pub mod routes; \ No newline at end of file diff --git a/axum-middleware-example/src/route/routes.rs b/axum-middleware-example/src/route/routes.rs new file mode 100644 index 0000000..42cbd02 --- /dev/null +++ b/axum-middleware-example/src/route/routes.rs @@ -0,0 +1,20 @@ +// DEFINE ROUTES HERE +use axum::{ + routing::{delete, get, post, put}, + Router, +}; + +use crate::api::user; + +pub fn routes() -> Router { + let router = Router::new() + .route("/api/auth/register", post(user::register)) + .route("/api/auth/signin", post(user::signin)) + .route("/api/users", get(user::get_all_user)) + .route("/api/user/:id", get(user::get_user)) + .route("/api/admin/:id", put(user::update_user)) + .route("/api/admin/:id", delete(user::delete_user)); + + // NEED TO ADD MIDDLEWARE HERE, BEFORE CALLING IN MAIN.RS + router +} diff --git a/axum-middleware-example/src/service/user.rs b/axum-middleware-example/src/service/user.rs index e8fc0ca..0a02a60 100644 --- a/axum-middleware-example/src/service/user.rs +++ b/axum-middleware-example/src/service/user.rs @@ -13,7 +13,6 @@ use axum::http::StatusCode; use axum_casbin_auth::casbin::{CachedEnforcer}; use axum_casbin_auth::CasbinVals; use serde::{Deserialize, Serialize}; -use http_body::Data; #[derive(Serialize, Deserialize)] pub struct TokenBodyResponse { @@ -21,23 +20,24 @@ pub struct TokenBodyResponse { pub token_type: String, } -pub async fn add_user() {} +// ADD USER +pub async fn register() {} -pub fn get_all_user(Extension(pool): Extension) -> Result, ServiceError>{ +pub fn get_all_user(Extension(pool): &Extension) -> Result, ServiceError>{ match User::get_all_user(&pool.get().unwrap()) { Ok(user) => Ok(user), Err(_) => Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(),)) } } -pub fn get_user(user_id: i32, Extension(pool): Extension) -> Result { +pub fn get_user(user_id: i32, Extension(pool): &Extension) -> Result { match User::get_user(user_id, &pool.get().unwrap()) { Ok(user) => Ok(user), Err(_) => Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(),)) } } -pub fn signin(login: LoginForm, Extension(pool): Extension) -> Result { +pub fn signin(login: LoginForm, Extension(pool): &Extension) -> Result { match User::signin(login, &pool.get().unwrap()) { Some(logged_user) => { match serde_json::from_value( diff --git a/axum-middleware-example/src/utils/token_utils.rs b/axum-middleware-example/src/utils/token_utils.rs index f1b3883..afee6c8 100644 --- a/axum-middleware-example/src/utils/token_utils.rs +++ b/axum-middleware-example/src/utils/token_utils.rs @@ -20,7 +20,7 @@ pub fn decode_token( } // VALIDATE TOKEN -pub fn validate_token(token_data: &TokenData, Extension(pool): Extension) -> Result { +pub fn validate_token(token_data: &TokenData, Extension(pool): &Extension) -> Result { if User::is_valid_login_session(&token_data.claims, &pool.get().unwrap()) { Ok(token_data.claims.user_name.to_string()) } else { From 25ef1cdec4efb2fed7e60254c27dd9d4ea84830e Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Fri, 29 Jul 2022 17:10:38 +0530 Subject: [PATCH 12/18] csv utils, main.rs, server setup --- axum-middleware-example/Cargo.toml | 2 + .../{src/config => }/rbac_model.conf | 0 .../rbac_model_with_pattern.csv | 6 + axum-middleware-example/src/api/user.rs | 36 +++--- axum-middleware-example/src/constants.rs | 2 + axum-middleware-example/src/errors.rs | 15 +-- axum-middleware-example/src/main.rs | 111 ++++++++++++++---- .../src/middleware/middleware.rs | 4 +- axum-middleware-example/src/model/response.rs | 2 - axum-middleware-example/src/model/user.rs | 1 - axum-middleware-example/src/repository/mod.rs | 0 .../src/repository/user_repository.rs | 0 axum-middleware-example/src/route/mod.rs | 1 - axum-middleware-example/src/route/routes.rs | 20 ---- axum-middleware-example/src/service/user.rs | 3 +- .../src/utils/csv_utils.rs | 84 +++++++++++++ axum-middleware-example/src/utils/mod.rs | 3 +- 17 files changed, 212 insertions(+), 78 deletions(-) rename axum-middleware-example/{src/config => }/rbac_model.conf (100%) create mode 100644 axum-middleware-example/rbac_model_with_pattern.csv delete mode 100644 axum-middleware-example/src/repository/mod.rs delete mode 100644 axum-middleware-example/src/repository/user_repository.rs delete mode 100644 axum-middleware-example/src/route/mod.rs delete mode 100644 axum-middleware-example/src/route/routes.rs create mode 100644 axum-middleware-example/src/utils/csv_utils.rs diff --git a/axum-middleware-example/Cargo.toml b/axum-middleware-example/Cargo.toml index ea7a27e..c2645b1 100644 --- a/axum-middleware-example/Cargo.toml +++ b/axum-middleware-example/Cargo.toml @@ -10,6 +10,7 @@ axum = "0.5.13" futures = "0.3.5" failure = "0.1.8" serde = "1.0.116" +async-std = { version = "1.10.0", default-features = false, optional = true } serde_derive = "1.0.116" serde_json = "1.0.57" derive_more = "0.99.10" @@ -29,4 +30,5 @@ diesel-adapter = "0.9.0" bytes = "1.1.0" uuid = {version = "1.1.2", features = ["v4"] } chrono = { version = "0.4.18", features = ["serde"] } +tokio = { version = "1.17.0", features = [ "full" ] } axum-casbin-auth = {git = "https://github.com/casbin-rs/axum-casbin-auth"} \ No newline at end of file diff --git a/axum-middleware-example/src/config/rbac_model.conf b/axum-middleware-example/rbac_model.conf similarity index 100% rename from axum-middleware-example/src/config/rbac_model.conf rename to axum-middleware-example/rbac_model.conf diff --git a/axum-middleware-example/rbac_model_with_pattern.csv b/axum-middleware-example/rbac_model_with_pattern.csv new file mode 100644 index 0000000..1a6f7e6 --- /dev/null +++ b/axum-middleware-example/rbac_model_with_pattern.csv @@ -0,0 +1,6 @@ +p, doctor, report, read +p, doctor, report, write +p, patient, report, read + +g, john, doctor +g, sam, patient \ No newline at end of file diff --git a/axum-middleware-example/src/api/user.rs b/axum-middleware-example/src/api/user.rs index 36ccd30..6dad9ca 100644 --- a/axum-middleware-example/src/api/user.rs +++ b/axum-middleware-example/src/api/user.rs @@ -6,12 +6,9 @@ use crate::{ response::ResponseBody, user::{LoginForm, NewUser}, }, - service::user::{self, TokenBodyResponse}, + service::user::{self}, }; -// use actix::Addr; -// use actix_casbin::CasbinActor; -// use actix_casbin_auth::casbin::CachedEnforcer; -// use actix_web::{web, HttpRequest, HttpResponse, Result}; + use axum::{ extract::{Extension, Path}, http::StatusCode, @@ -19,10 +16,6 @@ use axum::{ Json, }; use axum_casbin_auth::casbin::CachedEnforcer; -// use serde_json::json; -// use http::{StatusCode, Response}; -use chrono::{NaiveDateTime, Utc}; -use tower::balance::pool; // IMPLEMENT INTORESPONSE FOR SERVICE ERROR AND UPDATE ALL ERRORS OR MATCH THE ERROR WITH SERVICE ERROR (STATUSCODE, CONTANTSMSG).INTO_RESPONSE() // POST(api/auth/signin) @@ -37,21 +30,30 @@ pub async fn signin( token_res, )) .into_response(), - Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_INTERNAL_SERVER_ERROR.to_string()).into_response(), + Err(_) => ( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_INTERNAL_SERVER_ERROR.to_string(), + ) + .into_response(), } } // POST(api/auth/register) pub async fn register() {} + // DELETE(api/admin/{:id}) pub async fn delete_user() {} // GET(api/user/{:id}) -pub async fn get_user(Path(id): Path, pool: Extension) -> Response{ - match user::get_user(id.parse::().unwrap(), &pool){ - Ok(user) => {Json(ResponseBody::new(constants::MESSAGE_OK, user)).into_response()} - Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string()).into_response() +pub async fn get_user(Path(id): Path, pool: Extension) -> Response { + match user::get_user(id.parse::().unwrap(), &pool) { + Ok(user) => Json(ResponseBody::new(constants::MESSAGE_OK, user)).into_response(), + Err(_) => ( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(), + ) + .into_response(), } } @@ -61,7 +63,11 @@ pub async fn get_all_user(pool: Extension) -> Response { Ok(users) => { Json(ResponseBody::new(constants::MESSAGE_OK, users)).into_response() } - Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string()).into_response(), + Err(_) => ( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(), + ) + .into_response(), } } diff --git a/axum-middleware-example/src/constants.rs b/axum-middleware-example/src/constants.rs index fd2c5cb..b9486ba 100644 --- a/axum-middleware-example/src/constants.rs +++ b/axum-middleware-example/src/constants.rs @@ -10,6 +10,8 @@ pub const MESSAGE_INTERNAL_SERVER_ERROR: &str = "Internal Server Error"; pub const MESSAGE_SIGNIN_FAILED: &str = "Wrong email or password, please try again"; pub const MESSAGE_SIGNIN_SUCCESS: &str = "Signin successfully"; pub const MESSAGE_SIGNUP_SUCCESS: &str = "Signup successfully"; +pub const MESSAGE_NEW_USER_ADD_PERMISSION_ERROR: &str = + "Can not add new user when adding new permissions"; // BAD REQUEST pub const MESSAGE_TOKEN_MISSING: &str = "Token is missing"; diff --git a/axum-middleware-example/src/errors.rs b/axum-middleware-example/src/errors.rs index b87b7a9..6fae2e9 100644 --- a/axum-middleware-example/src/errors.rs +++ b/axum-middleware-example/src/errors.rs @@ -1,11 +1,6 @@ // DEFINE ERROR HERE use crate::model::response::ResponseBody; -use serde_json::json; -use axum::Json; -use axum::response::{IntoResponse, Response}; -use axum::http::{StatusCode}; -use axum::body::{self, BoxBody}; -use http_body::Full; +use axum::http::StatusCode; #[derive(Debug)] pub struct ServiceError { @@ -19,20 +14,18 @@ impl ServiceError { http_status, body: ResponseBody { message, - data: String::new(), // try box body, in this see if you can implement HttpResponse like service, post on axum + data: String::new(), }, } } - + // pub fn response(&self) -> http::Result>> { // Response::builder().status(self.http_status).body(&self.body) // } - - } // impl IntoResponse for ServiceError { // fn into_response(self) -> Response { - + // } // } diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs index ed55b0c..865f832 100644 --- a/axum-middleware-example/src/main.rs +++ b/axum-middleware-example/src/main.rs @@ -13,35 +13,100 @@ mod utils; mod errors; mod service; mod middleware; -mod repository; -mod route; mod constants; mod api; -use crate::model::*; -use crate::schema::*; -use crate::user::User; -use diesel::pg::PgConnection; -use diesel::prelude::*; -use dotenv::dotenv; +use crate::api::user as user_api; +use crate::utils::csv_utils::{load_csv, walk_csv}; + + +use axum_casbin_auth::casbin::MgmtApi; use std::env; -fn establish_connection() -> PgConnection { - dotenv().ok(); +use axum::{ + routing::{delete, get, post, put}, + extract::Extension, + Router, +}; - let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - PgConnection::establish(&database_url) - .expect(&format!("Error connecting to {}", database_url)) -} +use axum_casbin_auth::casbin::{CoreApi, DefaultModel, Result, function_map::key_match2}; +use axum_casbin_auth::CasbinAxumLayer; +use diesel_adapter::DieselAdapter; + + +#[tokio::main] +async fn main() -> Result<()> { + dotenv::dotenv().expect("Failed to read .env file, please add it"); + std::env::set_var("RUST_LOG", "actix_web=debug"); + env_logger::init(); + + let app_host = env::var("APP_HOST").expect("APP_HOST must be set."); + let app_port = env::var("APP_PORT").expect("APP_PORT must be set."); + let app_url = format!("{}:{}", &app_host, &app_port); + let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + let pool_size: u32 = std::env::var("POOL_SIZE") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(8); + + let pool = model::db::migrate_and_config_db(&database_url, pool_size); + let model = DefaultModel::from_file("rbac_model.conf").await.unwrap(); + let adapter = DieselAdapter::new(database_url, pool_size)?; + let mut casbin_middleware = CasbinAxumLayer::new(model, adapter).await.unwrap(); -fn main() { - let mut connection = establish_connection(); - let results = users::table - .limit(5) - .load::(&mut connection) - .expect("Error loading posts"); - println!("Displaying {} users", results.len()); - for user in results { - println!("{} {} {} {} {}", user.id, user.username, user.email, user.password, user.role); + casbin_middleware + .write() + .await + .get_role_manager() + .write() + .matching_fn(Some(key_match2), None); + + let share_enforcer = casbin_middleware.get_enforcer(); + let clone_enforcer = share_enforcer.clone(); + + let preset_rules = load_csv(walk_csv(".")); + for mut policy in preset_rules { + let ptype = policy.remove(0); + if ptype.starts_with('p') { + match clone_enforcer.write().await.add_policy(policy).await { + Ok(_) => info!("Present policies(p) added successfully"), + Err(err) => error!("Present policies(p) add error: {}", err.to_string()), + }; + continue; + } else if ptype.starts_with('g') { + match clone_enforcer + .write() + .await + .add_named_grouping_policy(&ptype, policy) + .await + { + Ok(_) => info!("Preset policies(g) added successfully"), + Err(err) => error!("Preset policies(g) add error: {}", err.to_string()), + } + continue; + } else { + unreachable!() + } } + + let app = Router::new() + .layer(Extension(pool.clone())) + .route("/api/auth/register", post(user_api::register)) + .route("/api/auth/signin", post(user_api::signin)) + .route("/api/users", get(user_api::get_all_user)) + .route("/api/user/:id", get(user_api::get_user)) + .route("/api/admin/:id", put(user_api::update_user)) + .route("/api/admin/:id", delete(user_api::delete_user)) + .layer(casbin_middleware.clone()) + .layer(middleware::middleware::AuthLayer); + // .with(pool.clone()); + + axum::Server::bind(&app_url.parse().unwrap()) + .serve(app.into_make_service()) + .await + .unwrap(); + + Ok(()) + + } diff --git a/axum-middleware-example/src/middleware/middleware.rs b/axum-middleware-example/src/middleware/middleware.rs index 78f373c..c4f3cee 100644 --- a/axum-middleware-example/src/middleware/middleware.rs +++ b/axum-middleware-example/src/middleware/middleware.rs @@ -24,7 +24,7 @@ use std::{ use tower::{Layer, Service}; #[derive(Clone)] -struct AuthLayer; +pub struct AuthLayer; impl Layer for AuthLayer { type Service = AuthMiddleware; @@ -35,7 +35,7 @@ impl Layer for AuthLayer { } #[derive(Clone)] -struct AuthMiddleware { +pub struct AuthMiddleware { inner: S, } diff --git a/axum-middleware-example/src/model/response.rs b/axum-middleware-example/src/model/response.rs index 43d20f6..677b441 100644 --- a/axum-middleware-example/src/model/response.rs +++ b/axum-middleware-example/src/model/response.rs @@ -1,5 +1,3 @@ -use axum::response::{IntoResponse, Response}; -use axum::body; use serde::{Serialize, Deserialize}; #[derive(Debug, Serialize, Deserialize)] diff --git a/axum-middleware-example/src/model/user.rs b/axum-middleware-example/src/model/user.rs index 580d76f..2361bb1 100644 --- a/axum-middleware-example/src/model/user.rs +++ b/axum-middleware-example/src/model/user.rs @@ -5,7 +5,6 @@ use crate::{ constants }; -use chrono::Utc; use diesel::prelude::*; use diesel::QueryDsl; use serde::{Deserialize, Serialize}; diff --git a/axum-middleware-example/src/repository/mod.rs b/axum-middleware-example/src/repository/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/axum-middleware-example/src/repository/user_repository.rs b/axum-middleware-example/src/repository/user_repository.rs deleted file mode 100644 index e69de29..0000000 diff --git a/axum-middleware-example/src/route/mod.rs b/axum-middleware-example/src/route/mod.rs deleted file mode 100644 index 8b4ddc8..0000000 --- a/axum-middleware-example/src/route/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod routes; \ No newline at end of file diff --git a/axum-middleware-example/src/route/routes.rs b/axum-middleware-example/src/route/routes.rs deleted file mode 100644 index 42cbd02..0000000 --- a/axum-middleware-example/src/route/routes.rs +++ /dev/null @@ -1,20 +0,0 @@ -// DEFINE ROUTES HERE -use axum::{ - routing::{delete, get, post, put}, - Router, -}; - -use crate::api::user; - -pub fn routes() -> Router { - let router = Router::new() - .route("/api/auth/register", post(user::register)) - .route("/api/auth/signin", post(user::signin)) - .route("/api/users", get(user::get_all_user)) - .route("/api/user/:id", get(user::get_user)) - .route("/api/admin/:id", put(user::update_user)) - .route("/api/admin/:id", delete(user::delete_user)); - - // NEED TO ADD MIDDLEWARE HERE, BEFORE CALLING IN MAIN.RS - router -} diff --git a/axum-middleware-example/src/service/user.rs b/axum-middleware-example/src/service/user.rs index 0a02a60..43d3765 100644 --- a/axum-middleware-example/src/service/user.rs +++ b/axum-middleware-example/src/service/user.rs @@ -10,8 +10,7 @@ use crate::{ use axum::extract::Extension; use axum::http::StatusCode; -use axum_casbin_auth::casbin::{CachedEnforcer}; -use axum_casbin_auth::CasbinVals; +use axum_casbin_auth::casbin::{CachedEnforcer, MgmtApi}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] diff --git a/axum-middleware-example/src/utils/csv_utils.rs b/axum-middleware-example/src/utils/csv_utils.rs new file mode 100644 index 0000000..7c37ca2 --- /dev/null +++ b/axum-middleware-example/src/utils/csv_utils.rs @@ -0,0 +1,84 @@ +use csv::{Error, ReaderBuilder, StringRecord, Trim}; +use walkdir::{DirEntry, WalkDir}; + +use std::{ + convert::AsRef, + fs, + path::{Path, PathBuf}, +}; + +pub fn walk_csv>(dir: P) -> Vec { + WalkDir::new(dir) + .follow_links(true) + .min_depth(1) + .max_depth(3) + .into_iter() + .filter_entry(|e| !is_hidden(e)) + .filter_map(|e| e.ok()) + .filter(|e| is_file(e) && is_csv(e)) + .filter_map(|e| fs::canonicalize(e.path()).ok()) + .collect::>() +} + +pub fn load_csv>(paths: Vec

) -> Vec> { + paths + .into_iter() + .map(load_records) + .flatten() + .filter_map(|r| r.deserialize::>(None).ok()) + .collect::>>() +} + +fn load_records>(p: P) -> Vec { + if let Ok(mut rdr) = ReaderBuilder::new() + .has_headers(false) + .flexible(true) + .double_quote(false) + .comment(Some(b'#')) + .delimiter(b',') + .trim(Trim::All) + .from_path(p) + { + if let Ok(records) = rdr.records().collect::, Error>>() + { + return records + .into_iter() + .filter(|r| is_valid_policy(r) || is_valid_grouping_policy(r)) + .collect::>(); + } + } + + vec![] +} + +fn is_hidden(entry: &DirEntry) -> bool { + entry + .file_name() + .to_str() + .map(|s| s.starts_with('.')) + .unwrap_or(false) +} + +fn is_file(entry: &DirEntry) -> bool { + entry.file_type().is_file() +} + +fn is_csv(entry: &DirEntry) -> bool { + entry.path().to_string_lossy().ends_with(".csv") +} + +fn is_valid_grouping_policy(record: &StringRecord) -> bool { + if let Some(ptype) = record.get(0) { + return ptype.starts_with('g') && record.len() >= 3; + } + + false +} + +fn is_valid_policy(record: &StringRecord) -> bool { + if let Some(ptype) = record.get(0) { + return ptype.starts_with('p') && record.len() >= 4; + } + + false +} diff --git a/axum-middleware-example/src/utils/mod.rs b/axum-middleware-example/src/utils/mod.rs index d5c3333..52a7fea 100644 --- a/axum-middleware-example/src/utils/mod.rs +++ b/axum-middleware-example/src/utils/mod.rs @@ -1,2 +1,3 @@ pub mod bcrypt; -pub mod token_utils; \ No newline at end of file +pub mod token_utils; +pub mod csv_utils; \ No newline at end of file From 02200c50187a5be76eadde72ef38d4fe0ee4f3a6 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Mon, 1 Aug 2022 19:53:56 +0530 Subject: [PATCH 13/18] register, update, delete services added --- axum-middleware-example/Cargo.toml | 3 +- axum-middleware-example/src/api/user.rs | 59 +++++++++++- axum-middleware-example/src/constants.rs | 9 +- axum-middleware-example/src/main.rs | 1 + .../src/middleware/authorizeJWT.rs | 2 - .../src/middleware/middleware.rs | 32 ++++--- axum-middleware-example/src/middleware/mod.rs | 3 +- axum-middleware-example/src/model/user.rs | 38 ++++++-- axum-middleware-example/src/service/user.rs | 96 ++++++++++++++++--- 9 files changed, 193 insertions(+), 50 deletions(-) delete mode 100644 axum-middleware-example/src/middleware/authorizeJWT.rs diff --git a/axum-middleware-example/Cargo.toml b/axum-middleware-example/Cargo.toml index c2645b1..3ae9713 100644 --- a/axum-middleware-example/Cargo.toml +++ b/axum-middleware-example/Cargo.toml @@ -7,10 +7,11 @@ edition = "2021" [dependencies] axum = "0.5.13" +axum-macros = "0.2.3" futures = "0.3.5" failure = "0.1.8" serde = "1.0.116" -async-std = { version = "1.10.0", default-features = false, optional = true } +async-std = "1.10.0" serde_derive = "1.0.116" serde_json = "1.0.57" derive_more = "0.99.10" diff --git a/axum-middleware-example/src/api/user.rs b/axum-middleware-example/src/api/user.rs index 6dad9ca..510e8a7 100644 --- a/axum-middleware-example/src/api/user.rs +++ b/axum-middleware-example/src/api/user.rs @@ -4,11 +4,12 @@ use crate::{ model::db::Pool, model::{ response::ResponseBody, - user::{LoginForm, NewUser}, + user::{AddUser, LoginForm}, }, service::user::{self}, }; +use async_std::sync::Arc; use axum::{ extract::{Extension, Path}, http::StatusCode, @@ -16,6 +17,8 @@ use axum::{ Json, }; use axum_casbin_auth::casbin::CachedEnforcer; +use axum_macros::debug_handler; +use tokio::sync::RwLock; // IMPLEMENT INTORESPONSE FOR SERVICE ERROR AND UPDATE ALL ERRORS OR MATCH THE ERROR WITH SERVICE ERROR (STATUSCODE, CONTANTSMSG).INTO_RESPONSE() // POST(api/auth/signin) @@ -39,11 +42,41 @@ pub async fn signin( } // POST(api/auth/register) -pub async fn register() {} - +// try to update the response, try to add result in all, if failed, then ask on discussion and search at night +#[debug_handler] +pub async fn register( + Json(reg_form): Json, + pool: Extension, + Extension(enforcer): Extension>>, +) -> Response { + let user = reg_form; + match user::register(user, &pool, enforcer).await { + Ok(message) => { + Json(ResponseBody::new(&message, constants::EMPTY)).into_response() + } + Err(_) => ( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_NEW_USER_ADD_PERMISSION_ERROR.to_string(), + ) + .into_response(), + } +} // DELETE(api/admin/{:id}) -pub async fn delete_user() {} +// IT DOESNT DO ANY USER VALIDATION +#[debug_handler] +pub async fn delete_user(Path(id): Path, pool: Extension) -> Response { + match user::delete_user(id.parse::().unwrap(), &pool) { + Ok(delete) => { + Json(ResponseBody::new(constants::MESSAGE_OK, delete)).into_response() + } + Err(_) => ( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(), + ) + .into_response(), + } +} // GET(api/user/{:id}) pub async fn get_user(Path(id): Path, pool: Extension) -> Response { @@ -72,4 +105,20 @@ pub async fn get_all_user(pool: Extension) -> Response { } // PUT(api/admin/{:id}) -pub async fn update_user() {} +// CAN UPDATE ROLE +pub async fn update_user( + Path(id): Path, + Json(update_form): Json, + pool: Extension, +) -> Response { + match user::update_user(id.parse::().unwrap(), update_form, &pool) { + Ok(message) => { + Json(ResponseBody::new(&message, constants::EMPTY)).into_response() + } + Err(_) => ( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_UPDATE_USER_ERROR.to_string(), + ) + .into_response(), + } +} diff --git a/axum-middleware-example/src/constants.rs b/axum-middleware-example/src/constants.rs index b9486ba..bd9f884 100644 --- a/axum-middleware-example/src/constants.rs +++ b/axum-middleware-example/src/constants.rs @@ -2,19 +2,18 @@ pub const MESSAGE_OK: &str = "ok"; pub const MESSAGE_CAN_NOT_FIND_USER: &str = "Can not find user, user not exist"; pub const MESSAGE_CAN_NOT_FETCH_DATA: &str = "Can not fetch data"; -pub const MESSAGE_CAN_NOT_INSERT_DATA: &str = "Can not insert data"; -pub const MESSAGE_CAN_NOT_DELETE_DATA: &str = "Can not delete data"; pub const MESSAGE_PROCESS_TOKEN_ERROR: &str = "Error while processing token"; pub const MESSAGE_INVALID_TOKEN: &str = "Invalid token, please login again"; pub const MESSAGE_INTERNAL_SERVER_ERROR: &str = "Internal Server Error"; pub const MESSAGE_SIGNIN_FAILED: &str = "Wrong email or password, please try again"; pub const MESSAGE_SIGNIN_SUCCESS: &str = "Signin successfully"; pub const MESSAGE_SIGNUP_SUCCESS: &str = "Signup successfully"; +pub const MESSAGE_UPDATE_USER_SUCCESS: &str = "User updated successfully"; pub const MESSAGE_NEW_USER_ADD_PERMISSION_ERROR: &str = - "Can not add new user when adding new permissions"; + "Can not add new user when adding new permissions, maybe user is already present"; + pub const MESSAGE_UPDATE_USER_ERROR: &str = + "Can not update user"; -// BAD REQUEST -pub const MESSAGE_TOKEN_MISSING: &str = "Token is missing"; // HEADERS pub const AUTHORIZATION: &str = "Authorization"; diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs index 865f832..b730da9 100644 --- a/axum-middleware-example/src/main.rs +++ b/axum-middleware-example/src/main.rs @@ -91,6 +91,7 @@ async fn main() -> Result<()> { let app = Router::new() .layer(Extension(pool.clone())) + .layer(Extension(clone_enforcer)) .route("/api/auth/register", post(user_api::register)) .route("/api/auth/signin", post(user_api::signin)) .route("/api/users", get(user_api::get_all_user)) diff --git a/axum-middleware-example/src/middleware/authorizeJWT.rs b/axum-middleware-example/src/middleware/authorizeJWT.rs deleted file mode 100644 index 059bec6..0000000 --- a/axum-middleware-example/src/middleware/authorizeJWT.rs +++ /dev/null @@ -1,2 +0,0 @@ -// JWT AUTHENTICATION -const BEARER: &str = "Bearer "; \ No newline at end of file diff --git a/axum-middleware-example/src/middleware/middleware.rs b/axum-middleware-example/src/middleware/middleware.rs index c4f3cee..3870250 100644 --- a/axum-middleware-example/src/middleware/middleware.rs +++ b/axum-middleware-example/src/middleware/middleware.rs @@ -1,4 +1,8 @@ -use crate::{constants, model::{db::Pool, response::ResponseBody}, utils::token_utils}; +use crate::{ + constants, + model::{db::Pool, response::ResponseBody}, + utils::token_utils, +}; use axum::{ body::{self, BoxBody}, @@ -7,15 +11,14 @@ use axum::{ header::{HeaderName, HeaderValue}, Method, }, - Json, - response::{Response, IntoResponse}, - BoxError + response::{IntoResponse, Response}, + BoxError, Json, }; use axum_casbin_auth::CasbinVals; use bytes::Bytes; use futures::future::BoxFuture; use http::{self, Request}; -use http_body::{Body as HttpBody}; +use http_body::Body as HttpBody; use std::{ boxed::Box, convert::Infallible, @@ -103,7 +106,8 @@ where .is_ok() { info!("Valid token"); - authenticate_username = token_data.claims.user_name; + authenticate_username = + token_data.claims.user_name; authenticate_pass = true; } else { error!("Invalid token"); @@ -122,15 +126,15 @@ where domain: None, }; req.extensions_mut().insert(vals); - Box::pin(async move { - Ok(inner.call(req).await?.map(body::boxed)) - }) - } else{ - Box::pin(async move{ - Ok(Json(ResponseBody::new(constants::MESSAGE_TOKEN_MISSING, constants::EMPTY)).into_response()) + Box::pin(async move { Ok(inner.call(req).await?.map(body::boxed)) }) + } else { + Box::pin(async move { + Ok(Json(ResponseBody::new( + constants::MESSAGE_INVALID_TOKEN, + constants::EMPTY, + )) + .into_response()) }) - } - } } diff --git a/axum-middleware-example/src/middleware/mod.rs b/axum-middleware-example/src/middleware/mod.rs index ff093dc..f35d8d4 100644 --- a/axum-middleware-example/src/middleware/mod.rs +++ b/axum-middleware-example/src/middleware/mod.rs @@ -1,2 +1 @@ -pub mod middleware; -pub mod authorizeJWT; \ No newline at end of file +pub mod middleware; \ No newline at end of file diff --git a/axum-middleware-example/src/model/user.rs b/axum-middleware-example/src/model/user.rs index 2361bb1..71fcd81 100644 --- a/axum-middleware-example/src/model/user.rs +++ b/axum-middleware-example/src/model/user.rs @@ -1,14 +1,15 @@ use crate::{ + constants, model::{db::Connection, user_token::UserToken}, schema::users::{self, dsl::*}, utils::bcrypt::{compare_password, hash_password}, - constants }; use diesel::prelude::*; use diesel::QueryDsl; use serde::{Deserialize, Serialize}; use uuid::Uuid; +use axum_macros::FromRequest; #[derive(Debug, Serialize, Deserialize, Queryable)] // #[derive(Identifiable, Queryable, PartialEq, Debug)] @@ -22,15 +23,15 @@ pub struct User { pub login_session: String, } -#[derive(Insertable, Serialize, Deserialize, AsChangeset, Clone)] +#[derive(Insertable, Serialize, Deserialize, AsChangeset, Clone, FromRequest)] #[table_name = "users"] -pub struct NewUser { +pub struct AddUser { pub username: String, pub email: String, pub password: String, #[serde(default = "default_role")] pub role: String, - pub login_session: String + pub login_session: String, } fn default_role() -> String { @@ -53,10 +54,10 @@ pub struct LoginInfo { } impl User { - pub fn register(user: NewUser, conn: &Connection) -> Result { + pub fn register(user: AddUser, conn: &Connection) -> Result { if Self::get_user_by_email(&user.email, conn).is_err() { let hashed_pwd = hash_password(&user.password).unwrap(); - let user_upd = NewUser { + let user_upd = AddUser { password: hashed_pwd, ..user }; @@ -64,13 +65,28 @@ impl User { .values(&user_upd) .execute(conn) .map_err(|e| e.to_string())?; - + Ok(constants::MESSAGE_SIGNUP_SUCCESS.to_string()) } else { Err(format!("User {} is already registered", &user.username)) } } + pub fn update_user(i: i32, user_data: AddUser, conn: &Connection) -> Result { + if Self::get_user_by_email(&user_data.email, conn).is_err() { + Err(format!("User is not present")) + } else { + let hashed_pwd = hash_password(&user_data.password).unwrap(); + let user_update = AddUser { + password: hashed_pwd, + ..user_data + }; + diesel::update(users.find(i)).set(&user_update).execute(conn).map_err(|e| e.to_string())?; + + Ok(constants::MESSAGE_UPDATE_USER_SUCCESS.to_string()) + } + } + pub fn get_user(i: i32, conn: &Connection) -> QueryResult { users.find(i).get_result::(conn) } @@ -78,7 +94,7 @@ impl User { pub fn get_all_user(conn: &Connection) -> QueryResult> { users.order(id.asc()).load::(conn) } - + pub fn signin(login: LoginForm, conn: &Connection) -> Option { if let Ok(user_to_verify) = users .filter(email.eq(&login.email)) @@ -104,9 +120,11 @@ impl User { None } - pub fn update_user() {} + - pub fn delete_user() {} + pub fn delete_user(delete_id: i32, conn: &Connection) -> QueryResult { + diesel::delete(users.filter(users::id.eq(delete_id))).execute(conn) + } pub fn update_login_session_to_db( eml: &str, diff --git a/axum-middleware-example/src/service/user.rs b/axum-middleware-example/src/service/user.rs index 43d3765..be4987e 100644 --- a/axum-middleware-example/src/service/user.rs +++ b/axum-middleware-example/src/service/user.rs @@ -1,17 +1,19 @@ - #![allow(clippy::if_same_then_else)] + use crate::{ - model::{db::Pool, user::LoginForm}, constants, errors::ServiceError, - model::user::{NewUser, User}, + model::user::{AddUser, User}, model::user_token::UserToken, + model::{db::Pool, user::LoginForm}, }; use axum::extract::Extension; use axum::http::StatusCode; use axum_casbin_auth::casbin::{CachedEnforcer, MgmtApi}; use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::RwLock; #[derive(Serialize, Deserialize)] pub struct TokenBodyResponse { @@ -20,23 +22,72 @@ pub struct TokenBodyResponse { } // ADD USER -pub async fn register() {} +pub async fn register( + user: AddUser, + Extension(pool): &Extension, + enforcer: Arc>, +) -> Result { + let username = user.clone().username; + let email = user.clone().email; + let clone_role = user.role.clone(); + let g_policies = vec![username.clone(), clone_role.to_string()]; + + // CHECK IF USER IS ALREADY PRESENT + if User::get_user_by_email(&email, &pool.get().unwrap()).is_err() { + match enforcer + .write() + .await + .add_named_grouping_policy(&"g", g_policies) + .await + { + Ok(_) => info!("Preset policies(p) add successfully"), + Err(err) => error!("Preset policies(g) add error: {}", err.to_string()), + }; -pub fn get_all_user(Extension(pool): &Extension) -> Result, ServiceError>{ + match User::register(user, &pool.get().unwrap()) { + Ok(message) => Ok(message), + Err(message) => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + message, + )), + } + } else { + Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_NEW_USER_ADD_PERMISSION_ERROR.to_string(), + )) + } +} + +pub fn get_all_user( + Extension(pool): &Extension, +) -> Result, ServiceError> { match User::get_all_user(&pool.get().unwrap()) { Ok(user) => Ok(user), - Err(_) => Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(),)) + Err(_) => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(), + )), } } -pub fn get_user(user_id: i32, Extension(pool): &Extension) -> Result { +pub fn get_user( + user_id: i32, + Extension(pool): &Extension, +) -> Result { match User::get_user(user_id, &pool.get().unwrap()) { Ok(user) => Ok(user), - Err(_) => Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(),)) + Err(_) => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_CAN_NOT_FETCH_DATA.to_string(), + )), } } -pub fn signin(login: LoginForm, Extension(pool): &Extension) -> Result { +pub fn signin( + login: LoginForm, + Extension(pool): &Extension, +) -> Result { match User::signin(login, &pool.get().unwrap()) { Some(logged_user) => { match serde_json::from_value( @@ -56,6 +107,29 @@ pub fn signin(login: LoginForm, Extension(pool): &Extension) -> Result, +) -> Result { + match User::update_user(update_id, user_data, &pool.get().unwrap()) { + Ok(message) => Ok(message), + Err(message) => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + message, + )), + } +} -pub fn delete_user() {} \ No newline at end of file +pub fn delete_user( + delete_id: i32, + Extension(pool): &Extension, +) -> Result { + match User::delete_user(delete_id, &pool.get().unwrap()) { + Ok(delete) => Ok(delete), + Err(_) => Err(ServiceError::new( + StatusCode::INTERNAL_SERVER_ERROR, + constants::MESSAGE_CAN_NOT_FIND_USER.to_string(), + )), + } +} From dcdd94fee90a727417c54cb86704b655dc4b9e6c Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Tue, 2 Aug 2022 18:24:02 +0530 Subject: [PATCH 14/18] make clippy happy, remove unnecessary commands --- actix-middleware-example/src/models/post.rs | 1 + actix-middleware-example/src/models/user.rs | 2 ++ actix-middleware-example/src/routers/mod.rs | 2 +- .../src/services/account_service.rs | 6 +++--- .../src/services/post_service.rs | 6 +++--- .../src/utils/csv_utils.rs | 3 +-- ....csv => rbac_model_with_preset_policy.csv} | 0 axum-middleware-example/src/api/user.rs | 2 -- axum-middleware-example/src/main.rs | 3 +-- .../src/middleware/{middleware.rs => auth.rs} | 1 - axum-middleware-example/src/middleware/mod.rs | 2 +- axum-middleware-example/src/model/db.rs | 1 - axum-middleware-example/src/model/user.rs | 19 +++++++++++++------ axum-middleware-example/src/service/user.rs | 2 +- .../src/utils/csv_utils.rs | 3 +-- 15 files changed, 28 insertions(+), 25 deletions(-) rename axum-middleware-example/{rbac_model_with_pattern.csv => rbac_model_with_preset_policy.csv} (100%) rename axum-middleware-example/src/middleware/{middleware.rs => auth.rs} (98%) diff --git a/actix-middleware-example/src/models/post.rs b/actix-middleware-example/src/models/post.rs index f18c8d5..b7679ce 100644 --- a/actix-middleware-example/src/models/post.rs +++ b/actix-middleware-example/src/models/post.rs @@ -1,3 +1,4 @@ +#![allow(clippy::extra_unused_lifetimes)] use crate::{ config::db::Connection, schema::posts::{self, dsl::*}, diff --git a/actix-middleware-example/src/models/user.rs b/actix-middleware-example/src/models/user.rs index df0f996..656ab8c 100644 --- a/actix-middleware-example/src/models/user.rs +++ b/actix-middleware-example/src/models/user.rs @@ -1,3 +1,5 @@ +#![allow(clippy::extra_unused_lifetimes)] + use crate::{ config::db::Connection, constants, diff --git a/actix-middleware-example/src/routers/mod.rs b/actix-middleware-example/src/routers/mod.rs index 084bccc..9bc72a0 100644 --- a/actix-middleware-example/src/routers/mod.rs +++ b/actix-middleware-example/src/routers/mod.rs @@ -14,7 +14,7 @@ pub fn routes(cfg: &mut web::ServiceConfig) { ) .service( web::scope("/user") - .service(web::resource("logout").route(web::post().to(user::logout))) + .service(web::resource("/logout").route(web::post().to(user::logout))) .service( web::resource("").route(web::delete().to(user::delete_self)), ), diff --git a/actix-middleware-example/src/services/account_service.rs b/actix-middleware-example/src/services/account_service.rs index 57441d4..e773d0b 100644 --- a/actix-middleware-example/src/services/account_service.rs +++ b/actix-middleware-example/src/services/account_service.rs @@ -98,7 +98,7 @@ pub fn logout(req: HttpRequest, pool: &web::Data) -> Result<(), ServiceErr } }; let username = &vals.subject; - let user = User::find_user_by_username(&username, &pool.get().unwrap()) + let user = User::find_user_by_username(username, &pool.get().unwrap()) .map_err(|_| make_error())?; User::logout(user.id, &pool.get().unwrap()); Ok(()) @@ -147,7 +147,7 @@ pub fn delete_admin( } }; let username = &vals.subject; - let user = User::find_user_by_username(&username, &pool.get().unwrap()) + let user = User::find_user_by_username(username, &pool.get().unwrap()) .map_err(|_| make_error())?; let delete_user_role = user.role; @@ -201,7 +201,7 @@ pub fn delete_self( } }; let username = &vals.subject; - let user = User::find_user_by_username(&username, &pool.get().unwrap()) + let user = User::find_user_by_username(username, &pool.get().unwrap()) .map_err(|_| make_error())?; if user.role == 0 { diff --git a/actix-middleware-example/src/services/post_service.rs b/actix-middleware-example/src/services/post_service.rs index b449e4e..6658378 100644 --- a/actix-middleware-example/src/services/post_service.rs +++ b/actix-middleware-example/src/services/post_service.rs @@ -39,7 +39,7 @@ pub fn find_all( } }; let username = &vals.subject; - let user = User::find_user_by_username(&username, &pool.get().unwrap()) + let user = User::find_user_by_username(username, &pool.get().unwrap()) .map_err(|_| make_error())?; let mut is_admin = false; if user.role == 0 || user.role == 1 { @@ -76,7 +76,7 @@ pub fn find_by_id( } }; let username = &vals.subject; - let user = User::find_user_by_username(&username, &pool.get().unwrap()) + let user = User::find_user_by_username(username, &pool.get().unwrap()) .map_err(|_| make_error())?; let mut is_admin = false; if user.role == 0 || user.role == 1 { @@ -134,7 +134,7 @@ pub fn delete( } }; let username = &vals.subject; - let user = User::find_user_by_username(&username, &pool.get().unwrap()) + let user = User::find_user_by_username(username, &pool.get().unwrap()) .map_err(|_| make_error())?; if user.role == 0 || user.role == 1 { match Post::find_by_id(true, id, &pool.get().unwrap()) { diff --git a/actix-middleware-example/src/utils/csv_utils.rs b/actix-middleware-example/src/utils/csv_utils.rs index 7c37ca2..3c682cc 100644 --- a/actix-middleware-example/src/utils/csv_utils.rs +++ b/actix-middleware-example/src/utils/csv_utils.rs @@ -23,8 +23,7 @@ pub fn walk_csv>(dir: P) -> Vec { pub fn load_csv>(paths: Vec

) -> Vec> { paths .into_iter() - .map(load_records) - .flatten() + .flat_map(load_records) .filter_map(|r| r.deserialize::>(None).ok()) .collect::>>() } diff --git a/axum-middleware-example/rbac_model_with_pattern.csv b/axum-middleware-example/rbac_model_with_preset_policy.csv similarity index 100% rename from axum-middleware-example/rbac_model_with_pattern.csv rename to axum-middleware-example/rbac_model_with_preset_policy.csv diff --git a/axum-middleware-example/src/api/user.rs b/axum-middleware-example/src/api/user.rs index 510e8a7..1b8f726 100644 --- a/axum-middleware-example/src/api/user.rs +++ b/axum-middleware-example/src/api/user.rs @@ -42,7 +42,6 @@ pub async fn signin( } // POST(api/auth/register) -// try to update the response, try to add result in all, if failed, then ask on discussion and search at night #[debug_handler] pub async fn register( Json(reg_form): Json, @@ -105,7 +104,6 @@ pub async fn get_all_user(pool: Extension) -> Response { } // PUT(api/admin/{:id}) -// CAN UPDATE ROLE pub async fn update_user( Path(id): Path, Json(update_form): Json, diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs index b730da9..a7b524a 100644 --- a/axum-middleware-example/src/main.rs +++ b/axum-middleware-example/src/main.rs @@ -99,8 +99,7 @@ async fn main() -> Result<()> { .route("/api/admin/:id", put(user_api::update_user)) .route("/api/admin/:id", delete(user_api::delete_user)) .layer(casbin_middleware.clone()) - .layer(middleware::middleware::AuthLayer); - // .with(pool.clone()); + .layer(middleware::auth::AuthLayer); axum::Server::bind(&app_url.parse().unwrap()) .serve(app.into_make_service()) diff --git a/axum-middleware-example/src/middleware/middleware.rs b/axum-middleware-example/src/middleware/auth.rs similarity index 98% rename from axum-middleware-example/src/middleware/middleware.rs rename to axum-middleware-example/src/middleware/auth.rs index 3870250..2a50793 100644 --- a/axum-middleware-example/src/middleware/middleware.rs +++ b/axum-middleware-example/src/middleware/auth.rs @@ -120,7 +120,6 @@ where } } if authenticate_pass { - // UNDERSTAND POLICY GROUPING AND UPDATE CASBINBALS HERE let vals = CasbinVals { subject: authenticate_username, domain: None, diff --git a/axum-middleware-example/src/middleware/mod.rs b/axum-middleware-example/src/middleware/mod.rs index f35d8d4..5696e21 100644 --- a/axum-middleware-example/src/middleware/mod.rs +++ b/axum-middleware-example/src/middleware/mod.rs @@ -1 +1 @@ -pub mod middleware; \ No newline at end of file +pub mod auth; \ No newline at end of file diff --git a/axum-middleware-example/src/model/db.rs b/axum-middleware-example/src/model/db.rs index b925404..1d4faac 100644 --- a/axum-middleware-example/src/model/db.rs +++ b/axum-middleware-example/src/model/db.rs @@ -10,7 +10,6 @@ embed_migrations!(); pub type Connection = PgConnection; pub type Pool = r2d2::Pool>; -// THIS HAS TO BE CALLED TO SETUP THE DATABASE pub fn migrate_and_config_db(url: &str, pool_size: u32) -> Pool { info!("Migrating and configurating database..."); let manager = ConnectionManager::::new(url); diff --git a/axum-middleware-example/src/model/user.rs b/axum-middleware-example/src/model/user.rs index 71fcd81..0359dd2 100644 --- a/axum-middleware-example/src/model/user.rs +++ b/axum-middleware-example/src/model/user.rs @@ -1,3 +1,5 @@ +#![allow(clippy::extra_unused_lifetimes)] + use crate::{ constants, model::{db::Connection, user_token::UserToken}, @@ -5,11 +7,11 @@ use crate::{ utils::bcrypt::{compare_password, hash_password}, }; +use axum_macros::FromRequest; use diesel::prelude::*; use diesel::QueryDsl; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use axum_macros::FromRequest; #[derive(Debug, Serialize, Deserialize, Queryable)] // #[derive(Identifiable, Queryable, PartialEq, Debug)] @@ -72,16 +74,23 @@ impl User { } } - pub fn update_user(i: i32, user_data: AddUser, conn: &Connection) -> Result { + pub fn update_user( + i: i32, + user_data: AddUser, + conn: &Connection, + ) -> Result { if Self::get_user_by_email(&user_data.email, conn).is_err() { - Err(format!("User is not present")) + Err("User is not present".to_string()) } else { let hashed_pwd = hash_password(&user_data.password).unwrap(); let user_update = AddUser { password: hashed_pwd, ..user_data }; - diesel::update(users.find(i)).set(&user_update).execute(conn).map_err(|e| e.to_string())?; + diesel::update(users.find(i)) + .set(&user_update) + .execute(conn) + .map_err(|e| e.to_string())?; Ok(constants::MESSAGE_UPDATE_USER_SUCCESS.to_string()) } @@ -120,8 +129,6 @@ impl User { None } - - pub fn delete_user(delete_id: i32, conn: &Connection) -> QueryResult { diesel::delete(users.filter(users::id.eq(delete_id))).execute(conn) } diff --git a/axum-middleware-example/src/service/user.rs b/axum-middleware-example/src/service/user.rs index be4987e..4af8be7 100644 --- a/axum-middleware-example/src/service/user.rs +++ b/axum-middleware-example/src/service/user.rs @@ -37,7 +37,7 @@ pub async fn register( match enforcer .write() .await - .add_named_grouping_policy(&"g", g_policies) + .add_named_grouping_policy("g", g_policies) .await { Ok(_) => info!("Preset policies(p) add successfully"), diff --git a/axum-middleware-example/src/utils/csv_utils.rs b/axum-middleware-example/src/utils/csv_utils.rs index 7c37ca2..3c682cc 100644 --- a/axum-middleware-example/src/utils/csv_utils.rs +++ b/axum-middleware-example/src/utils/csv_utils.rs @@ -23,8 +23,7 @@ pub fn walk_csv>(dir: P) -> Vec { pub fn load_csv>(paths: Vec

) -> Vec> { paths .into_iter() - .map(load_records) - .flatten() + .flat_map(load_records) .filter_map(|r| r.deserialize::>(None).ok()) .collect::>>() } From 6d0d40cbd7f028afcdf6ddeb3975e6ee40eafe30 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Fri, 5 Aug 2022 22:27:34 +0530 Subject: [PATCH 15/18] renamed files --- actix-middleware-example/.env.sample | 5 ----- actix-middleware-example/Cargo.toml | 2 +- actix-middleware-example/src/secret.key.sample | 1 - axum-middleware-example/{.env.sample => .env} | 0 .../src/{secret.key.sample => secret.key} | 0 5 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 actix-middleware-example/.env.sample delete mode 100644 actix-middleware-example/src/secret.key.sample rename axum-middleware-example/{.env.sample => .env} (100%) rename axum-middleware-example/src/{secret.key.sample => secret.key} (100%) diff --git a/actix-middleware-example/.env.sample b/actix-middleware-example/.env.sample deleted file mode 100644 index 3384e7c..0000000 --- a/actix-middleware-example/.env.sample +++ /dev/null @@ -1,5 +0,0 @@ -APP_HOST=127.0.0.1 -APP_PORT=8080 -DATABASE_URL=postgres://casbin_rs:casbin_rs@127.0.0.1:5432/test -POOL_SIZE=8 -HASH_ROUNDS=12 \ No newline at end of file diff --git a/actix-middleware-example/Cargo.toml b/actix-middleware-example/Cargo.toml index 71ff95d..5684021 100644 --- a/actix-middleware-example/Cargo.toml +++ b/actix-middleware-example/Cargo.toml @@ -33,4 +33,4 @@ diesel-adapter ="0.9.0" uuid = {version = "1.1.2", features = ["v4"] } # UPDATE AFTER LATEST RELEASE OF actix-casbin and actix-casbin-auth to CRATE.IO actix-casbin-auth = {git = "https://github.com/casbin-rs/actix-casbin-auth", default-features = false, features = [ "runtime-tokio" ]} -actix-casbin= {git = "https://github.com/casbin-rs/actix-casbin", default-features = false, features = [ "runtime-tokio" ]} +actix-casbin= {git = "https://github.com/casbin-rs/actix-casbin.git", default-features = false, features = [ "runtime-tokio" ]} diff --git a/actix-middleware-example/src/secret.key.sample b/actix-middleware-example/src/secret.key.sample deleted file mode 100644 index e71694d..0000000 --- a/actix-middleware-example/src/secret.key.sample +++ /dev/null @@ -1 +0,0 @@ -C�d���Pbbހ#� \ No newline at end of file diff --git a/axum-middleware-example/.env.sample b/axum-middleware-example/.env similarity index 100% rename from axum-middleware-example/.env.sample rename to axum-middleware-example/.env diff --git a/axum-middleware-example/src/secret.key.sample b/axum-middleware-example/src/secret.key similarity index 100% rename from axum-middleware-example/src/secret.key.sample rename to axum-middleware-example/src/secret.key From 4804e2829a3dd6b6fdadeacfdc3e31851594e6e9 Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sat, 6 Aug 2022 00:35:02 +0530 Subject: [PATCH 16/18] updated ci --- .github/workflows/check.yml | 8 +++++++- actix-middleware-example/.env.sample | 5 +++++ actix-middleware-example/src/secret.key.sample | 1 + axum-middleware-example/{.env => .env.sample} | 0 .../src/{secret.key => secret.key.sample} | 0 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 actix-middleware-example/.env.sample create mode 100644 actix-middleware-example/src/secret.key.sample rename axum-middleware-example/{.env => .env.sample} (100%) rename axum-middleware-example/src/{secret.key => secret.key.sample} (100%) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index add86d2..b8b6a29 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -65,11 +65,17 @@ jobs: - name: "Checkout Repository" uses: actions/checkout@v1 - - name: Generate test secret key + - name: Generate test secret key_actix shell: sh run: | mv src/secret.key.sample src/secret.key working-directory: actix-middleware-example + + - name: Generate test secret key_axum + shell: sh + run: | + mv src/secret.key.sample src/secret.key + working-directory: axum-middleware-example - name: "Use the latest Rust stable with clippy" uses: actions-rs/toolchain@v1 diff --git a/actix-middleware-example/.env.sample b/actix-middleware-example/.env.sample new file mode 100644 index 0000000..3384e7c --- /dev/null +++ b/actix-middleware-example/.env.sample @@ -0,0 +1,5 @@ +APP_HOST=127.0.0.1 +APP_PORT=8080 +DATABASE_URL=postgres://casbin_rs:casbin_rs@127.0.0.1:5432/test +POOL_SIZE=8 +HASH_ROUNDS=12 \ No newline at end of file diff --git a/actix-middleware-example/src/secret.key.sample b/actix-middleware-example/src/secret.key.sample new file mode 100644 index 0000000..e71694d --- /dev/null +++ b/actix-middleware-example/src/secret.key.sample @@ -0,0 +1 @@ +C�d���Pbbހ#� \ No newline at end of file diff --git a/axum-middleware-example/.env b/axum-middleware-example/.env.sample similarity index 100% rename from axum-middleware-example/.env rename to axum-middleware-example/.env.sample diff --git a/axum-middleware-example/src/secret.key b/axum-middleware-example/src/secret.key.sample similarity index 100% rename from axum-middleware-example/src/secret.key rename to axum-middleware-example/src/secret.key.sample From 657b826311a6b92acbe47bfad1cb0ba50c9d115e Mon Sep 17 00:00:00 2001 From: Siddhesh Kanawade Date: Sat, 6 Aug 2022 11:56:15 +0530 Subject: [PATCH 17/18] formatting, clippy happy in poem-todo --- .../src/middleware/authn.rs | 15 +++-- actix-middleware-example/src/routers/mod.rs | 4 +- .../src/services/account_service.rs | 4 +- .../src/services/post_service.rs | 2 +- axum-middleware-example/src/api/mod.rs | 2 +- axum-middleware-example/src/constants.rs | 4 +- axum-middleware-example/src/main.rs | 66 +++++++++---------- axum-middleware-example/src/middleware/mod.rs | 2 +- axum-middleware-example/src/model/db.rs | 2 +- axum-middleware-example/src/model/mod.rs | 4 +- axum-middleware-example/src/model/response.rs | 4 +- .../src/model/user_token.rs | 10 +-- axum-middleware-example/src/service/mod.rs | 2 +- axum-middleware-example/src/utils/bcrypt.rs | 6 +- axum-middleware-example/src/utils/mod.rs | 2 +- .../src/utils/token_utils.rs | 17 ++--- poem-todo/src/main.rs | 2 +- poem-todo/src/models.rs | 5 +- 18 files changed, 78 insertions(+), 75 deletions(-) diff --git a/actix-middleware-example/src/middleware/authn.rs b/actix-middleware-example/src/middleware/authn.rs index 81a308f..60d6b99 100644 --- a/actix-middleware-example/src/middleware/authn.rs +++ b/actix-middleware-example/src/middleware/authn.rs @@ -30,8 +30,8 @@ pub struct Authentication; impl Transform for Authentication where -S: Service, Error = Error> + 'static, -B: MessageBody, + S: Service, Error = Error> + 'static, + B: MessageBody, { type Response = ServiceResponse>; type Error = Error; @@ -123,14 +123,21 @@ where domain: None, }; req.extensions_mut().insert(vals); - Box::pin(async move { srv.call(req).await.map(|res| res.map_into_left_body()) }) + Box::pin(async move { + srv.call(req).await.map(|res| res.map_into_left_body()) + }) } else { let vals = CasbinVals { subject: authenticate_username, domain: None, }; req.extensions_mut().insert(vals); - Box::pin(async move { srv.clone().call(req).await.map(|res| res.map_into_left_body()) }) + Box::pin(async move { + srv.clone() + .call(req) + .await + .map(|res| res.map_into_left_body()) + }) } } else { Box::pin(async move { diff --git a/actix-middleware-example/src/routers/mod.rs b/actix-middleware-example/src/routers/mod.rs index 9bc72a0..afcc8c7 100644 --- a/actix-middleware-example/src/routers/mod.rs +++ b/actix-middleware-example/src/routers/mod.rs @@ -14,7 +14,9 @@ pub fn routes(cfg: &mut web::ServiceConfig) { ) .service( web::scope("/user") - .service(web::resource("/logout").route(web::post().to(user::logout))) + .service( + web::resource("/logout").route(web::post().to(user::logout)), + ) .service( web::resource("").route(web::delete().to(user::delete_self)), ), diff --git a/actix-middleware-example/src/services/account_service.rs b/actix-middleware-example/src/services/account_service.rs index e773d0b..0296b8d 100644 --- a/actix-middleware-example/src/services/account_service.rs +++ b/actix-middleware-example/src/services/account_service.rs @@ -8,9 +8,9 @@ use crate::{ }; use actix::Addr; use actix_casbin::{CasbinActor, CasbinCmd, CasbinResult}; -use actix_casbin_auth::casbin::{CachedEnforcer}; +use actix_casbin_auth::casbin::CachedEnforcer; use actix_casbin_auth::CasbinVals; -use actix_web::{http::StatusCode, web, HttpRequest, HttpMessage}; +use actix_web::{http::StatusCode, web, HttpMessage, HttpRequest}; #[derive(Serialize, Deserialize)] pub struct TokenBodyResponse { diff --git a/actix-middleware-example/src/services/post_service.rs b/actix-middleware-example/src/services/post_service.rs index 6658378..c8669ce 100644 --- a/actix-middleware-example/src/services/post_service.rs +++ b/actix-middleware-example/src/services/post_service.rs @@ -6,7 +6,7 @@ use crate::{ models::user::User, }; use actix_casbin_auth::CasbinVals; -use actix_web::{http::StatusCode, web, HttpRequest, HttpMessage}; +use actix_web::{http::StatusCode, web, HttpMessage, HttpRequest}; pub fn find_all_public(pool: &web::Data) -> Result, ServiceError> { match Post::find_all(false, &pool.get().unwrap()) { diff --git a/axum-middleware-example/src/api/mod.rs b/axum-middleware-example/src/api/mod.rs index 018ff2e..22d12a3 100644 --- a/axum-middleware-example/src/api/mod.rs +++ b/axum-middleware-example/src/api/mod.rs @@ -1 +1 @@ -pub mod user; \ No newline at end of file +pub mod user; diff --git a/axum-middleware-example/src/constants.rs b/axum-middleware-example/src/constants.rs index bd9f884..c0595f8 100644 --- a/axum-middleware-example/src/constants.rs +++ b/axum-middleware-example/src/constants.rs @@ -11,9 +11,7 @@ pub const MESSAGE_SIGNUP_SUCCESS: &str = "Signup successfully"; pub const MESSAGE_UPDATE_USER_SUCCESS: &str = "User updated successfully"; pub const MESSAGE_NEW_USER_ADD_PERMISSION_ERROR: &str = "Can not add new user when adding new permissions, maybe user is already present"; - pub const MESSAGE_UPDATE_USER_ERROR: &str = - "Can not update user"; - +pub const MESSAGE_UPDATE_USER_ERROR: &str = "Can not update user"; // HEADERS pub const AUTHORIZATION: &str = "Authorization"; diff --git a/axum-middleware-example/src/main.rs b/axum-middleware-example/src/main.rs index a7b524a..2f44c07 100644 --- a/axum-middleware-example/src/main.rs +++ b/axum-middleware-example/src/main.rs @@ -7,33 +7,33 @@ extern crate log; #[macro_use] extern crate serde_json; +mod api; +mod constants; +mod errors; +mod middleware; mod model; mod schema; -mod utils; -mod errors; mod service; -mod middleware; -mod constants; -mod api; +mod utils; use crate::api::user as user_api; use crate::utils::csv_utils::{load_csv, walk_csv}; - use axum_casbin_auth::casbin::MgmtApi; use std::env; use axum::{ - routing::{delete, get, post, put}, extract::Extension, + routing::{delete, get, post, put}, Router, }; -use axum_casbin_auth::casbin::{CoreApi, DefaultModel, Result, function_map::key_match2}; +use axum_casbin_auth::casbin::{ + function_map::key_match2, CoreApi, DefaultModel, Result, +}; use axum_casbin_auth::CasbinAxumLayer; use diesel_adapter::DieselAdapter; - #[tokio::main] async fn main() -> Result<()> { dotenv::dotenv().expect("Failed to read .env file, please add it"); @@ -48,18 +48,18 @@ async fn main() -> Result<()> { .ok() .and_then(|s| s.parse().ok()) .unwrap_or(8); - + let pool = model::db::migrate_and_config_db(&database_url, pool_size); let model = DefaultModel::from_file("rbac_model.conf").await.unwrap(); let adapter = DieselAdapter::new(database_url, pool_size)?; let mut casbin_middleware = CasbinAxumLayer::new(model, adapter).await.unwrap(); casbin_middleware - .write() - .await - .get_role_manager() - .write() - .matching_fn(Some(key_match2), None); + .write() + .await + .get_role_manager() + .write() + .matching_fn(Some(key_match2), None); let share_enforcer = casbin_middleware.get_enforcer(); let clone_enforcer = share_enforcer.clone(); @@ -79,34 +79,32 @@ async fn main() -> Result<()> { .await .add_named_grouping_policy(&ptype, policy) .await - { - Ok(_) => info!("Preset policies(g) added successfully"), - Err(err) => error!("Preset policies(g) add error: {}", err.to_string()), - } - continue; + { + Ok(_) => info!("Preset policies(g) added successfully"), + Err(err) => error!("Preset policies(g) add error: {}", err.to_string()), + } + continue; } else { unreachable!() } } - + let app = Router::new() - .layer(Extension(pool.clone())) - .layer(Extension(clone_enforcer)) - .route("/api/auth/register", post(user_api::register)) - .route("/api/auth/signin", post(user_api::signin)) - .route("/api/users", get(user_api::get_all_user)) - .route("/api/user/:id", get(user_api::get_user)) - .route("/api/admin/:id", put(user_api::update_user)) - .route("/api/admin/:id", delete(user_api::delete_user)) - .layer(casbin_middleware.clone()) - .layer(middleware::auth::AuthLayer); + .layer(Extension(pool.clone())) + .layer(Extension(clone_enforcer)) + .route("/api/auth/register", post(user_api::register)) + .route("/api/auth/signin", post(user_api::signin)) + .route("/api/users", get(user_api::get_all_user)) + .route("/api/user/:id", get(user_api::get_user)) + .route("/api/admin/:id", put(user_api::update_user)) + .route("/api/admin/:id", delete(user_api::delete_user)) + .layer(casbin_middleware.clone()) + .layer(middleware::auth::AuthLayer); axum::Server::bind(&app_url.parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); - Ok(()) - - + Ok(()) } diff --git a/axum-middleware-example/src/middleware/mod.rs b/axum-middleware-example/src/middleware/mod.rs index 5696e21..0e4a05d 100644 --- a/axum-middleware-example/src/middleware/mod.rs +++ b/axum-middleware-example/src/middleware/mod.rs @@ -1 +1 @@ -pub mod auth; \ No newline at end of file +pub mod auth; diff --git a/axum-middleware-example/src/model/db.rs b/axum-middleware-example/src/model/db.rs index 1d4faac..c3dd7bc 100644 --- a/axum-middleware-example/src/model/db.rs +++ b/axum-middleware-example/src/model/db.rs @@ -22,4 +22,4 @@ pub fn migrate_and_config_db(url: &str, pool_size: u32) -> Pool { .expect("Failed to migrate."); pool -} \ No newline at end of file +} diff --git a/axum-middleware-example/src/model/mod.rs b/axum-middleware-example/src/model/mod.rs index 632ddb7..cf7d6bd 100644 --- a/axum-middleware-example/src/model/mod.rs +++ b/axum-middleware-example/src/model/mod.rs @@ -1,4 +1,4 @@ -pub mod user; pub mod db; pub mod response; -pub mod user_token; \ No newline at end of file +pub mod user; +pub mod user_token; diff --git a/axum-middleware-example/src/model/response.rs b/axum-middleware-example/src/model/response.rs index 677b441..e620bce 100644 --- a/axum-middleware-example/src/model/response.rs +++ b/axum-middleware-example/src/model/response.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct ResponseBody { @@ -19,4 +19,4 @@ impl ResponseBody { // fn into_response(self) -> Response { // Response::new(ReponseBody) // } -// } \ No newline at end of file +// } diff --git a/axum-middleware-example/src/model/user_token.rs b/axum-middleware-example/src/model/user_token.rs index df4199f..5c2082a 100644 --- a/axum-middleware-example/src/model/user_token.rs +++ b/axum-middleware-example/src/model/user_token.rs @@ -2,7 +2,7 @@ use crate::model::user::LoginInfo; use chrono::Utc; use jsonwebtoken::{EncodingKey, Header}; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; static THREE_HOUR: i64 = 60 * 60 * 3; pub static KEY: [u8; 16] = *include_bytes!("../secret.key"); @@ -16,18 +16,18 @@ pub struct UserToken { // userID pub user_name: String, pub role: String, - pub login_session: String + pub login_session: String, } impl UserToken { - pub fn generate_token(login: LoginInfo) -> String{ + pub fn generate_token(login: LoginInfo) -> String { let now = Utc::now().timestamp_nanos() / 1_000_000_000; let payload = UserToken { iat: now, exp: now + THREE_HOUR, user_name: login.username, role: login.role, - login_session:login.login_session + login_session: login.login_session, }; jsonwebtoken::encode( @@ -36,5 +36,5 @@ impl UserToken { &EncodingKey::from_secret(&KEY), ) .unwrap() - } + } } diff --git a/axum-middleware-example/src/service/mod.rs b/axum-middleware-example/src/service/mod.rs index 018ff2e..22d12a3 100644 --- a/axum-middleware-example/src/service/mod.rs +++ b/axum-middleware-example/src/service/mod.rs @@ -1 +1 @@ -pub mod user; \ No newline at end of file +pub mod user; diff --git a/axum-middleware-example/src/utils/bcrypt.rs b/axum-middleware-example/src/utils/bcrypt.rs index 41f0470..522e2ca 100644 --- a/axum-middleware-example/src/utils/bcrypt.rs +++ b/axum-middleware-example/src/utils/bcrypt.rs @@ -17,7 +17,7 @@ pub fn hash_password(plain: &str) -> Result { }) } // VERIFY PASSWORD -pub fn compare_password(plain: &str, hash: &str) -> Result{ +pub fn compare_password(plain: &str, hash: &str) -> Result { verify(plain, hash).map_err(|_| { ServiceError::new( StatusCode::INTERNAL_SERVER_ERROR, @@ -25,7 +25,3 @@ pub fn compare_password(plain: &str, hash: &str) -> Result{ ) }) } - - - - diff --git a/axum-middleware-example/src/utils/mod.rs b/axum-middleware-example/src/utils/mod.rs index 52a7fea..df912ee 100644 --- a/axum-middleware-example/src/utils/mod.rs +++ b/axum-middleware-example/src/utils/mod.rs @@ -1,3 +1,3 @@ pub mod bcrypt; +pub mod csv_utils; pub mod token_utils; -pub mod csv_utils; \ No newline at end of file diff --git a/axum-middleware-example/src/utils/token_utils.rs b/axum-middleware-example/src/utils/token_utils.rs index afee6c8..a487425 100644 --- a/axum-middleware-example/src/utils/token_utils.rs +++ b/axum-middleware-example/src/utils/token_utils.rs @@ -1,9 +1,7 @@ -use crate::{ - model::{ - user::User, - user_token::{UserToken, KEY}, - db::Pool - }, +use crate::model::{ + db::Pool, + user::User, + user_token::{UserToken, KEY}, }; use axum::extract::Extension; use jsonwebtoken::{DecodingKey, TokenData, Validation}; @@ -20,10 +18,13 @@ pub fn decode_token( } // VALIDATE TOKEN -pub fn validate_token(token_data: &TokenData, Extension(pool): &Extension) -> Result { +pub fn validate_token( + token_data: &TokenData, + Extension(pool): &Extension, +) -> Result { if User::is_valid_login_session(&token_data.claims, &pool.get().unwrap()) { Ok(token_data.claims.user_name.to_string()) } else { Err("Invalid token".to_string()) } -} \ No newline at end of file +} diff --git a/poem-todo/src/main.rs b/poem-todo/src/main.rs index f24ab9e..9ca7a07 100644 --- a/poem-todo/src/main.rs +++ b/poem-todo/src/main.rs @@ -24,7 +24,7 @@ mod schema; fn establish_connection() -> PgConnection { let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); PgConnection::establish(&database_url) - .expect(&format!("Error connecting to {}", database_url)) + .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) } #[tokio::main] diff --git a/poem-todo/src/models.rs b/poem-todo/src/models.rs index a32f1b2..8678146 100644 --- a/poem-todo/src/models.rs +++ b/poem-todo/src/models.rs @@ -66,8 +66,9 @@ impl Todo { .values(&new_todo) .returning(todos::id) .execute(conn); - if todo_id.is_err() { - return Err(todo_id.unwrap_err()); + + if let Err(err) = todo_id { + return Err(err); } todos::table .find(todo_id.unwrap() as i32) From 90c6c75d6f60f823412ea500e1df28c67545f019 Mon Sep 17 00:00:00 2001 From: macbook air Date: Mon, 8 Aug 2022 16:22:55 +0530 Subject: [PATCH 18/18] normalize::TrailingSlash->TrailingSlash --- .github/workflows/check.yml | 8 +------- actix-middleware-example/src/main.rs | 2 +- axum-middleware-example/Cargo.toml | 1 + .../src/{secret.key.sample => secret.key} | 0 4 files changed, 3 insertions(+), 8 deletions(-) rename axum-middleware-example/src/{secret.key.sample => secret.key} (100%) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index b8b6a29..add86d2 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -65,17 +65,11 @@ jobs: - name: "Checkout Repository" uses: actions/checkout@v1 - - name: Generate test secret key_actix + - name: Generate test secret key shell: sh run: | mv src/secret.key.sample src/secret.key working-directory: actix-middleware-example - - - name: Generate test secret key_axum - shell: sh - run: | - mv src/secret.key.sample src/secret.key - working-directory: axum-middleware-example - name: "Use the latest Rust stable with clippy" uses: actions-rs/toolchain@v1 diff --git a/actix-middleware-example/src/main.rs b/actix-middleware-example/src/main.rs index 43d492e..59ac76a 100644 --- a/actix-middleware-example/src/main.rs +++ b/actix-middleware-example/src/main.rs @@ -19,9 +19,9 @@ use actix_casbin::casbin::{ use actix_casbin::CasbinActor; use actix_casbin_auth::CasbinService; use actix_cors::Cors; -use actix_web::middleware::normalize::TrailingSlash; use actix_web::middleware::Logger; use actix_web::middleware::NormalizePath; +use actix_web::middleware::TrailingSlash; use actix_web::{App, HttpServer}; use diesel_adapter::DieselAdapter; use std::env; diff --git a/axum-middleware-example/Cargo.toml b/axum-middleware-example/Cargo.toml index 3ae9713..9eaeb56 100644 --- a/axum-middleware-example/Cargo.toml +++ b/axum-middleware-example/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "axum-middleware-example" version = "0.1.0" +authors = ["SiddheshKanawade "] edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/axum-middleware-example/src/secret.key.sample b/axum-middleware-example/src/secret.key similarity index 100% rename from axum-middleware-example/src/secret.key.sample rename to axum-middleware-example/src/secret.key