1pub 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
22pub use schemas::adminx_schema::AdminxSchema;
24
25pub use configs::initializer::{
27 get_adminx_config,
28 setup_adminx_logging,
29 get_adminx_session_middleware,
30 adminx_initialize,
31 AdminxConfig
32};
33
34pub use utils::{
36 jwt::create_jwt_token, auth::{extract_claims_from_session, AdminxStatus, NewAdminxUser, InitOutcome},
38 structs::{LoginForm, RoleGuard, Claims}, };
40
41pub use resource::AdmixResource;
43
44pub use models::adminx_model::{AdminxUser, AdminxUserPublic};
46
47pub use controllers::{
49 auth_controller::{login_form, login_action, logout_action},
50 dashboard_controller::{adminx_home, adminx_stats, adminx_profile},
51};
52
53pub use router::register_all_admix_routes;
55
56pub 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
66pub use middleware::role_guard::RoleGuardMiddleware;
68
69pub const VERSION: &str = env!("CARGO_PKG_VERSION");
71pub const NAME: &str = env!("CARGO_PKG_NAME");
72
73pub mod prelude {
75 pub use crate::{
76 AdminxConfig,
77 adminx_initialize,
78 Claims, AdminxUser,
80 LoginForm,
81 RoleGuard,
82 render_template,
83 extract_claims_from_session,
84 AdmixResource, };
86}
87
88pub fn validate_config() -> Result<(), Box<dyn std::error::Error>> {
90 use std::env;
91
92 let required_vars = vec![
94 "JWT_SECRET",
95 ];
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
107pub 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 env::set_var("JWT_SECRET", "test_secret_that_is_long_enough_for_testing");
137
138 assert!(validate_config().is_ok());
140
141 env::remove_var("JWT_SECRET");
143
144 assert!(validate_config().is_err());
146 }
147
148 #[test]
149 fn test_claims_consistency() {
150 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 use crate::prelude::*;
170
171 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}