firebase_rs_sdk/auth/oauth/
redirect.rs

1use std::sync::{Arc, Mutex};
2
3use serde::{Deserialize, Serialize};
4
5use crate::auth::error::AuthResult;
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8pub struct PendingRedirectEvent {
9    pub provider_id: String,
10    pub operation: RedirectOperation,
11    pub pkce_verifier: Option<String>,
12}
13
14#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
15pub enum RedirectOperation {
16    SignIn,
17    Link,
18}
19
20pub trait RedirectPersistence: Send + Sync {
21    fn set(&self, event: Option<PendingRedirectEvent>) -> AuthResult<()>;
22    fn get(&self) -> AuthResult<Option<PendingRedirectEvent>>;
23}
24
25#[derive(Default, Debug)]
26pub struct InMemoryRedirectPersistence {
27    inner: Mutex<Option<PendingRedirectEvent>>,
28}
29
30impl RedirectPersistence for InMemoryRedirectPersistence {
31    fn set(&self, event: Option<PendingRedirectEvent>) -> AuthResult<()> {
32        *self.inner.lock().unwrap() = event;
33        Ok(())
34    }
35
36    fn get(&self) -> AuthResult<Option<PendingRedirectEvent>> {
37        Ok(self.inner.lock().unwrap().clone())
38    }
39}
40
41impl InMemoryRedirectPersistence {
42    /// Returns a new shared in-memory redirect persistence implementation.
43    pub fn shared() -> Arc<Self> {
44        Arc::new(Self::default())
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn in_memory_persistence_round_trip() {
54        let persistence = InMemoryRedirectPersistence::shared();
55        let event = PendingRedirectEvent {
56            provider_id: "google.com".into(),
57            operation: RedirectOperation::Link,
58            pkce_verifier: None,
59        };
60
61        persistence.set(Some(event.clone())).unwrap();
62        assert_eq!(persistence.get().unwrap(), Some(event.clone()));
63
64        persistence.set(None).unwrap();
65        assert_eq!(persistence.get().unwrap(), None);
66    }
67}