util.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. use std::fs::{create_dir_all, File};
  2. use std::io::copy;
  3. use std::ops::Deref;
  4. use std::path::{Path, PathBuf};
  5. use std::sync::Arc;
  6. use std::time::Duration;
  7. use anyhow::Error;
  8. use collab_folder::core::FolderData;
  9. use collab_plugins::cloud_storage::RemoteCollabStorage;
  10. use nanoid::nanoid;
  11. use tokio::sync::mpsc::Receiver;
  12. use tokio::time::timeout;
  13. use zip::ZipArchive;
  14. use flowy_database_deps::cloud::DatabaseCloudService;
  15. use flowy_folder_deps::cloud::{FolderCloudService, FolderSnapshot};
  16. use flowy_server::supabase::api::*;
  17. use flowy_server::{AppFlowyEncryption, EncryptionImpl};
  18. use flowy_server_config::supabase_config::SupabaseConfiguration;
  19. use flowy_test::event_builder::EventBuilder;
  20. use flowy_test::Cleaner;
  21. use flowy_test::FlowyCoreTest;
  22. use flowy_user::entities::{AuthTypePB, UpdateUserProfilePayloadPB, UserCredentialsPB};
  23. use flowy_user::errors::FlowyError;
  24. use flowy_user::event_map::UserCloudServiceProvider;
  25. use flowy_user::event_map::UserEvent::*;
  26. use flowy_user_deps::cloud::UserCloudService;
  27. use flowy_user_deps::entities::AuthType;
  28. pub fn get_supabase_config() -> Option<SupabaseConfiguration> {
  29. dotenv::from_path(".env.ci").ok()?;
  30. SupabaseConfiguration::from_env().ok()
  31. }
  32. pub struct FlowySupabaseTest {
  33. inner: FlowyCoreTest,
  34. }
  35. impl FlowySupabaseTest {
  36. pub fn new() -> Option<Self> {
  37. let _ = get_supabase_config()?;
  38. let test = FlowyCoreTest::new();
  39. test.set_auth_type(AuthTypePB::Supabase);
  40. test.server_provider.set_auth_type(AuthType::Supabase);
  41. Some(Self { inner: test })
  42. }
  43. pub async fn check_user_with_uuid(&self, uuid: &str) -> Result<(), FlowyError> {
  44. match EventBuilder::new(self.inner.clone())
  45. .event(CheckUser)
  46. .payload(UserCredentialsPB::from_uuid(uuid))
  47. .async_send()
  48. .await
  49. .error()
  50. {
  51. None => Ok(()),
  52. Some(error) => Err(error),
  53. }
  54. }
  55. pub async fn update_user_profile(
  56. &self,
  57. payload: UpdateUserProfilePayloadPB,
  58. ) -> Option<FlowyError> {
  59. EventBuilder::new(self.inner.clone())
  60. .event(UpdateUserProfile)
  61. .payload(payload)
  62. .async_send()
  63. .await
  64. .error()
  65. }
  66. }
  67. impl Deref for FlowySupabaseTest {
  68. type Target = FlowyCoreTest;
  69. fn deref(&self) -> &Self::Target {
  70. &self.inner
  71. }
  72. }
  73. pub async fn receive_with_timeout<T>(
  74. receiver: &mut Receiver<T>,
  75. duration: Duration,
  76. ) -> Result<T, Box<dyn std::error::Error>> {
  77. let res = timeout(duration, receiver.recv())
  78. .await?
  79. .ok_or(anyhow::anyhow!("recv timeout"))?;
  80. Ok(res)
  81. }
  82. pub fn get_supabase_ci_config() -> Option<SupabaseConfiguration> {
  83. dotenv::from_filename("./.env.ci").ok()?;
  84. SupabaseConfiguration::from_env().ok()
  85. }
  86. #[allow(dead_code)]
  87. pub fn get_supabase_dev_config() -> Option<SupabaseConfiguration> {
  88. dotenv::from_filename("./.env.dev").ok()?;
  89. SupabaseConfiguration::from_env().ok()
  90. }
  91. pub fn collab_service() -> Arc<dyn RemoteCollabStorage> {
  92. let (server, encryption_impl) = appflowy_server(None);
  93. Arc::new(SupabaseCollabStorageImpl::new(
  94. server,
  95. None,
  96. Arc::downgrade(&encryption_impl),
  97. ))
  98. }
  99. pub fn database_service() -> Arc<dyn DatabaseCloudService> {
  100. let (server, _encryption_impl) = appflowy_server(None);
  101. Arc::new(SupabaseDatabaseServiceImpl::new(server))
  102. }
  103. pub fn user_auth_service() -> Arc<dyn UserCloudService> {
  104. let (server, _encryption_impl) = appflowy_server(None);
  105. Arc::new(SupabaseUserServiceImpl::new(server, vec![], None))
  106. }
  107. pub fn folder_service() -> Arc<dyn FolderCloudService> {
  108. let (server, _encryption_impl) = appflowy_server(None);
  109. Arc::new(SupabaseFolderServiceImpl::new(server))
  110. }
  111. #[allow(dead_code)]
  112. pub fn encryption_folder_service(
  113. secret: Option<String>,
  114. ) -> (Arc<dyn FolderCloudService>, Arc<dyn AppFlowyEncryption>) {
  115. let (server, encryption_impl) = appflowy_server(secret);
  116. let service = Arc::new(SupabaseFolderServiceImpl::new(server));
  117. (service, encryption_impl)
  118. }
  119. pub fn encryption_collab_service(
  120. secret: Option<String>,
  121. ) -> (Arc<dyn RemoteCollabStorage>, Arc<dyn AppFlowyEncryption>) {
  122. let (server, encryption_impl) = appflowy_server(secret);
  123. let service = Arc::new(SupabaseCollabStorageImpl::new(
  124. server,
  125. None,
  126. Arc::downgrade(&encryption_impl),
  127. ));
  128. (service, encryption_impl)
  129. }
  130. pub async fn get_folder_data_from_server(
  131. folder_id: &str,
  132. encryption_secret: Option<String>,
  133. ) -> Result<Option<FolderData>, Error> {
  134. let (cloud_service, _encryption) = encryption_folder_service(encryption_secret);
  135. cloud_service.get_folder_data(folder_id).await
  136. }
  137. pub async fn get_folder_snapshots(
  138. folder_id: &str,
  139. encryption_secret: Option<String>,
  140. ) -> Vec<FolderSnapshot> {
  141. let (cloud_service, _encryption) = encryption_folder_service(encryption_secret);
  142. cloud_service
  143. .get_folder_snapshots(folder_id, 10)
  144. .await
  145. .unwrap()
  146. }
  147. pub fn appflowy_server(
  148. encryption_secret: Option<String>,
  149. ) -> (SupabaseServerServiceImpl, Arc<dyn AppFlowyEncryption>) {
  150. let config = SupabaseConfiguration::from_env().unwrap();
  151. let encryption_impl: Arc<dyn AppFlowyEncryption> =
  152. Arc::new(EncryptionImpl::new(encryption_secret));
  153. let encryption = Arc::downgrade(&encryption_impl);
  154. let server = Arc::new(RESTfulPostgresServer::new(config, encryption));
  155. (SupabaseServerServiceImpl::new(server), encryption_impl)
  156. }
  157. pub fn unzip_history_user_db(root: &str, folder_name: &str) -> std::io::Result<(Cleaner, PathBuf)> {
  158. // Open the zip file
  159. let zip_file_path = format!("{}/{}.zip", root, folder_name);
  160. let reader = File::open(zip_file_path)?;
  161. let output_folder_path = format!("{}/unit_test_{}", root, nanoid!(6));
  162. // Create a ZipArchive from the file
  163. let mut archive = ZipArchive::new(reader)?;
  164. // Iterate through each file in the zip
  165. for i in 0..archive.len() {
  166. let mut file = archive.by_index(i)?;
  167. let output_path = Path::new(&output_folder_path).join(file.mangled_name());
  168. if file.name().ends_with('/') {
  169. // Create directory
  170. create_dir_all(&output_path)?;
  171. } else {
  172. // Write file
  173. if let Some(p) = output_path.parent() {
  174. if !p.exists() {
  175. create_dir_all(p)?;
  176. }
  177. }
  178. let mut outfile = File::create(&output_path)?;
  179. copy(&mut file, &mut outfile)?;
  180. }
  181. }
  182. let path = format!("{}/{}", output_folder_path, folder_name);
  183. Ok((
  184. Cleaner::new(PathBuf::from(output_folder_path)),
  185. PathBuf::from(path),
  186. ))
  187. }