feat: auth
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@ utoipa = { version = "5.3.1", features = ["axum_extras"] }
|
|||||||
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
|
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
|
||||||
redis = "0.28.2"
|
redis = "0.28.2"
|
||||||
lettre = { version = "0.11.12", features = ["tokio1-native-tls"] }
|
lettre = { version = "0.11.12", features = ["tokio1-native-tls"] }
|
||||||
surrealdb = "2.2.1"
|
surrealdb = { version = "2.2.1", features = ["protocol-http"] }
|
||||||
thiserror = "2.0.11"
|
thiserror = "2.0.11"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ pub mod v2;
|
|||||||
|
|
||||||
pub async fn apps(surrealdb: SurrealClient, redisdb: RedisClient) -> Router {
|
pub async fn apps(surrealdb: SurrealClient, redisdb: RedisClient) -> Router {
|
||||||
let state = AppState { surrealdb, redisdb };
|
let state = AppState { surrealdb, redisdb };
|
||||||
|
|
||||||
Router::new()
|
Router::new()
|
||||||
.nest("/v1", v1::routes().await)
|
.nest("/v1", v1::routes().await)
|
||||||
.nest("/v2", v2::routes().await)
|
.nest("/v2", v2::routes().await)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use axum::{response::IntoResponse, Extension, Json};
|
use super::{
|
||||||
|
mutation_login, mutation_register, AuthLoginRequestDto, AuthRegisterRequestDto,
|
||||||
use super::{mutation_login, AuthLoginRequestDto};
|
};
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
use axum::{response::IntoResponse, Extension, Json};
|
||||||
|
|
||||||
pub async fn post_login(
|
pub async fn post_login(
|
||||||
Extension(state): Extension<AppState>,
|
Extension(state): Extension<AppState>,
|
||||||
@@ -9,3 +10,10 @@ pub async fn post_login(
|
|||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
mutation_login(payload, &state).await
|
mutation_login(payload, &state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn post_register(
|
||||||
|
Extension(state): Extension<AppState>,
|
||||||
|
Json(payload): Json<AuthRegisterRequestDto>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
mutation_register(payload, &state).await
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ pub struct AuthLoginRequestDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||||
pub struct AuthRegisterRequestDto {
|
pub struct AuthLoginResponsetDto {
|
||||||
pub email: String,
|
pub token: TokenDto,
|
||||||
pub password: String,
|
}
|
||||||
pub fullname: String,
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||||
|
pub struct TokenDto {
|
||||||
|
pub access_token: String,
|
||||||
|
pub refresh_token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||||
|
|||||||
@@ -1,107 +1,32 @@
|
|||||||
use super::{auth_dto::AuthLoginRequestDto, AuthRegisterRequestDto};
|
use crate::{v1::UsersItemDto, AppState};
|
||||||
use crate::{
|
use std::error::Error;
|
||||||
common_response, hash_password, success_response, v1::UsersItemDto, AppState,
|
|
||||||
ResponseSuccessDto,
|
|
||||||
};
|
|
||||||
use axum::{http::StatusCode, response::Response};
|
|
||||||
use serde_json;
|
|
||||||
|
|
||||||
const USERS_KEY: &str = "users";
|
use super::AuthRegisterRequestDto;
|
||||||
|
|
||||||
pub async fn mutation_login(
|
pub async fn query_user_by_email(
|
||||||
params: AuthLoginRequestDto,
|
email: String,
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
) -> Response {
|
) -> Result<UsersItemDto, Box<dyn Error>> {
|
||||||
let user: Option<AuthLoginRequestDto> = match state
|
let db = &state.surrealdb;
|
||||||
.surrealdb
|
|
||||||
.select((USERS_KEY, params.email.as_str()))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(user) => user,
|
|
||||||
Err(err) => {
|
|
||||||
return common_response(
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
&err.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut redis_conn = match state.redisdb.get_connection() {
|
let mut result = db
|
||||||
Ok(conn) => conn,
|
.query("SELECT * FROM app_users WHERE email = $email LIMIT 1;")
|
||||||
Err(err) => {
|
.bind(("email", email.clone()))
|
||||||
return common_response(
|
.await?;
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
&err.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let user_json = match serde_json::to_string(&user) {
|
let user: Option<UsersItemDto> = result.take(0)?;
|
||||||
Ok(json) => json,
|
|
||||||
Err(err) => {
|
|
||||||
return common_response(
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
&err.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(err) = redis::cmd("SET")
|
user.ok_or_else(|| format!("User not found for email: {}", email).into())
|
||||||
.arg("users_data")
|
|
||||||
.arg(user_json)
|
|
||||||
.query::<()>(&mut redis_conn)
|
|
||||||
{
|
|
||||||
return common_response(StatusCode::INTERNAL_SERVER_ERROR, &err.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = ResponseSuccessDto { data: params };
|
|
||||||
|
|
||||||
success_response(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mutation_register(
|
pub async fn query_create_user(
|
||||||
params: AuthRegisterRequestDto,
|
data: AuthRegisterRequestDto,
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
) -> Response {
|
) -> Result<String, Box<dyn Error>> {
|
||||||
let user_key = format!("{}:{}", USERS_KEY, params.email);
|
let db = &state.surrealdb;
|
||||||
|
|
||||||
let existing_user: Option<UsersItemDto> =
|
let _record: Option<UsersItemDto> =
|
||||||
match state.surrealdb.select(&user_key).await {
|
db.create(("app_users", &data.email)).content(data).await?;
|
||||||
Ok(user) => user,
|
|
||||||
Err(err) => {
|
|
||||||
return common_response(
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
&err.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if existing_user.is_some() {
|
Ok("Success create user".into())
|
||||||
return common_response(StatusCode::CONFLICT, "User already exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
let hashed_password = hash_password(¶ms.password);
|
|
||||||
|
|
||||||
let created_user: AuthLoginRequestDto =
|
|
||||||
match state.surrealdb.create(&user_key, ¶ms).await {
|
|
||||||
Ok(user) => Some(user),
|
|
||||||
Err(err) => {
|
|
||||||
return common_response(
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
&err.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let user_json = match serde_json::to_string(&created_user) {
|
|
||||||
Ok(json) => json,
|
|
||||||
Err(err) => {
|
|
||||||
return common_response(
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
&err.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
common_response(StatusCode::CREATED, "Success Register User")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
use axum::{http::StatusCode, response::Response};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
query_create_user, query_user_by_email, AuthLoginRequestDto,
|
||||||
|
AuthRegisterRequestDto,
|
||||||
|
};
|
||||||
|
use crate::{common_response, hash_password, verify_password, AppState};
|
||||||
|
|
||||||
|
pub async fn mutation_login(
|
||||||
|
payload: AuthLoginRequestDto,
|
||||||
|
state: &AppState,
|
||||||
|
) -> Response {
|
||||||
|
match query_user_by_email(payload.email, state).await {
|
||||||
|
Ok(user) => {
|
||||||
|
let is_password_correct =
|
||||||
|
verify_password(&payload.password, &user.password).unwrap_or(false);
|
||||||
|
|
||||||
|
if is_password_correct {
|
||||||
|
common_response(
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"Email or password not correct",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
common_response(StatusCode::OK, "Success Login")
|
||||||
|
}
|
||||||
|
Err(err) => common_response(StatusCode::UNAUTHORIZED, &err.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn mutation_register(
|
||||||
|
payload: AuthRegisterRequestDto,
|
||||||
|
state: &AppState,
|
||||||
|
) -> Response {
|
||||||
|
if query_user_by_email(payload.email.clone(), state)
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
return common_response(StatusCode::BAD_REQUEST, "User already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
let hashed_password = match hash_password(&payload.password) {
|
||||||
|
Ok(hash) => hash,
|
||||||
|
Err(_) => {
|
||||||
|
return common_response(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"Failed to hash password",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_user = AuthRegisterRequestDto {
|
||||||
|
email: payload.email,
|
||||||
|
password: hashed_password,
|
||||||
|
fullname: payload.fullname,
|
||||||
|
};
|
||||||
|
|
||||||
|
match query_create_user(new_user, state).await {
|
||||||
|
Ok(_) => common_response(StatusCode::CREATED, "Registration successful"),
|
||||||
|
Err(err) => {
|
||||||
|
common_response(StatusCode::INTERNAL_SERVER_ERROR, &err.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,14 @@ pub mod auth_controller;
|
|||||||
pub mod auth_dto;
|
pub mod auth_dto;
|
||||||
pub mod auth_middleware;
|
pub mod auth_middleware;
|
||||||
pub mod auth_repository;
|
pub mod auth_repository;
|
||||||
|
pub mod auth_service;
|
||||||
|
|
||||||
pub use auth_dto::*;
|
pub use auth_dto::*;
|
||||||
pub use auth_repository::*;
|
pub use auth_repository::*;
|
||||||
|
pub use auth_service::*;
|
||||||
|
|
||||||
pub fn auth_router() -> Router {
|
pub fn auth_router() -> Router {
|
||||||
Router::new().route("/login", post(auth_controller::post_login))
|
Router::new()
|
||||||
|
.route("/login", post(auth_controller::post_login))
|
||||||
|
.route("/register", post(auth_controller::post_register))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ use utoipa::ToSchema;
|
|||||||
pub struct UsersItemDto {
|
pub struct UsersItemDto {
|
||||||
pub email: String,
|
pub email: String,
|
||||||
pub fullname: String,
|
pub fullname: String,
|
||||||
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use surrealdb::{engine::remote::ws::Client, Surreal};
|
use surrealdb::{engine::remote::http::Client, Surreal};
|
||||||
use utoipa::{IntoParams, ToSchema};
|
use utoipa::{IntoParams, ToSchema};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||||
|
|||||||
+6
-15
@@ -1,31 +1,22 @@
|
|||||||
|
use crate::{redisdb_init, Env, RedisClient};
|
||||||
|
use crate::{surrealdb_init, SurrealClient};
|
||||||
use axum::{serve, Router};
|
use axum::{serve, Router};
|
||||||
use std::env;
|
|
||||||
use std::{future::Future, net::SocketAddr};
|
use std::{future::Future, net::SocketAddr};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
use crate::{redisdb_init, RedisClient};
|
|
||||||
use crate::{surrealdb_init, SurrealClient};
|
|
||||||
|
|
||||||
pub async fn axum_init<F, Fut>(router_fn: F)
|
pub async fn axum_init<F, Fut>(router_fn: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(SurrealClient, RedisClient) -> Fut,
|
F: FnOnce(SurrealClient, RedisClient) -> Fut,
|
||||||
Fut: Future<Output = Router>,
|
Fut: Future<Output = Router>,
|
||||||
{
|
{
|
||||||
|
let env = Env::new();
|
||||||
let surrealdb = surrealdb_init().await.expect("Failed surrealdb");
|
let surrealdb = surrealdb_init().await.expect("Failed surrealdb");
|
||||||
let redisdb = redisdb_init().await.expect("Failed redisdb");
|
let redisdb = redisdb_init().await.expect("Failed redisdb");
|
||||||
let router = router_fn(surrealdb, redisdb).await;
|
let router = router_fn(surrealdb, redisdb).await;
|
||||||
|
let port = env.port;
|
||||||
let addr = SocketAddr::from((
|
let addr = SocketAddr::from(([0, 0, 0, 0], port));
|
||||||
[0, 0, 0, 0],
|
|
||||||
env::var("PORT")
|
|
||||||
.unwrap_or_else(|_| "3000".to_string())
|
|
||||||
.parse()
|
|
||||||
.unwrap(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let listener = TcpListener::bind(&addr).await.unwrap();
|
let listener = TcpListener::bind(&addr).await.unwrap();
|
||||||
println!("Listening on http://{}", addr);
|
println!("Listening on http://{}", addr);
|
||||||
|
|
||||||
match serve(listener, router).await {
|
match serve(listener, router).await {
|
||||||
Ok(_) => println!("Server stopped gracefully."),
|
Ok(_) => println!("Server stopped gracefully."),
|
||||||
Err(err) => println!("Server encountered an error: {}", err),
|
Err(err) => println!("Server encountered an error: {}", err),
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
pub struct Env {
|
||||||
|
pub port: u16,
|
||||||
|
pub access_token_secret: String,
|
||||||
|
pub refresh_token_secret: String,
|
||||||
|
pub database_url: String,
|
||||||
|
pub database_schema: String,
|
||||||
|
pub smtp_email: String,
|
||||||
|
pub smtp_password: String,
|
||||||
|
pub smtp_name: String,
|
||||||
|
pub smpt_host: String,
|
||||||
|
pub redis_hostname: String,
|
||||||
|
pub fe_url: String,
|
||||||
|
pub rust_env: String,
|
||||||
|
pub minio_endpoint: String,
|
||||||
|
pub minio_bucket_name: String,
|
||||||
|
pub minio_access_key: String,
|
||||||
|
pub minio_secret_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Env {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
port: env::var("PORT")
|
||||||
|
.unwrap_or("3000".to_string())
|
||||||
|
.parse()
|
||||||
|
.unwrap_or(3000),
|
||||||
|
access_token_secret: env::var("ACCESS_TOKEN_SECRET")
|
||||||
|
.unwrap_or("default_access_secret".to_string()),
|
||||||
|
refresh_token_secret: env::var("REFRESH_TOKEN_SECRET")
|
||||||
|
.unwrap_or("default_refresh_secret".to_string()),
|
||||||
|
database_url: env::var("DATABASE_URL")
|
||||||
|
.unwrap_or("postgres://localhost".to_string()),
|
||||||
|
database_schema: env::var("DATABASE_SCHEMA")
|
||||||
|
.unwrap_or("public".to_string()),
|
||||||
|
smtp_email: env::var("SMTP_EMAIL")
|
||||||
|
.unwrap_or("no-reply@example.com".to_string()),
|
||||||
|
smtp_password: env::var("SMTP_PASSWORD")
|
||||||
|
.unwrap_or("default_smtp_password".to_string()),
|
||||||
|
smtp_name: env::var("SMTP_NAME").unwrap_or("MyApp SMTP".to_string()),
|
||||||
|
smpt_host: env::var("SMPT_HOST").unwrap_or("smpt.gmail.com".to_string()),
|
||||||
|
redis_hostname: env::var("REDIS_HOSTNAME")
|
||||||
|
.unwrap_or("localhost".to_string()),
|
||||||
|
fe_url: env::var("FE_URL").unwrap_or("http://localhost".to_string()),
|
||||||
|
rust_env: env::var("RUST_ENV").unwrap_or("development".to_string()),
|
||||||
|
minio_endpoint: env::var("MINIO_ENDPOINT")
|
||||||
|
.unwrap_or("http://localhost:9000".to_string()),
|
||||||
|
minio_bucket_name: env::var("MINIO_BUCKET_NAME")
|
||||||
|
.unwrap_or("default_bucket".to_string()),
|
||||||
|
minio_access_key: env::var("MINIO_ACCESS_KEY")
|
||||||
|
.unwrap_or("minio_access".to_string()),
|
||||||
|
minio_secret_key: env::var("MINIO_SECRET_KEY")
|
||||||
|
.unwrap_or("minio_secret".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +1,32 @@
|
|||||||
|
use super::Env;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use chrono::{Duration, TimeDelta, Utc};
|
use chrono::{Duration, TimeDelta, Utc};
|
||||||
use jsonwebtoken::{
|
use jsonwebtoken::{
|
||||||
decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation,
|
decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::env;
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct TokenSub {
|
||||||
|
pub email: String,
|
||||||
|
pub role_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Claims {
|
pub struct Claims {
|
||||||
pub exp: usize,
|
pub exp: usize,
|
||||||
pub iat: usize,
|
pub iat: usize,
|
||||||
pub email: String,
|
pub sub: TokenSub,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_access_token(email: &str) -> Result<String, StatusCode> {
|
pub fn encode_access_token(sub: TokenSub) -> Result<String, StatusCode> {
|
||||||
let secret: String = env::var("ACCESS_TOKEN_SECRET")
|
let env = Env::new();
|
||||||
.unwrap_or("this-is-secret".to_string())
|
let secret: String = env.access_token_secret;
|
||||||
.to_string();
|
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
let expire: TimeDelta = Duration::minutes(15);
|
let expire: TimeDelta = Duration::minutes(15);
|
||||||
let exp: usize = (now + expire).timestamp() as usize;
|
let exp: usize = (now + expire).timestamp() as usize;
|
||||||
let iat: usize = now.timestamp() as usize;
|
let iat: usize = now.timestamp() as usize;
|
||||||
let claim = Claims {
|
let claim = Claims { iat, exp, sub };
|
||||||
iat,
|
|
||||||
exp,
|
|
||||||
email: email.to_string(),
|
|
||||||
};
|
|
||||||
encode(
|
encode(
|
||||||
&Header::default(),
|
&Header::default(),
|
||||||
&claim,
|
&claim,
|
||||||
@@ -37,9 +38,8 @@ pub fn encode_access_token(email: &str) -> Result<String, StatusCode> {
|
|||||||
pub fn decode_access_token(
|
pub fn decode_access_token(
|
||||||
jwt_token: &str,
|
jwt_token: &str,
|
||||||
) -> Result<TokenData<Claims>, StatusCode> {
|
) -> Result<TokenData<Claims>, StatusCode> {
|
||||||
let secret = env::var("ACCESS_TOKEN_SECRET")
|
let env = Env::new();
|
||||||
.unwrap_or("this-is-secret".to_string())
|
let secret: String = env.access_token_secret;
|
||||||
.to_string();
|
|
||||||
let result: Result<TokenData<Claims>, StatusCode> = decode(
|
let result: Result<TokenData<Claims>, StatusCode> = decode(
|
||||||
&jwt_token,
|
&jwt_token,
|
||||||
&DecodingKey::from_secret(secret.as_ref()),
|
&DecodingKey::from_secret(secret.as_ref()),
|
||||||
@@ -49,19 +49,14 @@ pub fn decode_access_token(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_refresh_token(email: &str) -> Result<String, StatusCode> {
|
pub fn encode_refresh_token(sub: TokenSub) -> Result<String, StatusCode> {
|
||||||
let secret: String = env::var("REFRESH_TOKEN_SECRET")
|
let env = Env::new();
|
||||||
.unwrap_or("this-is-secret".to_string())
|
let secret: String = env.refresh_token_secret;
|
||||||
.to_string();
|
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
let expire: TimeDelta = Duration::days(1);
|
let expire: TimeDelta = Duration::days(1);
|
||||||
let exp: usize = (now + expire).timestamp() as usize;
|
let exp: usize = (now + expire).timestamp() as usize;
|
||||||
let iat: usize = now.timestamp() as usize;
|
let iat: usize = now.timestamp() as usize;
|
||||||
let claim = Claims {
|
let claim = Claims { iat, exp, sub };
|
||||||
iat,
|
|
||||||
exp,
|
|
||||||
email: email.to_string(),
|
|
||||||
};
|
|
||||||
encode(
|
encode(
|
||||||
&Header::default(),
|
&Header::default(),
|
||||||
&claim,
|
&claim,
|
||||||
@@ -73,9 +68,8 @@ pub fn encode_refresh_token(email: &str) -> Result<String, StatusCode> {
|
|||||||
pub fn decode_refresh_token(
|
pub fn decode_refresh_token(
|
||||||
jwt_token: &str,
|
jwt_token: &str,
|
||||||
) -> Result<TokenData<Claims>, StatusCode> {
|
) -> Result<TokenData<Claims>, StatusCode> {
|
||||||
let secret = env::var("REFRESH_TOKEN_SECRET")
|
let env = Env::new();
|
||||||
.unwrap_or("this-is-secret".to_string())
|
let secret: String = env.refresh_token_secret;
|
||||||
.to_string();
|
|
||||||
let result: Result<TokenData<Claims>, StatusCode> = decode(
|
let result: Result<TokenData<Claims>, StatusCode> = decode(
|
||||||
&jwt_token,
|
&jwt_token,
|
||||||
&DecodingKey::from_secret(secret.as_ref()),
|
&DecodingKey::from_secret(secret.as_ref()),
|
||||||
|
|||||||
+9
-10
@@ -1,18 +1,20 @@
|
|||||||
|
use super::Env;
|
||||||
use lettre::message::Mailbox;
|
use lettre::message::Mailbox;
|
||||||
use lettre::transport::smtp::authentication::Credentials;
|
use lettre::transport::smtp::authentication::Credentials;
|
||||||
use lettre::{Message, SmtpTransport, Transport};
|
use lettre::{Message, SmtpTransport, Transport};
|
||||||
use std::env;
|
use std::error::Error;
|
||||||
|
|
||||||
pub fn send_email(
|
pub fn send_email(
|
||||||
to: &str,
|
to: &str,
|
||||||
subject: &str,
|
subject: &str,
|
||||||
body: &str,
|
body: &str,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
let sender_email = env::var("SMTP_EMAIL")?.to_string();
|
let env = Env::new();
|
||||||
let sender_name = env::var("SMTP_NAME")?.to_string();
|
let host = env.smpt_host;
|
||||||
let sender_password = env::var("SMTP_PASSWORD")?.to_string();
|
let sender_email = env.smtp_email;
|
||||||
|
let sender_name = env.smtp_name;
|
||||||
|
let sender_password = env.smtp_password;
|
||||||
let recipient_email = to;
|
let recipient_email = to;
|
||||||
|
|
||||||
let email = Message::builder()
|
let email = Message::builder()
|
||||||
.from(Mailbox::new(
|
.from(Mailbox::new(
|
||||||
Some(sender_name.replace("-", " ")),
|
Some(sender_name.replace("-", " ")),
|
||||||
@@ -21,14 +23,11 @@ pub fn send_email(
|
|||||||
.to(recipient_email.parse()?)
|
.to(recipient_email.parse()?)
|
||||||
.subject(subject)
|
.subject(subject)
|
||||||
.body(body.to_string())?;
|
.body(body.to_string())?;
|
||||||
|
|
||||||
let smtp_credentials =
|
let smtp_credentials =
|
||||||
Credentials::new(sender_email, sender_password.replace("-", " "));
|
Credentials::new(sender_email, sender_password.replace("-", " "));
|
||||||
|
let mailer = SmtpTransport::relay(&host)?
|
||||||
let mailer = SmtpTransport::relay("smtp.gmail.com")?
|
|
||||||
.credentials(smtp_credentials)
|
.credentials(smtp_credentials)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
match mailer.send(&email) {
|
match mailer.send(&email) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("Email sent successfully to {}", to);
|
println!("Email sent successfully to {}", to);
|
||||||
|
|||||||
+4
-2
@@ -1,13 +1,15 @@
|
|||||||
pub mod argon;
|
pub mod argon;
|
||||||
pub mod axum;
|
pub mod axum;
|
||||||
|
pub mod enviroment;
|
||||||
pub mod jsonwebtoken;
|
pub mod jsonwebtoken;
|
||||||
pub mod lettre;
|
pub mod lettre;
|
||||||
pub mod redis;
|
pub mod redisdb;
|
||||||
pub mod surrealdb;
|
pub mod surrealdb;
|
||||||
|
|
||||||
pub use argon::*;
|
pub use argon::*;
|
||||||
pub use axum::*;
|
pub use axum::*;
|
||||||
|
pub use enviroment::*;
|
||||||
pub use jsonwebtoken::*;
|
pub use jsonwebtoken::*;
|
||||||
pub use lettre::*;
|
pub use lettre::*;
|
||||||
pub use redis::*;
|
pub use redisdb::*;
|
||||||
pub use surrealdb::*;
|
pub use surrealdb::*;
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
use redis::Client;
|
|
||||||
use redis::RedisResult;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
pub async fn redisdb_init() -> RedisResult<Client> {
|
|
||||||
let host_name =
|
|
||||||
env::var("REDIS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string());
|
|
||||||
let uri_scheme = if env::var("IS_TLS").is_ok() {
|
|
||||||
"rediss"
|
|
||||||
} else {
|
|
||||||
"redis"
|
|
||||||
};
|
|
||||||
let url = format!("{}://{}", uri_scheme, host_name);
|
|
||||||
let client = Client::open(url)?;
|
|
||||||
Ok(client)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
use super::Env;
|
||||||
|
use redis::Client;
|
||||||
|
use redis::RedisResult;
|
||||||
|
|
||||||
|
pub async fn redisdb_init() -> RedisResult<Client> {
|
||||||
|
let env = Env::new();
|
||||||
|
let host_name = env.redis_hostname;
|
||||||
|
let url = format!("redis://{}", host_name);
|
||||||
|
let client = Client::open(url)?;
|
||||||
|
Ok(client)
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
use surrealdb::engine::remote::ws::{Client, Ws};
|
|
||||||
use surrealdb::{Result, Surreal};
|
|
||||||
|
|
||||||
use crate::SurrealClient;
|
use crate::SurrealClient;
|
||||||
|
use surrealdb::engine::remote::http::{Client, Http};
|
||||||
|
use surrealdb::{Result, Surreal};
|
||||||
|
|
||||||
pub async fn surrealdb_init() -> Result<SurrealClient> {
|
pub async fn surrealdb_init() -> Result<SurrealClient> {
|
||||||
let db = Surreal::<Client>::init();
|
let db = Surreal::<Client>::init();
|
||||||
db.connect::<Ws>("ws://localhost:8000").await?;
|
db.connect::<Http>("localhost:8000").await?;
|
||||||
|
db.signin(surrealdb::opt::auth::Root {
|
||||||
|
username: "root",
|
||||||
|
password: "root",
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
db.use_ns("test").use_db("test").await?;
|
db.use_ns("test").use_db("test").await?;
|
||||||
Ok(db)
|
Ok(db)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user