feat: Create workspace (#357)
* feat: initialize collab for user after workspace creation * fix: add permission before adding new collab for new workspace * chore: simplify logic
This commit is contained in:
parent
1cb2620ec7
commit
79a0dd43c6
|
|
@ -29,7 +29,7 @@ pub async fn delete_from_workspace(pg_pool: &PgPool, workspace_id: &Uuid) -> Res
|
|||
|
||||
#[inline]
|
||||
pub async fn insert_user_workspace(
|
||||
pg_pool: &PgPool,
|
||||
tx: &mut Transaction<'_, sqlx::Postgres>,
|
||||
user_uuid: &Uuid,
|
||||
workspace_name: &str,
|
||||
) -> Result<AFWorkspaceRow, AppError> {
|
||||
|
|
@ -43,7 +43,7 @@ pub async fn insert_user_workspace(
|
|||
user_uuid,
|
||||
workspace_name,
|
||||
)
|
||||
.fetch_one(pg_pool)
|
||||
.fetch_one(tx.deref_mut())
|
||||
.await?;
|
||||
|
||||
Ok(workspace)
|
||||
|
|
|
|||
|
|
@ -130,14 +130,18 @@ async fn create_workpace_handler(
|
|||
.into_inner()
|
||||
.workspace_name
|
||||
.unwrap_or_else(|| format!("workspace_{}", chrono::Utc::now().timestamp()));
|
||||
let new_workspace =
|
||||
workspace::ops::create_workspace_for_user(&state.pg_pool, &uuid, &workspace_name).await?;
|
||||
|
||||
let uid = state.users.get_user_uid(&uuid).await?;
|
||||
state
|
||||
.workspace_access_control
|
||||
.insert_workspace_role(&uid, &new_workspace.workspace_id, AFRole::Owner)
|
||||
.await?;
|
||||
let new_workspace = workspace::ops::create_workspace_for_user(
|
||||
&state.pg_pool,
|
||||
&state.workspace_access_control,
|
||||
&state.collab_storage,
|
||||
&uuid,
|
||||
uid,
|
||||
&workspace_name,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(AppResponse::Ok().with_data(new_workspace).into())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,14 @@ use shared_entity::response::AppResponseError;
|
|||
use sqlx::{types::uuid, PgPool, Transaction};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, event, instrument};
|
||||
use uuid::Uuid;
|
||||
use workspace_template::document::get_started::GetStartedDocumentTemplate;
|
||||
use workspace_template::{WorkspaceTemplate, WorkspaceTemplateBuilder};
|
||||
|
||||
use super::collab::storage::CollabStorageImpl;
|
||||
|
||||
/// Verify the token from the gotrue server and create the user if it is a new user
|
||||
/// Return true if the user is a new user
|
||||
///
|
||||
|
|
@ -64,12 +67,12 @@ pub async fn verify_token(access_token: &str, state: &AppState) -> Result<bool,
|
|||
.await?;
|
||||
|
||||
// Create a workspace with the GetStarted template
|
||||
create_workspace_for_user(
|
||||
initialize_workspace_for_user(
|
||||
new_uid,
|
||||
&workspace_id,
|
||||
&mut txn,
|
||||
vec![GetStartedDocumentTemplate],
|
||||
state,
|
||||
&state.collab_storage,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
|
@ -80,26 +83,26 @@ pub async fn verify_token(access_token: &str, state: &AppState) -> Result<bool,
|
|||
Ok(is_new)
|
||||
}
|
||||
|
||||
/// Create a workspace for a user.
|
||||
/// This function generates a workspace along with its templates and stores them in the database.
|
||||
/// This function generates templates for a workspace and stores them in the database.
|
||||
/// Each template is stored as an individual collaborative object.
|
||||
#[instrument(level = "debug", skip_all, err)]
|
||||
async fn create_workspace_for_user<T>(
|
||||
new_uid: i64,
|
||||
pub async fn initialize_workspace_for_user<T>(
|
||||
uid: i64,
|
||||
workspace_id: &str,
|
||||
txn: &mut Transaction<'_, sqlx::Postgres>,
|
||||
templates: Vec<T>,
|
||||
state: &AppState,
|
||||
// state: &AppState,
|
||||
collab_storage: &Arc<CollabStorageImpl>,
|
||||
) -> Result<(), AppError>
|
||||
where
|
||||
T: WorkspaceTemplate + Send + Sync + 'static,
|
||||
{
|
||||
let templates = WorkspaceTemplateBuilder::new(new_uid, workspace_id)
|
||||
let templates = WorkspaceTemplateBuilder::new(uid, workspace_id)
|
||||
.with_templates(templates)
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
debug!("create {} templates for user:{}", templates.len(), new_uid);
|
||||
debug!("create {} templates for user:{}", templates.len(), uid);
|
||||
for template in templates {
|
||||
let object_id = template.object_id;
|
||||
let encoded_collab_v1 = template
|
||||
|
|
@ -107,11 +110,10 @@ where
|
|||
.encode_to_bytes()
|
||||
.map_err(|err| AppError::Internal(anyhow::Error::from(err)))?;
|
||||
|
||||
state
|
||||
.collab_storage
|
||||
collab_storage
|
||||
.upsert_collab_with_transaction(
|
||||
workspace_id,
|
||||
&new_uid,
|
||||
&uid,
|
||||
CollabParams {
|
||||
object_id,
|
||||
encoded_collab_v1,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ use std::ops::DerefMut;
|
|||
use std::sync::Arc;
|
||||
use tracing::instrument;
|
||||
use uuid::Uuid;
|
||||
use workspace_template::document::get_started::GetStartedDocumentTemplate;
|
||||
|
||||
use crate::biz::casbin::WorkspaceAccessControlImpl;
|
||||
use crate::biz::collab::storage::CollabStorageImpl;
|
||||
use crate::biz::user::initialize_workspace_for_user;
|
||||
|
||||
use super::access_control::WorkspaceAccessControl;
|
||||
|
||||
pub async fn delete_workspace_for_user(
|
||||
pg_pool: &PgPool,
|
||||
|
|
@ -50,11 +57,32 @@ pub async fn delete_workspace_for_user(
|
|||
|
||||
pub async fn create_workspace_for_user(
|
||||
pg_pool: &PgPool,
|
||||
workspace_access_control: &WorkspaceAccessControlImpl,
|
||||
collab_storage: &Arc<CollabStorageImpl>,
|
||||
user_uuid: &Uuid,
|
||||
user_uid: i64,
|
||||
workspace_name: &str,
|
||||
) -> Result<AFWorkspace, AppResponseError> {
|
||||
let new_workspace_row = insert_user_workspace(pg_pool, user_uuid, workspace_name).await?;
|
||||
let mut txn = pg_pool.begin().await?;
|
||||
|
||||
let new_workspace_row = insert_user_workspace(&mut txn, user_uuid, workspace_name).await?;
|
||||
let new_workspace = AFWorkspace::try_from(new_workspace_row)?;
|
||||
|
||||
workspace_access_control
|
||||
.insert_workspace_role(&user_uid, &new_workspace.workspace_id, AFRole::Owner)
|
||||
.await?;
|
||||
|
||||
// add create initial collab for user
|
||||
initialize_workspace_for_user(
|
||||
user_uid,
|
||||
new_workspace.workspace_id.to_string().as_str(),
|
||||
&mut txn,
|
||||
vec![GetStartedDocumentTemplate],
|
||||
collab_storage,
|
||||
)
|
||||
.await?;
|
||||
|
||||
txn.commit().await?;
|
||||
Ok(new_workspace)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use client_api_test_util::generate_unique_registered_user_client;
|
||||
use collab_entity::CollabType;
|
||||
use database_entity::dto::AFRole;
|
||||
use database_entity::dto::QueryCollabParams;
|
||||
use shared_entity::dto::workspace_dto::CreateWorkspaceMember;
|
||||
use shared_entity::dto::workspace_dto::CreateWorkspaceParam;
|
||||
use shared_entity::dto::workspace_dto::PatchWorkspaceParam;
|
||||
|
|
@ -26,9 +28,18 @@ async fn add_and_delete_workspace_for_user() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
c.delete_workspace(&newly_added_workspace.workspace_id.to_string())
|
||||
// Workspace need to have at least one collab
|
||||
let workspace_id = newly_added_workspace.workspace_id.to_string();
|
||||
let _ = c
|
||||
.get_collab(QueryCollabParams::new(
|
||||
&workspace_id,
|
||||
CollabType::Folder,
|
||||
&workspace_id,
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
c.delete_workspace(&workspace_id).await.unwrap();
|
||||
let workspaces = c.get_workspaces().await.unwrap();
|
||||
assert_eq!(workspaces.0.len(), 1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue