diff --git a/Cargo.lock b/Cargo.lock index d2a7754..ad094d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2165,6 +2165,7 @@ dependencies = [ "axum", "axum-test", "chrono", + "dotenvy", "imphnen-entities", "imphnen-libs", "rand 0.9.1", @@ -2174,6 +2175,7 @@ dependencies = [ "strum_macros 0.27.1", "surrealdb", "tracing", + "tracing-subscriber", "uuid", "validator", ] @@ -2338,7 +2340,7 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.8.5", "string_cache", "term", "tiny-keccak", @@ -2352,7 +2354,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata", + "regex-automata 0.4.9", ] [[package]] @@ -2518,6 +2520,15 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.8.4" @@ -3467,8 +3478,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -3479,9 +3499,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -4907,10 +4933,14 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] diff --git a/imphnen-utils/Cargo.toml b/imphnen-utils/Cargo.toml index a008f34..2b36cd9 100644 --- a/imphnen-utils/Cargo.toml +++ b/imphnen-utils/Cargo.toml @@ -19,3 +19,5 @@ strum.workspace = true strum_macros.workspace = true uuid.workspace = true tracing.workspace = true +dotenvy = "0.15" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/imphnen-utils/src/bind_filter.rs b/imphnen-utils/src/bind_filter.rs index fedf43c..ecaac3e 100644 --- a/imphnen-utils/src/bind_filter.rs +++ b/imphnen-utils/src/bind_filter.rs @@ -1,9 +1,14 @@ +use tracing::{info}; use surrealdb::engine::any; use surrealdb::method::Query; +/// Binds a filter value to the query under the key "filter". pub fn bind_filter_value( query: Query<'_, any::Any>, val: String, ) -> Query<'_, any::Any> { - query.bind(("filter", val)) + info!(?val, "bind_filter_value called with arguments"); + let result = query.bind(("filter", val.clone())); + info!(?val, "bind_filter_value returning query with bound filter"); + result } diff --git a/imphnen-utils/src/extract_email.rs b/imphnen-utils/src/extract_email.rs index 6d61f3b..5691765 100644 --- a/imphnen-utils/src/extract_email.rs +++ b/imphnen-utils/src/extract_email.rs @@ -1,17 +1,55 @@ +use tracing::{info, error}; use crate::decode_access_token; use axum::http::{HeaderMap, header::AUTHORIZATION}; +/// Extracts the email from the Authorization header, if present and valid. pub fn extract_email(headers: &HeaderMap) -> Option { - let auth_header = headers.get(AUTHORIZATION)?.to_str().ok()?; - let token = auth_header.strip_prefix("Bearer ")?; - - match decode_access_token(token) { - Ok(data) => Some(data.claims.sub), - Err(_e) => None, - } + info!(?headers, "extract_email called with headers"); + let auth_header = match headers.get(AUTHORIZATION) { + Some(h) => h, + None => { + error!("Authorization header missing in extract_email"); + return None; + } + }; + let auth_str = match auth_header.to_str() { + Ok(s) => s, + Err(e) => { + error!(error = ?e, "Failed to convert Authorization header to str in extract_email"); + return None; + } + }; + let token = match auth_str.strip_prefix("Bearer ") { + Some(t) => t, + None => { + error!(auth_str, "Authorization header does not start with 'Bearer ' in extract_email"); + return None; + } + }; + info!(token, "Extracted bearer token in extract_email"); + match decode_access_token(token) { + Ok(data) => { + info!(email = %data.claims.sub, "Successfully decoded access token in extract_email"); + Some(data.claims.sub) + } + Err(e) => { + error!(error = ?e, "Failed to decode access token in extract_email"); + None + } + } } +/// Extracts the email from a JWT token string. pub fn extract_email_token(token: String) -> Option { - let token_data = decode_access_token(&token).ok()?; - Some(token_data.claims.sub) + info!(token = %token, "extract_email_token called with token"); + match decode_access_token(&token) { + Ok(data) => { + info!(email = %data.claims.sub, "Successfully decoded token in extract_email_token"); + Some(data.claims.sub) + } + Err(e) => { + error!(error = ?e, "Failed to decode token in extract_email_token"); + None + } + } } diff --git a/imphnen-utils/src/generate_date.rs b/imphnen-utils/src/generate_date.rs index 7970532..c2d637a 100644 --- a/imphnen-utils/src/generate_date.rs +++ b/imphnen-utils/src/generate_date.rs @@ -1,6 +1,11 @@ +use tracing::{info}; use chrono::{DateTime, Utc}; +/// Returns the current UTC date/time as an RFC3339 string. pub fn get_iso_date() -> String { - let now: DateTime = Utc::now(); - now.to_rfc3339() + info!("get_iso_date called"); + let now: DateTime = Utc::now(); + let date_str = now.to_rfc3339(); + info!(date_str = %date_str, "get_iso_date returning RFC3339 date string"); + date_str } diff --git a/imphnen-utils/src/get_id.rs b/imphnen-utils/src/get_id.rs index 3901507..6a6af20 100644 --- a/imphnen-utils/src/get_id.rs +++ b/imphnen-utils/src/get_id.rs @@ -1,15 +1,29 @@ +use tracing::{info, error}; use anyhow::{Result, bail}; use surrealdb::sql::Thing; +/// Extracts the table and id from a Thing, returning (&str, &str). pub fn get_id(thing: &Thing) -> Result<(&str, &str)> { - let table = thing.tb.as_str(); - let id = match &thing.id { - surrealdb::sql::Id::String(s) => s.as_str(), - _ => bail!("Unsupported ID type"), - }; - Ok((table, id)) + info!(?thing, "get_id called with argument"); + let table = thing.tb.as_str(); + let id = match &thing.id { + surrealdb::sql::Id::String(s) => { + info!(id = %s, "ID extracted as string in get_id"); + s.as_str() + } + other => { + error!(?other, "Unsupported ID type in get_id"); + bail!("Unsupported ID type"); + } + }; + info!(table = %table, id = %id, "get_id returning table and id"); + Ok((table, id)) } +/// Extracts the raw id string from a Thing. pub fn extract_id(thing: &Thing) -> String { - thing.id.to_raw() + info!(?thing, "extract_id called with argument"); + let raw_id = thing.id.to_raw(); + info!(raw_id = %raw_id, "extract_id returning raw id string"); + raw_id } diff --git a/imphnen-utils/src/lib.rs b/imphnen-utils/src/lib.rs index 8ba084c..84aec51 100644 --- a/imphnen-utils/src/lib.rs +++ b/imphnen-utils/src/lib.rs @@ -1,4 +1,4 @@ -mod logger; +pub mod logger; pub mod bind_filter; pub mod extract_email; pub mod generate_date; diff --git a/imphnen-utils/src/logger.rs b/imphnen-utils/src/logger.rs index 4ef1d44..3fd2602 100644 --- a/imphnen-utils/src/logger.rs +++ b/imphnen-utils/src/logger.rs @@ -1,14 +1,12 @@ -//! Logger initialization using tracing, tracing-subscriber, and dotenvy. -use std::env; use dotenvy::dotenv; use tracing_subscriber::{EnvFilter, fmt}; /// Initializes the logger using tracing and tracing-subscriber. /// Loads environment variables from `.env` and sets log level from `RUST_LOG`. pub fn init_logger() { - // Load .env file if present dotenv().ok(); + // Set up the tracing subscriber with EnvFilter from RUST_LOG let filter = EnvFilter::try_from_default_env() .or_else(|_| EnvFilter::try_new("warn")) diff --git a/test.sh b/test.sh index 340ac25..9d23bc2 100644 --- a/test.sh +++ b/test.sh @@ -163,7 +163,7 @@ test_server_connection() { clear_database() { write_test_log "INFO" "Membersihkan database via WebSocket..." - if ! cargo run --bin clear_db_test --release; then + if ! RUST_LOG=debug cargo run --bin clear_db_test --release; then write_test_log "ERROR" "Gagal membersihkan database." exit 1 fi @@ -776,7 +776,7 @@ if [ "$START_SERVER" = true ]; then exit 1 fi printf "${YELLOW}Memulai server backend...${NC}\n" - cargo run --bin api & + RUST_LOG=debug cargo run --bin api & SERVER_PID=$! printf "${YELLOW}Menunggu server siap...${NC}\n" @@ -803,7 +803,7 @@ fi clear_database printf "\n${CYAN}=== Menjalankan Seeders ===${NC}\n" -if ! cargo run --bin seeder; then +if ! RUST_LOG=debug cargo run --bin seeder; then write_test_log "ERROR" "Gagal menjalankan seeder roles permissions." exit 1 fi