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