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

198 lines
6.5 KiB
Rust

use crate::{AppService, error::AppError};
use chrono::Utc;
use models::projects::{MemberRole, project_audit_log, project_history_name};
use models::repos::{Repo, repo};
use models::users::user;
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;
#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct ExchangeProjectVisibility {
pub is_public: bool,
}
#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct ExchangeProjectTitle {
pub display_name: Option<String>,
pub description: Option<String>,
}
#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct ExchangeProjectName {
pub name: String,
}
impl AppService {
pub async fn project_exchange_name(
&self,
ctx: &Session,
project_name: String,
params: ExchangeProjectName,
) -> Result<(), AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let project = self
.utils_find_project_by_name(project_name.clone())
.await?;
let oper = user::Entity::find()
.filter(user::Column::Uid.eq(user_uid))
.one(&self.db)
.await?
.ok_or(AppError::UserNotFound)?;
if let Ok(role) = self.utils_project_context_role(&ctx, project_name).await {
if role != MemberRole::Owner {
return Err(AppError::NoPower);
}
} else {
return Err(AppError::NoPower);
}
let txn = self.db.begin().await?;
let mut active = project.clone().into_active_model();
active.name = Set(params.name.clone());
active.update(&txn).await?;
// Update repo names for all repos in this project
let repos = Repo::find()
.filter(repo::Column::Project.eq(project.id))
.all(&txn)
.await?;
for r in repos {
let repo_name = r.repo_name.clone();
let mut ra: repo::ActiveModel = r.into();
ra.repo_name = Set(format!("{}/{}", params.name.clone(), repo_name));
ra.update(&txn).await?;
}
let log = project_audit_log::ActiveModel {
project: Set(project.id),
actor: Set(user_uid),
action: Set("exchange_name".to_string()),
details: Set(Some(serde_json::json!({
"name": params.name,
"old_name": project.name,
"username": oper.username,
"user_uid": user_uid,
}))),
created_at: Set(Utc::now()),
..Default::default()
};
let history = project_history_name::ActiveModel {
id: NotSet,
project_uid: Set(project.id),
history_name: Set(project.name),
changed_at: Set(Utc::now()),
};
history.insert(&txn).await?;
log.insert(&txn).await?;
txn.commit().await?;
Ok(())
}
pub async fn project_exchange_visibility(
&self,
ctx: &Session,
project_name: String,
params: ExchangeProjectVisibility,
) -> Result<(), AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let project = self
.utils_find_project_by_name(project_name.clone())
.await?;
if let Ok(role) = self.utils_project_context_role(&ctx, project_name).await {
if role == MemberRole::Member {
return Err(AppError::NoPower);
}
} else {
return Err(AppError::NoPower);
}
if project.is_public != params.is_public {
let txn = self.db.begin().await?;
let mut active = project.clone().into_active_model();
active.is_public = Set(params.is_public);
active.update(&txn).await?;
let oper = user::Entity::find()
.filter(user::Column::Uid.eq(user_uid))
.one(&txn)
.await?
.ok_or(AppError::UserNotFound)?;
let log = project_audit_log::ActiveModel {
project: Set(project.id),
actor: Set(user_uid),
action: Set("exchange_visibility".to_string()),
details: Set(Some(serde_json::json!({
"is_public": params.is_public,
"old_is_public": project.is_public,
"username": oper.username,
"user_uid": user_uid,
}))),
created_at: Set(Utc::now()),
..Default::default()
};
log.insert(&txn).await?;
txn.commit().await?;
}
Ok(())
}
pub async fn project_exchange_title(
&self,
ctx: &Session,
project_name: String,
params: ExchangeProjectTitle,
) -> Result<(), AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let project = self
.utils_find_project_by_name(project_name.clone())
.await?;
if let Ok(role) = self.utils_project_context_role(&ctx, project_name).await {
if role == MemberRole::Member {
return Err(AppError::NoPower);
}
} else {
return Err(AppError::NoPower);
}
let txn = self.db.begin().await?;
let mut active = project.clone().into_active_model();
if let Some(description) = params.description.clone() {
active.description = Set(Some(description));
}
if let Some(display_name) = params.display_name.clone() {
active.display_name = Set(display_name);
}
active.update(&txn).await?;
let oper = user::Entity::find()
.filter(user::Column::Uid.eq(user_uid))
.one(&txn)
.await?
.ok_or(AppError::UserNotFound)?;
let log = project_audit_log::ActiveModel {
project: Set(project.id),
actor: Set(user_uid),
action: Set("exchange_description".to_string()),
details: Set(Some(serde_json::json!({
"description": params.description,
"username": oper.username,
"user_uid": user_uid,
"old_description": project.description,
"display_name": params.display_name,
"old_display_name": project.display_name,
}))),
created_at: Set(Utc::now()),
..Default::default()
};
log.insert(&txn).await?;
txn.commit().await?;
Ok(())
}
}