Skip to content

Commit

Permalink
Refactor code, add login for getting token
Browse files Browse the repository at this point in the history
  • Loading branch information
Daelon022 committed Mar 16, 2024
1 parent d39acff commit b5ab349
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 114 deletions.
48 changes: 47 additions & 1 deletion src/actors/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::actors::messages::{
CreateUser, DeleteUser, UpdateActivateEmail, UpdateEmail, UpdatePassword, UpdateUsername,
CheckIfRegisteredUser, CheckUser, CreateUser, DeleteUser, UpdateActivateEmail, UpdateEmail,
UpdatePassword, UpdateUsername,
};
use crate::db::postgres_db::DbService;
use crate::db::tables::Users;
Expand Down Expand Up @@ -144,3 +145,48 @@ impl Handler<UpdateUsername> for DbService {
AtomicResponse::new(Box::pin(query.into_actor(&db)))
}
}

impl Handler<CheckUser> for DbService {
type Result = AtomicResponse<Self, crate::errors::Result<bool>>;

fn handle(&mut self, msg: CheckUser, _: &mut Self::Context) -> Self::Result {
let db = self.clone();
let conn = async move { db.pool.get().await };
let query = async move {
let user = crate::db::schema::users::table
.filter(crate::db::schema::users::id.eq(msg.id))
.first::<Users>(&mut conn.await?)
.await?;
Ok(user.id == msg.id)
};
log::info!("Checking user {}", msg.id);

let db = self.clone();
AtomicResponse::new(Box::pin(query.into_actor(&db)))
}
}

impl Handler<CheckIfRegisteredUser> for DbService {
type Result = AtomicResponse<Self, crate::errors::Result<bool>>;

fn handle(&mut self, msg: CheckIfRegisteredUser, _: &mut Self::Context) -> Self::Result {
let db = self.clone();
let conn = async move { db.pool.get().await };
let query = async move {
let user = crate::db::schema::users::table
.filter(crate::db::schema::users::username.eq(msg.username))
.filter(crate::db::schema::users::email.eq(msg.email))
.first::<Users>(&mut conn.await?)
.await;

match user {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
};
log::info!("Checking if user is registered");

let db = self.clone();
AtomicResponse::new(Box::pin(query.into_actor(&db)))
}
}
16 changes: 15 additions & 1 deletion src/actors/messages.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use actix::Message;
use serde::Serialize;
use uuid::Uuid;

#[derive(Message)]
#[derive(Message, Serialize, Clone)]
#[rtype(result = "crate::errors::Result<()>")]
pub(crate) struct CreateUser {
pub id: Uuid,
Expand Down Expand Up @@ -42,3 +43,16 @@ pub(crate) struct UpdateUsername {
pub user_id: Uuid,
pub username: String,
}

#[derive(Message)]
#[rtype(result = "crate::errors::Result<bool>")]
pub(crate) struct CheckUser {
pub id: Uuid,
}

#[derive(Message)]
#[rtype(result = "crate::errors::Result<bool>")]
pub(crate) struct CheckIfRegisteredUser {
pub username: String,
pub email: String,
}
70 changes: 1 addition & 69 deletions src/db/utils.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
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 crate::errors::Result;
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<AsyncPgConnection>;

Expand All @@ -16,66 +11,3 @@ pub async fn create_connection_pool(database_url: String) -> Result<DatabasePool

Ok(pool)
}

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 body = generate_body_for_auth0(user, user_id);

client
.request(Method::POST, &url)
.header(CONTENT_TYPE, APPLICATION_JSON)
.json(&body)
.send()
.await?;
Ok(())
}

pub async fn get_jwt_user_token(user: UserData) -> Result<String> {
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<Value> = 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,
}
}
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ pub enum Error {

#[error("Cannot get token from Auth0")]
InvalidToken,

#[error(transparent)]
SerdeJsonError(#[from] serde_json::Error),
}

pub type Result<T> = std::result::Result<T, Error>;
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ pub mod consts;
pub mod db;
pub mod errors;
pub mod models;
pub mod registration;
pub mod user_flow;
pub mod utils;

use crate::db::postgres_db::DbService;
use crate::errors::Result;
use crate::registration::{check_token, login, register};
use crate::user_flow::requests::{check_token, login, register};
use crate::utils::init_logging;
use actix::Actor;
use actix_web::web::Data;
Expand Down
25 changes: 20 additions & 5 deletions src/models.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserData {
Expand All @@ -8,20 +9,34 @@ pub struct UserData {
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserFlow {
#[serde(flatten)]
pub connect: ConnectToAuth0,
pub struct RegisteredUserData {
pub id: Uuid,
pub username: String,
pub password: String,
pub email: String,
pub password: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectToAuth0 {
pub struct ConnectToAuth0<T: Serialize> {
pub client_id: String,
pub client_secret: String,
pub audience: String,
pub grant_type: String,
pub user_id: String,
pub connection: String,
#[serde(flatten)]
pub extra: T,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegistrationFlow {
pub username: String,
pub password: String,
pub email: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoginFlow {
pub username: String,
pub password: String,
}
36 changes: 0 additions & 36 deletions src/registration/mod.rs

This file was deleted.

100 changes: 100 additions & 0 deletions src/user_flow/auth0.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use crate::consts::{ACCESS_TOKEN, APPLICATION_JSON, AUDIENCE, CONTENT_TYPE, GRANT_TYPE_PASS};
use crate::errors::Error;
use crate::models::{ConnectToAuth0, LoginFlow, RegisteredUserData, RegistrationFlow, UserData};
use crate::user_flow::consts::{LOGIN_URL, REGISTRATION_URL};
use actix_web::http::Method;
use reqwest::Client;
use serde_json::Value;
use uuid::Uuid;

pub async fn register_user(user: UserData, user_id: Uuid) -> crate::errors::Result<()> {
let client = Client::new();
let client_url = dotenv::var("CLIENT").unwrap_or_else(|_| "localhost:8080".to_string());

let url = format!("{}{}", client_url, REGISTRATION_URL);

let body = generate_body_for_registration(user_id, user.username, user.password, user.email);

client
.request(Method::POST, &url)
.header(CONTENT_TYPE, APPLICATION_JSON)
.json(&body)
.send()
.await?;
Ok(())
}

pub async fn get_jwt_user_token(user: RegisteredUserData) -> crate::errors::Result<String> {
let client = Client::new();
let client_url = dotenv::var("CLIENT").unwrap_or_else(|_| "localhost:8080".to_string());

let url = format!("{}{}", client_url, LOGIN_URL);

let body = generate_body_for_login(user.id, user.username, user.password).await;

let response = client
.request(Method::POST, &url)
.header(CONTENT_TYPE, APPLICATION_JSON)
.json(&body)
.send()
.await?;

let response: crate::errors::Result<Value> = response.json().await.map_err(Error::from);
match response {
Ok(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_registration(
user_id: Uuid,
username: String,
password: String,
email: String,
) -> ConnectToAuth0<RegistrationFlow> {
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());

ConnectToAuth0 {
client_id,
client_secret,
audience: AUDIENCE.to_string(),
grant_type: GRANT_TYPE_PASS.to_string(),
user_id: user_id.to_string(),
connection,
extra: RegistrationFlow {
username,
password,
email,
},
}
}

pub async fn generate_body_for_login(
user_id: Uuid,
username: String,
password: String,
) -> ConnectToAuth0<LoginFlow> {
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());

ConnectToAuth0 {
client_id,
client_secret,
audience: AUDIENCE.to_string(),
grant_type: GRANT_TYPE_PASS.to_string(),
user_id: user_id.to_string(),
connection,
extra: LoginFlow { username, password },
}
}
2 changes: 2 additions & 0 deletions src/user_flow/consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub const REGISTRATION_URL: &str = "/dbconnections/signup";
pub const LOGIN_URL: &str = "/oauth/token";
3 changes: 3 additions & 0 deletions src/user_flow/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod auth0;
pub mod consts;
pub mod requests;
Loading

0 comments on commit b5ab349

Please sign in to comment.