1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! API URI builder interface and API path definitions

pub mod error;

use error::InvalidApiUriError;
use error_stack::{Report, ResultExt};
use http::uri::{Authority, Parts, PathAndQuery, Scheme, Uri};

/// Firebase Auth admin REST API endpoints
pub enum FirebaseAuthRestApi {
    CreateUser,
    GetUsers,
    ListUsers,
    DeleteUser,
    DeleteUsers,
    UpdateUser,
    ImportUsers,
    CreateSessionCookie,
    SendOobCode,
}

impl From<FirebaseAuthRestApi> for &'static str {
    fn from(path: FirebaseAuthRestApi) -> Self {
        match path {
            FirebaseAuthRestApi::CreateUser => "/accounts",
            FirebaseAuthRestApi::GetUsers => "/accounts:lookup",
            FirebaseAuthRestApi::ListUsers => "/accounts:batchGet",
            FirebaseAuthRestApi::DeleteUser => "/accounts:delete",
            FirebaseAuthRestApi::DeleteUsers => "/accounts:batchDelete",
            FirebaseAuthRestApi::UpdateUser => "/accounts:update",
            FirebaseAuthRestApi::ImportUsers => "/accounts:batchCreate",
            FirebaseAuthRestApi::CreateSessionCookie => ":createSessionCookie",
            FirebaseAuthRestApi::SendOobCode => "/accounts:sendOobCode",
        }
    }
}

/// Firebase Auth emulator admin REST API endpoints
pub enum FirebaseAuthEmulatorRestApi {
    ClearUserAccounts,
    Configuration,
    OobCodes,
    SmsVerificationCodes,
}

impl From<FirebaseAuthEmulatorRestApi> for &'static str {
    fn from(path: FirebaseAuthEmulatorRestApi) -> Self {
        match path {
            FirebaseAuthEmulatorRestApi::ClearUserAccounts => "/accounts",
            FirebaseAuthEmulatorRestApi::Configuration => "/config",
            FirebaseAuthEmulatorRestApi::OobCodes => "/oobCodes",
            FirebaseAuthEmulatorRestApi::SmsVerificationCodes => "/verificationCodes",
        }
    }
}

#[derive(Debug, Clone)]
pub struct ApiUriBuilder {
    scheme: Scheme,
    authority: Authority,
    path_prefix: Option<String>,
}

impl ApiUriBuilder {
    pub fn new(scheme: Scheme, authority: Authority, path_prefix: Option<String>) -> Self {
        Self {
            scheme,
            authority,
            path_prefix,
        }
    }

    pub fn build<PathT: Into<&'static str>>(
        &self,
        path: PathT,
    ) -> Result<Uri, Report<InvalidApiUriError>> {
        let mut parts = Parts::default();
        parts.scheme = Some(self.scheme.clone());
        parts.authority = Some(self.authority.clone());
        parts.path_and_query = Some(
            PathAndQuery::from_maybe_shared(if let Some(prefix) = &self.path_prefix {
                prefix.clone() + path.into()
            } else {
                String::new() + path.into()
            })
            .change_context(InvalidApiUriError)?,
        );

        Uri::from_parts(parts).change_context(InvalidApiUriError)
    }
}