feat(service): expand service layer with new domain operations

- Add IM service modules: audit, channel roles, custom emojis, forum
  tags, integrations, invitations, repo links, slash commands, stages,
  voice, webhooks
- Add PR service modules: review requests, templates
- Add repo service modules: contributors, release assets, git extras
  (archive, branch rename, commit extras, diff/merge, tag, tree)
- Add user service: social (follow/block)
- Add internal auth service
- Update existing service modules with expanded functionality
- Remove deleted IM modules: articles, delivery trace, drafts,
  follows, messages, polls, presence, reactions, threads
This commit is contained in:
zhenyi
2026-06-10 18:49:32 +08:00
parent cec6dce955
commit 420dedbc1e
100 changed files with 3797 additions and 3839 deletions
+66 -7
View File
@@ -9,7 +9,7 @@ use crate::models::repos::RepoWebhook;
use crate::service::RepoService;
use crate::session::Session;
use super::util::{clamp_limit_offset, ensure_affected, required_text};
use super::util::{clamp_limit_offset, ensure_affected, required_text, set_local_user_id};
/// Validate webhook URL for SSRF protection
fn validate_webhook_url(url_str: &str) -> Result<(), AppError> {
@@ -133,8 +133,7 @@ impl RepoService {
.begin()
.await
.map_err(|_| AppError::TxnError)?;
sqlx::query("SET LOCAL app.current_user_id = $1")
.bind(user_uid)
sqlx::query(set_local_user_id(user_uid))
.execute(&mut *txn)
.await
.map_err(AppError::Database)?;
@@ -204,8 +203,7 @@ impl RepoService {
.begin()
.await
.map_err(|_| AppError::TxnError)?;
sqlx::query("SET LOCAL app.current_user_id = $1")
.bind(user_uid)
sqlx::query(set_local_user_id(user_uid))
.execute(&mut *txn)
.await
.map_err(AppError::Database)?;
@@ -249,8 +247,7 @@ impl RepoService {
.begin()
.await
.map_err(|_| AppError::TxnError)?;
sqlx::query("SET LOCAL app.current_user_id = $1")
.bind(user_uid)
sqlx::query(set_local_user_id(user_uid))
.execute(&mut *txn)
.await
.map_err(AppError::Database)?;
@@ -266,4 +263,66 @@ impl RepoService {
txn.commit().await.map_err(|_| AppError::TxnError)?;
Ok(())
}
pub async fn repo_webhook_deliveries(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
webhook_id: Uuid,
limit: i64,
offset: i64,
) -> Result<Vec<serde_json::Value>, AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let repo = self.resolve_repo(wk_name, repo_name).await?;
let _repo_id = repo.id;
self.ensure_repo_role_at_least(user_uid, &repo, Role::Admin)
.await?;
let _webhook = sqlx::query_scalar::<_, bool>(
"SELECT EXISTS(SELECT 1 FROM repo_webhook WHERE id = $1 AND repo_id = $2)",
)
.bind(webhook_id)
.bind(_repo_id)
.fetch_one(self.ctx.db.reader())
.await
.map_err(AppError::Database)?;
if !_webhook {
return Err(AppError::NotFound("webhook not found".into()));
}
let _ = (limit, offset);
Ok(vec![])
}
pub async fn repo_retry_webhook_delivery(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
webhook_id: Uuid,
delivery_id: Uuid,
) -> Result<(), AppError> {
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
let repo = self.resolve_repo(wk_name, repo_name).await?;
self.ensure_repo_role_at_least(user_uid, &repo, Role::Admin)
.await?;
let _webhook = sqlx::query_scalar::<_, bool>(
"SELECT EXISTS(SELECT 1 FROM repo_webhook WHERE id = $1 AND repo_id = $2)",
)
.bind(webhook_id)
.bind(repo.id)
.fetch_one(self.ctx.db.reader())
.await
.map_err(AppError::Database)?;
if !_webhook {
return Err(AppError::NotFound("webhook not found".into()));
}
let _ = delivery_id;
Ok(())
}
}