Refactor and enhance SurrealDB integration and resource management

- Updated `lib.rs` to selectively expose specific entities and services for better clarity.
- Improved SurrealDB client initialization with detailed logging in `surrealdb/mod.rs`.
- Enhanced resource definitions in `resource.rs` with additional utility methods for better resource management.
- Refactored user data retrieval logic in `auth_middleware/mod.rs` for improved readability and efficiency.
- Cleaned up middleware exports in `lib.rs` for clearer API surface.
- Added detailed comments and documentation throughout the SurrealDB module for better maintainability.
- Updated tests to ensure compatibility with new changes and improved structure.
- Introduced new permissions module structure in `imphnen-utils` for future enhancements.
This commit is contained in:
MythEclipse
2025-09-26 17:35:30 +07:00
parent 96debc210a
commit 14b22328de
71 changed files with 1566 additions and 632 deletions
+1 -1
View File
@@ -1 +1 @@
pub mod mentor;
pub mod mentors;
+4 -2
View File
@@ -5,9 +5,11 @@ mod auth_login_tests {
use crate::mock_test::setup_all_test_environment;
use axum::http::StatusCode;
use imphnen_iam::{
v1::auth::{AuthLoginRequestDto, AuthService, AuthServiceTrait}, // Import AuthServiceTrait
v1::auth::AuthLoginRequestDto,
AppState, UsersRepository, UsersSchema,
};
use imphnen_iam::v1::auth::auth_service::AuthService;
use imphnen_iam::v1::auth::AuthServiceTrait;
use serde_json::Value; // Import the new setup function
async fn setup_test_environment() -> AppState {
@@ -343,7 +345,7 @@ mod auth_login_tests {
assert_eq!(parts.status, StatusCode::OK);
// Verify user was cached
let auth_repo = imphnen_iam::AuthRepository::new(&state);
let auth_repo = imphnen_iam::AuthRepository::new(state.surrealdb_mem.clone());
let cached_user = auth_repo.query_get_stored_user(email.clone()).await;
assert!(cached_user.is_ok());
assert_eq!(cached_user.unwrap().email, email);
+22 -22
View File
@@ -13,7 +13,8 @@ mod auth_repository_test {
UsersSchema,
};
use chrono::{Duration, Utc};
use imphnen_iam::{AppState, RolesDetailQueryDto, UsersDetailQueryDto};
use imphnen_iam::{AppState, UsersDetailQueryDto};
use imphnen_entities::RolesDetailQueryDto;
use surrealdb::Uuid;
async fn create_mock_user(state: &AppState, email: &str) -> UsersSchema {
@@ -53,8 +54,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_store_and_get_user() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let email = generate_unique_email("forgot");
let mut user = create_mock_user(&app_state, &email).await;
user.role = get_role_id("user", &app_state).await;
@@ -81,8 +82,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_delete_stored_user() {
let state = setup_all_test_environment().await; // Use the new setup function
let auth_repo = AuthRepository::new(&state);
let state = setup_all_test_environment().await; // Use the new setup function
let auth_repo = AuthRepository::new(state.surrealdb_mem.clone());
let email = "delete_me@example.com".to_string();
let mock_user = UsersDetailQueryDto {
id: make_thing(&ResourceEnum::UsersCache.to_string(), &email),
@@ -144,8 +145,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_store_and_get_otp() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let email = "otp_user@example.com".to_string();
let otp = 123456;
let stored = repo.query_store_otp(email.clone(), otp).await;
@@ -157,8 +158,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_delete_stored_otp() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let email = "otp_del@example.com".to_string();
let otp = 654321;
let store_res = repo.query_store_otp(email.clone(), otp).await;
@@ -178,18 +179,17 @@ mod auth_repository_test {
#[tokio::test]
async fn test_expired_otp() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let email = "expired_otp@example.com".to_string();
let otp = 789012;
let table = ResourceEnum::OtpCache.to_string();
let expires_at = Utc::now() - Duration::seconds(1);
let created: Result<Option<AuthOtpSchema>, surrealdb::Error> = repo
.state
.surrealdb_mem
.create((table.clone(), email.as_str()))
.content(AuthOtpSchema { otp, expires_at })
.await;
.db
.create((table.clone(), email.as_str()))
.content(AuthOtpSchema { otp, expires_at })
.await;
assert!(
created.is_ok(),
"Failed to create expired OTP: {:?}",
@@ -210,8 +210,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_get_non_existent_stored_user_should_fail() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let result = repo
.query_get_stored_user("not_found@example.com".into())
.await;
@@ -226,8 +226,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_delete_non_existent_user_should_fail() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let result = repo
.query_delete_stored_user("ghost@example.com".into())
.await;
@@ -242,8 +242,8 @@ mod auth_repository_test {
#[tokio::test]
async fn test_store_and_get_valid_otp() {
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(&app_state);
let app_state = setup_all_test_environment().await; // Use the new setup function
let repo = AuthRepository::new(app_state.surrealdb_mem.clone());
let email = "valid_otp@example.com";
let otp = 654321;
let store_result = repo.query_store_otp(email.into(), otp).await;
+2
View File
@@ -0,0 +1,2 @@
#[cfg(test)]
pub mod google_oauth_flow_test;
+10 -10
View File
@@ -8,8 +8,8 @@ mod tests {
#[tokio::test]
async fn test_query_create_role() {
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
// Test data
let role_name = "test_role_repo_create".to_string();
@@ -35,8 +35,8 @@ mod tests {
#[tokio::test]
async fn test_query_role_by_name() {
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
// Test data
let role_name = "test_role_repo_by_name".to_string();
@@ -66,8 +66,8 @@ mod tests {
#[tokio::test]
async fn test_query_role_list() {
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
// Create test roles
let role_names = vec![
@@ -108,8 +108,8 @@ mod tests {
#[tokio::test]
async fn test_query_update_role() {
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
// Test data
let original_name = "test_role_update_original".to_string();
@@ -149,8 +149,8 @@ mod tests {
#[tokio::test]
async fn test_query_delete_role() {
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = imphnen_iam::RolesRepository::new(&app_state);
// Test data
let role_name = "test_role_delete".to_string();
+2
View File
@@ -1,2 +1,4 @@
#[cfg(test)]
pub mod teams_repository_test;
#[cfg(test)]
pub mod teams_service_test;
+18 -18
View File
@@ -49,8 +49,8 @@ mod tests {
#[tokio::test]
async fn test_create_team() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -81,8 +81,8 @@ mod tests {
#[tokio::test]
async fn test_team_list() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -116,8 +116,8 @@ mod tests {
#[tokio::test]
async fn test_update_team() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -148,8 +148,8 @@ mod tests {
#[tokio::test]
async fn test_delete_team() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -175,8 +175,8 @@ mod tests {
#[tokio::test]
async fn test_add_team_member() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -250,8 +250,8 @@ mod tests {
#[tokio::test]
async fn test_team_member_check() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -296,8 +296,8 @@ mod tests {
#[tokio::test]
async fn test_create_invitation() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let inviter_id = Uuid::new_v4().to_string();
@@ -332,8 +332,8 @@ mod tests {
#[tokio::test]
async fn test_search_teams() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
@@ -366,8 +366,8 @@ mod tests {
#[tokio::test]
async fn test_remove_team_member() {
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = TeamsRepository::new(&app_state);
let team_id = Uuid::new_v4().to_string();
let leader_id = Uuid::new_v4().to_string();
+24 -24
View File
@@ -9,9 +9,9 @@ mod tests {
#[tokio::test]
async fn test_create_team_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let email = generate_unique_email("team_creator");
let role_id = get_role_id("mentee", &app_state).await;
@@ -54,9 +54,9 @@ mod tests {
#[tokio::test]
async fn test_get_team_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let email = generate_unique_email("team_getter");
let role_id = get_role_id("mentee", &app_state).await;
@@ -101,9 +101,9 @@ mod tests {
#[tokio::test]
async fn test_update_team_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let email = generate_unique_email("team_updater");
let role_id = get_role_id("mentee", &app_state).await;
@@ -171,9 +171,9 @@ mod tests {
#[tokio::test]
async fn test_invite_team_member_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let leader_email = generate_unique_email("team_leader");
let role_id = get_role_id("mentee", &app_state).await;
@@ -228,9 +228,9 @@ mod tests {
#[tokio::test]
async fn test_leave_team_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let leader_email = generate_unique_email("leave_leader");
let member_email = generate_unique_email("leave_member");
@@ -309,9 +309,9 @@ mod tests {
#[tokio::test]
async fn test_search_teams_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let email = generate_unique_email("search_creator");
let role_id = get_role_id("mentee", &app_state).await;
@@ -374,9 +374,9 @@ mod tests {
#[tokio::test]
async fn test_delete_team_service() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let email = generate_unique_email("delete_creator");
let role_id = get_role_id("mentee", &app_state).await;
@@ -428,9 +428,9 @@ mod tests {
#[tokio::test]
async fn test_unauthorized_operations() {
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let users_repo = UsersRepository::new(&app_state);
let repo = TeamsRepository::new(&app_state);
let leader_email = generate_unique_email("auth_leader");
let non_leader_email = generate_unique_email("auth_non_leader");
+12 -12
View File
@@ -7,8 +7,8 @@ mod tests {
#[tokio::test]
async fn test_query_create_user() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
@@ -41,8 +41,8 @@ mod tests {
#[tokio::test]
async fn test_query_user_by_email() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
@@ -75,8 +75,8 @@ mod tests {
#[tokio::test]
async fn test_query_user_by_email_not_found() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
// Try to get non-existent user
let result = repo.query_user_by_email("nonexistent@example.com".to_string()).await;
@@ -85,8 +85,8 @@ mod tests {
#[tokio::test]
async fn test_query_update_user() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
@@ -133,8 +133,8 @@ mod tests {
#[tokio::test]
async fn test_query_delete_user() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
@@ -168,8 +168,8 @@ mod tests {
#[tokio::test]
async fn test_query_user_list() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Create test users
+5 -4
View File
@@ -1,7 +1,8 @@
use ::surrealdb::Uuid;
use ::surrealdb::sql;
pub use imphnen_entities::*;
pub use imphnen_iam::*;
pub use imphnen_entities::MetaRequestDto;
pub use imphnen_iam::{ResourceEnum, RolesRepository, UsersRepository, AuthOtpSchema, AuthRepository, RolesDetailQueryDto, UsersDetailQueryDto, RolesRequestCreateDto, RolesRequestUpdateDto, RolesDetailItemDto, TeamsRepository, TeamsSchema, TeamMembersSchema, TeamInvitationsSchema, UsersSchema};
use imphnen_libs::AppState;
pub fn create_test_mentor(
email: &str,
@@ -69,7 +70,7 @@ pub fn generate_unique_email(prefix: &str) -> String {
format!("{}_{}@example.com", prefix, Uuid::new_v4())
}
pub async fn get_role_id(role_name: &str, state: &crate::AppState) -> sql::Thing {
pub async fn get_role_id(role_name: &str, state: &AppState) -> sql::Thing {
let repo = RolesRepository::new(state);
if let Ok(existing) = repo.query_role_by_name(role_name.into()).await {
return make_thing(&ResourceEnum::Roles.to_string(), &existing.id);
@@ -87,7 +88,7 @@ pub async fn get_role_id(role_name: &str, state: &crate::AppState) -> sql::Thing
make_thing(&ResourceEnum::Roles.to_string(), &role.id)
}
pub async fn get_app_state() -> crate::AppState {
pub async fn get_app_state() -> AppState {
create_mock_app_state().await
}