fix: fix various publish issues
This commit is contained in:
parent
b02f8a2844
commit
395486adc3
|
|
@ -117,9 +117,6 @@ pub enum AppError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
OverrideWithIncorrectData(String),
|
OverrideWithIncorrectData(String),
|
||||||
|
|
||||||
#[error("{0}")]
|
|
||||||
PublishNamespaceNotSet(String),
|
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
PublishNamespaceAlreadyTaken(String),
|
PublishNamespaceAlreadyTaken(String),
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +177,6 @@ impl AppError {
|
||||||
AppError::NoRequiredData(_) => ErrorCode::NoRequiredData,
|
AppError::NoRequiredData(_) => ErrorCode::NoRequiredData,
|
||||||
AppError::OverrideWithIncorrectData(_) => ErrorCode::OverrideWithIncorrectData,
|
AppError::OverrideWithIncorrectData(_) => ErrorCode::OverrideWithIncorrectData,
|
||||||
AppError::Utf8Error(_) => ErrorCode::Internal,
|
AppError::Utf8Error(_) => ErrorCode::Internal,
|
||||||
AppError::PublishNamespaceNotSet(_) => ErrorCode::PublishNamespaceNotSet,
|
|
||||||
AppError::PublishNamespaceAlreadyTaken(_) => ErrorCode::PublishNamespaceAlreadyTaken,
|
AppError::PublishNamespaceAlreadyTaken(_) => ErrorCode::PublishNamespaceAlreadyTaken,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -887,7 +887,7 @@ pub async fn update_workspace_publish_namespace<'a, E: Executor<'a, Database = P
|
||||||
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,
|
||||||
workspace_id: &Uuid,
|
workspace_id: &Uuid,
|
||||||
) -> Result<Option<String>, AppError> {
|
) -> Result<String, AppError> {
|
||||||
let res = sqlx::query_scalar!(
|
let res = sqlx::query_scalar!(
|
||||||
r#"
|
r#"
|
||||||
SELECT publish_namespace
|
SELECT publish_namespace
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- Update existing null values to ensure no nulls are present before adding NOT NULL constraint
|
||||||
|
UPDATE public.af_workspace
|
||||||
|
SET publish_namespace = uuid_generate_v4()::text
|
||||||
|
WHERE publish_namespace IS NULL;
|
||||||
|
|
||||||
|
-- Alter the column to set NOT NULL constraint and a default value
|
||||||
|
ALTER TABLE public.af_workspace
|
||||||
|
ALTER COLUMN publish_namespace SET NOT NULL,
|
||||||
|
ALTER COLUMN publish_namespace SET DEFAULT uuid_generate_v4()::text;
|
||||||
|
|
@ -47,6 +47,7 @@ pub const WORKSPACE_MEMBER_PATTERN: &str = "/api/workspace/{workspace_id}/member
|
||||||
pub const WORKSPACE_INVITE_PATTERN: &str = "/api/workspace/{workspace_id}/invite";
|
pub const WORKSPACE_INVITE_PATTERN: &str = "/api/workspace/{workspace_id}/invite";
|
||||||
pub const COLLAB_PATTERN: &str = "/api/workspace/{workspace_id}/collab/{object_id}";
|
pub const COLLAB_PATTERN: &str = "/api/workspace/{workspace_id}/collab/{object_id}";
|
||||||
pub const V1_COLLAB_PATTERN: &str = "/api/workspace/v1/{workspace_id}/collab/{object_id}";
|
pub const V1_COLLAB_PATTERN: &str = "/api/workspace/v1/{workspace_id}/collab/{object_id}";
|
||||||
|
pub const WORKSPACE_PUBLISH_PATTERN: &str = "/api/workspace/{workspace_id}/publish";
|
||||||
pub const WORKSPACE_PUBLISH_NAMESPACE_PATTERN: &str =
|
pub const WORKSPACE_PUBLISH_NAMESPACE_PATTERN: &str =
|
||||||
"/api/workspace/{workspace_id}/publish-namespace";
|
"/api/workspace/{workspace_id}/publish-namespace";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ use database_entity::dto::AFRole;
|
||||||
|
|
||||||
use crate::api::workspace::{
|
use crate::api::workspace::{
|
||||||
WORKSPACE_INVITE_PATTERN, WORKSPACE_MEMBER_PATTERN, WORKSPACE_PATTERN,
|
WORKSPACE_INVITE_PATTERN, WORKSPACE_MEMBER_PATTERN, WORKSPACE_PATTERN,
|
||||||
WORKSPACE_PUBLISH_NAMESPACE_PATTERN,
|
WORKSPACE_PUBLISH_NAMESPACE_PATTERN, WORKSPACE_PUBLISH_PATTERN,
|
||||||
};
|
};
|
||||||
use crate::middleware::access_control_mw::{AccessResource, MiddlewareAccessControl};
|
use crate::middleware::access_control_mw::{AccessResource, MiddlewareAccessControl};
|
||||||
use crate::state::UserCache;
|
use crate::state::UserCache;
|
||||||
|
|
@ -48,6 +48,10 @@ where
|
||||||
],
|
],
|
||||||
// Require role for given resources
|
// Require role for given resources
|
||||||
require_role_rules: vec![
|
require_role_rules: vec![
|
||||||
|
(
|
||||||
|
ResourceDef::new(WORKSPACE_PUBLISH_PATTERN),
|
||||||
|
[(Method::DELETE, AFRole::Member)].into(),
|
||||||
|
),
|
||||||
// Only the Owner can manager the workspace members
|
// Only the Owner can manager the workspace members
|
||||||
(
|
(
|
||||||
ResourceDef::new(WORKSPACE_MEMBER_PATTERN),
|
ResourceDef::new(WORKSPACE_MEMBER_PATTERN),
|
||||||
|
|
|
||||||
|
|
@ -132,15 +132,7 @@ pub async fn get_workspace_publish_namespace(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
workspace_id: &Uuid,
|
workspace_id: &Uuid,
|
||||||
) -> Result<String, AppError> {
|
) -> Result<String, AppError> {
|
||||||
let namespace = match select_workspace_publish_namespace(pg_pool, workspace_id).await? {
|
select_workspace_publish_namespace(pg_pool, workspace_id).await
|
||||||
Some(namespace) => namespace,
|
|
||||||
None => {
|
|
||||||
return Err(AppError::PublishNamespaceNotSet(
|
|
||||||
"publish namespace is not set for the workspace".to_string(),
|
|
||||||
))
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Ok(namespace)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn publish_collabs(
|
pub async fn publish_collabs(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use client_api::entity::{PublishCollabItem, PublishCollabMetadata};
|
use client_api::entity::{AFRole, PublishCollabItem, PublishCollabMetadata};
|
||||||
|
use client_api_test::TestClient;
|
||||||
use client_api_test::{generate_unique_registered_user_client, localhost_client};
|
use client_api_test::{generate_unique_registered_user_client, localhost_client};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -7,13 +8,11 @@ async fn test_set_publish_namespace_set() {
|
||||||
let workspace_id = get_first_workspace_string(&c).await;
|
let workspace_id = get_first_workspace_string(&c).await;
|
||||||
|
|
||||||
{
|
{
|
||||||
// cannot get namespace if not set
|
// can get namespace before setting, which is random string
|
||||||
let err = c
|
let _ = c
|
||||||
.get_workspace_publish_namespace(&workspace_id.to_string())
|
.get_workspace_publish_namespace(&workspace_id.to_string())
|
||||||
.await
|
.await
|
||||||
.err()
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(format!("{:?}", err.code), "PublishNamespaceNotSet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let namespace = uuid::Uuid::new_v4().to_string();
|
let namespace = uuid::Uuid::new_v4().to_string();
|
||||||
|
|
@ -127,6 +126,20 @@ async fn test_publish_doc() {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(blob, "yrs_encoded_data_1");
|
assert_eq!(blob, "yrs_encoded_data_1");
|
||||||
|
|
||||||
|
let publish_info = guest_client
|
||||||
|
.get_published_collab_info(&view_id_2)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(publish_info.namespace, Some(my_namespace.clone()));
|
||||||
|
assert_eq!(publish_info.publish_name, publish_name_2);
|
||||||
|
assert_eq!(publish_info.view_id, view_id_2);
|
||||||
|
|
||||||
|
let blob = guest_client
|
||||||
|
.get_published_collab_blob(&my_namespace, publish_name_2)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(blob, "yrs_encoded_data_2");
|
||||||
}
|
}
|
||||||
|
|
||||||
c.unpublish_collabs(&workspace_id, &[view_id_1])
|
c.unpublish_collabs(&workspace_id, &[view_id_1])
|
||||||
|
|
@ -200,6 +213,43 @@ async fn get_first_workspace_string(c: &client_api::Client) -> String {
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn workspace_member_publish_unpublish() {
|
||||||
|
let client_1 = TestClient::new_user_without_ws_conn().await;
|
||||||
|
let workspace_id = client_1.workspace_id().await;
|
||||||
|
let client_2 = TestClient::new_user_without_ws_conn().await;
|
||||||
|
client_1
|
||||||
|
.invite_and_accepted_workspace_member(&workspace_id, &client_2, AFRole::Member)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let view_id = uuid::Uuid::new_v4();
|
||||||
|
// member can publish without owner setting namespace
|
||||||
|
client_2
|
||||||
|
.api_client
|
||||||
|
.publish_collabs::<MyCustomMetadata, &[u8]>(
|
||||||
|
&workspace_id,
|
||||||
|
vec![PublishCollabItem {
|
||||||
|
meta: PublishCollabMetadata {
|
||||||
|
view_id,
|
||||||
|
publish_name: "publish-name-1".to_string(),
|
||||||
|
metadata: MyCustomMetadata {
|
||||||
|
title: "my_title_1".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: "yrs_encoded_data_1".as_bytes(),
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
client_2
|
||||||
|
.api_client
|
||||||
|
.unpublish_collabs(&workspace_id, &[view_id])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
struct MyCustomMetadata {
|
struct MyCustomMetadata {
|
||||||
title: String,
|
title: String,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue