Skip to main content

alibi_core/plugin/
mod.rs

1mod context;
2mod contracts;
3mod extensions;
4mod initialization;
5mod routes;
6
7use crate::config::AuthConfig;
8use crate::email::EmailProvider;
9use crate::entity::AuthSession;
10use crate::error::{AuthError, AuthResult};
11use crate::schema::AuthSchema;
12use crate::session::SessionManager;
13use crate::store::AuthStore;
14use crate::types::{AuthRequest, AuthResponse, HttpMethod};
15use async_trait::async_trait;
16pub use context::AuthContext;
17pub use contracts::AuthPlugin;
18pub use contracts::BeforeRequestAction;
19pub use contracts::HttpEndpointResponse;
20pub use contracts::HttpRequestAction;
21pub use contracts::VerificationEmailOverride;
22pub use contracts::VerificationEmailOverrideHandle;
23pub use extensions::ContextExtensions;
24pub use initialization::AuthInitContext;
25pub use initialization::AuthInitParts;
26pub use routes::AuthRoute;
27pub use routes::ResolvedEndpoint;
28use std::any::{Any, TypeId};
29use std::collections::HashMap;
30use std::sync::Arc;
31
32type MetadataMap = HashMap<String, serde_json::Value>;
33
34// LCOV_EXCL_START
35#[cfg(test)]
36mod tests {
37    use super::*;
38    use crate::entity::AuthUser;
39    use crate::test_store::test_database;
40
41    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
42    #[test]
43    fn auth_route_constructors() {
44        let get = AuthRoute::get("/test", "getTest");
45        assert_eq!(get.method, HttpMethod::Get);
46        assert_eq!(get.path, "/test");
47        assert_eq!(get.operation_id, "getTest");
48
49        let post = AuthRoute::post("/create", "createItem");
50        assert_eq!(post.method, HttpMethod::Post);
51
52        let put = AuthRoute::put("/update", "updateItem");
53        assert_eq!(put.method, HttpMethod::Put);
54
55        let delete = AuthRoute::delete("/remove", "deleteItem");
56        assert_eq!(delete.method, HttpMethod::Delete);
57    }
58
59    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
60    #[test]
61    fn auth_route_new() {
62        let route = AuthRoute::new(HttpMethod::Patch, "/patch", "patchIt");
63        assert_eq!(route.method, HttpMethod::Patch);
64        assert_eq!(route.path, "/patch");
65    }
66
67    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
68    #[test]
69    fn auth_context_new() {
70        let config = Arc::new(AuthConfig::new("test-secret-min-32-chars-1234567"));
71        let runtime = tokio::runtime::Runtime::new().expect("runtime should build");
72        let db = runtime.block_on(test_database());
73        let ctx = AuthContext::new(config, db);
74        assert!(ctx.email_provider.is_none());
75        assert!(ctx.metadata.is_empty());
76    }
77
78    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
79    #[test]
80    fn auth_context_metadata() {
81        let config = Arc::new(AuthConfig::new("test-secret-min-32-chars-1234567"));
82        let runtime = tokio::runtime::Runtime::new().expect("runtime should build");
83        let db = runtime.block_on(test_database());
84        let mut ctx = AuthContext::new(config, db);
85
86        ctx.set_metadata("key", serde_json::json!("value"));
87        assert_eq!(ctx.get_metadata("key"), Some(&serde_json::json!("value")));
88        assert!(ctx.get_metadata("missing").is_none());
89    }
90
91    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
92    #[test]
93    fn auth_context_email_provider_error_when_none() {
94        let config = Arc::new(AuthConfig::new("test-secret-min-32-chars-1234567"));
95        let runtime = tokio::runtime::Runtime::new().expect("runtime should build");
96        let db = runtime.block_on(test_database());
97        let ctx = AuthContext::new(config, db);
98        assert!(ctx.email_provider().is_err());
99    }
100
101    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
102    #[tokio::test]
103    async fn auth_context_require_session_unauthenticated() {
104        let config = Arc::new(AuthConfig::new("test-secret-min-32-chars-1234567"));
105        let db = test_database().await;
106        let ctx = AuthContext::new(config, db);
107        let req = AuthRequest::new(HttpMethod::Get, "/test");
108        let result = ctx.require_session(&req).await;
109        assert!(result.is_err());
110    }
111
112    // Rust-specific surface: plugin infrastructure helpers and request-dispatch helpers in `crates/core::plugin` are Rust library APIs with no direct TS analogue.
113    #[tokio::test]
114    async fn auth_context_require_session_with_valid_session() {
115        let config = Arc::new(AuthConfig::new("test-secret-min-32-chars-1234567"));
116        let db = test_database().await;
117
118        // Create a user
119        let user = db
120            .create_user(crate::types::CreateUser::new().with_email("test@test.com"))
121            .await
122            .unwrap();
123
124        // Create a session
125        let sm = SessionManager::new(Arc::clone(&config), Arc::clone(&db));
126        let session = sm.create_session(&user, None, None).await.unwrap();
127
128        // Build request with the session token
129        let ctx = AuthContext::new(Arc::clone(&config), db);
130        let mut req = AuthRequest::new(HttpMethod::Get, "/test");
131        drop(req.headers.insert(
132            "cookie".into(),
133            format!(
134                "better-auth.session_token={}",
135                crate::utils::cookie_utils::sign_cookie_value(session.token(), &config.secret)
136            ),
137        ));
138
139        let (found_user, _found_session) = ctx.require_session(&req).await.unwrap();
140        assert_eq!(found_user.id(), user.id());
141    }
142}
143// LCOV_EXCL_STOP