Files
appks/service/notify/core.rs
T
2026-06-07 11:30:56 +08:00

142 lines
4.3 KiB
Rust

use crate::error::AppError;
use crate::models::notifications::Notification;
use crate::service::NotificationService;
use crate::session::Session;
use chrono::Utc;
use uuid::Uuid;
use super::util::clamp_limit_offset;
impl NotificationService {
pub async fn list_notifications(
&self,
session: &Session,
unread_only: bool,
limit: i64,
offset: i64,
) -> Result<Vec<Notification>, AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
let (limit, offset) = clamp_limit_offset(limit, offset);
Notification::list_for_user(self.ctx.db.reader(), user_id, unread_only, limit, offset).await
}
pub async fn count_unread(&self, session: &Session) -> Result<i64, AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
Notification::count_unread(self.ctx.db.reader(), user_id).await
}
pub async fn mark_as_read(
&self,
session: &Session,
notification_id: Uuid,
) -> Result<Notification, AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
let now = Utc::now();
sqlx::query(
"UPDATE notification SET read_at = $1, updated_at = $2 \
WHERE id = $3 AND user_id = $4 AND deleted_at IS NULL",
)
.bind(now)
.bind(now)
.bind(notification_id)
.bind(user_id)
.execute(self.ctx.db.writer())
.await
.map_err(AppError::Database)?;
Notification::find_by_id(self.ctx.db.reader(), notification_id, user_id)
.await?
.ok_or(AppError::NotFound("notification not found".into()))
}
pub async fn mark_all_as_read(&self, session: &Session) -> Result<i64, AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
let now = Utc::now();
let result = sqlx::query(
"UPDATE notification SET read_at = $1, updated_at = $2 \
WHERE user_id = $3 AND deleted_at IS NULL AND read_at IS NULL",
)
.bind(now)
.bind(now)
.bind(user_id)
.execute(self.ctx.db.writer())
.await
.map_err(AppError::Database)?;
Ok(result.rows_affected() as i64)
}
pub async fn dismiss_notification(
&self,
session: &Session,
notification_id: Uuid,
) -> Result<Notification, AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
let now = Utc::now();
sqlx::query(
"UPDATE notification SET dismissed_at = $1, updated_at = $2 \
WHERE id = $3 AND user_id = $4 AND deleted_at IS NULL",
)
.bind(now)
.bind(now)
.bind(notification_id)
.bind(user_id)
.execute(self.ctx.db.writer())
.await
.map_err(AppError::Database)?;
Notification::find_by_id(self.ctx.db.reader(), notification_id, user_id)
.await?
.ok_or(AppError::NotFound("notification not found".into()))
}
pub async fn delete_notification(
&self,
session: &Session,
notification_id: Uuid,
) -> Result<(), AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
let now = Utc::now();
let result = sqlx::query(
"UPDATE notification SET deleted_at = $1, updated_at = $2 \
WHERE id = $3 AND user_id = $4 AND deleted_at IS NULL",
)
.bind(now)
.bind(now)
.bind(notification_id)
.bind(user_id)
.execute(self.ctx.db.writer())
.await
.map_err(AppError::Database)?;
if result.rows_affected() == 0 {
return Err(AppError::NotFound("notification not found".into()));
}
Ok(())
}
pub async fn clear_all_notifications(&self, session: &Session) -> Result<i64, AppError> {
let user_id = session.user().ok_or(AppError::Unauthorized)?;
let now = Utc::now();
let result = sqlx::query(
"UPDATE notification SET dismissed_at = $1, updated_at = $2 \
WHERE user_id = $3 AND deleted_at IS NULL AND dismissed_at IS NULL",
)
.bind(now)
.bind(now)
.bind(user_id)
.execute(self.ctx.db.writer())
.await
.map_err(AppError::Database)?;
Ok(result.rows_affected() as i64)
}
}