cloud.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. use std::collections::HashMap;
  2. use std::fmt::{Display, Formatter};
  3. use std::str::FromStr;
  4. use anyhow::Error;
  5. use collab_entity::CollabObject;
  6. use serde::{Deserialize, Serialize};
  7. use serde_json::Value;
  8. use uuid::Uuid;
  9. use flowy_error::{ErrorCode, FlowyError};
  10. use lib_infra::box_any::BoxAny;
  11. use lib_infra::future::FutureResult;
  12. use crate::entities::{
  13. AuthResponse, UpdateUserProfileParams, UserCredentials, UserProfile, UserWorkspace,
  14. };
  15. #[derive(Debug, Clone, Serialize, Deserialize)]
  16. pub struct UserCloudConfig {
  17. pub enable_sync: bool,
  18. enable_encrypt: bool,
  19. // The secret used to encrypt the user's data
  20. pub encrypt_secret: String,
  21. }
  22. impl UserCloudConfig {
  23. pub fn new(encrypt_secret: String) -> Self {
  24. Self {
  25. enable_sync: true,
  26. enable_encrypt: false,
  27. encrypt_secret,
  28. }
  29. }
  30. pub fn enable_encrypt(&self) -> bool {
  31. self.enable_encrypt
  32. }
  33. pub fn with_enable_encrypt(mut self, enable_encrypt: bool) -> Self {
  34. self.enable_encrypt = enable_encrypt;
  35. // When the enable_encrypt is true, the encrypt_secret should not be empty
  36. debug_assert!(!self.encrypt_secret.is_empty());
  37. self
  38. }
  39. }
  40. impl Display for UserCloudConfig {
  41. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  42. write!(
  43. f,
  44. "enable_sync: {}, enable_encrypt: {}",
  45. self.enable_sync, self.enable_encrypt
  46. )
  47. }
  48. }
  49. /// Provide the generic interface for the user cloud service
  50. /// The user cloud service is responsible for the user authentication and user profile management
  51. pub trait UserCloudService: Send + Sync + 'static {
  52. /// Sign up a new account.
  53. /// The type of the params is defined the this trait's implementation.
  54. /// Use the `unbox_or_error` of the [BoxAny] to get the params.
  55. fn sign_up(&self, params: BoxAny) -> FutureResult<AuthResponse, Error>;
  56. /// Sign in an account
  57. /// The type of the params is defined the this trait's implementation.
  58. fn sign_in(&self, params: BoxAny) -> FutureResult<AuthResponse, Error>;
  59. /// Sign out an account
  60. fn sign_out(&self, token: Option<String>) -> FutureResult<(), Error>;
  61. /// Generate a sign in url for the user with the given email
  62. fn generate_sign_in_url_with_email(&self, email: &str) -> FutureResult<String, Error>;
  63. /// When the user opens the OAuth URL, it redirects to the corresponding provider's OAuth web page.
  64. /// After the user is authenticated, the browser will open a deep link to the AppFlowy app (iOS, macOS, etc.),
  65. /// which will call [Client::sign_in_with_url] to sign in.
  66. ///
  67. /// For example, the OAuth URL on Google looks like `https://appflowy.io/authorize?provider=google`.
  68. fn generate_oauth_url_with_provider(&self, provider: &str) -> FutureResult<String, Error>;
  69. /// Using the user's token to update the user information
  70. fn update_user(
  71. &self,
  72. credential: UserCredentials,
  73. params: UpdateUserProfileParams,
  74. ) -> FutureResult<(), Error>;
  75. /// Get the user information using the user's token or uid
  76. /// return None if the user is not found
  77. fn get_user_profile(
  78. &self,
  79. credential: UserCredentials,
  80. ) -> FutureResult<Option<UserProfile>, Error>;
  81. /// Return the all the workspaces of the user
  82. fn get_user_workspaces(&self, uid: i64) -> FutureResult<Vec<UserWorkspace>, Error>;
  83. fn check_user(&self, credential: UserCredentials) -> FutureResult<(), Error>;
  84. fn add_workspace_member(
  85. &self,
  86. user_email: String,
  87. workspace_id: String,
  88. ) -> FutureResult<(), Error>;
  89. fn remove_workspace_member(
  90. &self,
  91. user_email: String,
  92. workspace_id: String,
  93. ) -> FutureResult<(), Error>;
  94. fn get_user_awareness_updates(&self, uid: i64) -> FutureResult<Vec<Vec<u8>>, Error>;
  95. fn receive_realtime_event(&self, _json: Value) {}
  96. fn subscribe_user_update(&self) -> Option<UserUpdateReceiver> {
  97. None
  98. }
  99. fn reset_workspace(&self, collab_object: CollabObject) -> FutureResult<(), Error>;
  100. fn create_collab_object(
  101. &self,
  102. collab_object: &CollabObject,
  103. data: Vec<u8>,
  104. ) -> FutureResult<(), Error>;
  105. }
  106. pub type UserUpdateReceiver = tokio::sync::broadcast::Receiver<UserUpdate>;
  107. pub type UserUpdateSender = tokio::sync::broadcast::Sender<UserUpdate>;
  108. #[derive(Debug, Clone)]
  109. pub struct UserUpdate {
  110. pub uid: i64,
  111. pub name: String,
  112. pub email: String,
  113. pub encryption_sign: String,
  114. }
  115. pub fn uuid_from_map(map: &HashMap<String, String>) -> Result<Uuid, Error> {
  116. let uuid = map
  117. .get("uuid")
  118. .ok_or_else(|| FlowyError::new(ErrorCode::MissingAuthField, "Missing uuid field"))?
  119. .as_str();
  120. let uuid = Uuid::from_str(uuid)?;
  121. Ok(uuid)
  122. }