Merge pull request #940 from AppFlowy-IO/feat/custom-namespace-v2

feat: delete default view for workspace
This commit is contained in:
Zack 2024-10-28 15:46:13 +08:00 committed by GitHub
commit 348a73685e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 103 additions and 39 deletions

View File

@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE af_workspace\n SET default_published_view_id = NULL\n WHERE workspace_id = $1\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": []
},
"hash": "fffe6f01abf0e5d8649a49b5793ccb92a9f823f07c363341357ea74bf4f4a16d"
}

View File

@ -217,6 +217,23 @@ impl Client {
AppResponse::<()>::from_response(resp).await?.into_error()
}
pub async fn delete_default_publish_view(
&self,
workspace_id: &str,
) -> Result<(), AppResponseError> {
let url = format!(
"{}/api/workspace/{}/publish-default",
self.base_url, workspace_id
);
let resp = self
.http_client_with_auth(Method::DELETE, &url)
.await?
.send()
.await?;
log_request_id(&resp);
AppResponse::<()>::from_response(resp).await?.into_error()
}
pub async fn get_default_publish_view_info(
&self,
workspace_id: &str,

View File

@ -112,6 +112,36 @@ pub async fn update_workspace_default_publish_view<'a, E: Executor<'a, Database
Ok(())
}
#[inline]
pub async fn update_workspace_default_publish_view_set_null<
'a,
E: Executor<'a, Database = Postgres>,
>(
executor: E,
workspace_id: &Uuid,
) -> Result<(), AppError> {
let res = sqlx::query!(
r#"
UPDATE af_workspace
SET default_published_view_id = NULL
WHERE workspace_id = $1
"#,
workspace_id,
)
.execute(executor)
.await?;
if res.rows_affected() != 1 {
tracing::error!(
"Failed to unset workspace default publish view, workspace_id: {}, rows_affected: {}",
workspace_id,
res.rows_affected()
);
}
Ok(())
}
#[inline]
pub async fn select_workspace_publish_namespace<'a, E: Executor<'a, Database = Postgres>>(
executor: E,

View File

@ -199,6 +199,7 @@ pub fn workspace_scope() -> Scope {
.service(
web::resource("/{workspace_id}/publish-default")
.route(web::put().to(put_workspace_default_published_view_handler))
.route(web::delete().to(delete_workspace_default_published_view_handler))
.route(web::get().to(get_workspace_published_default_info_handler)),
)
.service(
@ -1148,7 +1149,6 @@ async fn put_workspace_default_published_view_handler(
let new_default_pub_view_id = payload.into_inner().view_id;
biz::workspace::publish::set_workspace_default_publish_view(
&state.pg_pool,
&user_uuid,
&workspace_id,
&new_default_pub_view_id,
)
@ -1156,6 +1156,21 @@ async fn put_workspace_default_published_view_handler(
Ok(Json(AppResponse::Ok()))
}
async fn delete_workspace_default_published_view_handler(
user_uuid: UserUuid,
workspace_id: web::Path<Uuid>,
state: Data<AppState>,
) -> Result<Json<AppResponse<()>>> {
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
state
.workspace_access_control
.enforce_role(&uid, &workspace_id.to_string(), AFRole::Owner)
.await?;
biz::workspace::publish::unset_workspace_default_publish_view(&state.pg_pool, &workspace_id)
.await?;
Ok(Json(AppResponse::Ok()))
}
async fn get_workspace_published_default_info_handler(
workspace_id: web::Path<Uuid>,
state: Data<AppState>,
@ -1180,13 +1195,8 @@ async fn put_publish_namespace_handler(
.enforce_role(&uid, &workspace_id.to_string(), AFRole::Owner)
.await?;
let new_namespace = payload.into_inner().new_namespace;
biz::workspace::publish::set_workspace_namespace(
&state.pg_pool,
&user_uuid,
&workspace_id,
&new_namespace,
)
.await?;
biz::workspace::publish::set_workspace_namespace(&state.pg_pool, &workspace_id, &new_namespace)
.await?;
Ok(Json(AppResponse::Ok()))
}
@ -1546,14 +1556,10 @@ async fn get_workspace_usage_handler(
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
state
.workspace_access_control
.enforce_action(&uid, &workspace_id.to_string(), Action::Read)
.enforce_role(&uid, &workspace_id.to_string(), AFRole::Owner)
.await?;
let res = biz::workspace::ops::get_workspace_document_total_bytes(
&state.pg_pool,
&user_uuid,
&workspace_id,
)
.await?;
let res =
biz::workspace::ops::get_workspace_document_total_bytes(&state.pg_pool, &workspace_id).await?;
Ok(Json(AppResponse::Ok().with_data(res)))
}

View File

@ -604,11 +604,8 @@ pub async fn update_workspace_member(
pub async fn get_workspace_document_total_bytes(
pg_pool: &PgPool,
user_uuid: &Uuid,
workspace_id: &Uuid,
) -> Result<WorkspaceUsage, AppError> {
check_workspace_owner(pg_pool, user_uuid, workspace_id).await?;
let byte_count = select_workspace_total_collab_bytes(pg_pool, workspace_id).await?;
Ok(WorkspaceUsage {
total_document_size: byte_count,
@ -646,19 +643,6 @@ pub async fn update_workspace_settings(
Ok(setting)
}
pub async fn check_workspace_owner(
pg_pool: &PgPool,
user_uuid: &Uuid,
workspace_id: &Uuid,
) -> Result<(), AppError> {
match select_user_is_workspace_owner(pg_pool, user_uuid, workspace_id).await? {
true => Ok(()),
false => Err(AppError::UserUnAuthorized(
"User is not the owner of the workspace".to_string(),
)),
}
}
async fn check_if_user_is_allowed_to_delete_comment(
pg_pool: &PgPool,
user_uuid: &Uuid,

View File

@ -4,7 +4,7 @@ use database::{
publish::{
select_all_published_collab_info, select_default_published_view_id,
select_default_published_view_id_for_namespace, update_published_collabs,
update_workspace_default_publish_view,
update_workspace_default_publish_view, update_workspace_default_publish_view_set_null,
},
};
use database_entity::dto::PatchPublishedCollab;
@ -39,8 +39,6 @@ use crate::{
biz::collab::{folder_view::to_dto_folder_view_miminal, ops::get_latest_collab_folder},
};
use super::ops::check_workspace_owner;
async fn check_workspace_owner_or_publisher(
pg_pool: &PgPool,
user_uuid: &Uuid,
@ -87,11 +85,9 @@ fn get_collab_s3_key(workspace_id: &Uuid, view_id: &Uuid) -> String {
pub async fn set_workspace_namespace(
pg_pool: &PgPool,
user_uuid: &Uuid,
workspace_id: &Uuid,
new_namespace: &str,
) -> Result<(), AppError> {
check_workspace_owner(pg_pool, user_uuid, workspace_id).await?;
check_workspace_namespace(new_namespace).await?;
if select_workspace_publish_namespace_exists(pg_pool, workspace_id, new_namespace).await? {
return Err(AppError::PublishNamespaceAlreadyTaken(
@ -104,15 +100,21 @@ pub async fn set_workspace_namespace(
pub async fn set_workspace_default_publish_view(
pg_pool: &PgPool,
user_uuid: &Uuid,
workspace_id: &Uuid,
new_view_id: &Uuid,
) -> Result<(), AppError> {
check_workspace_owner(pg_pool, user_uuid, workspace_id).await?;
update_workspace_default_publish_view(pg_pool, workspace_id, new_view_id).await?;
Ok(())
}
pub async fn unset_workspace_default_publish_view(
pg_pool: &PgPool,
workspace_id: &Uuid,
) -> Result<(), AppError> {
update_workspace_default_publish_view_set_null(pg_pool, workspace_id).await?;
Ok(())
}
pub async fn get_workspace_default_publish_view_info(
pg_pool: &PgPool,
workspace_id: &Uuid,

View File

@ -17,6 +17,7 @@ use collab_document::document::Document;
use collab_entity::CollabType;
use collab_folder::{CollabOrigin, Folder, UserId};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use shared_entity::dto::publish_dto::PublishDatabaseData;
use std::collections::{HashMap, HashSet};
use std::thread::sleep;
@ -249,6 +250,16 @@ async fn test_publish_doc() {
.unwrap();
assert_eq!(default_info_meta.info.view_id, view_id_1);
assert_eq!(default_info_meta.meta.title, "my_title_1");
// Owner of workspace unset the default publish view
c.delete_default_publish_view(&workspace_id).await.unwrap();
// Public can no longer get default publish view info
let err = localhost_client()
.get_default_published_collab::<PublishInfoMeta<MyCustomMetadata>>(&my_namespace)
.await
.unwrap_err();
assert_eq!(err.code, ErrorCode::RecordNotFound, "{:?}", err);
}
{
@ -778,7 +789,7 @@ async fn workspace_member_publish_unpublish() {
.unwrap();
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
struct MyCustomMetadata {
title: String,
}