gitdataai/libs/service/workspace/init.rs
2026-04-14 19:02:01 +08:00

98 lines
2.9 KiB
Rust

use crate::AppService;
use crate::error::AppError;
use chrono::Utc;
use models::WorkspaceRole;
use models::workspaces::workspace;
use models::workspaces::workspace_membership;
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;
#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct WorkspaceInitParams {
pub slug: String,
pub name: String,
pub description: Option<String>,
}
impl AppService {
pub async fn workspace_init(
&self,
ctx: &Session,
params: WorkspaceInitParams,
) -> Result<workspace::Model, AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let user = self.utils_find_user_by_uid(user_uid).await?;
// Validate slug format: alphanumeric, dashes, underscores
if !params
.slug
.chars()
.all(|c| c.is_alphanumeric() || c == '-' || c == '_')
{
return Err(AppError::BadRequest(
"Slug must contain only letters, numbers, hyphens and underscores".to_string(),
));
}
// Check slug uniqueness
if workspace::Entity::find()
.filter(workspace::Column::Slug.eq(&params.slug))
.filter(workspace::Column::DeletedAt.is_null())
.one(&self.db)
.await?
.is_some()
{
return Err(AppError::WorkspaceSlugAlreadyExists);
}
// Check name uniqueness
if workspace::Entity::find()
.filter(workspace::Column::Name.eq(&params.name))
.filter(workspace::Column::DeletedAt.is_null())
.one(&self.db)
.await?
.is_some()
{
return Err(AppError::WorkspaceNameAlreadyExists);
}
let txn = self.db.begin().await?;
let ws = workspace::ActiveModel {
id: Set(Uuid::now_v7()),
slug: Set(params.slug),
name: Set(params.name),
description: Set(params.description),
avatar_url: Set(None),
plan: Set("free".to_string()),
billing_email: Set(None),
stripe_customer_id: Set(None),
stripe_subscription_id: Set(None),
plan_expires_at: Set(None),
deleted_at: Set(None),
created_at: Set(Utc::now()),
updated_at: Set(Utc::now()),
};
let ws = ws.insert(&txn).await?;
let membership = workspace_membership::ActiveModel {
id: Default::default(),
workspace_id: Set(ws.id),
user_id: Set(user.uid),
role: Set(WorkspaceRole::Owner.to_string()),
status: Set("active".to_string()),
invited_by: Set(None),
joined_at: Set(Utc::now()),
invite_token: Set(None),
invite_expires_at: Set(None),
};
membership.insert(&txn).await?;
txn.commit().await?;
Ok(ws)
}
}
use uuid::Uuid;