gitdataai/lib/service/git/watch.rs

103 lines
3.4 KiB
Rust

use db::sqlx;
use session::Session;
use crate::{AppService, error::AppError, session_user};
impl AppService {
pub async fn git_repo_watch(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
level: Option<String>,
) -> Result<serde_json::Value, AppError> {
let user_uid = session_user(ctx)?;
let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
let level = level.unwrap_or_else(|| "participating".to_string());
sqlx::query(
"INSERT INTO repo_watch (repo, \"user\", \"level\", created_at, updated_at) \
VALUES ($1, $2, $3, $4, $5) \
ON CONFLICT (repo, \"user\") DO UPDATE SET level = $3, updated_at = $5",
)
.bind(repo.id)
.bind(user_uid)
.bind(&level)
.bind(chrono::Utc::now())
.bind(chrono::Utc::now())
.execute(self.db.writer())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
let count: (i64,) =
sqlx::query_as("SELECT COUNT(*) FROM repo_watch WHERE repo = $1")
.bind(repo.id)
.fetch_one(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(
serde_json::json!({ "watching": true, "count": count.0, "level": level }),
)
}
pub async fn git_repo_unwatch(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
) -> Result<serde_json::Value, AppError> {
let user_uid = session_user(ctx)?;
let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
sqlx::query("DELETE FROM repo_watch WHERE repo = $1 AND \"user\" = $2")
.bind(repo.id)
.bind(user_uid)
.execute(self.db.writer())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
let count: (i64,) =
sqlx::query_as("SELECT COUNT(*) FROM repo_watch WHERE repo = $1")
.bind(repo.id)
.fetch_one(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(serde_json::json!({ "watching": false, "count": count.0 }))
}
pub async fn git_repo_watch_status(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
) -> Result<serde_json::Value, AppError> {
let user_uid = session_user(ctx)?;
let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
let watch: Option<(bool, String)> = sqlx::query_as(
"SELECT EXISTS(SELECT 1 FROM repo_watch WHERE repo = $1 AND \"user\" = $2), \
COALESCE((SELECT level FROM repo_watch WHERE repo = $1 AND \"user\" = $2), '')",
)
.bind(repo.id)
.bind(user_uid)
.fetch_optional(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
let count: (i64,) =
sqlx::query_as("SELECT COUNT(*) FROM repo_watch WHERE repo = $1")
.bind(repo.id)
.fetch_one(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(serde_json::json!({
"watching": watch.as_ref().map(|(w, _)| *w).unwrap_or(false),
"count": count.0,
"level": watch.map(|(_, l)| l).unwrap_or_default(),
}))
}
}