From d39acffc42c20fbca9d49b5de1a9eca354c3503f Mon Sep 17 00:00:00 2001 From: Daelon022 Date: Sun, 10 Mar 2024 20:30:58 +0200 Subject: [PATCH] Add sign up for user --- Cargo.toml | 3 +- src/consts.rs | 5 +++ src/db/utils.rs | 77 +++++++++++++++++++++++++++++++---------- src/errors.rs | 3 ++ src/main.rs | 2 ++ src/models.rs | 27 +++++++++++++++ src/registration/mod.rs | 22 +++++++----- 7 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 src/consts.rs create mode 100644 src/models.rs diff --git a/Cargo.toml b/Cargo.toml index fe78048..9061c1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ diesel-derive-enum = { version = "2.0.0-rc.0", features = ["postgres"] } diesel-async = { version = "0.4.1", features = ["postgres", "deadpool"] } tokio = "1.36.0" thiserror = "1.0.57" -uuid = { version = "1.7.0", features = ["v4"] } +uuid = { version = "1.7.0", features = ["v4", "serde"] } chrono = "0.4.35" reqwest = { version = "0.11.25", features = ["json"] } log = "0.4.21" @@ -28,3 +28,4 @@ anyhow = "1.0.80" fern = "0.6.2" colored = "2.1.0" dotenv = "0.15.0" +jsonwebtoken = "9.2.0" diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..da43559 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,5 @@ +pub static AUDIENCE: &str = "https://someexample.com"; +pub static GRANT_TYPE_PASS: &str = "password"; +pub static CONTENT_TYPE: &str = "Content-Type"; +pub static APPLICATION_JSON: &str = "application/json"; +pub static ACCESS_TOKEN: &str = "access_token"; diff --git a/src/db/utils.rs b/src/db/utils.rs index 75f7611..73677e6 100644 --- a/src/db/utils.rs +++ b/src/db/utils.rs @@ -1,9 +1,12 @@ +use crate::consts::{ACCESS_TOKEN, APPLICATION_JSON, AUDIENCE, CONTENT_TYPE, GRANT_TYPE_PASS}; use crate::errors::{Error, Result}; +use crate::models::{ConnectToAuth0, UserData, UserFlow}; use diesel_async::pooled_connection::deadpool::Pool; use diesel_async::pooled_connection::AsyncDieselConnectionManager; use diesel_async::AsyncPgConnection; use reqwest::{Client, Method}; use serde_json::Value; +use uuid::Uuid; pub type DatabasePool = Pool; @@ -14,27 +17,65 @@ pub async fn create_connection_pool(database_url: String) -> Result Result { +pub async fn register_user(user: UserData, user_id: Uuid) -> Result<()> { let client = Client::new(); let url = dotenv::var("CLIENT").unwrap_or_else(|_| "localhost:8080".to_string()); - let client_id = dotenv::var("CLIENT_ID").unwrap_or_else(|_| "admin".to_string()); - let client_secret = dotenv::var("CLIENT_SECRET").unwrap_or_else(|_| "admin".to_string()); - let request = client + + let body = generate_body_for_auth0(user, user_id); + + client .request(Method::POST, &url) - .header("Content-Type", "application/json") - .json(&serde_json::json!({ - "client_id": client_id, - "client_secret": client_secret, - "audience":"https://someexample.com", - "grant_type":"client_credentials" - })) + .header(CONTENT_TYPE, APPLICATION_JSON) + .json(&body) .send() .await?; - let response = request.json::().await?; - log::info!("Response: {:?}", response); - let token = match response["access_token"].as_str() { - Some(token) => token, - None => return Err(Error::InvalidInput("Invalid token".to_string())), - }; - Ok(token.to_string()) + Ok(()) +} + +pub async fn get_jwt_user_token(user: UserData) -> Result { + let client = Client::new(); + let url = dotenv::var("CLIENT").unwrap_or_else(|_| "localhost:8080".to_string()); + + let body = generate_body_for_auth0(user, Uuid::new_v4()); + + let response = client + .request(Method::POST, &url) + .header(CONTENT_TYPE, APPLICATION_JSON) + .json(&body) + .send() + .await?; + + let response: Result = response.json().await.map_err(Error::from); + match response { + Ok(value) => { + log::info!("Value: {:?}", value); + let token = value[ACCESS_TOKEN].as_str().ok_or(Error::InvalidToken)?; + Ok(token.to_string()) + } + Err(e) => { + log::error!("Error: {}", e); + Err(Error::InvalidToken) + } + } +} + +fn generate_body_for_auth0(user: UserData, user_id: Uuid) -> UserFlow { + let client_id = dotenv::var("CLIENT_ID").unwrap_or_else(|_| "admin".to_string()); + let client_secret = dotenv::var("CLIENT_SECRET").unwrap_or_else(|_| "admin".to_string()); + let connection = dotenv::var("CONNECTION") + .unwrap_or_else(|_| "Username-Password-Authentication".to_string()); + + UserFlow { + connect: ConnectToAuth0 { + client_id, + client_secret, + audience: AUDIENCE.to_string(), + grant_type: GRANT_TYPE_PASS.to_string(), + user_id: user_id.to_string(), + connection, + }, + username: user.username, + password: user.password, + email: user.email, + } } diff --git a/src/errors.rs b/src/errors.rs index f379bbf..1500d18 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -38,6 +38,9 @@ pub enum Error { #[error(transparent)] ReqwestError(#[from] reqwest::Error), + + #[error("Cannot get token from Auth0")] + InvalidToken, } pub type Result = std::result::Result; diff --git a/src/main.rs b/src/main.rs index 6d03999..4749275 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ pub mod actors; +pub mod consts; pub mod db; pub mod errors; +pub mod models; pub mod registration; pub mod utils; diff --git a/src/models.rs b/src/models.rs new file mode 100644 index 0000000..776dcd3 --- /dev/null +++ b/src/models.rs @@ -0,0 +1,27 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UserData { + pub username: String, + pub password: String, + pub email: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UserFlow { + #[serde(flatten)] + pub connect: ConnectToAuth0, + pub username: String, + pub password: String, + pub email: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ConnectToAuth0 { + pub client_id: String, + pub client_secret: String, + pub audience: String, + pub grant_type: String, + pub user_id: String, + pub connection: String, +} diff --git a/src/registration/mod.rs b/src/registration/mod.rs index d5eebe6..03688fd 100644 --- a/src/registration/mod.rs +++ b/src/registration/mod.rs @@ -1,18 +1,24 @@ use crate::actors::messages::CreateUser; use crate::db::postgres_db::DbService; -use crate::db::utils::get_jwt_token; +use crate::db::utils::{get_jwt_user_token, register_user}; use crate::errors::Result; +use crate::models::UserData; use actix::Addr; -use actix_web::web::Data; +use actix_web::web::{Data, Json}; use actix_web::HttpResponse; +use uuid::Uuid; + +pub async fn register(user: Json, db: Data>) -> Result { + let user_id = Uuid::new_v4(); + register_user(user.clone(), user_id).await?; + + let token = get_jwt_user_token(user.clone()).await?; -pub async fn register(db: Data>) -> Result { - let token = get_jwt_token().await?; db.send(CreateUser { - id: Default::default(), - username: "".to_string(), - password: "".to_string(), - email: "".to_string(), + id: user_id, + username: user.username.clone(), + password: user.password.clone(), + email: user.email.clone(), }) .await??; log::info!("Getting request for register!");