opendal/services/gdrive/
builder.rs1use std::fmt::Debug;
19use std::fmt::Formatter;
20use std::sync::Arc;
21
22use chrono::DateTime;
23use chrono::Utc;
24use log::debug;
25use tokio::sync::Mutex;
26
27use super::backend::GdriveBackend;
28use super::core::GdriveCore;
29use super::core::GdrivePathQuery;
30use super::core::GdriveSigner;
31use crate::raw::Access;
32use crate::raw::HttpClient;
33use crate::raw::PathCacher;
34use crate::raw::{normalize_root, AccessorInfo};
35use crate::services::GdriveConfig;
36use crate::Scheme;
37use crate::*;
38
39impl Configurator for GdriveConfig {
40 type Builder = GdriveBuilder;
41
42 #[allow(deprecated)]
43 fn into_builder(self) -> Self::Builder {
44 GdriveBuilder {
45 config: self,
46 http_client: None,
47 }
48 }
49}
50
51#[derive(Default)]
53#[doc = include_str!("docs.md")]
54pub struct GdriveBuilder {
55 config: GdriveConfig,
56
57 #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
58 http_client: Option<HttpClient>,
59}
60
61impl Debug for GdriveBuilder {
62 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63 f.debug_struct("Backend")
64 .field("config", &self.config)
65 .finish()
66 }
67}
68
69impl GdriveBuilder {
70 pub fn root(mut self, root: &str) -> Self {
72 self.config.root = if root.is_empty() {
73 None
74 } else {
75 Some(root.to_string())
76 };
77
78 self
79 }
80
81 pub fn access_token(mut self, access_token: &str) -> Self {
92 self.config.access_token = Some(access_token.to_string());
93 self
94 }
95
96 pub fn refresh_token(mut self, refresh_token: &str) -> Self {
102 self.config.refresh_token = Some(refresh_token.to_string());
103 self
104 }
105
106 pub fn client_id(mut self, client_id: &str) -> Self {
110 self.config.client_id = Some(client_id.to_string());
111 self
112 }
113
114 pub fn client_secret(mut self, client_secret: &str) -> Self {
118 self.config.client_secret = Some(client_secret.to_string());
119 self
120 }
121
122 #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
129 #[allow(deprecated)]
130 pub fn http_client(mut self, http_client: HttpClient) -> Self {
131 self.http_client = Some(http_client);
132 self
133 }
134}
135
136impl Builder for GdriveBuilder {
137 const SCHEME: Scheme = Scheme::Gdrive;
138 type Config = GdriveConfig;
139
140 fn build(self) -> Result<impl Access> {
141 let root = normalize_root(&self.config.root.unwrap_or_default());
142 debug!("backend use root {}", root);
143
144 let info = AccessorInfo::default();
145 info.set_scheme(Scheme::Gdrive)
146 .set_root(&root)
147 .set_native_capability(Capability {
148 stat: true,
149 stat_has_content_length: true,
150 stat_has_content_type: true,
151 stat_has_last_modified: true,
152
153 read: true,
154
155 list: true,
156 list_has_content_type: true,
157 list_has_content_length: true,
158 list_has_etag: true,
159
160 write: true,
161
162 create_dir: true,
163 delete: true,
164 rename: true,
165 copy: true,
166
167 shared: true,
168
169 ..Default::default()
170 });
171
172 #[allow(deprecated)]
174 if let Some(client) = self.http_client {
175 info.update_http_client(|_| client);
176 }
177
178 let accessor_info = Arc::new(info);
179 let mut signer = GdriveSigner::new(accessor_info.clone());
180 match (self.config.access_token, self.config.refresh_token) {
181 (Some(access_token), None) => {
182 signer.access_token = access_token;
183 signer.expires_in = DateTime::<Utc>::MAX_UTC;
185 }
186 (None, Some(refresh_token)) => {
187 let client_id = self.config.client_id.ok_or_else(|| {
188 Error::new(
189 ErrorKind::ConfigInvalid,
190 "client_id must be set when refresh_token is set",
191 )
192 .with_context("service", Scheme::Gdrive)
193 })?;
194 let client_secret = self.config.client_secret.ok_or_else(|| {
195 Error::new(
196 ErrorKind::ConfigInvalid,
197 "client_secret must be set when refresh_token is set",
198 )
199 .with_context("service", Scheme::Gdrive)
200 })?;
201
202 signer.refresh_token = refresh_token;
203 signer.client_id = client_id;
204 signer.client_secret = client_secret;
205 }
206 (Some(_), Some(_)) => {
207 return Err(Error::new(
208 ErrorKind::ConfigInvalid,
209 "access_token and refresh_token cannot be set at the same time",
210 )
211 .with_context("service", Scheme::Gdrive))
212 }
213 (None, None) => {
214 return Err(Error::new(
215 ErrorKind::ConfigInvalid,
216 "access_token or refresh_token must be set",
217 )
218 .with_context("service", Scheme::Gdrive))
219 }
220 };
221
222 let signer = Arc::new(Mutex::new(signer));
223
224 Ok(GdriveBackend {
225 core: Arc::new(GdriveCore {
226 info: accessor_info.clone(),
227 root,
228 signer: signer.clone(),
229 path_cache: PathCacher::new(GdrivePathQuery::new(accessor_info, signer))
230 .with_lock(),
231 }),
232 })
233 }
234}