adminx/
lib.rs

1// crates/adminx/src/lib.rs - Fixed version
2
3pub mod resource;
4pub mod filters;
5pub mod pagination;
6pub mod error;
7pub mod router;
8pub mod menu;
9pub mod registry;
10pub mod health;
11pub mod middleware;
12pub mod nested;
13pub mod utils;
14pub mod actions;
15pub mod helpers;
16pub mod controllers;
17pub mod configs;
18pub mod models;
19pub mod schemas;
20pub mod errors;
21
22// Re-export main types for easier importing
23pub use schemas::adminx_schema::AdminxSchema;
24
25// Export configuration and app creation functions
26pub use configs::initializer::{
27    get_adminx_config,
28    setup_adminx_logging, 
29    get_adminx_session_middleware,
30    adminx_initialize,
31    AdminxConfig
32};
33
34// Export commonly used utilities - ✅ FIXED: Use Claims from structs only
35pub use utils::{
36    jwt::create_jwt_token, // ✅ Don't export Claims from jwt
37    auth::{extract_claims_from_session, AdminxStatus, NewAdminxUser, InitOutcome},
38    structs::{LoginForm, RoleGuard, Claims}, // ✅ Export Claims from structs
39};
40
41// Export core traits and types
42pub use resource::AdmixResource;
43
44// Export models
45pub use models::adminx_model::{AdminxUser, AdminxUserPublic};
46
47// Export controllers for custom route registration
48pub use controllers::{
49    auth_controller::{login_form, login_action, logout_action},
50    dashboard_controller::{adminx_home, adminx_stats, adminx_profile},
51};
52
53// Export router for custom integration
54pub use router::register_all_admix_routes;
55
56// Export template helpers
57pub use helpers::template_helper::{
58    render_template, 
59    render_template_with_auth, 
60    render_protected_template,
61    render_404,
62    render_403,
63    render_500,
64};
65
66// Export middleware
67pub use middleware::role_guard::RoleGuardMiddleware;
68
69// Version information
70pub const VERSION: &str = env!("CARGO_PKG_VERSION");
71pub const NAME: &str = env!("CARGO_PKG_NAME");
72
73// Convenience functions for common operations
74pub mod prelude {
75    pub use crate::{
76        AdminxConfig,
77        adminx_initialize,
78        Claims, // ✅ This now comes from structs
79        AdminxUser,
80        LoginForm,
81        RoleGuard,
82        render_template,
83        extract_claims_from_session,
84        AdmixResource, // ✅ Added this for convenience
85    };
86}
87
88// Configuration validation
89pub fn validate_config() -> Result<(), Box<dyn std::error::Error>> {
90    use std::env;
91    
92    // Check required environment variables
93    let required_vars = vec![
94        "JWT_SECRET",
95        // Add other required vars here
96    ];
97    
98    for var in required_vars {
99        if env::var(var).is_err() {
100            return Err(format!("Required environment variable {} is not set", var).into());
101        }
102    }
103    
104    Ok(())
105}
106
107// Health check function
108pub async fn health_check() -> Result<serde_json::Value, Box<dyn std::error::Error>> {
109    use crate::utils::database::check_database_health;
110    
111    let db_healthy = check_database_health().await.unwrap_or(false);
112    
113    Ok(serde_json::json!({
114        "status": if db_healthy { "healthy" } else { "unhealthy" },
115        "version": VERSION,
116        "name": NAME,
117        "database": if db_healthy { "connected" } else { "disconnected" },
118        "timestamp": chrono::Utc::now().to_rfc3339(),
119    }))
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125    use std::env;
126
127    #[test]
128    fn test_version_info() {
129        assert!(!VERSION.is_empty());
130        assert_eq!(NAME, "adminx");
131    }
132
133    #[test]
134    fn test_config_validation() {
135        // Set test environment variables
136        env::set_var("JWT_SECRET", "test_secret_that_is_long_enough_for_testing");
137        
138        // Should pass with required vars set
139        assert!(validate_config().is_ok());
140        
141        // Clean up
142        env::remove_var("JWT_SECRET");
143        
144        // Should fail without required vars
145        assert!(validate_config().is_err());
146    }
147
148    #[test]
149    fn test_claims_consistency() {
150        // Test that Claims struct is accessible and consistent
151        use crate::utils::structs::Claims;
152        
153        let claims = Claims {
154            sub: "test_user".to_string(),
155            exp: 1234567890,
156            email: "test@example.com".to_string(),
157            role: "admin".to_string(),
158            roles: vec!["admin".to_string()],
159        };
160        
161        assert_eq!(claims.role, "admin");
162        assert_eq!(claims.email, "test@example.com");
163        assert!(claims.roles.contains(&"admin".to_string()));
164    }
165
166    #[test]
167    fn test_prelude_imports() {
168        // Test that prelude imports work correctly
169        use crate::prelude::*;
170        
171        // This should compile without errors, proving all exports are consistent
172        let _config_exists = std::marker::PhantomData::<AdminxConfig>;
173        let _claims_exists = std::marker::PhantomData::<Claims>;
174        let _resource_exists = std::marker::PhantomData::<Box<dyn AdmixResource>>;
175    }
176}