This commit is contained in:
parent
cc8fcd682b
commit
91db5861c8
21 changed files with 1263 additions and 79 deletions
128
src/server/notifications/push_handlers.rs
Normal file
128
src/server/notifications/push_handlers.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use axum::{
|
||||
Json,
|
||||
extract::{Path, State},
|
||||
};
|
||||
use chrono::Utc;
|
||||
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::entities::{push_subscription, task_subscription};
|
||||
use crate::error::{AppError, AppResult};
|
||||
use crate::server::AppState;
|
||||
use crate::server::auth::AuthenticatedUser;
|
||||
use base64::Engine;
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct RegisterPushRequest {
|
||||
pub endpoint: String,
|
||||
pub p256dh: String,
|
||||
pub auth: String,
|
||||
}
|
||||
|
||||
pub async fn register_push(
|
||||
State(state): State<Arc<AppState>>,
|
||||
user: AuthenticatedUser,
|
||||
Json(payload): Json<RegisterPushRequest>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let user_sub = user.0.sub;
|
||||
|
||||
// Check if subscription exists
|
||||
let existing = push_subscription::Entity::find()
|
||||
.filter(push_subscription::Column::UserSub.eq(user_sub.clone()))
|
||||
.filter(push_subscription::Column::Endpoint.eq(payload.endpoint.clone()))
|
||||
.one(&state.db)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
|
||||
if existing.is_none() {
|
||||
let new_sub = push_subscription::ActiveModel {
|
||||
id: Set(Uuid::new_v4()),
|
||||
user_sub: Set(user_sub),
|
||||
endpoint: Set(payload.endpoint),
|
||||
p256dh: Set(payload.p256dh),
|
||||
auth: Set(payload.auth),
|
||||
created_at: Set(Utc::now().into()),
|
||||
};
|
||||
new_sub
|
||||
.insert(&state.db)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
}
|
||||
|
||||
Ok(Json(serde_json::json!({ "status": "registered" })))
|
||||
}
|
||||
|
||||
pub async fn subscribe_task(
|
||||
State(state): State<Arc<AppState>>,
|
||||
user: AuthenticatedUser,
|
||||
Path(task_id): Path<Uuid>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let user_sub = user.0.sub;
|
||||
|
||||
let existing = task_subscription::Entity::find()
|
||||
.filter(task_subscription::Column::UserSub.eq(user_sub.clone()))
|
||||
.filter(task_subscription::Column::TaskId.eq(task_id))
|
||||
.one(&state.db)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
|
||||
if existing.is_none() {
|
||||
let new_sub = task_subscription::ActiveModel {
|
||||
id: Set(Uuid::new_v4()),
|
||||
user_sub: Set(user_sub),
|
||||
task_id: Set(task_id),
|
||||
created_at: Set(Utc::now().into()),
|
||||
};
|
||||
new_sub
|
||||
.insert(&state.db)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
}
|
||||
|
||||
Ok(Json(serde_json::json!({ "status": "subscribed" })))
|
||||
}
|
||||
|
||||
pub async fn unsubscribe_task(
|
||||
State(state): State<Arc<AppState>>,
|
||||
user: AuthenticatedUser,
|
||||
Path(task_id): Path<Uuid>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let user_sub = user.0.sub;
|
||||
|
||||
task_subscription::Entity::delete_many()
|
||||
.filter(task_subscription::Column::UserSub.eq(user_sub))
|
||||
.filter(task_subscription::Column::TaskId.eq(task_id))
|
||||
.exec(&state.db)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
|
||||
Ok(Json(serde_json::json!({ "status": "unsubscribed" })))
|
||||
}
|
||||
|
||||
pub async fn get_vapid_key(
|
||||
State(state): State<Arc<AppState>>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let public_key = state.scheduler.push_sender.get_public_key()?;
|
||||
let encoded = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(public_key);
|
||||
Ok(Json(serde_json::json!({ "publicKey": encoded })))
|
||||
}
|
||||
|
||||
pub async fn get_subscription_status(
|
||||
State(state): State<Arc<AppState>>,
|
||||
user: AuthenticatedUser,
|
||||
Path(task_id): Path<Uuid>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let user_sub = user.0.sub;
|
||||
|
||||
let existing = task_subscription::Entity::find()
|
||||
.filter(task_subscription::Column::UserSub.eq(user_sub))
|
||||
.filter(task_subscription::Column::TaskId.eq(task_id))
|
||||
.one(&state.db)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
|
||||
Ok(Json(
|
||||
serde_json::json!({ "isSubscribed": existing.is_some() }),
|
||||
))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue