From bb1029077ce9116c4e895e34bdaeeb59125d74ce Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 24 Jan 2024 11:46:23 +0800 Subject: [PATCH] refactor: template --- libs/workspace-template/src/lib.rs | 19 +++++- src/biz/user.rs | 100 ++++++++++++++++++----------- 2 files changed, 79 insertions(+), 40 deletions(-) diff --git a/libs/workspace-template/src/lib.rs b/libs/workspace-template/src/lib.rs index 616d68f82..d09242d26 100644 --- a/libs/workspace-template/src/lib.rs +++ b/libs/workspace-template/src/lib.rs @@ -34,6 +34,8 @@ pub struct TemplateData { pub type WorkspaceTemplateHandlers = HashMap>; +/// A builder for creating a workspace template. +/// workspace template is a set of views that are created when a workspace is created. pub struct WorkspaceTemplateBuilder { pub uid: i64, pub workspace_id: String, @@ -50,12 +52,25 @@ impl WorkspaceTemplateBuilder { } } - pub fn with_template(mut self, template: T) -> Self { + pub fn with_template(mut self, template: T) -> Self + where + T: WorkspaceTemplate + Send + Sync + 'static, + { self.handlers.insert(template.layout(), Arc::new(template)); self } - pub async fn default_workspace(&self) -> Result> { + pub fn with_templates(mut self, templates: Vec) -> Self + where + T: WorkspaceTemplate + Send + Sync + 'static, + { + for template in templates { + self.handlers.insert(template.layout(), Arc::new(template)); + } + self + } + + pub async fn build(&self) -> Result> { let workspace_view_builder = Arc::new(RwLock::new(WorkspaceViewBuilder::new( self.workspace_id.clone(), self.uid, diff --git a/src/biz/user.rs b/src/biz/user.rs index 2e89a1875..bddeffc72 100644 --- a/src/biz/user.rs +++ b/src/biz/user.rs @@ -22,11 +22,11 @@ use database::user::{create_user, is_user_exist}; use realtime::entities::RealtimeUser; use shared_entity::dto::auth_dto::UpdateUserParams; use snowflake::Snowflake; -use sqlx::{types::uuid, PgPool}; +use sqlx::{types::uuid, PgPool, Transaction}; use tokio::sync::RwLock; use tracing::{debug, event, instrument}; use workspace_template::document::get_started::GetStartedDocumentTemplate; -use workspace_template::WorkspaceTemplateBuilder; +use workspace_template::{WorkspaceTemplate, WorkspaceTemplateBuilder}; /// 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 @@ -87,42 +87,15 @@ where ) .await?; - // Create the default workspace for the user. A default workspace might contain multiple - // templates, e.g. a document template, a database template, etc. - let templates = WorkspaceTemplateBuilder::new(new_uid, &workspace_id) - .with_template(GetStartedDocumentTemplate) - .default_workspace() - .await?; - - debug!("create {} templates for user:{}", templates.len(), new_uid); - for template in templates { - let object_id = template.object_id; - let encoded_collab_v1 = template - .object_data - .encode_to_bytes() - .map_err(|err| AppError::Internal(anyhow::Error::from(err)))?; - - collab_access_control - .cache_collab_access_level( - realtime::collaborate::CollabUserId::UserId(&new_uid), - &object_id, - AFAccessLevel::FullAccess, - ) - .await?; - - insert_into_af_collab( - &mut txn, - &new_uid, - &workspace_id, - &CollabParams { - object_id, - encoded_collab_v1, - collab_type: template.object_type, - override_if_exist: false, - }, - ) - .await?; - } + // Create a workspace with the GetStarted template + create_workspace_for_user( + new_uid, + &workspace_id, + collab_access_control, + &mut txn, + vec![GetStartedDocumentTemplate], + ) + .await?; } txn .commit() @@ -131,6 +104,57 @@ where Ok(is_new) } +/// Create a workspace for a user. +/// This function generates a workspace along with its templates and stores them in the database. +/// Each template is stored as an individual collaborative object. +async fn create_workspace_for_user( + new_uid: i64, + workspace_id: &str, + collab_access_control: &C, + txn: &mut Transaction<'_, sqlx::Postgres>, + templates: Vec, +) -> Result<(), AppError> +where + C: CollabAccessControl, + T: WorkspaceTemplate + Send + Sync + 'static, +{ + let templates = WorkspaceTemplateBuilder::new(new_uid, workspace_id) + .with_templates(templates) + .build() + .await?; + + debug!("create {} templates for user:{}", templates.len(), new_uid); + for template in templates { + let object_id = template.object_id; + let encoded_collab_v1 = template + .object_data + .encode_to_bytes() + .map_err(|err| AppError::Internal(anyhow::Error::from(err)))?; + + collab_access_control + .cache_collab_access_level( + realtime::collaborate::CollabUserId::UserId(&new_uid), + &object_id, + AFAccessLevel::FullAccess, + ) + .await?; + + insert_into_af_collab( + txn, + &new_uid, + workspace_id, + &CollabParams { + object_id, + encoded_collab_v1, + collab_type: template.object_type, + override_if_exist: false, + }, + ) + .await?; + } + Ok(()) +} + pub async fn get_profile(pg_pool: &PgPool, uuid: &Uuid) -> Result { let row = select_user_profile(pg_pool, uuid) .await?