From a100ea52a0fad67515f63c5b5368ad8659b8ff40 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 27 Aug 2021 08:50:48 +0200 Subject: [PATCH 1/4] First draft stuff --- src/db/mod.rs | 3 +++ src/errors.rs | 44 +++++++++++++++++++++++++------------------- src/routes/admin.rs | 19 ++++++++----------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/db/mod.rs b/src/db/mod.rs index bf3b714..8979d35 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,2 +1,5 @@ pub mod tokens; pub mod users; + +pub use users::{User, NewUser}; +pub use tokens::{RefreshToken, NewRefreshToken}; diff --git a/src/errors.rs b/src/errors.rs index 7072dab..969e573 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -7,35 +7,41 @@ use rocket::{ }; #[derive(Debug)] -pub enum RBError +pub enum RbError { - /// When the login requests an unknown user - UnknownUser, - BlockedUser, - /// Invalid login password. - InvalidPassword, - /// When a non-admin user tries to use an admin endpoint - Unauthorized, - /// When an expired JWT token is used for auth. - JWTTokenExpired, - /// Umbrella error for when something goes wrong whilst creating a JWT token pair - JWTCreationError, - JWTError, - MissingJWTKey, - PWSaltError, + AuthUnknownUser, + AuthBlockedUser, + AuthInvalidPassword, + AuthUnauthorized, + AuthTokenExpired, + AuthRefreshTokenExpired, + AuthInvalidRefreshToken, + AuthDuplicateRefreshToken, + + Custom(&'static str), + AdminCreationError, - TokenExpired, - InvalidRefreshToken, - DuplicateRefreshToken, DBError, DuplicateUser, } +impl RbError { + pub fn status(&self) -> Status { + Status::NotFound + } + + pub fn message(&self) -> &'static str { + match self { + + } + } +} + impl<'r> Responder<'r, 'static> for RBError { fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> { - let (status, message): (Status, &str) = match self { + let (status, message): (Status, &'static str) = match self { RBError::UnknownUser => (Status::NotFound, "Unknown user"), RBError::BlockedUser => (Status::Unauthorized, "This user is blocked"), RBError::InvalidPassword => (Status::Unauthorized, "Invalid password"), diff --git a/src/routes/admin.rs b/src/routes/admin.rs index b3db29b..87396ca 100644 --- a/src/routes/admin.rs +++ b/src/routes/admin.rs @@ -1,8 +1,5 @@ use rb::{ - db::{ - users as db_users, - users::{NewUser, User}, - }, + db, errors::RBError, }; use rocket::serde::json::Json; @@ -12,29 +9,29 @@ use crate::{guards::Admin, RbDbConn}; pub fn routes() -> Vec { - routes![get_users, get_user_info] + routes![get_users, get_user_info, create_user] } #[get("/users")] -async fn get_users(admin: Admin, conn: RbDbConn) -> rb::Result>> +async fn get_users(admin: Admin, conn: RbDbConn) -> rb::Result>> { - Ok(Json(conn.run(|c| rb::db::users::all(c)).await?)) + Ok(Json(conn.run(|c| db::users::all(c)).await?)) } #[post("/users", data = "")] -async fn create_user(admin: Admin, conn: RbDbConn, user: Json) -> rb::Result<()> +async fn create_user(admin: Admin, conn: RbDbConn, user: Json) -> rb::Result<()> { Ok(conn - .run(move |c| db_users::create(c, &user.into_inner())) + .run(move |c| db::users::create(c, &user.into_inner())) .await?) } #[get("/users/")] -async fn get_user_info(_admin: Admin, conn: RbDbConn, user_id_str: &str) -> rb::Result> +async fn get_user_info(_admin: Admin, conn: RbDbConn, user_id_str: &str) -> rb::Result> { let user_id = Uuid::parse_str(user_id_str).map_err(|_| RBError::UnknownUser)?; - match conn.run(move |c| db_users::find(c, user_id)).await { + match conn.run(move |c| db::users::find(c, user_id)).await { Some(user) => Ok(Json(user)), None => Err(RBError::UnknownUser), } From dd51d107e3ef0d412634f9b3ce9521cff28c8c52 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 28 Aug 2021 22:06:09 +0200 Subject: [PATCH 2/4] Renamed errors; changed Responser implementation --- src/auth.rs | 36 ++++++++++--------- src/db/mod.rs | 4 +-- src/db/users.rs | 12 ++++--- src/errors.rs | 86 +++++++++++++++++++++++++++------------------ src/guards.rs | 24 ++++++++----- src/routes/admin.rs | 15 ++++---- 6 files changed, 104 insertions(+), 73 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index efd991d..cb4e4b5 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -12,7 +12,7 @@ use crate::{ tokens::{NewRefreshToken, RefreshToken}, users::{NewUser, User}, }, - errors::RBError, + errors::RbError, schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users}, }; @@ -22,16 +22,16 @@ pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> crate let user = users::users .filter(users::username.eq(username)) .first::(conn) - .map_err(|_| RBError::UnknownUser)?; + .map_err(|_| RbError::AuthUnknownUser)?; // Check if a user is blocked if user.blocked { - return Err(RBError::BlockedUser); + return Err(RbError::AuthBlockedUser); } match verify_encoded(user.password.as_str(), password.as_bytes()) { Ok(true) => Ok(user), - _ => Err(RBError::InvalidPassword), + _ => Err(RbError::AuthInvalidPassword), } } @@ -54,9 +54,9 @@ pub struct Claims pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result { - let secret = std::env::var("JWT_KEY").map_err(|_| RBError::MissingJWTKey)?; - let key: Hmac = - Hmac::new_from_slice(secret.as_bytes()).map_err(|_| RBError::JWTCreationError)?; + let secret = std::env::var("JWT_KEY").map_err(|_| RbError::Custom("Missing JWT key."))?; + let key: Hmac = Hmac::new_from_slice(secret.as_bytes()) + .map_err(|_| RbError::Custom("Couldn't create Hmac key."))?; let current_time = Utc::now(); @@ -71,7 +71,7 @@ pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result crate::Result crate::Result // Encode the actual password let config = argon2::Config::default(); - argon2::hash_encoded(password.as_bytes(), &salt, &config).map_err(|_| RBError::PWSaltError) + argon2::hash_encoded(password.as_bytes(), &salt, &config) + .map_err(|_| RbError::Custom("Couldn't hash password.")) } pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) @@ -123,21 +124,22 @@ pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) .do_update() .set(&new_user) .execute(conn) - .map_err(|_| RBError::AdminCreationError)?; + .map_err(|_| RbError::Custom("Couldn't create admin."))?; Ok(true) } pub fn refresh_token(conn: &PgConnection, refresh_token: &str) -> crate::Result { - let token_bytes = base64::decode(refresh_token).map_err(|_| RBError::InvalidRefreshToken)?; + let token_bytes = + base64::decode(refresh_token).map_err(|_| RbError::AuthInvalidRefreshToken)?; // First, we request the token from the database to see if it's really a valid token let (token_entry, user) = refresh_tokens::refresh_tokens .inner_join(users::users) .filter(refresh_tokens::token.eq(token_bytes)) .first::<(RefreshToken, User)>(conn) - .map_err(|_| RBError::InvalidRefreshToken)?; + .map_err(|_| RbError::AuthInvalidRefreshToken)?; // If we see that the token has already been used before, we block the user. if token_entry.last_used_at.is_some() { @@ -145,16 +147,16 @@ pub fn refresh_token(conn: &PgConnection, refresh_token: &str) -> crate::Result< diesel::update(target) .set(users::blocked.eq(true)) .execute(conn) - .map_err(|_| RBError::DBError)?; + .map_err(|_| RbError::Custom("Couldn't block user."))?; - return Err(RBError::DuplicateRefreshToken); + return Err(RbError::AuthDuplicateRefreshToken); } // Now we check if the token has already expired let cur_time = Utc::now().naive_utc(); if token_entry.expires_at < cur_time { - return Err(RBError::TokenExpired); + return Err(RbError::AuthTokenExpired); } // We update the last_used_at value for the refresh token @@ -162,7 +164,7 @@ pub fn refresh_token(conn: &PgConnection, refresh_token: &str) -> crate::Result< diesel::update(target) .set(refresh_tokens::last_used_at.eq(cur_time)) .execute(conn) - .map_err(|_| RBError::DBError)?; + .map_err(|_| RbError::Custom("Couldn't update last used time."))?; generate_jwt_token(conn, &user) } diff --git a/src/db/mod.rs b/src/db/mod.rs index 8979d35..9c831dd 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,5 +1,5 @@ pub mod tokens; pub mod users; -pub use users::{User, NewUser}; -pub use tokens::{RefreshToken, NewRefreshToken}; +pub use tokens::{NewRefreshToken, RefreshToken}; +pub use users::{NewUser, User}; diff --git a/src/db/users.rs b/src/db/users.rs index b005295..79d337a 100644 --- a/src/db/users.rs +++ b/src/db/users.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - errors::RBError, + errors::RbError, schema::{users, users::dsl::*}, }; @@ -30,7 +30,9 @@ pub struct NewUser pub fn all(conn: &PgConnection) -> crate::Result> { - users.load::(conn).map_err(|_| RBError::DBError) + users + .load::(conn) + .map_err(|_| RbError::DbError("Couldn't get all users.")) } pub fn find(conn: &PgConnection, user_id: Uuid) -> Option @@ -43,10 +45,10 @@ pub fn create(conn: &PgConnection, new_user: &NewUser) -> crate::Result<()> let count = diesel::insert_into(users) .values(new_user) .execute(conn) - .map_err(|_| RBError::DBError)?; + .map_err(|_| RbError::DbError("Couldn't create user."))?; if count == 0 { - return Err(RBError::DuplicateUser); + return Err(RbError::UMDuplicateUser); } Ok(()) @@ -56,7 +58,7 @@ pub fn delete(conn: &PgConnection, user_id: Uuid) -> crate::Result<()> { diesel::delete(users.filter(id.eq(user_id))) .execute(conn) - .map_err(|_| RBError::DBError)?; + .map_err(|_| RbError::DbError("Couldn't delete user."))?; Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index 969e573..886b6fe 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,9 +1,8 @@ -use std::io; - use rocket::{ http::Status, request::Request, - response::{self, Responder, Response}, + response::{self, Responder}, + serde::json::json, }; #[derive(Debug)] @@ -18,51 +17,70 @@ pub enum RbError AuthInvalidRefreshToken, AuthDuplicateRefreshToken, - Custom(&'static str), + // UM = User Management + UMDuplicateUser, + UMUnknownUser, - AdminCreationError, - DBError, - DuplicateUser, + DbError(&'static str), + Custom(&'static str), } -impl RbError { - pub fn status(&self) -> Status { - Status::NotFound +impl RbError +{ + pub fn status(&self) -> Status + { + // Every entry gets its own line for easy editing later when needed + match self { + RbError::AuthUnknownUser => Status::NotFound, + RbError::AuthBlockedUser => Status::Forbidden, + RbError::AuthInvalidPassword => Status::Unauthorized, + RbError::AuthUnauthorized => Status::Unauthorized, + RbError::AuthTokenExpired => Status::Unauthorized, + RbError::AuthRefreshTokenExpired => Status::Unauthorized, + RbError::AuthInvalidRefreshToken => Status::Unauthorized, + RbError::AuthDuplicateRefreshToken => Status::Unauthorized, + + RbError::UMDuplicateUser => Status::Conflict, + + RbError::Custom(_) => Status::InternalServerError, + _ => Status::InternalServerError, + } } - pub fn message(&self) -> &'static str { + pub fn message(&self) -> &'static str + { match self { + RbError::AuthUnknownUser => "This user doesn't exist.", + RbError::AuthBlockedUser => "This user is blocked.", + RbError::AuthInvalidPassword => "Invalid credentials.", + RbError::AuthUnauthorized => "You are not authorized to access this resource.", + RbError::AuthTokenExpired => "This token is not valid anymore.", + RbError::AuthRefreshTokenExpired => "This refresh token is not valid anymore.", + RbError::AuthInvalidRefreshToken => "This refresh token is not valid.", + RbError::AuthDuplicateRefreshToken => { + "This refresh token has already been used. The user has been blocked." + } + RbError::UMDuplicateUser => "This user already exists.", + + RbError::Custom(message) => message, + _ => "", } } } -impl<'r> Responder<'r, 'static> for RBError +impl<'r> Responder<'r, 'static> for RbError { - fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> + fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> { - let (status, message): (Status, &'static str) = match self { - RBError::UnknownUser => (Status::NotFound, "Unknown user"), - RBError::BlockedUser => (Status::Unauthorized, "This user is blocked"), - RBError::InvalidPassword => (Status::Unauthorized, "Invalid password"), - RBError::Unauthorized => (Status::Unauthorized, "Unauthorized"), - RBError::JWTTokenExpired => (Status::Unauthorized, "Token expired"), - RBError::JWTCreationError | RBError::MissingJWTKey => { - (Status::InternalServerError, "Failed to create tokens.") - } - RBError::InvalidRefreshToken | RBError::DuplicateRefreshToken => { - (Status::Unauthorized, "Invalid refresh token.") - } - RBError::DuplicateUser => (Status::Conflict, "User already exists"), - _ => (Status::InternalServerError, "Internal server error"), - }; + let status = self.status(); + let content = json!({ + "status": status.code, + "message": self.message(), + }); - let mut res = Response::new(); - res.set_status(status); - res.set_sized_body(message.len(), io::Cursor::new(message)); - - Ok(res) + content.respond_to(req) } } -pub type Result = std::result::Result; +pub type Result = std::result::Result; diff --git a/src/guards.rs b/src/guards.rs index 2994313..ae6782b 100644 --- a/src/guards.rs +++ b/src/guards.rs @@ -14,7 +14,7 @@ pub struct Bearer<'a>(&'a str); #[rocket::async_trait] impl<'r> FromRequest<'r> for Bearer<'r> { - type Error = rb::errors::RBError; + type Error = rb::errors::RbError; async fn from_request(req: &'r Request<'_>) -> Outcome { @@ -44,7 +44,7 @@ pub struct JWT(Claims); #[rocket::async_trait] impl<'r> FromRequest<'r> for JWT { - type Error = rb::errors::RBError; + type Error = rb::errors::RbError; async fn from_request(req: &'r Request<'_>) -> Outcome { @@ -54,19 +54,27 @@ impl<'r> FromRequest<'r> for JWT let secret = match std::env::var("JWT_KEY") { Ok(key) => key, Err(_) => { - return Outcome::Failure((Status::InternalServerError, Self::Error::MissingJWTKey)) + return Outcome::Failure(( + Status::InternalServerError, + Self::Error::AuthUnauthorized, + )) } }; let key: Hmac = match Hmac::new_from_slice(secret.as_bytes()) { Ok(key) => key, Err(_) => { - return Outcome::Failure((Status::InternalServerError, Self::Error::JWTError)) + return Outcome::Failure(( + Status::InternalServerError, + Self::Error::Custom("Failed to do Hmac thing."), + )) } }; // Verify token using key let claims: Claims = match bearer.verify_with_key(&key) { Ok(claims) => claims, - Err(_) => return Outcome::Failure((Status::Unauthorized, Self::Error::Unauthorized)), + Err(_) => { + return Outcome::Failure((Status::Unauthorized, Self::Error::AuthUnauthorized)) + } }; Outcome::Success(Self(claims)) @@ -79,7 +87,7 @@ pub struct User(Claims); #[rocket::async_trait] impl<'r> FromRequest<'r> for User { - type Error = rb::errors::RBError; + type Error = rb::errors::RbError; async fn from_request(req: &'r Request<'_>) -> Outcome { @@ -87,7 +95,7 @@ impl<'r> FromRequest<'r> for User // Verify key hasn't yet expired if chrono::Utc::now().timestamp() > claims.exp { - return Outcome::Failure((Status::Forbidden, Self::Error::TokenExpired)); + return Outcome::Failure((Status::Forbidden, Self::Error::AuthTokenExpired)); } Outcome::Success(Self(claims)) @@ -100,7 +108,7 @@ pub struct Admin(Claims); #[rocket::async_trait] impl<'r> FromRequest<'r> for Admin { - type Error = rb::errors::RBError; + type Error = rb::errors::RbError; async fn from_request(req: &'r Request<'_>) -> Outcome { diff --git a/src/routes/admin.rs b/src/routes/admin.rs index 87396ca..bd6f53f 100644 --- a/src/routes/admin.rs +++ b/src/routes/admin.rs @@ -1,7 +1,4 @@ -use rb::{ - db, - errors::RBError, -}; +use rb::{db, errors::RbError}; use rocket::serde::json::Json; use uuid::Uuid; @@ -27,12 +24,16 @@ async fn create_user(admin: Admin, conn: RbDbConn, user: Json) -> r } #[get("/users/")] -async fn get_user_info(_admin: Admin, conn: RbDbConn, user_id_str: &str) -> rb::Result> +async fn get_user_info( + _admin: Admin, + conn: RbDbConn, + user_id_str: &str, +) -> rb::Result> { - let user_id = Uuid::parse_str(user_id_str).map_err(|_| RBError::UnknownUser)?; + let user_id = Uuid::parse_str(user_id_str).map_err(|_| RbError::UMUnknownUser)?; match conn.run(move |c| db::users::find(c, user_id)).await { Some(user) => Ok(Json(user)), - None => Err(RBError::UnknownUser), + None => Err(RbError::UMUnknownUser), } } From 6858e9da62bdb6c22be61b0823651c8f8b80d4b5 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 29 Aug 2021 19:04:06 +0200 Subject: [PATCH 3/4] Restructured auth --- src/{auth.rs => auth/jwt.rs} | 53 --------------------------- src/auth/mod.rs | 71 ++++++++++++++++++++++++++++++++++++ src/errors.rs | 1 + src/guards.rs | 2 +- src/routes/auth.rs | 7 +++- 5 files changed, 78 insertions(+), 56 deletions(-) rename src/{auth.rs => auth/jwt.rs} (70%) create mode 100644 src/auth/mod.rs diff --git a/src/auth.rs b/src/auth/jwt.rs similarity index 70% rename from src/auth.rs rename to src/auth/jwt.rs index cb4e4b5..5c15d57 100644 --- a/src/auth.rs +++ b/src/auth/jwt.rs @@ -1,4 +1,3 @@ -use argon2::verify_encoded; use chrono::Utc; use diesel::{insert_into, prelude::*, PgConnection}; use hmac::{Hmac, NewMac}; @@ -16,25 +15,6 @@ use crate::{ schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users}, }; -pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result -{ - // TODO handle non-"NotFound" Diesel errors accordingely - let user = users::users - .filter(users::username.eq(username)) - .first::(conn) - .map_err(|_| RbError::AuthUnknownUser)?; - - // Check if a user is blocked - if user.blocked { - return Err(RbError::AuthBlockedUser); - } - - match verify_encoded(user.password.as_str(), password.as_bytes()) { - Ok(true) => Ok(user), - _ => Err(RbError::AuthInvalidPassword), - } -} - #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct JWTResponse @@ -96,39 +76,6 @@ pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result crate::Result -{ - // Generate a random salt - let mut salt = [0u8; 64]; - thread_rng().fill(&mut salt[..]); - - // Encode the actual password - let config = argon2::Config::default(); - argon2::hash_encoded(password.as_bytes(), &salt, &config) - .map_err(|_| RbError::Custom("Couldn't hash password.")) -} - -pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) - -> crate::Result -{ - let pass_hashed = hash_password(password)?; - let new_user = NewUser { - username: username.to_string(), - password: pass_hashed, - admin: true, - }; - - insert_into(users::users) - .values(&new_user) - .on_conflict(users::username) - .do_update() - .set(&new_user) - .execute(conn) - .map_err(|_| RbError::Custom("Couldn't create admin."))?; - - Ok(true) -} - pub fn refresh_token(conn: &PgConnection, refresh_token: &str) -> crate::Result { let token_bytes = diff --git a/src/auth/mod.rs b/src/auth/mod.rs new file mode 100644 index 0000000..838a080 --- /dev/null +++ b/src/auth/mod.rs @@ -0,0 +1,71 @@ +use ::jwt::SignWithKey; +use argon2::verify_encoded; +use chrono::Utc; +use diesel::{insert_into, prelude::*, PgConnection}; +use hmac::{Hmac, NewMac}; +use rand::{thread_rng, Rng}; +use serde::{Deserialize, Serialize}; +use sha2::Sha256; + +use crate::{ + db::{ + tokens::{NewRefreshToken, RefreshToken}, + users::{NewUser, User}, + }, + errors::RbError, + schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users}, +}; + +pub mod jwt; + +pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result +{ + // TODO handle non-"NotFound" Diesel errors accordingely + let user = users::users + .filter(users::username.eq(username)) + .first::(conn) + .map_err(|_| RbError::AuthUnknownUser)?; + + // Check if a user is blocked + if user.blocked { + return Err(RbError::AuthBlockedUser); + } + + match verify_encoded(user.password.as_str(), password.as_bytes()) { + Ok(true) => Ok(user), + _ => Err(RbError::AuthInvalidPassword), + } +} + +pub fn hash_password(password: &str) -> crate::Result +{ + // Generate a random salt + let mut salt = [0u8; 64]; + thread_rng().fill(&mut salt[..]); + + // Encode the actual password + let config = argon2::Config::default(); + argon2::hash_encoded(password.as_bytes(), &salt, &config) + .map_err(|_| RbError::Custom("Couldn't hash password.")) +} + +pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) + -> crate::Result +{ + let pass_hashed = hash_password(password)?; + let new_user = NewUser { + username: username.to_string(), + password: pass_hashed, + admin: true, + }; + + insert_into(users::users) + .values(&new_user) + .on_conflict(users::username) + .do_update() + .set(&new_user) + .execute(conn) + .map_err(|_| RbError::Custom("Couldn't create admin."))?; + + Ok(true) +} diff --git a/src/errors.rs b/src/errors.rs index 886b6fe..daca6bb 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -79,6 +79,7 @@ impl<'r> Responder<'r, 'static> for RbError "message": self.message(), }); + // TODO add status to response content.respond_to(req) } } diff --git a/src/guards.rs b/src/guards.rs index ae6782b..26cda21 100644 --- a/src/guards.rs +++ b/src/guards.rs @@ -1,6 +1,6 @@ use hmac::{Hmac, NewMac}; use jwt::VerifyWithKey; -use rb::auth::Claims; +use rb::auth::jwt::Claims; use rocket::{ http::Status, outcome::try_outcome, diff --git a/src/routes/auth.rs b/src/routes/auth.rs index 9551ace..955cfaa 100644 --- a/src/routes/auth.rs +++ b/src/routes/auth.rs @@ -1,4 +1,7 @@ -use rb::auth::{generate_jwt_token, verify_user, JWTResponse}; +use rb::auth::{ + jwt::{generate_jwt_token, JWTResponse}, + verify_user, +}; use rocket::serde::json::Json; use serde::Deserialize; @@ -51,7 +54,7 @@ async fn refresh_token( let refresh_token = refresh_token_request.into_inner().refresh_token; Ok(Json( - conn.run(move |c| rb::auth::refresh_token(c, &refresh_token)) + conn.run(move |c| rb::auth::jwt::refresh_token(c, &refresh_token)) .await?, )) } From 27b904b3f5b2724729b7d553b77b7e6304f715bf Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 29 Aug 2021 19:07:36 +0200 Subject: [PATCH 4/4] Pleased the linters --- src/auth/jwt.rs | 2 +- src/auth/mod.rs | 12 ++---------- src/guards.rs | 6 +++--- src/routes/admin.rs | 4 ++-- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/auth/jwt.rs b/src/auth/jwt.rs index 5c15d57..8767bb3 100644 --- a/src/auth/jwt.rs +++ b/src/auth/jwt.rs @@ -9,7 +9,7 @@ use sha2::Sha256; use crate::{ db::{ tokens::{NewRefreshToken, RefreshToken}, - users::{NewUser, User}, + users::User, }, errors::RbError, schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users}, diff --git a/src/auth/mod.rs b/src/auth/mod.rs index 838a080..b315e82 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -1,19 +1,11 @@ -use ::jwt::SignWithKey; use argon2::verify_encoded; -use chrono::Utc; use diesel::{insert_into, prelude::*, PgConnection}; -use hmac::{Hmac, NewMac}; use rand::{thread_rng, Rng}; -use serde::{Deserialize, Serialize}; -use sha2::Sha256; use crate::{ - db::{ - tokens::{NewRefreshToken, RefreshToken}, - users::{NewUser, User}, - }, + db::users::{NewUser, User}, errors::RbError, - schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users}, + schema::users::dsl as users, }; pub mod jwt; diff --git a/src/guards.rs b/src/guards.rs index 26cda21..55df193 100644 --- a/src/guards.rs +++ b/src/guards.rs @@ -39,10 +39,10 @@ impl<'r> FromRequest<'r> for Bearer<'r> } /// Verifies the provided JWT is valid. -pub struct JWT(Claims); +pub struct Jwt(Claims); #[rocket::async_trait] -impl<'r> FromRequest<'r> for JWT +impl<'r> FromRequest<'r> for Jwt { type Error = rb::errors::RbError; @@ -91,7 +91,7 @@ impl<'r> FromRequest<'r> for User async fn from_request(req: &'r Request<'_>) -> Outcome { - let claims = try_outcome!(req.guard::().await).0; + let claims = try_outcome!(req.guard::().await).0; // Verify key hasn't yet expired if chrono::Utc::now().timestamp() > claims.exp { diff --git a/src/routes/admin.rs b/src/routes/admin.rs index bd6f53f..9da75f5 100644 --- a/src/routes/admin.rs +++ b/src/routes/admin.rs @@ -10,13 +10,13 @@ pub fn routes() -> Vec } #[get("/users")] -async fn get_users(admin: Admin, conn: RbDbConn) -> rb::Result>> +async fn get_users(_admin: Admin, conn: RbDbConn) -> rb::Result>> { Ok(Json(conn.run(|c| db::users::all(c)).await?)) } #[post("/users", data = "")] -async fn create_user(admin: Admin, conn: RbDbConn, user: Json) -> rb::Result<()> +async fn create_user(_admin: Admin, conn: RbDbConn, user: Json) -> rb::Result<()> { Ok(conn .run(move |c| db::users::create(c, &user.into_inner()))