controller.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. use crate::{
  2. entities::logged_user::LoggedUser,
  3. services::{
  4. core::{trash::read_trash_ids, view::persistence::*},
  5. document::persistence::{create_document, delete_document, DocumentKVPersistence},
  6. },
  7. util::sqlx_ext::{map_sqlx_error, DBTransaction, SqlBuilder},
  8. };
  9. use backend_service::errors::{invalid_params, ServerError};
  10. use bytes::Bytes;
  11. use chrono::Utc;
  12. use flowy_collaboration::{
  13. entities::revision::{RepeatedRevision, Revision},
  14. protobuf::CreateDocParams as CreateDocParamsPB,
  15. };
  16. use flowy_core_data_model::{
  17. parser::{
  18. app::AppIdentify,
  19. view::{ViewDesc, ViewName, ViewThumbnail},
  20. },
  21. protobuf::{CreateViewParams as CreateViewParamsPB, RepeatedView as RepeatedViewPB, View as ViewPB},
  22. };
  23. use sqlx::{postgres::PgArguments, Postgres};
  24. use std::{convert::TryInto, sync::Arc};
  25. use uuid::Uuid;
  26. pub(crate) async fn update_view(
  27. transaction: &mut DBTransaction<'_>,
  28. view_id: Uuid,
  29. name: Option<String>,
  30. desc: Option<String>,
  31. thumbnail: Option<String>,
  32. ) -> Result<(), ServerError> {
  33. let (sql, args) = SqlBuilder::update(VIEW_TABLE)
  34. .add_some_arg("name", name)
  35. .add_some_arg("description", desc)
  36. .add_some_arg("thumbnail", thumbnail)
  37. .add_some_arg("modified_time", Some(Utc::now()))
  38. .and_where_eq("id", view_id)
  39. .build()?;
  40. sqlx::query_with(&sql, args)
  41. .execute(transaction)
  42. .await
  43. .map_err(map_sqlx_error)?;
  44. Ok(())
  45. }
  46. #[tracing::instrument(skip(transaction, kv_store), err)]
  47. pub(crate) async fn delete_view(
  48. transaction: &mut DBTransaction<'_>,
  49. kv_store: &Arc<DocumentKVPersistence>,
  50. view_ids: Vec<Uuid>,
  51. ) -> Result<(), ServerError> {
  52. for view_id in view_ids {
  53. let (sql, args) = SqlBuilder::delete(VIEW_TABLE).and_where_eq("id", &view_id).build()?;
  54. let _ = sqlx::query_with(&sql, args)
  55. .execute(transaction as &mut DBTransaction<'_>)
  56. .await
  57. .map_err(map_sqlx_error)?;
  58. let _ = delete_document(kv_store, view_id).await?;
  59. }
  60. Ok(())
  61. }
  62. #[tracing::instrument(name = "create_view", level = "debug", skip(transaction, kv_store), err)]
  63. pub(crate) async fn create_view(
  64. transaction: &mut DBTransaction<'_>,
  65. kv_store: Arc<DocumentKVPersistence>,
  66. params: CreateViewParamsPB,
  67. user_id: &str,
  68. ) -> Result<ViewPB, ServerError> {
  69. let view_id = check_view_id(params.view_id.clone())?;
  70. let name = ViewName::parse(params.name).map_err(invalid_params)?;
  71. let belong_to_id = AppIdentify::parse(params.belong_to_id).map_err(invalid_params)?;
  72. let thumbnail = ViewThumbnail::parse(params.thumbnail).map_err(invalid_params)?;
  73. let desc = ViewDesc::parse(params.desc).map_err(invalid_params)?;
  74. let (sql, args, view) = NewViewSqlBuilder::new(view_id, belong_to_id.as_ref())
  75. .name(name.as_ref())
  76. .desc(desc.as_ref())
  77. .thumbnail(thumbnail.as_ref())
  78. .view_type(params.view_type)
  79. .build()?;
  80. let _ = sqlx::query_with(&sql, args)
  81. .execute(transaction as &mut DBTransaction<'_>)
  82. .await
  83. .map_err(map_sqlx_error)?;
  84. let delta_data = Bytes::from(params.view_data);
  85. let md5 = format!("{:x}", md5::compute(&delta_data));
  86. let revision = Revision::new(&view.id, 0, 0, delta_data, user_id, md5);
  87. let repeated_revision = RepeatedRevision::new(vec![revision]);
  88. let mut create_doc_params = CreateDocParamsPB::new();
  89. create_doc_params.set_revisions(repeated_revision.try_into().unwrap());
  90. create_doc_params.set_id(view.id.clone());
  91. let _ = create_document(&kv_store, create_doc_params).await?;
  92. Ok(view)
  93. }
  94. pub(crate) async fn read_view(
  95. user: &LoggedUser,
  96. view_id: Uuid,
  97. transaction: &mut DBTransaction<'_>,
  98. ) -> Result<ViewPB, ServerError> {
  99. let table = read_view_table(view_id, transaction as &mut DBTransaction<'_>).await?;
  100. let read_trash_ids = read_trash_ids(user, transaction).await?;
  101. if read_trash_ids.contains(&table.id.to_string()) {
  102. return Err(ServerError::record_not_found());
  103. }
  104. let mut views = RepeatedViewPB::default();
  105. views.set_items(
  106. read_view_belong_to_id(&table.id.to_string(), &user, transaction)
  107. .await?
  108. .into(),
  109. );
  110. let mut view: ViewPB = table.into();
  111. view.set_belongings(views);
  112. Ok(view)
  113. }
  114. pub(crate) async fn read_view_table(
  115. view_id: Uuid,
  116. transaction: &mut DBTransaction<'_>,
  117. ) -> Result<ViewTable, ServerError> {
  118. let (sql, args) = SqlBuilder::select(VIEW_TABLE)
  119. .add_field("*")
  120. .and_where_eq("id", view_id)
  121. .build()?;
  122. let table = sqlx::query_as_with::<Postgres, ViewTable, PgArguments>(&sql, args)
  123. .fetch_one(transaction as &mut DBTransaction<'_>)
  124. .await
  125. .map_err(map_sqlx_error)?;
  126. Ok(table)
  127. }
  128. // transaction must be commit from caller
  129. pub(crate) async fn read_view_belong_to_id<'c>(
  130. id: &str,
  131. user: &LoggedUser,
  132. transaction: &mut DBTransaction<'_>,
  133. ) -> Result<Vec<ViewPB>, ServerError> {
  134. // TODO: add index for app_table
  135. let (sql, args) = SqlBuilder::select(VIEW_TABLE)
  136. .add_field("*")
  137. .and_where_eq("belong_to_id", id)
  138. .build()?;
  139. let mut tables = sqlx::query_as_with::<Postgres, ViewTable, PgArguments>(&sql, args)
  140. .fetch_all(transaction as &mut DBTransaction<'_>)
  141. .await
  142. .map_err(map_sqlx_error)?;
  143. let read_trash_ids = read_trash_ids(user, transaction).await?;
  144. tables.retain(|table| !read_trash_ids.contains(&table.id.to_string()));
  145. let views = tables.into_iter().map(|table| table.into()).collect::<Vec<ViewPB>>();
  146. Ok(views)
  147. }