gcp_bigquery_client/
client_builder.rs

1use std::path::{Path, PathBuf};
2use std::sync::Arc;
3
4use yup_oauth2::ServiceAccountKey;
5
6use crate::auth::{
7    application_default_credentials_authenticator, authorized_user_authenticator, installed_flow_authenticator,
8    service_account_authenticator, Authenticator, ServiceAccountAuthenticator,
9};
10use crate::error::BQError;
11use crate::{Client, BIG_QUERY_AUTH_URL, BIG_QUERY_V2_URL};
12
13pub struct ClientBuilder {
14    v2_base_url: String,
15    auth_base_url: String,
16}
17
18impl ClientBuilder {
19    pub fn new() -> Self {
20        Self {
21            v2_base_url: BIG_QUERY_V2_URL.to_string(),
22            auth_base_url: BIG_QUERY_AUTH_URL.to_string(),
23        }
24    }
25
26    pub fn with_v2_base_url(&mut self, base_url: String) -> &mut Self {
27        self.v2_base_url = base_url;
28        self
29    }
30
31    pub fn with_auth_base_url(&mut self, base_url: String) -> &mut Self {
32        self.auth_base_url = base_url;
33        self
34    }
35
36    pub async fn build_from_authenticator(&self, auth: Arc<dyn Authenticator>) -> Result<Client, BQError> {
37        let mut client = Client::from_authenticator(auth).await?;
38        client.v2_base_url(self.v2_base_url.clone());
39        Ok(client)
40    }
41
42    pub async fn build_from_service_account_key(
43        &self,
44        sa_key: ServiceAccountKey,
45        readonly: bool,
46    ) -> Result<Client, BQError> {
47        let scope = if readonly {
48            format!("{}.readonly", self.auth_base_url)
49        } else {
50            self.auth_base_url.clone()
51        };
52        let sa_auth = ServiceAccountAuthenticator::from_service_account_key(sa_key, &[&scope]).await?;
53
54        self.build_from_authenticator(sa_auth).await
55    }
56
57    pub async fn build_from_service_account_key_file(&self, sa_key_file: &str) -> Result<Client, BQError> {
58        let scopes = vec![self.auth_base_url.as_str()];
59        let sa_auth = service_account_authenticator(scopes, sa_key_file).await?;
60
61        self.build_from_authenticator(sa_auth).await
62    }
63
64    pub async fn build_with_workload_identity(&self, readonly: bool) -> Result<Client, BQError> {
65        let scope = if readonly {
66            format!("{BIG_QUERY_AUTH_URL}.readonly")
67        } else {
68            BIG_QUERY_AUTH_URL.to_string()
69        };
70
71        let sa_auth = ServiceAccountAuthenticator::with_workload_identity(&[&scope]).await?;
72
73        self.build_from_authenticator(sa_auth).await
74    }
75
76    pub async fn build_from_installed_flow_authenticator<S: AsRef<[u8]>, P: Into<PathBuf>>(
77        &self,
78        secret: S,
79        persistant_file_path: P,
80    ) -> Result<Client, BQError> {
81        let scopes = vec![self.auth_base_url.as_str()];
82        let auth = installed_flow_authenticator(secret, &scopes, persistant_file_path).await?;
83
84        let mut client = Client::from_authenticator(auth).await?;
85        client.v2_base_url(self.v2_base_url.clone());
86        Ok(client)
87    }
88
89    pub async fn build_from_installed_flow_authenticator_from_secret_file<P: Into<PathBuf>>(
90        &self,
91        secret_file: &str,
92        persistant_file_path: P,
93    ) -> Result<Client, BQError> {
94        self.build_from_installed_flow_authenticator(
95            tokio::fs::read(secret_file)
96                .await
97                .expect("expecting a valid secret file."),
98            persistant_file_path,
99        )
100        .await
101    }
102
103    pub async fn build_from_application_default_credentials(&self) -> Result<Client, BQError> {
104        let scopes = vec![self.auth_base_url.as_str()];
105        let auth = application_default_credentials_authenticator(&scopes).await?;
106
107        let mut client = Client::from_authenticator(auth).await?;
108        client.v2_base_url(self.v2_base_url.clone());
109        Ok(client)
110    }
111
112    pub async fn build_from_authorized_user_authenticator<P: AsRef<Path>>(
113        &self,
114        authorized_user_secret_path: P,
115    ) -> Result<Client, BQError> {
116        let scopes = vec![self.auth_base_url.as_str()];
117        let auth = authorized_user_authenticator(authorized_user_secret_path, &scopes).await?;
118
119        let mut client = Client::from_authenticator(auth).await?;
120        client.v2_base_url(self.v2_base_url.clone());
121        Ok(client)
122    }
123}
124
125impl Default for ClientBuilder {
126    fn default() -> Self {
127        Self::new()
128    }
129}