dittolive_ditto/identity/
mod.rs1use std::sync::{Arc, Mutex};
20
21use ffi_sdk::BoxedIdentityConfig;
22
23use crate::{
24 ditto::AppId,
25 error::{DittoError, ErrorKind},
26};
27use_prelude!();
28
29#[doc(hidden)]
31pub mod auth;
32
33use self::auth::LoginProvider;
34pub use self::auth::{
35 AuthenticationClientFeedback, DittoAuthenticationEventHandler, DittoAuthenticator,
36};
37
38#[doc(hidden)]
42pub trait Identity: private::Sealed + Send + Sync {
43 fn identity_config(&self) -> Option<BoxedIdentityConfig>;
45
46 fn involves_authenticator(&self) -> bool {
48 false
49 }
50
51 fn set_login_provider_with_ditto_pointer(
57 &self,
58 _ditto_fields: &Arc<crate::ditto::DittoFields>,
59 ) {
60 }
61
62 fn is_cloud_sync_enabled(&self) -> bool;
64
65 fn auth_url(&self) -> Result<String, DittoError>;
67
68 fn sync_url(&self) -> Result<String, DittoError>;
72
73 fn requires_offline_only_license_token(&self) -> bool;
76}
77
78pub struct OnlineWithAuthentication {
98 app_id: AppId,
99 enable_cloud_sync: bool,
100 auth_url: String,
101 identity_config: Mutex<Option<BoxedIdentityConfig>>,
102 auth_event_handler: Arc<dyn 'static + DittoAuthenticationEventHandler>,
103}
104
105#[doc(hidden)]
106#[deprecated(note = "use OnlinePlayground instead")]
107pub type OnlinePlaygroundV2 = OnlinePlayground;
108
109pub struct OnlinePlayground {
113 app_id: AppId,
114 enable_cloud_sync: bool,
115 auth_url: String,
116 identity_config: Mutex<Option<BoxedIdentityConfig>>,
117}
118
119pub struct OfflinePlayground {
123 identity_config: Mutex<Option<BoxedIdentityConfig>>,
124}
125
126pub struct SharedKey {
131 identity_config: Mutex<Option<BoxedIdentityConfig>>,
132}
133
134pub struct Manual {
137 identity_config: Mutex<Option<BoxedIdentityConfig>>,
138}
139
140impl OnlineWithAuthentication {
141 pub fn new(
150 _ditto_root: Arc<dyn DittoRoot>, app_id: AppId,
152 auth_event_handler: impl DittoAuthenticationEventHandler + 'static,
153 enable_cloud_sync: bool,
154 custom_auth_url: Option<&str>,
155 ) -> Result<Self, DittoError> {
156 let auth_url = match custom_auth_url {
157 Some(url) => url.to_owned(),
158 None => app_id.default_auth_url(),
159 };
160 let c_app_id = char_p::new(app_id.to_string());
161 let c_auth_url = char_p::new(auth_url.as_str());
162
163 let identity_config = Mutex::new(Some(
164 ffi_sdk::ditto_identity_config_make_online_with_authentication(
165 c_app_id.as_ref(),
166 c_auth_url.as_ref(),
167 )
168 .ok_or(ErrorKind::Config)?,
169 ));
170
171 Ok(OnlineWithAuthentication {
172 app_id,
173 enable_cloud_sync,
174 auth_url,
175 identity_config,
176 auth_event_handler: Arc::new(auth_event_handler),
177 })
178 }
179}
180
181impl Identity for OnlineWithAuthentication {
182 fn identity_config(&self) -> Option<BoxedIdentityConfig> {
183 let mut config = self.identity_config.lock().unwrap();
184 config.take()
185 }
186
187 fn involves_authenticator(&self) -> bool {
188 true
189 }
190
191 fn set_login_provider_with_ditto_pointer(&self, ditto_fields: &Arc<crate::ditto::DittoFields>) {
192 let authenticator = DittoAuthenticator {
193 ditto_fields: Arc::downgrade(ditto_fields),
194 };
195 let auth_event_handler = self.auth_event_handler.retain();
196 let LoginProvider(c_provider) = LoginProvider::new(auth_event_handler, authenticator);
197 ffi_sdk::ditto_auth_set_login_provider(&ditto_fields.ditto, Some(c_provider));
198 }
199
200 fn is_cloud_sync_enabled(&self) -> bool {
201 self.enable_cloud_sync
202 }
203
204 fn auth_url(&self) -> Result<String, DittoError> {
205 Ok(self.auth_url.to_owned())
206 }
207
208 fn sync_url(&self) -> Result<String, DittoError> {
209 Ok(self.app_id.default_sync_url())
210 }
211
212 fn requires_offline_only_license_token(&self) -> bool {
213 false
214 }
215}
216
217impl OnlinePlayground {
218 pub fn new(
228 _ditto_root: Arc<dyn DittoRoot>, app_id: AppId,
230 shared_token: String,
231 enable_cloud_sync: bool,
232 custom_auth_url: Option<&str>,
233 ) -> Result<Self, DittoError> {
234 let c_app_id = app_id.to_c_string();
235 let c_shared_token = char_p::new(shared_token.as_str());
236 let auth_url = match custom_auth_url {
237 Some(url) => url.to_owned(),
238 None => app_id.default_auth_url(),
239 };
240 let c_auth_url = char_p::new(auth_url.as_str());
241 let identity_config = Mutex::new(Some(
242 ffi_sdk::ditto_identity_config_make_online_playground(
243 c_app_id.as_ref(),
244 c_shared_token.as_ref(),
245 c_auth_url.as_ref(),
246 )
247 .ok_or(ErrorKind::Config)?,
248 ));
249
250 Ok(Self {
251 app_id,
252 enable_cloud_sync,
253 auth_url,
254 identity_config,
255 })
256 }
257}
258
259impl Identity for OnlinePlayground {
260 fn identity_config(&self) -> Option<BoxedIdentityConfig> {
261 let mut config = self.identity_config.lock().unwrap();
262 config.take()
263 }
264
265 fn involves_authenticator(&self) -> bool {
266 true
267 }
268
269 fn auth_url(&self) -> Result<String, DittoError> {
270 Ok(self.auth_url.to_owned())
271 }
272
273 fn sync_url(&self) -> Result<String, DittoError> {
274 Ok(self.app_id.default_sync_url())
275 }
276
277 fn is_cloud_sync_enabled(&self) -> bool {
278 self.enable_cloud_sync
279 }
280
281 fn requires_offline_only_license_token(&self) -> bool {
282 false
283 }
284}
285
286impl OfflinePlayground {
287 pub fn new(_ditto_root: Arc<dyn DittoRoot>, app_id: AppId) -> Result<Self, DittoError> {
294 let c_app_id = app_id.to_c_string();
295 let identity_config = Mutex::new(Some(
296 ffi_sdk::ditto_identity_config_make_offline_playground(c_app_id.as_ref(), 0)
297 .ok_or(ErrorKind::Config)?,
298 ));
299 Ok(Self { identity_config })
300 }
301
302 pub fn random(ditto_root: Arc<dyn DittoRoot>) -> Result<Self, DittoError> {
304 let app_id = AppId::generate();
305 Self::new(ditto_root, app_id)
306 }
307}
308
309impl Identity for OfflinePlayground {
310 fn identity_config(&self) -> Option<BoxedIdentityConfig> {
311 let mut config = self.identity_config.lock().unwrap();
312 config.take()
313 }
314
315 fn is_cloud_sync_enabled(&self) -> bool {
316 false
317 }
318
319 fn auth_url(&self) -> Result<String, DittoError> {
320 Err(DittoError::new(
321 ErrorKind::InvalidInput,
322 "Cloud Auth is not enabled for OfflinePlayground Identities".to_string(),
323 ))
324 }
325 fn sync_url(&self) -> Result<String, DittoError> {
326 Err(DittoError::new(
327 ErrorKind::InvalidInput,
328 "Cloud sync is not enabled for OfflinePlayground Identities".to_string(),
329 ))
330 }
331
332 fn requires_offline_only_license_token(&self) -> bool {
333 true
334 }
335}
336
337impl SharedKey {
338 pub fn new(
345 _ditto_root: Arc<dyn DittoRoot>, app_id: AppId,
347 key_der_b64: &str,
348 ) -> Result<Self, DittoError> {
349 let c_app_id = app_id.to_c_string();
350 let c_key_der = char_p::new(key_der_b64);
351 let identity_config = Mutex::new(Some(
352 ffi_sdk::ditto_identity_config_make_shared_key(
353 c_app_id.as_ref(),
354 c_key_der.as_ref(),
355 0,
356 )
357 .ok_or(ErrorKind::Config)?,
358 ));
359 Ok(Self { identity_config })
360 }
361}
362
363impl Identity for SharedKey {
364 fn identity_config(&self) -> Option<BoxedIdentityConfig> {
365 let mut config = self.identity_config.lock().unwrap();
366 config.take()
367 }
368
369 fn auth_url(&self) -> Result<String, DittoError> {
370 let msg = "SharedKey Identities don't support auth urls".to_owned();
371 Err(DittoError::new(ErrorKind::Config, msg))
372 }
373
374 fn sync_url(&self) -> Result<String, DittoError> {
375 let msg = "SharedKey Identities to support cloud sync".to_owned();
376 Err(DittoError::new(ErrorKind::Config, msg))
377 }
378
379 fn is_cloud_sync_enabled(&self) -> bool {
380 false
381 }
382
383 fn requires_offline_only_license_token(&self) -> bool {
384 true
385 }
386}
387
388impl Manual {
389 pub fn new(manual_identity: impl Into<String>) -> Result<Self, DittoError> {
398 let manual_identity_str = char_p::new(manual_identity.into());
399 let identity_config = Mutex::new(Some(
400 ffi_sdk::ditto_identity_config_make_manual(manual_identity_str.as_ref())
401 .ok_or(ErrorKind::Config)?,
402 ));
403 Ok(Self { identity_config })
404 }
405}
406
407impl Identity for Manual {
408 fn identity_config(&self) -> Option<BoxedIdentityConfig> {
409 let mut config = self.identity_config.lock().unwrap();
410 config.take()
411 }
412
413 fn auth_url(&self) -> Result<String, DittoError> {
414 let msg = "Manual Identities don't support auth urls".to_owned();
415 Err(DittoError::new(ErrorKind::Config, msg))
416 }
417
418 fn sync_url(&self) -> Result<String, DittoError> {
419 let msg = "Manual Identities to support cloud sync".to_owned();
420 Err(DittoError::new(ErrorKind::Config, msg))
421 }
422
423 fn is_cloud_sync_enabled(&self) -> bool {
424 false
425 }
426
427 fn requires_offline_only_license_token(&self) -> bool {
428 true
429 }
430}
431
432mod private {
433 use super::*;
434 pub trait Sealed {}
435 impl Sealed for OnlineWithAuthentication {}
436 impl Sealed for OnlinePlayground {}
437 impl Sealed for OfflinePlayground {}
438 impl Sealed for SharedKey {}
439 impl Sealed for Manual {}
440}