refactor: streamline environment variable loading and improve logging

This commit is contained in:
MythEclipse
2025-07-31 15:07:18 +07:00
parent ee9d23e01b
commit 148cf3a5cd
19 changed files with 253 additions and 173 deletions
+1
View File
@@ -1,4 +1,5 @@
RUST_ENV=development RUST_ENV=development
RUST_LOG=debug
PORT=4099 PORT=4099
SURREALDB_URL=ws://localhost:8000/rpc SURREALDB_URL=ws://localhost:8000/rpc
SURREALDB_USERNAME=root SURREALDB_USERNAME=root
Generated
+1
View File
@@ -2124,6 +2124,7 @@ dependencies = [
"jsonwebtoken", "jsonwebtoken",
"lettre", "lettre",
"log", "log",
"once_cell",
"serde", "serde",
"surrealdb", "surrealdb",
"tokio", "tokio",
+5 -6
View File
@@ -1,21 +1,20 @@
use imphnen_cms::v1::landing::events::events_schema::EventsSchema; use imphnen_cms::v1::landing::events::events_schema::EventsSchema;
use imphnen_libs::enviroment::load_env; use imphnen_utils::{get_iso_date};
use imphnen_utils::{get_iso_date, Env};
use std::error::Error; use std::error::Error;
use surrealdb::engine::any; use surrealdb::engine::any;
use surrealdb::{opt::auth::Root, sql::Thing, Uuid}; // Added Uuid use surrealdb::{opt::auth::Root, sql::Thing, Uuid}; // Added Uuid
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
username: &env.surrealdb_username, username: &env.surrealdb_username,
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
let events = vec![ let events = vec![
+4 -7
View File
@@ -1,14 +1,11 @@
use imphnen_libs::enviroment::load_env; use imphnen_utils::{get_iso_date};
use imphnen_utils::{get_iso_date, Env};
use std::error::Error; use std::error::Error;
use surrealdb::opt::auth::Root; use surrealdb::opt::auth::Root;
use surrealdb::sql::Thing; use surrealdb::sql::Thing;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
use surrealdb::engine::any; use surrealdb::engine::any;
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
@@ -16,8 +13,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
db.query("DELETE type::thing('app_gacha_items', $id)") db.query("DELETE type::thing('app_gacha_items', $id)")
+4 -6
View File
@@ -1,13 +1,11 @@
use imphnen_libs::enviroment::load_env; use imphnen_utils::{get_iso_date, hash_password};
use imphnen_utils::{get_iso_date, hash_password, Env};
use serde_json::json; use serde_json::json;
use std::error::Error; use std::error::Error;
use surrealdb::opt::auth::Root; use surrealdb::opt::auth::Root;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
use surrealdb::engine::any; use surrealdb::engine::any;
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
@@ -15,8 +13,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
db.query("DELETE type::thing('app_mentors', $id)") db.query("DELETE type::thing('app_mentors', $id)")
+4 -7
View File
@@ -1,6 +1,5 @@
use imphnen_iam::PermissionsEnum; use imphnen_iam::PermissionsEnum;
use imphnen_libs::enviroment::load_env; use imphnen_utils::{get_iso_date};
use imphnen_utils::{get_iso_date, Env};
use serde_json::json; use serde_json::json;
use std::error::Error; use std::error::Error;
use surrealdb::engine::any; use surrealdb::engine::any;
@@ -8,17 +7,15 @@ use surrealdb::opt::auth::Root;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
username: &env.surrealdb_username, username: &env.surrealdb_username,
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
for permission in [ for permission in [
+4 -6
View File
@@ -1,21 +1,19 @@
use imphnen_libs::enviroment::load_env; use imphnen_utils::{get_iso_date};
use imphnen_utils::{get_iso_date, Env};
use serde_json::json; use serde_json::json;
use std::error::Error; use std::error::Error;
use surrealdb::engine::any; use surrealdb::engine::any;
use surrealdb::opt::auth::Root; use surrealdb::opt::auth::Root;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
username: &env.surrealdb_username, username: &env.surrealdb_username,
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
let roles = vec![ let roles = vec![
@@ -1,21 +1,19 @@
use imphnen_iam::{get_iso_date, make_thing, Env, PermissionsEnum}; use imphnen_iam::{get_iso_date, make_thing, PermissionsEnum};
use imphnen_libs::enviroment::load_env;
use std::error::Error; use std::error::Error;
use surrealdb::engine::any; use surrealdb::engine::any;
use surrealdb::opt::auth::Root; use surrealdb::opt::auth::Root;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
username: &env.surrealdb_username, username: &env.surrealdb_username,
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
let roles_permissions = vec![ let roles_permissions = vec![
+4 -6
View File
@@ -1,13 +1,11 @@
use imphnen_iam::UsersSchema; use imphnen_iam::UsersSchema;
use imphnen_libs::enviroment::load_env; use imphnen_utils::{get_iso_date, hash_password};
use imphnen_utils::{get_iso_date, hash_password, Env};
use std::error::Error; use std::error::Error;
use surrealdb::{opt::auth::Root, sql::Thing}; use surrealdb::{opt::auth::Root, sql::Thing};
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
load_env(); let env = &imphnen_libs::enviroment::ENV;
let env = Env::new();
use surrealdb::engine::any; use surrealdb::engine::any;
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
@@ -15,8 +13,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
password: &env.surrealdb_password, password: &env.surrealdb_password,
}) })
.await?; .await?;
db.use_ns(env.surrealdb_namespace) db.use_ns(env.surrealdb_namespace.clone())
.use_db(env.surrealdb_dbname) .use_db(env.surrealdb_dbname.clone())
.await?; .await?;
let users = vec![ let users = vec![
+3 -3
View File
@@ -4,7 +4,7 @@ use super::{
AuthResendOtpRequestDto, AuthVerifyEmailRequestDto, TokenDto, AuthResendOtpRequestDto, AuthVerifyEmailRequestDto, TokenDto,
}; };
use crate::{ use crate::{
AppState, Env, ResourceEnum, ResponseSuccessDto, RolesEnum, RolesRepository, AppState, ResourceEnum, ResponseSuccessDto, RolesEnum, RolesRepository,
UsersDetailItemDto, UsersRepository, UsersSchema, common_response, UsersDetailItemDto, UsersRepository, UsersSchema, common_response,
decode_refresh_token, encode_access_token, encode_refresh_token, decode_refresh_token, encode_access_token, encode_refresh_token,
encode_reset_password_token, extract_email_token, generate_otp, get_iso_date, encode_reset_password_token, extract_email_token, generate_otp, get_iso_date,
@@ -414,8 +414,8 @@ impl AuthService {
); );
} }
}; };
let env = Env::new(); let env = &crate::enviroment::ENV;
let fe_url = env.fe_url; let fe_url = env.fe_url.clone();
let message = format!( let message = format!(
"You have requested a password reset. Please click the link below to continue: {fe_url}/auth/reset-password?token={token}" "You have requested a password reset. Please click the link below to continue: {fe_url}/auth/reset-password?token={token}"
); );
+1
View File
@@ -5,6 +5,7 @@ edition = "2024"
[dependencies] [dependencies]
imphnen-entities.workspace = true imphnen-entities.workspace = true
once_cell = "1"
log.workspace = true log.workspace = true
axum.workspace = true axum.workspace = true
tokio.workspace = true tokio.workspace = true
+3 -3
View File
@@ -1,16 +1,16 @@
use crate::{Env, load_env, surrealdb_init_mem, surrealdb_init_ws}; use crate::{surrealdb_init_mem, surrealdb_init_ws};
use axum::{Router, serve}; use axum::{Router, serve};
use imphnen_entities::{SurrealMemClient, SurrealWsClient}; use imphnen_entities::{SurrealMemClient, SurrealWsClient};
use std::{future::Future, net::SocketAddr}; use std::{future::Future, net::SocketAddr};
use tokio::net::TcpListener; use tokio::net::TcpListener;
use crate::enviroment::ENV;
pub async fn axum_init<F, Fut>(router_fn: F) pub async fn axum_init<F, Fut>(router_fn: F)
where where
F: FnOnce(SurrealWsClient, SurrealMemClient) -> Fut, F: FnOnce(SurrealWsClient, SurrealMemClient) -> Fut,
Fut: Future<Output = Router>, Fut: Future<Output = Router>,
{ {
load_env(); let env = &ENV;
let env = Env::new();
let surrealdb_ws = surrealdb_init_ws().await.expect("Failed surrealdb ws"); let surrealdb_ws = surrealdb_init_ws().await.expect("Failed surrealdb ws");
+179 -75
View File
@@ -1,100 +1,204 @@
//! Environment configuration module using once_cell::sync::Lazy for one-time loading.
use std::env; use std::env;
use once_cell::sync::Lazy;
// Logging for warnings if .env is missing
use log::warn;
pub fn load_env() { /// Struct holding all environment configuration.
if dotenvy::dotenv().is_ok() {}
}
pub struct Env { pub struct Env {
pub port: u16, pub port: u16,
pub access_token_secret: String, pub access_token_secret: String,
pub refresh_token_secret: String, pub refresh_token_secret: String,
pub surrealdb_url: String, pub surrealdb_url: String,
pub surrealdb_username: String, pub surrealdb_username: String,
pub surrealdb_password: String, pub surrealdb_password: String,
pub surrealdb_namespace: String, pub surrealdb_namespace: String,
pub surrealdb_dbname: String, pub surrealdb_dbname: String,
pub surrealdb_url_ws: String, pub surrealdb_url_ws: String,
pub smtp_email: String, pub smtp_email: String,
pub smtp_password: String, pub smtp_password: String,
pub smtp_name: String, pub smtp_name: String,
pub smtp_host: String, pub smtp_host: String,
pub redisdb_url: String, pub redisdb_url: String,
pub fe_url: String, pub fe_url: String,
pub rust_env: String, pub rust_env: String,
pub minio_endpoint: String, pub minio_endpoint: String,
pub minio_bucket_name: String, pub minio_bucket_name: String,
pub minio_access_key: String, pub minio_access_key: String,
pub minio_secret_key: String, pub minio_secret_key: String,
} }
impl Env { /// Loads environment variables from .env and system, only once.
#[must_use] pub static ENV: Lazy<Env> = Lazy::new(|| {
pub fn new() -> Self { // Try to load .env file, log a warning if not found, proceed regardless.
Self { match dotenvy::dotenv() {
port: env::var("PORT") Ok(_) => {}
.unwrap_or_else(|_| "3000".to_string()) Err(dotenvy::Error::Io(ref e)) if e.kind() == std::io::ErrorKind::NotFound => {
.parse() warn!(".env file not found, falling back to system environment variables");
.unwrap_or(3000), }
Err(_) => {}
}
rust_env: env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()), Env {
port: match env::var("PORT") {
Ok(val) => val.parse().unwrap_or(3000),
Err(_) => {
warn!("Environment variable PORT not set, using default 3000.");
3000
}
},
access_token_secret: env::var("ACCESS_TOKEN_SECRET") rust_env: match env::var("RUST_ENV") {
.unwrap_or_else(|_| "default_access_secret".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable RUST_ENV not set, using default 'development'.");
"development".to_string()
}
},
refresh_token_secret: env::var("REFRESH_TOKEN_SECRET") access_token_secret: match env::var("ACCESS_TOKEN_SECRET") {
.unwrap_or_else(|_| "default_refresh_secret".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable ACCESS_TOKEN_SECRET not set, using default.");
"default_access_secret".to_string()
}
},
surrealdb_url: env::var("SURREALDB_URL") refresh_token_secret: match env::var("REFRESH_TOKEN_SECRET") {
.unwrap_or_else(|_| "http://localhost:8000".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable REFRESH_TOKEN_SECRET not set, using default.");
"default_refresh_secret".to_string()
}
},
surrealdb_username: env::var("SURREALDB_USERNAME") surrealdb_url: match env::var("SURREALDB_URL") {
.unwrap_or_else(|_| "root".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SURREALDB_URL not set, using default 'http://localhost:8000'.");
"http://localhost:8000".to_string()
}
},
surrealdb_password: env::var("SURREALDB_PASSWORD") surrealdb_username: match env::var("SURREALDB_USERNAME") {
.unwrap_or_else(|_| "password".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SURREALDB_USERNAME not set, using default 'root'.");
"root".to_string()
}
},
surrealdb_namespace: env::var("SURREALDB_NAMESPACE") surrealdb_password: match env::var("SURREALDB_PASSWORD") {
.unwrap_or_else(|_| "namespace".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SURREALDB_PASSWORD not set, using default 'password'.");
"password".to_string()
}
},
surrealdb_dbname: env::var("SURREALDB_DBNAME") surrealdb_namespace: match env::var("SURREALDB_NAMESPACE") {
.unwrap_or_else(|_| "database".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SURREALDB_NAMESPACE not set, using default 'namespace'.");
"namespace".to_string()
}
},
surrealdb_url_ws: env::var("SURREALDB_URL_WS") surrealdb_dbname: match env::var("SURREALDB_DBNAME") {
.unwrap_or_else(|_| "ws://localhost:8000/rpc".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SURREALDB_DBNAME not set, using default 'database'.");
"database".to_string()
}
},
smtp_email: env::var("SMTP_EMAIL") surrealdb_url_ws: match env::var("SURREALDB_URL_WS") {
.unwrap_or_else(|_| "no-reply@example.com".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SURREALDB_URL_WS not set, using default 'ws://localhost:8000/rpc'.");
"ws://localhost:8000/rpc".to_string()
}
},
smtp_password: env::var("SMTP_PASSWORD") smtp_email: match env::var("SMTP_EMAIL") {
.unwrap_or_else(|_| "default_smtp_password".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SMTP_EMAIL not set, using default 'no-reply@example.com'.");
"no-reply@example.com".to_string()
}
},
smtp_name: env::var("SMTP_NAME").unwrap_or_else(|_| "MyApp SMTP".to_string()), smtp_password: match env::var("SMTP_PASSWORD") {
Ok(val) => val,
Err(_) => {
warn!("Environment variable SMTP_PASSWORD not set, using default.");
"default_smtp_password".to_string()
}
},
smtp_host: env::var("SMTP_HOST") smtp_name: match env::var("SMTP_NAME") {
.unwrap_or_else(|_| "smtp.gmail.com".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SMTP_NAME not set, using default 'MyApp SMTP'.");
"MyApp SMTP".to_string()
}
},
redisdb_url: env::var("REDISDB_URL") smtp_host: match env::var("SMTP_HOST") {
.unwrap_or_else(|_| "localhost".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable SMTP_HOST not set, using default 'smtp.gmail.com'.");
"smtp.gmail.com".to_string()
}
},
fe_url: env::var("FE_URL").unwrap_or_else(|_| "http://localhost".to_string()), redisdb_url: match env::var("REDISDB_URL") {
Ok(val) => val,
Err(_) => {
warn!("Environment variable REDISDB_URL not set, using default 'localhost'.");
"localhost".to_string()
}
},
minio_endpoint: env::var("MINIO_ENDPOINT") fe_url: match env::var("FE_URL") {
.unwrap_or_else(|_| "http://localhost:9000".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable FE_URL not set, using default 'http://localhost'.");
"http://localhost".to_string()
}
},
minio_bucket_name: env::var("MINIO_BUCKET_NAME") minio_endpoint: match env::var("MINIO_ENDPOINT") {
.unwrap_or_else(|_| "default_bucket".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable MINIO_ENDPOINT not set, using default 'http://localhost:9000'.");
"http://localhost:9000".to_string()
}
},
minio_access_key: env::var("MINIO_ACCESS_KEY") minio_bucket_name: match env::var("MINIO_BUCKET_NAME") {
.unwrap_or_else(|_| "minio_access".to_string()), Ok(val) => val,
Err(_) => {
warn!("Environment variable MINIO_BUCKET_NAME not set, using default 'default_bucket'.");
"default_bucket".to_string()
}
},
minio_secret_key: env::var("MINIO_SECRET_KEY") minio_access_key: match env::var("MINIO_ACCESS_KEY") {
.unwrap_or_else(|_| "minio_secret".to_string()), Ok(val) => val,
} Err(_) => {
} warn!("Environment variable MINIO_ACCESS_KEY not set, using default 'minio_access'.");
} "minio_access".to_string()
}
},
impl Default for Env { minio_secret_key: match env::var("MINIO_SECRET_KEY") {
fn default() -> Self { Ok(val) => val,
Self::new() Err(_) => {
} warn!("Environment variable MINIO_SECRET_KEY not set, using default 'minio_secret'.");
} "minio_secret".to_string()
}
},
}
});
+11 -11
View File
@@ -1,4 +1,4 @@
use super::Env; use crate::enviroment::ENV;
use axum::http::StatusCode; use axum::http::StatusCode;
use chrono::{Duration, TimeDelta, Utc}; use chrono::{Duration, TimeDelta, Utc};
use jsonwebtoken::{ use jsonwebtoken::{
@@ -14,8 +14,8 @@ pub struct Claims {
} }
pub fn encode_access_token(sub: String) -> Result<String, StatusCode> { pub fn encode_access_token(sub: String) -> Result<String, StatusCode> {
let env = Env::new(); let env = &ENV;
let secret: String = env.access_token_secret; let secret: String = env.access_token_secret.clone();
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;
@@ -30,8 +30,8 @@ pub fn encode_access_token(sub: String) -> Result<String, StatusCode> {
} }
pub fn encode_reset_password_token(sub: String) -> Result<String, StatusCode> { pub fn encode_reset_password_token(sub: String) -> Result<String, StatusCode> {
let env = Env::new(); let env = &ENV;
let secret: String = env.access_token_secret; let secret: String = env.access_token_secret.clone();
let now = Utc::now(); let now = Utc::now();
let expire: TimeDelta = Duration::minutes(5); let expire: TimeDelta = Duration::minutes(5);
let exp: usize = (now + expire).timestamp() as usize; let exp: usize = (now + expire).timestamp() as usize;
@@ -48,8 +48,8 @@ pub fn encode_reset_password_token(sub: String) -> 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 env = Env::new(); let env = &ENV;
let secret: String = env.access_token_secret; let secret: String = env.access_token_secret.clone();
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()),
@@ -60,8 +60,8 @@ pub fn decode_access_token(
} }
pub fn encode_refresh_token(sub: String) -> Result<String, StatusCode> { pub fn encode_refresh_token(sub: String) -> Result<String, StatusCode> {
let env = Env::new(); let env = &ENV;
let secret: String = env.refresh_token_secret; let secret: String = env.refresh_token_secret.clone();
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;
@@ -78,8 +78,8 @@ pub fn encode_refresh_token(sub: String) -> 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 env = Env::new(); let env = &ENV;
let secret: String = env.refresh_token_secret; let secret: String = env.refresh_token_secret.clone();
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()),
+6 -6
View File
@@ -1,4 +1,4 @@
use super::Env; use crate::enviroment::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};
@@ -9,11 +9,11 @@ pub fn send_email(
subject: &str, subject: &str,
body: &str, body: &str,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let env = Env::new(); let env = &ENV;
let host = env.smtp_host; let host = env.smtp_host.clone();
let sender_email = env.smtp_email; let sender_email = env.smtp_email.clone();
let sender_name = env.smtp_name; let sender_name = env.smtp_name.clone();
let sender_password = env.smtp_password; let sender_password = env.smtp_password.clone();
let recipient_email = to; let recipient_email = to;
let email = Message::builder() let email = Message::builder()
.from(Mailbox::new( .from(Mailbox::new(
+3 -5
View File
@@ -1,6 +1,5 @@
use super::Env; use crate::enviroment::ENV;
use crate::SurrealMemClient; use crate::SurrealMemClient;
use crate::enviroment::load_env;
use surrealdb::engine::any; use surrealdb::engine::any;
use surrealdb::engine::local::Mem; use surrealdb::engine::local::Mem;
use surrealdb::opt::auth::Root; use surrealdb::opt::auth::Root;
@@ -10,8 +9,7 @@ pub mod resource;
pub use resource::*; pub use resource::*;
pub async fn surrealdb_init_ws() -> Result<Surreal<any::Any>> { pub async fn surrealdb_init_ws() -> Result<Surreal<any::Any>> {
load_env(); let env = &ENV;
let env = Env::new();
let db = any::connect(&env.surrealdb_url).await?; let db = any::connect(&env.surrealdb_url).await?;
db.signin(Root { db.signin(Root {
@@ -26,7 +24,7 @@ pub async fn surrealdb_init_ws() -> Result<Surreal<any::Any>> {
} }
pub async fn surrealdb_init_mem() -> Result<SurrealMemClient> { pub async fn surrealdb_init_mem() -> Result<SurrealMemClient> {
let env = Env::new(); let env = &ENV;
let db = Surreal::new::<Mem>(()).await?; let db = Surreal::new::<Mem>(()).await?;
db.use_ns(&env.surrealdb_namespace) db.use_ns(&env.surrealdb_namespace)
.use_db(&env.surrealdb_dbname) .use_db(&env.surrealdb_dbname)
@@ -1,9 +1,9 @@
use axum::http::{HeaderValue, Method, header}; use axum::http::{HeaderValue, Method, header};
use imphnen_libs::Env; use imphnen_libs::enviroment::ENV;
use tower_http::cors::CorsLayer; use tower_http::cors::CorsLayer;
pub fn cors_middleware() -> CorsLayer { pub fn cors_middleware() -> CorsLayer {
let env = Env::new(); let env = &ENV;
let cors_origins = match env.rust_env.as_str() { let cors_origins = match env.rust_env.as_str() {
"development" => vec!["http://localhost:3000"], "development" => vec!["http://localhost:3000"],
"production" => { "production" => {
+12 -12
View File
@@ -72,7 +72,7 @@ mod auth_login_tests {
async fn test_successful_login_with_valid_credentials() { async fn test_successful_login_with_valid_credentials() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_login_success"); let email = generate_unique_email("test_login_success");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "User", true).await; create_test_user_with_role(&state, &email, password, "User", true).await;
@@ -105,7 +105,7 @@ mod auth_login_tests {
let login_dto = AuthLoginRequestDto { let login_dto = AuthLoginRequestDto {
email: "invalid-email".to_string(), email: "invalid-email".to_string(),
password: "TestPass123!".to_string(), password: "password".to_string(),
}; };
let response = AuthService::mutation_login(login_dto, &state).await; let response = AuthService::mutation_login(login_dto, &state).await;
@@ -124,7 +124,7 @@ mod auth_login_tests {
let login_dto = AuthLoginRequestDto { let login_dto = AuthLoginRequestDto {
email: "".to_string(), email: "".to_string(),
password: "TestPass123!".to_string(), password: "password".to_string(),
}; };
let response = AuthService::mutation_login(login_dto, &state).await; let response = AuthService::mutation_login(login_dto, &state).await;
@@ -160,7 +160,7 @@ mod auth_login_tests {
async fn test_login_with_wrong_password() { async fn test_login_with_wrong_password() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_wrong_pass"); let email = generate_unique_email("test_wrong_pass");
let correct_password = "TestPass123!"; let correct_password = "password";
create_test_user_with_role(&state, &email, correct_password, "User", true).await; create_test_user_with_role(&state, &email, correct_password, "User", true).await;
@@ -186,7 +186,7 @@ mod auth_login_tests {
let login_dto = AuthLoginRequestDto { let login_dto = AuthLoginRequestDto {
email: generate_unique_email("nonexistent"), email: generate_unique_email("nonexistent"),
password: "TestPass123!".to_string(), password: "password".to_string(),
}; };
let response = AuthService::mutation_login(login_dto, &state).await; let response = AuthService::mutation_login(login_dto, &state).await;
@@ -206,7 +206,7 @@ mod auth_login_tests {
async fn test_login_with_inactive_user() { async fn test_login_with_inactive_user() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_inactive"); let email = generate_unique_email("test_inactive");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "User", false).await; create_test_user_with_role(&state, &email, password, "User", false).await;
@@ -233,7 +233,7 @@ mod auth_login_tests {
async fn test_successful_mentor_login() { async fn test_successful_mentor_login() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_mentor_login"); let email = generate_unique_email("test_mentor_login");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "Mentor", true).await; create_test_user_with_role(&state, &email, password, "Mentor", true).await;
@@ -258,7 +258,7 @@ mod auth_login_tests {
async fn test_mentor_login_with_non_mentor_user() { async fn test_mentor_login_with_non_mentor_user() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_user_not_mentor"); let email = generate_unique_email("test_user_not_mentor");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "User", true).await; create_test_user_with_role(&state, &email, password, "User", true).await;
@@ -285,7 +285,7 @@ mod auth_login_tests {
async fn test_mentor_login_with_inactive_mentor() { async fn test_mentor_login_with_inactive_mentor() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_inactive_mentor"); let email = generate_unique_email("test_inactive_mentor");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "Mentor", false).await; create_test_user_with_role(&state, &email, password, "Mentor", false).await;
@@ -312,7 +312,7 @@ mod auth_login_tests {
async fn test_login_creates_user_cache() { async fn test_login_creates_user_cache() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_cache"); let email = generate_unique_email("test_cache");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "User", true).await; create_test_user_with_role(&state, &email, password, "User", true).await;
@@ -337,7 +337,7 @@ mod auth_login_tests {
async fn test_login_with_special_characters_in_email() { async fn test_login_with_special_characters_in_email() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test+special"); let email = generate_unique_email("test+special");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "User", true).await; create_test_user_with_role(&state, &email, password, "User", true).await;
@@ -356,7 +356,7 @@ mod auth_login_tests {
async fn test_login_with_case_sensitive_email() { async fn test_login_with_case_sensitive_email() {
let state = setup_test_environment().await; let state = setup_test_environment().await;
let email = generate_unique_email("test_case"); let email = generate_unique_email("test_case");
let password = "TestPass123!"; let password = "password";
create_test_user_with_role(&state, &email, password, "User", true).await; create_test_user_with_role(&state, &email, password, "User", true).await;
+2 -12
View File
@@ -1,7 +1,7 @@
// Restore only the necessary imports to fix unresolved function errors
use crate::{get_iso_date, hash_password}; use crate::{get_iso_date, hash_password};
use imphnen_entities::AppState; use imphnen_entities::AppState;
use imphnen_iam::{PermissionsEnum, UsersSchema}; use imphnen_iam::{PermissionsEnum, UsersSchema};
use imphnen_libs::enviroment::load_env;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use surrealdb::engine::{any, local}; use surrealdb::engine::{any, local};
@@ -29,23 +29,15 @@ struct RoleSeedData {
} }
pub async fn create_mock_app_state() -> AppState { pub async fn create_mock_app_state() -> AppState {
load_env();
let db_ws = any::connect("ws://127.00.1:8000/rpc").await.unwrap(); let db_ws = any::connect("ws://127.00.1:8000/rpc").await.unwrap();
let db_mem = Surreal::new::<local::Mem>(()).await.unwrap(); let db_mem = Surreal::new::<local::Mem>(()).await.unwrap();
let unique_id = Uuid::new_v4().to_string(); let unique_id = Uuid::new_v4().to_string();
let ns = format!("test_ns_{unique_id}"); let ns = format!("test_ns_{unique_id}");
let db = format!("test_db_{unique_id}"); let db = format!("test_db_{unique_id}");
db_ws db_ws
.signin(Root { .signin(Root {
username: "root", username: "root",
@@ -54,11 +46,8 @@ pub async fn create_mock_app_state() -> AppState {
.await .await
.unwrap(); .unwrap();
db_ws.use_ns(&ns).use_db(&db).await.unwrap(); db_ws.use_ns(&ns).use_db(&db).await.unwrap();
AppState { AppState {
surrealdb_ws: db_ws, surrealdb_ws: db_ws,
surrealdb_mem: db_mem, surrealdb_mem: db_mem,
@@ -183,6 +172,7 @@ pub async fn seed_users_for_test(
} }
pub async fn setup_all_test_environment() -> AppState { pub async fn setup_all_test_environment() -> AppState {
debug!("Setting up all test environment in setup_all_test_environment()");
let app_state = create_mock_app_state().await; let app_state = create_mock_app_state().await;
app_state app_state
.surrealdb_mem .surrealdb_mem