firebase_rs_sdk/auth/oauth/
redirect.rs1use 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 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}