rs_firebase_admin_sdk/credentials/
mod.rs1pub mod emulator;
4pub mod error;
5pub mod gcp;
6
7#[cfg(test)]
8mod test;
9
10use error::CredentialsError;
11use error_stack::{Report, ResultExt};
12use headers::{Authorization, HeaderMapExt, authorization::Bearer};
13use headers::{Header, HeaderName, HeaderValue};
14use http::header::HeaderMap;
15use std::future::Future;
16
17static X_GOOG_USER_PROJECT: HeaderName = HeaderName::from_static("x-goog-user-project");
18
19pub struct GoogleUserProject(String);
20
21impl Header for GoogleUserProject {
22 fn name() -> &'static HeaderName {
23 &X_GOOG_USER_PROJECT
24 }
25
26 fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
27 where
28 I: Iterator<Item = &'i HeaderValue>,
29 {
30 let value = values
31 .next()
32 .ok_or_else(headers::Error::invalid)?
33 .as_bytes();
34
35 match std::str::from_utf8(value) {
36 Ok(v) => Ok(Self(v.into())),
37 Err(_) => Err(headers::Error::invalid()),
38 }
39 }
40
41 fn encode<E>(&self, values: &mut E)
42 where
43 E: Extend<HeaderValue>,
44 {
45 let value = HeaderValue::from_str(&self.0).unwrap_or_else(|_| HeaderValue::from_static(""));
46
47 values.extend(std::iter::once(value));
48 }
49}
50
51pub trait Credentials: Send + Sync + 'static {
52 fn get_access_token(
54 &self,
55 scopes: &[&str],
56 ) -> impl Future<Output = Result<String, Report<CredentialsError>>> + Send;
57
58 fn get_project_id(
60 &self,
61 ) -> impl Future<Output = Result<String, Report<CredentialsError>>> + Send;
62
63 fn set_credentials(
65 &self,
66 headers: &mut HeaderMap,
67 scopes: &[&str],
68 ) -> impl Future<Output = Result<(), Report<CredentialsError>>> + Send {
69 async move {
70 let token = self.get_access_token(scopes).await?;
71
72 headers.typed_insert(
73 Authorization::<Bearer>::bearer(&token)
74 .change_context(CredentialsError::InvalidAccessToken)?,
75 );
76
77 headers.typed_insert(GoogleUserProject(self.get_project_id().await?));
78
79 Ok(())
80 }
81 }
82}