Merge pull request #940 from AppFlowy-IO/feat/custom-namespace-v2
feat: delete default view for workspace
This commit is contained in:
commit
348a73685e
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -217,6 +217,23 @@ impl Client {
|
||||||
AppResponse::<()>::from_response(resp).await?.into_error()
|
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(
|
pub async fn get_default_publish_view_info(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,36 @@ pub async fn update_workspace_default_publish_view<'a, E: Executor<'a, Database
|
||||||
Ok(())
|
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]
|
#[inline]
|
||||||
pub async fn select_workspace_publish_namespace<'a, E: Executor<'a, Database = Postgres>>(
|
pub async fn select_workspace_publish_namespace<'a, E: Executor<'a, Database = Postgres>>(
|
||||||
executor: E,
|
executor: E,
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,7 @@ pub fn workspace_scope() -> Scope {
|
||||||
.service(
|
.service(
|
||||||
web::resource("/{workspace_id}/publish-default")
|
web::resource("/{workspace_id}/publish-default")
|
||||||
.route(web::put().to(put_workspace_default_published_view_handler))
|
.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)),
|
.route(web::get().to(get_workspace_published_default_info_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
|
|
@ -1148,7 +1149,6 @@ async fn put_workspace_default_published_view_handler(
|
||||||
let new_default_pub_view_id = payload.into_inner().view_id;
|
let new_default_pub_view_id = payload.into_inner().view_id;
|
||||||
biz::workspace::publish::set_workspace_default_publish_view(
|
biz::workspace::publish::set_workspace_default_publish_view(
|
||||||
&state.pg_pool,
|
&state.pg_pool,
|
||||||
&user_uuid,
|
|
||||||
&workspace_id,
|
&workspace_id,
|
||||||
&new_default_pub_view_id,
|
&new_default_pub_view_id,
|
||||||
)
|
)
|
||||||
|
|
@ -1156,6 +1156,21 @@ async fn put_workspace_default_published_view_handler(
|
||||||
Ok(Json(AppResponse::Ok()))
|
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(
|
async fn get_workspace_published_default_info_handler(
|
||||||
workspace_id: web::Path<Uuid>,
|
workspace_id: web::Path<Uuid>,
|
||||||
state: Data<AppState>,
|
state: Data<AppState>,
|
||||||
|
|
@ -1180,13 +1195,8 @@ async fn put_publish_namespace_handler(
|
||||||
.enforce_role(&uid, &workspace_id.to_string(), AFRole::Owner)
|
.enforce_role(&uid, &workspace_id.to_string(), AFRole::Owner)
|
||||||
.await?;
|
.await?;
|
||||||
let new_namespace = payload.into_inner().new_namespace;
|
let new_namespace = payload.into_inner().new_namespace;
|
||||||
biz::workspace::publish::set_workspace_namespace(
|
biz::workspace::publish::set_workspace_namespace(&state.pg_pool, &workspace_id, &new_namespace)
|
||||||
&state.pg_pool,
|
.await?;
|
||||||
&user_uuid,
|
|
||||||
&workspace_id,
|
|
||||||
&new_namespace,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(Json(AppResponse::Ok()))
|
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?;
|
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
|
||||||
state
|
state
|
||||||
.workspace_access_control
|
.workspace_access_control
|
||||||
.enforce_action(&uid, &workspace_id.to_string(), Action::Read)
|
.enforce_role(&uid, &workspace_id.to_string(), AFRole::Owner)
|
||||||
.await?;
|
.await?;
|
||||||
let res = biz::workspace::ops::get_workspace_document_total_bytes(
|
let res =
|
||||||
&state.pg_pool,
|
biz::workspace::ops::get_workspace_document_total_bytes(&state.pg_pool, &workspace_id).await?;
|
||||||
&user_uuid,
|
|
||||||
&workspace_id,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(Json(AppResponse::Ok().with_data(res)))
|
Ok(Json(AppResponse::Ok().with_data(res)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -604,11 +604,8 @@ pub async fn update_workspace_member(
|
||||||
|
|
||||||
pub async fn get_workspace_document_total_bytes(
|
pub async fn get_workspace_document_total_bytes(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
|
||||||
workspace_id: &Uuid,
|
workspace_id: &Uuid,
|
||||||
) -> Result<WorkspaceUsage, AppError> {
|
) -> 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?;
|
let byte_count = select_workspace_total_collab_bytes(pg_pool, workspace_id).await?;
|
||||||
Ok(WorkspaceUsage {
|
Ok(WorkspaceUsage {
|
||||||
total_document_size: byte_count,
|
total_document_size: byte_count,
|
||||||
|
|
@ -646,19 +643,6 @@ pub async fn update_workspace_settings(
|
||||||
Ok(setting)
|
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(
|
async fn check_if_user_is_allowed_to_delete_comment(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
user_uuid: &Uuid,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use database::{
|
||||||
publish::{
|
publish::{
|
||||||
select_all_published_collab_info, select_default_published_view_id,
|
select_all_published_collab_info, select_default_published_view_id,
|
||||||
select_default_published_view_id_for_namespace, update_published_collabs,
|
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;
|
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},
|
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(
|
async fn check_workspace_owner_or_publisher(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
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(
|
pub async fn set_workspace_namespace(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
|
||||||
workspace_id: &Uuid,
|
workspace_id: &Uuid,
|
||||||
new_namespace: &str,
|
new_namespace: &str,
|
||||||
) -> Result<(), AppError> {
|
) -> Result<(), AppError> {
|
||||||
check_workspace_owner(pg_pool, user_uuid, workspace_id).await?;
|
|
||||||
check_workspace_namespace(new_namespace).await?;
|
check_workspace_namespace(new_namespace).await?;
|
||||||
if select_workspace_publish_namespace_exists(pg_pool, workspace_id, new_namespace).await? {
|
if select_workspace_publish_namespace_exists(pg_pool, workspace_id, new_namespace).await? {
|
||||||
return Err(AppError::PublishNamespaceAlreadyTaken(
|
return Err(AppError::PublishNamespaceAlreadyTaken(
|
||||||
|
|
@ -104,15 +100,21 @@ pub async fn set_workspace_namespace(
|
||||||
|
|
||||||
pub async fn set_workspace_default_publish_view(
|
pub async fn set_workspace_default_publish_view(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
|
||||||
workspace_id: &Uuid,
|
workspace_id: &Uuid,
|
||||||
new_view_id: &Uuid,
|
new_view_id: &Uuid,
|
||||||
) -> Result<(), AppError> {
|
) -> 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?;
|
update_workspace_default_publish_view(pg_pool, workspace_id, new_view_id).await?;
|
||||||
Ok(())
|
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(
|
pub async fn get_workspace_default_publish_view_info(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
workspace_id: &Uuid,
|
workspace_id: &Uuid,
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use collab_document::document::Document;
|
||||||
use collab_entity::CollabType;
|
use collab_entity::CollabType;
|
||||||
use collab_folder::{CollabOrigin, Folder, UserId};
|
use collab_folder::{CollabOrigin, Folder, UserId};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use shared_entity::dto::publish_dto::PublishDatabaseData;
|
use shared_entity::dto::publish_dto::PublishDatabaseData;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
|
|
@ -249,6 +250,16 @@ async fn test_publish_doc() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(default_info_meta.info.view_id, view_id_1);
|
assert_eq!(default_info_meta.info.view_id, view_id_1);
|
||||||
assert_eq!(default_info_meta.meta.title, "my_title_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();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MyCustomMetadata {
|
struct MyCustomMetadata {
|
||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue