From 9da5a6f737b123e30dea898c5c3a34e840f06769 Mon Sep 17 00:00:00 2001 From: jenoh Date: Fri, 9 Sep 2022 16:26:29 +0200 Subject: [PATCH 1/3] add route to send email confirmation --- Cargo.lock | 1 + Cargo.toml | 2 +- migrations/.gitkeep | 0 .../down.sql | 1 + .../up.sql | 5 ++ .../down.sql | 1 + .../up.sql | 11 +++ src/main.rs | 1 + src/schema.rs | 43 ++++++++--- src/services/email.rs | 32 ++++---- src/services/response.rs | 19 +---- src/services/template.rs | 7 +- src/users/mod.rs | 16 +++- src/users/model.rs | 76 +++++++++++++++---- .../{alert.hbs => confirmation_email.hbs} | 2 +- 15 files changed, 152 insertions(+), 65 deletions(-) delete mode 100644 migrations/.gitkeep create mode 100644 migrations/2022-07-08-151204_create_email_confirmations/down.sql create mode 100644 migrations/2022-07-08-151204_create_email_confirmations/up.sql create mode 100644 migrations/2022-07-08-152149_create_users_email_confirmations/down.sql create mode 100644 migrations/2022-07-08-152149_create_users_email_confirmations/up.sql rename templates/{alert.hbs => confirmation_email.hbs} (98%) diff --git a/Cargo.lock b/Cargo.lock index c24e739..1509545 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -510,6 +510,7 @@ checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" dependencies = [ "bitflags", "byteorder", + "chrono", "diesel_derives", "pq-sys", "r2d2", diff --git a/Cargo.toml b/Cargo.toml index bdb1fb6..ded9458 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] actix-web = "4" uuid = { version = "0.8.2", features = ["serde", "v4"] } -diesel = { version = "1.4.5", features = ["postgres", "r2d2", "uuidv07"] } +diesel = { version = "1.4.5", features = ["postgres", "r2d2", "uuidv07", "chrono"] } dotenv = "0.15.0" r2d2 = "0.8.8" serde_json = "1.0.44" diff --git a/migrations/.gitkeep b/migrations/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/migrations/2022-07-08-151204_create_email_confirmations/down.sql b/migrations/2022-07-08-151204_create_email_confirmations/down.sql new file mode 100644 index 0000000..5f7b7e0 --- /dev/null +++ b/migrations/2022-07-08-151204_create_email_confirmations/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS email_confirmations CASCADE; \ No newline at end of file diff --git a/migrations/2022-07-08-151204_create_email_confirmations/up.sql b/migrations/2022-07-08-151204_create_email_confirmations/up.sql new file mode 100644 index 0000000..3f05d4a --- /dev/null +++ b/migrations/2022-07-08-151204_create_email_confirmations/up.sql @@ -0,0 +1,5 @@ +CREATE TABLE email_confirmations ( + id SERIAL PRIMARY KEY, + code INT NOT NULL, + expiration_date DATE NOT NULL +) \ No newline at end of file diff --git a/migrations/2022-07-08-152149_create_users_email_confirmations/down.sql b/migrations/2022-07-08-152149_create_users_email_confirmations/down.sql new file mode 100644 index 0000000..f9a7d49 --- /dev/null +++ b/migrations/2022-07-08-152149_create_users_email_confirmations/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS users_email_confirmations CASCADE; \ No newline at end of file diff --git a/migrations/2022-07-08-152149_create_users_email_confirmations/up.sql b/migrations/2022-07-08-152149_create_users_email_confirmations/up.sql new file mode 100644 index 0000000..b1ef367 --- /dev/null +++ b/migrations/2022-07-08-152149_create_users_email_confirmations/up.sql @@ -0,0 +1,11 @@ +CREATE TABLE users_email_confirmations ( + id SERIAL PRIMARY KEY, + id_user UUID, + id_email_confirmation INT, + CONSTRAINT fk_user + FOREIGN KEY(id_user) + REFERENCES users(id), + CONSTRAINT fk_email_confirmation + FOREIGN KEY(id_email_confirmation) + REFERENCES email_confirmations(id) +) \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cac8122..cb4d5a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,6 +57,7 @@ async fn main() -> std::io::Result<()> { .service(roles::get_roles) .service(users::register) .service(users::login) + .service(users::email_confirmation) .service(users::user_informations) }) .bind(("0.0.0.0", 8080))? diff --git a/src/schema.rs b/src/schema.rs index 5928ae3..ffee9be 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -1,4 +1,6 @@ -table! { +// @generated automatically by Diesel CLI. + +diesel::table! { agents (id) { id -> Int4, name -> Varchar, @@ -6,7 +8,15 @@ table! { } } -table! { +diesel::table! { + email_confirmations (id) { + id -> Int4, + code -> Int4, + expiration_date -> Date, + } +} + +diesel::table! { lambdas (id) { id -> Int4, aws_lambda_region -> Varchar, @@ -15,7 +25,7 @@ table! { } } -table! { +diesel::table! { metrics (id) { id -> Int4, load_average_1 -> Nullable, @@ -29,7 +39,7 @@ table! { } } -table! { +diesel::table! { monitors (id) { id -> Int4, name -> Varchar, @@ -45,14 +55,14 @@ table! { } } -table! { +diesel::table! { organizations (id) { id -> Int4, name -> Varchar, } } -table! { +diesel::table! { organizations_users (id) { id -> Int4, id_organization -> Nullable, @@ -60,14 +70,14 @@ table! { } } -table! { +diesel::table! { roles (id) { id -> Int4, name -> Varchar, } } -table! { +diesel::table! { users (id) { id -> Uuid, email -> Varchar, @@ -77,11 +87,21 @@ table! { } } -joinable!(monitors -> lambdas (id_lambda)); -joinable!(users -> roles (id_role)); +diesel::table! { + users_email_confirmations (id) { + id -> Int4, + id_user -> Nullable, + id_email_confirmation -> Nullable, + } +} + +diesel::joinable!(monitors -> lambdas (id_lambda)); +diesel::joinable!(users -> roles (id_role)); +diesel::joinable!(users_email_confirmations -> email_confirmations (id_email_confirmation)); -allow_tables_to_appear_in_same_query!( +diesel::allow_tables_to_appear_in_same_query!( agents, + email_confirmations, lambdas, metrics, monitors, @@ -89,4 +109,5 @@ allow_tables_to_appear_in_same_query!( organizations_users, roles, users, + users_email_confirmations, ); diff --git a/src/services/email.rs b/src/services/email.rs index d3d6e56..4f8595e 100644 --- a/src/services/email.rs +++ b/src/services/email.rs @@ -1,32 +1,34 @@ use super::template; use bytes::Bytes; use mail_builder::MessageBuilder; -use rusoto_ses::{Ses, SesClient}; +use rusoto_core::{Region, RusotoError}; +use rusoto_ses::{RawMessage, SendRawEmailError, SendRawEmailRequest, Ses, SesClient}; -pub async fn send_alert_email(to: String) -> bool { - println!("{}", template::alert_template()); - let sesclient = SesClient::new(rusoto_core::Region::EuWest3); +pub async fn send_confirmation_email( + to: String, + code: i16, +) -> Result<(), RusotoError> { + let sesclient = SesClient::new(Region::EuWest3); let data_email = MessageBuilder::new() - .from(("John Doe", "john@jenoh.dev")) + .from(("The squareview team", "john@jenoh.dev")) .to(to.clone()) .subject("Hello, world!") - .html_body(template::alert_template()) + .html_body(template::confirmation_email(code)) .write_to_string() .unwrap(); - let result = sesclient - .send_raw_email(rusoto_ses::SendRawEmailRequest { - raw_message: rusoto_ses::RawMessage { + match sesclient + .send_raw_email(SendRawEmailRequest { + raw_message: RawMessage { data: Bytes::from(base64::encode(data_email.to_string())), }, destinations: Some(vec![to]), source: Some("john@jenoh.dev".to_string()), - ..rusoto_ses::SendRawEmailRequest::default() + ..SendRawEmailRequest::default() }) - .await; - if result.is_err() { - eprintln!("Couldn't send email : {:?}", result); - return false; + .await + { + Ok(_) => Ok(()), + Err(e) => Err(e), } - return true; } diff --git a/src/services/response.rs b/src/services/response.rs index a1619b8..ca9e201 100644 --- a/src/services/response.rs +++ b/src/services/response.rs @@ -1,12 +1,6 @@ -use crate::users::model::{InsertableUser, User}; +use crate::users::model::User; use serde::{Deserialize, Serialize}; -// #[derive(Serialize, Deserialize, Debug, Clone)] -// pub struct RegisterResponse { -// pub already_exist: bool, -// pub user: Option, -// } - #[derive(Serialize, Deserialize, Debug, Clone)] pub struct CustomResponse { pub status: bool, @@ -24,14 +18,3 @@ pub struct UserResponse { pub status: bool, pub user: Option, } -// impl RegisterResponse { -// pub fn set_register_response( -// already_exist: bool, -// user: Option, -// ) -> RegisterResponse { -// RegisterResponse { -// already_exist: already_exist, -// user: user, -// } -// } -// } diff --git a/src/services/template.rs b/src/services/template.rs index 764ecd5..103e247 100644 --- a/src/services/template.rs +++ b/src/services/template.rs @@ -1,15 +1,16 @@ use handlebars::Handlebars; use serde_json::json; -pub fn alert_template() -> String { +pub fn confirmation_email(code: i16) -> String { let mut handlebars = Handlebars::new(); handlebars - .register_template_file("alert", "templates/alert.hbs") + .register_template_file("alert", "templates/confirmation_email.hbs") .unwrap(); let data0 = json!({ "title": "example 0", - "text": "base0" + "text": "base0", + "code": code.to_string() }); return handlebars.render("alert", &data0).unwrap(); diff --git a/src/users/mod.rs b/src/users/mod.rs index bce483f..cbd5492 100644 --- a/src/users/mod.rs +++ b/src/users/mod.rs @@ -28,7 +28,7 @@ pub async fn login(pool: web::Data, user: web::Json) -> Result, + _: AuthorizationService, +) -> Result { + let token = User::get_token_from_request(&_req); + let conn = pool.get().unwrap(); + let resp = User::email_confirmation(&token, &conn) + .await + .map_err(actix_web::error::ErrorInternalServerError)?; + Ok(HttpResponse::Ok().json(resp)) +} diff --git a/src/users/model.rs b/src/users/model.rs index c53ab49..7ae69a7 100644 --- a/src/users/model.rs +++ b/src/users/model.rs @@ -1,14 +1,17 @@ use crate::diesel::RunQueryDsl; use crate::roles::model::Role; +use crate::schema::email_confirmations; use crate::schema::users; +use crate::services::email; use crate::services::response::{CustomResponse, LoginResponse, UserResponse}; -use actix_web::{get, post, web, Error, HttpRequest, HttpResponse}; -use chrono::{DateTime, Duration, Utc}; +use actix_web::HttpRequest; +use chrono::{Duration, Utc}; use crypto::digest::Digest; use crypto::sha2::Sha256; use diesel::prelude::*; use diesel::{AsChangeset, Queryable}; use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation}; +use rand::Rng; use serde_derive::{Deserialize, Serialize}; use uuid::Uuid; @@ -33,6 +36,14 @@ pub struct InsertableUser { pub id_role: i32, } +#[derive(Serialize, Clone, Deserialize, Debug, Insertable)] +#[table_name = "email_confirmations"] +pub struct InsertableEmailConfirmations { + pub id: i32, + pub code: i32, + pub expiration_date: chrono::NaiveDate, +} + #[derive(Serialize, Deserialize, Debug)] pub struct Login { pub email: String, @@ -124,43 +135,78 @@ impl User { } } - pub fn get_user_informations( - token: &str, - conn: &PgConnection, - ) -> Result { + pub fn get_user_from_token(token: &str, conn: &PgConnection) -> Option { let key = std::env::var("SECRET_TOKEN").expect("SECRET_TOKEN"); let _decode = decode::( token, &DecodingKey::from_secret(key.as_bytes()), &Validation::new(Algorithm::HS256), ); + match _decode { Ok(decoded) => { match User::find_user_with_email( (decoded.claims.sub.to_string()).parse().unwrap(), conn, ) { - Some(user) => Ok(UserResponse { - status: true, - user: Some(user), - }), - None => Ok(UserResponse { - status: false, - user: None, - }), + Some(user) => return Some(user), + None => return None, } } - Err(_) => Ok(UserResponse { + Err(_) => return None, + } + } + + pub fn get_user_informations( + token: &str, + conn: &PgConnection, + ) -> Result { + match User::get_user_from_token(&token, &conn) { + Some(user) => Ok(UserResponse { + status: true, + user: Some(user), + }), + None => Ok(UserResponse { status: false, user: None, }), } } + pub fn hash_pw(password: String) -> String { let mut sha = Sha256::new(); sha.input_str(&password); return sha.result_str(); } + + pub async fn email_confirmation( + token: &str, + conn: &PgConnection, + ) -> Result { + match User::get_user_from_token(&token, &conn) { + Some(user) => { + // Generate code + expiration date (store bdd) + let mut rng = rand::thread_rng(); + let random: i16 = rng.gen::(); + let date = Utc::now() + Duration::minutes(30); + + // Send email with the code + email::send_confirmation_email(user.email, random) + .await + .unwrap(); + return Ok(CustomResponse { + status: true, + message: "Email send".to_owned(), + }); + } + None => { + return Ok(CustomResponse { + status: false, + message: "token expired".to_owned(), + }) + } + } + } } impl Login { diff --git a/templates/alert.hbs b/templates/confirmation_email.hbs similarity index 98% rename from templates/alert.hbs rename to templates/confirmation_email.hbs index 9dcf2c8..e399901 100644 --- a/templates/alert.hbs +++ b/templates/confirmation_email.hbs @@ -350,7 +350,7 @@

Hi there, {{title}}

-

{{text}}Sometimes you just want to send a simple HTML email with a simple design and clear call to action. This is it.

+

{{text}}{{code}}Sometimes you just want to send a simple HTML email with a simple design and clear call to action. This is it.

From 125a660594c8bde1697a8066a72a4cfd12a85b8d Mon Sep 17 00:00:00 2001 From: jenoh Date: Thu, 15 Sep 2022 16:57:08 +0200 Subject: [PATCH 2/3] Add email confirmation system & insert in database + maj migration --- .../up.sql | 2 +- src/agents/model.rs | 12 +++++----- src/metrics/mod.rs | 3 --- src/metrics/model.rs | 22 +++++++++---------- src/schema.rs | 2 +- src/services/email.rs | 2 +- src/services/template.rs | 2 +- src/users/model.rs | 19 ++++++++++++---- 8 files changed, 36 insertions(+), 28 deletions(-) diff --git a/migrations/2022-07-08-151204_create_email_confirmations/up.sql b/migrations/2022-07-08-151204_create_email_confirmations/up.sql index 3f05d4a..0557175 100644 --- a/migrations/2022-07-08-151204_create_email_confirmations/up.sql +++ b/migrations/2022-07-08-151204_create_email_confirmations/up.sql @@ -1,5 +1,5 @@ CREATE TABLE email_confirmations ( id SERIAL PRIMARY KEY, code INT NOT NULL, - expiration_date DATE NOT NULL + expiration_date TIMESTAMP NOT NULL ) \ No newline at end of file diff --git a/src/agents/model.rs b/src/agents/model.rs index b6c3b08..00083fc 100644 --- a/src/agents/model.rs +++ b/src/agents/model.rs @@ -29,12 +29,12 @@ pub struct AgentName { } impl InsertableAgent { - fn from_agent(agent: Agent) -> InsertableAgent { - InsertableAgent { - name: agent.name, - token: agent.token, - } - } + // fn from_agent(agent: Agent) -> InsertableAgent { + // InsertableAgent { + // name: agent.name, + // token: agent.token, + // } + // } } impl Agent { diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index e5f3dea..c206bc3 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -1,10 +1,8 @@ use self::model::{InsertableMetric, Metric}; -use super::services::email; use super::DbPool; use actix_web::{post, web, Error, HttpResponse}; pub mod model; -/// Inserts new user with name defined in form. #[post("/metrics")] pub async fn add_metrics( pool: web::Data, @@ -16,6 +14,5 @@ pub async fn add_metrics( }) .await? .map_err(actix_web::error::ErrorInternalServerError)?; - let bool = email::send_alert_email("service-ses@jenoh.dev".to_string()).await; Ok(HttpResponse::Created().json(metric)) } diff --git a/src/metrics/model.rs b/src/metrics/model.rs index 4bc25bd..0fa08d2 100644 --- a/src/metrics/model.rs +++ b/src/metrics/model.rs @@ -32,17 +32,17 @@ pub struct InsertableMetric { } impl InsertableMetric { - fn from_metric(metric: Metric) -> InsertableMetric { - InsertableMetric { - load_average_1: metric.load_average_1, - load_average_2: metric.load_average_2, - load_average_3: metric.load_average_3, - memory_used: metric.memory_used, - memory_total: metric.memory_total, - cpu_temp: metric.cpu_temp, - cpu_load: metric.cpu_load, - } - } + // fn from_metric(metric: Metric) -> InsertableMetric { + // InsertableMetric { + // load_average_1: metric.load_average_1, + // load_average_2: metric.load_average_2, + // load_average_3: metric.load_average_3, + // memory_used: metric.memory_used, + // memory_total: metric.memory_total, + // cpu_temp: metric.cpu_temp, + // cpu_load: metric.cpu_load, + // } + // } } impl Metric { diff --git a/src/schema.rs b/src/schema.rs index ffee9be..700c8d9 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -12,7 +12,7 @@ diesel::table! { email_confirmations (id) { id -> Int4, code -> Int4, - expiration_date -> Date, + expiration_date -> Timestamp, } } diff --git a/src/services/email.rs b/src/services/email.rs index 4f8595e..9f7402e 100644 --- a/src/services/email.rs +++ b/src/services/email.rs @@ -6,7 +6,7 @@ use rusoto_ses::{RawMessage, SendRawEmailError, SendRawEmailRequest, Ses, SesCli pub async fn send_confirmation_email( to: String, - code: i16, + code: i32, ) -> Result<(), RusotoError> { let sesclient = SesClient::new(Region::EuWest3); let data_email = MessageBuilder::new() diff --git a/src/services/template.rs b/src/services/template.rs index 103e247..5fecc22 100644 --- a/src/services/template.rs +++ b/src/services/template.rs @@ -1,7 +1,7 @@ use handlebars::Handlebars; use serde_json::json; -pub fn confirmation_email(code: i16) -> String { +pub fn confirmation_email(code: i32) -> String { let mut handlebars = Handlebars::new(); handlebars .register_template_file("alert", "templates/confirmation_email.hbs") diff --git a/src/users/model.rs b/src/users/model.rs index 7ae69a7..2b4164f 100644 --- a/src/users/model.rs +++ b/src/users/model.rs @@ -11,7 +11,7 @@ use crypto::sha2::Sha256; use diesel::prelude::*; use diesel::{AsChangeset, Queryable}; use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation}; -use rand::Rng; +use rand::{thread_rng, Rng}; use serde_derive::{Deserialize, Serialize}; use uuid::Uuid; @@ -39,9 +39,9 @@ pub struct InsertableUser { #[derive(Serialize, Clone, Deserialize, Debug, Insertable)] #[table_name = "email_confirmations"] pub struct InsertableEmailConfirmations { - pub id: i32, + // pub id: i32, pub code: i32, - pub expiration_date: chrono::NaiveDate, + pub expiration_date: chrono::NaiveDateTime, } #[derive(Serialize, Deserialize, Debug)] @@ -187,8 +187,19 @@ impl User { Some(user) => { // Generate code + expiration date (store bdd) let mut rng = rand::thread_rng(); - let random: i16 = rng.gen::(); + let random: i32 = rng.gen_range(1000000..9999999); let date = Utc::now() + Duration::minutes(30); + use crate::schema::email_confirmations::dsl::*; + + let insertable_mail_confirmation = InsertableEmailConfirmations { + code: random, + expiration_date: date.naive_local(), + }; + + // Insert into database + diesel::insert_into(email_confirmations) + .values(insertable_mail_confirmation.clone()) + .execute(conn)?; // Send email with the code email::send_confirmation_email(user.email, random) From e8026d462211ce0804b1e65ec572b526e2893760 Mon Sep 17 00:00:00 2001 From: jenoh Date: Fri, 16 Sep 2022 17:10:39 +0200 Subject: [PATCH 3/3] Add new route to verify the confirmation code --- .../up.sql | 6 ++- .../down.sql | 1 - .../up.sql | 11 ---- src/main.rs | 3 +- src/schema.rs | 11 +--- src/users/mod.rs | 18 ++++++- src/users/model.rs | 51 ++++++++++++++++++- 7 files changed, 73 insertions(+), 28 deletions(-) delete mode 100644 migrations/2022-07-08-152149_create_users_email_confirmations/down.sql delete mode 100644 migrations/2022-07-08-152149_create_users_email_confirmations/up.sql diff --git a/migrations/2022-07-08-151204_create_email_confirmations/up.sql b/migrations/2022-07-08-151204_create_email_confirmations/up.sql index 0557175..dfebc5e 100644 --- a/migrations/2022-07-08-151204_create_email_confirmations/up.sql +++ b/migrations/2022-07-08-151204_create_email_confirmations/up.sql @@ -1,5 +1,9 @@ CREATE TABLE email_confirmations ( id SERIAL PRIMARY KEY, + id_user UUID NOT NULL, code INT NOT NULL, - expiration_date TIMESTAMP NOT NULL + expiration_date TIMESTAMP NOT NULL, + CONSTRAINT fk_user + FOREIGN KEY(id_user) + REFERENCES users(id) ) \ No newline at end of file diff --git a/migrations/2022-07-08-152149_create_users_email_confirmations/down.sql b/migrations/2022-07-08-152149_create_users_email_confirmations/down.sql deleted file mode 100644 index f9a7d49..0000000 --- a/migrations/2022-07-08-152149_create_users_email_confirmations/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS users_email_confirmations CASCADE; \ No newline at end of file diff --git a/migrations/2022-07-08-152149_create_users_email_confirmations/up.sql b/migrations/2022-07-08-152149_create_users_email_confirmations/up.sql deleted file mode 100644 index b1ef367..0000000 --- a/migrations/2022-07-08-152149_create_users_email_confirmations/up.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE users_email_confirmations ( - id SERIAL PRIMARY KEY, - id_user UUID, - id_email_confirmation INT, - CONSTRAINT fk_user - FOREIGN KEY(id_user) - REFERENCES users(id), - CONSTRAINT fk_email_confirmation - FOREIGN KEY(id_email_confirmation) - REFERENCES email_confirmations(id) -) \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cb4d5a5..a7fc922 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,13 +45,11 @@ async fn main() -> std::io::Result<()> { App::new() // set up DB pool to be used with web::Data extractor .app_data(web::Data::new(pool.clone())) - // .wrap(middleware::Compress::new(ContentEncoding::Br)) .wrap(middleware::Logger::default()) .route("/", web::get().to(index)) .service(metrics::add_metrics) .service(organizations::add_organization) .service(monitors::add_monitor) - // .service(monitors::get_all_monitors_of_user) .service(agents::add_agents) .service(roles::add_role) .service(roles::get_roles) @@ -59,6 +57,7 @@ async fn main() -> std::io::Result<()> { .service(users::login) .service(users::email_confirmation) .service(users::user_informations) + .service(users::verify_email_confirmation) }) .bind(("0.0.0.0", 8080))? .run() diff --git a/src/schema.rs b/src/schema.rs index 700c8d9..b3c07ae 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -11,6 +11,7 @@ diesel::table! { diesel::table! { email_confirmations (id) { id -> Int4, + id_user -> Uuid, code -> Int4, expiration_date -> Timestamp, } @@ -87,17 +88,8 @@ diesel::table! { } } -diesel::table! { - users_email_confirmations (id) { - id -> Int4, - id_user -> Nullable, - id_email_confirmation -> Nullable, - } -} - diesel::joinable!(monitors -> lambdas (id_lambda)); diesel::joinable!(users -> roles (id_role)); -diesel::joinable!(users_email_confirmations -> email_confirmations (id_email_confirmation)); diesel::allow_tables_to_appear_in_same_query!( agents, @@ -109,5 +101,4 @@ diesel::allow_tables_to_appear_in_same_query!( organizations_users, roles, users, - users_email_confirmations, ); diff --git a/src/users/mod.rs b/src/users/mod.rs index cbd5492..d245b7e 100644 --- a/src/users/mod.rs +++ b/src/users/mod.rs @@ -48,7 +48,7 @@ pub async fn user_informations( Ok(HttpResponse::Ok().json(user)) } -#[post("/email_confirmation")] +#[get("/email_confirmation")] pub async fn email_confirmation( _req: HttpRequest, pool: web::Data, @@ -61,3 +61,19 @@ pub async fn email_confirmation( .map_err(actix_web::error::ErrorInternalServerError)?; Ok(HttpResponse::Ok().json(resp)) } + +#[post("/verify_email_confirmation")] +pub async fn verify_email_confirmation( + _req: HttpRequest, + pool: web::Data, + _: AuthorizationService, +) -> Result { + let token = User::get_token_from_request(&_req); + let resp = web::block(move || { + let conn = pool.get()?; + User::verify_email_confirmation(&token, &conn) + }) + .await? + .map_err(actix_web::error::ErrorInternalServerError)?; + Ok(HttpResponse::Ok().json(resp)) +} diff --git a/src/users/model.rs b/src/users/model.rs index 2b4164f..0d1a2ba 100644 --- a/src/users/model.rs +++ b/src/users/model.rs @@ -11,7 +11,7 @@ use crypto::sha2::Sha256; use diesel::prelude::*; use diesel::{AsChangeset, Queryable}; use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation}; -use rand::{thread_rng, Rng}; +use rand::Rng; use serde_derive::{Deserialize, Serialize}; use uuid::Uuid; @@ -39,7 +39,16 @@ pub struct InsertableUser { #[derive(Serialize, Clone, Deserialize, Debug, Insertable)] #[table_name = "email_confirmations"] pub struct InsertableEmailConfirmations { - // pub id: i32, + pub id_user: Uuid, + pub code: i32, + pub expiration_date: chrono::NaiveDateTime, +} + +#[derive(Serialize, Clone, Deserialize, Debug, Queryable, AsChangeset)] +#[table_name = "email_confirmations"] +pub struct EmailConfirmations { + pub id: i32, + pub id_user: Uuid, pub code: i32, pub expiration_date: chrono::NaiveDateTime, } @@ -192,6 +201,7 @@ impl User { use crate::schema::email_confirmations::dsl::*; let insertable_mail_confirmation = InsertableEmailConfirmations { + id_user: user.id, code: random, expiration_date: date.naive_local(), }; @@ -218,6 +228,43 @@ impl User { } } } + pub fn verify_email_confirmation( + token: &str, + conn: &PgConnection, + ) -> Result { + // return Ok(CustomResponse { + // status: false, + // message: "token expired".to_owned(), + // }); + match User::get_user_from_token(&token, &conn) { + Some(user) => { + use crate::schema::email_confirmations::dsl::*; + let email_confirmation = email_confirmations + .filter(id_user.eq(user.id)) + .select((id, id_user, code, expiration_date)) + .load::(conn) + .unwrap(); + + println!("{:?}", email_confirmation); + + // if user.len() > 0 { + // return Some(user[0].clone()); + // } else { + // return None; + // } + return Ok(CustomResponse { + status: true, + message: "Email send".to_owned(), + }); + } + None => { + return Ok(CustomResponse { + status: false, + message: "token expired".to_owned(), + }) + } + } + } } impl Login {