Skip to main content

pocopine_auth/
provider.rs

1//! Provider/session-store traits and the [`AuthError`] type.
2//!
3//! The traits and futures here are host-only; the wasm client uses
4//! its own session bridge (`pocopine-auth-client`).
5
6use std::fmt;
7#[cfg(not(target_arch = "wasm32"))]
8use std::future::Future;
9#[cfg(not(target_arch = "wasm32"))]
10use std::pin::Pin;
11
12use pocopine_core::ServerError;
13
14#[cfg(not(target_arch = "wasm32"))]
15use crate::context::RequestContext;
16#[cfg(not(target_arch = "wasm32"))]
17use crate::principal::Session;
18#[cfg(not(target_arch = "wasm32"))]
19use crate::user::AuthUser;
20
21/// Auth provider failure.
22#[derive(Clone, Debug, Eq, PartialEq)]
23pub struct AuthError {
24    message: String,
25}
26
27impl AuthError {
28    /// Build an auth failure.
29    pub fn new(message: impl Into<String>) -> Self {
30        Self {
31            message: message.into(),
32        }
33    }
34}
35
36impl fmt::Display for AuthError {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        f.write_str(&self.message)
39    }
40}
41
42impl std::error::Error for AuthError {}
43
44impl From<AuthError> for ServerError {
45    fn from(err: AuthError) -> Self {
46        ServerError::unauthorized(err.to_string())
47    }
48}
49
50/// Provider/session result type.
51pub type AuthResult<T> = Result<T, AuthError>;
52
53/// Boxed async result used by provider traits without choosing an
54/// async-trait dependency.
55#[cfg(not(target_arch = "wasm32"))]
56pub type AuthFuture<'a, T> = Pin<Box<dyn Future<Output = AuthResult<T>> + Send + 'a>>;
57
58/// Auth provider contract. Clerk/Auth0/Supabase adapters can implement
59/// this without changing the server-function guard ABI.
60#[cfg(not(target_arch = "wasm32"))]
61pub trait AuthProvider: Send + Sync {
62    /// Authenticate a request and return an optional user.
63    fn authenticate<'a>(&'a self, ctx: &'a RequestContext) -> AuthFuture<'a, Option<AuthUser>>;
64}
65
66/// Session persistence contract for first-party/simple auth.
67#[cfg(not(target_arch = "wasm32"))]
68pub trait SessionStore: Send + Sync {
69    /// Load a session by id.
70    fn load<'a>(&'a self, session_id: &'a str) -> AuthFuture<'a, Option<Session>>;
71
72    /// Save a session.
73    fn save<'a>(&'a self, session: Session) -> AuthFuture<'a, ()>;
74
75    /// Delete a session by id.
76    fn delete<'a>(&'a self, session_id: &'a str) -> AuthFuture<'a, ()>;
77}