gitdataai/libs/service/project/join_settings.rs
2026-04-15 09:08:09 +08:00

140 lines
4.7 KiB
Rust

use crate::AppService;
use crate::error::AppError;
use chrono::Utc;
use models::projects::{project_audit_log, project_member_join_settings};
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct JoinSettingsResponse {
pub project_uid: String,
pub require_approval: bool,
pub require_questions: bool,
pub questions: serde_json::Value,
}
#[derive(Debug, Clone, Deserialize, Serialize, utoipa::ToSchema)]
pub struct UpdateJoinSettingsRequest {
pub require_approval: bool,
pub require_questions: bool,
pub questions: Vec<QuestionSchema>,
}
#[derive(Debug, Clone, Deserialize, Serialize, utoipa::ToSchema)]
pub struct QuestionSchema {
pub question: String,
}
impl AppService {
pub async fn project_get_join_settings(
&self,
project_name: String,
ctx: &Session,
) -> Result<JoinSettingsResponse, AppError> {
let _user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let project = self.utils_find_project_by_name(project_name).await?;
let settings = project_member_join_settings::Entity::find()
.filter(project_member_join_settings::Column::Project.eq(project.id))
.one(&self.db)
.await?;
match settings {
Some(s) => Ok(JoinSettingsResponse {
project_uid: project.id.to_string(),
require_approval: s.require_approval,
require_questions: s.require_questions,
questions: s.questions,
}),
None => Ok(JoinSettingsResponse {
project_uid: project.id.to_string(),
require_approval: false,
require_questions: false,
questions: serde_json::json!([]),
}),
}
}
pub async fn project_update_join_settings(
&self,
project_name: String,
request: UpdateJoinSettingsRequest,
ctx: &Session,
) -> Result<JoinSettingsResponse, AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let project = self
.utils_find_project_by_name(project_name.clone())
.await?;
let role = self
.utils_project_context_role(&ctx, project_name.clone())
.await
.map_err(|_| AppError::NoPower)?;
if role != models::projects::MemberRole::Owner
&& role != models::projects::MemberRole::Admin
{
return Err(AppError::NoPower);
}
let txn = self.db.begin().await?;
let existing = project_member_join_settings::Entity::find()
.filter(project_member_join_settings::Column::Project.eq(project.id))
.one(&txn)
.await?;
let questions_json: serde_json::Value = serde_json::json!(
request
.questions
.iter()
.map(|q| q.question.clone())
.collect::<Vec<_>>()
);
if let Some(settings) = existing {
let mut active: project_member_join_settings::ActiveModel = settings.into();
active.require_approval = Set(request.require_approval);
active.require_questions = Set(request.require_questions);
active.questions = Set(questions_json.clone());
active.updated_at = Set(Utc::now());
active.update(&txn).await?;
} else {
let new_settings = project_member_join_settings::ActiveModel {
id: Default::default(),
project: Set(project.id),
require_approval: Set(request.require_approval),
require_questions: Set(request.require_questions),
questions: Set(questions_json.clone()),
created_at: Set(Utc::now()),
updated_at: Set(Utc::now()),
};
new_settings.insert(&txn).await?;
}
let log = project_audit_log::ActiveModel {
project: Set(project.id),
actor: Set(user_uid),
action: Set("update_join_settings".to_string()),
details: Set(Some(serde_json::json!({
"require_approval": request.require_approval,
"require_questions": request.require_questions,
"questions_count": request.questions.len(),
}))),
created_at: Set(Utc::now()),
..Default::default()
};
log.insert(&txn).await?;
txn.commit().await?;
Ok(JoinSettingsResponse {
project_uid: project.id.to_string(),
require_approval: request.require_approval,
require_questions: request.require_questions,
questions: questions_json,
})
}
}