this repo has no description
1use axum::extract::State;
2use axum::Json;
3use serde_json::json;
4
5use crate::auth::AuthUser;
6use crate::config::AppState;
7use crate::errors::AppError;
8use crate::models::{PushPreferencesRequest, PushPreferencesResponse, PushSubscribeRequest};
9
10/// GET /api/push/vapid-key
11pub async fn vapid_key(State(state): State<AppState>) -> Json<serde_json::Value> {
12 Json(json!({ "vapid_public_key": state.vapid_public_key }))
13}
14
15/// POST /api/push/subscribe
16pub async fn subscribe(
17 AuthUser(user_id): AuthUser,
18 State(state): State<AppState>,
19 Json(req): Json<PushSubscribeRequest>,
20) -> Result<Json<serde_json::Value>, AppError> {
21 let id = uuid::Uuid::new_v4().to_string();
22
23 sqlx::query(
24 "INSERT INTO push_subscriptions (id, user_id, endpoint, p256dh, auth)
25 VALUES (?, ?, ?, ?, ?)
26 ON CONFLICT(endpoint) DO UPDATE SET p256dh = excluded.p256dh, auth = excluded.auth, user_id = excluded.user_id",
27 )
28 .bind(&id)
29 .bind(&user_id)
30 .bind(&req.endpoint)
31 .bind(&req.p256dh)
32 .bind(&req.auth)
33 .execute(&state.db)
34 .await?;
35
36 Ok(Json(json!({ "ok": true })))
37}
38
39/// DELETE /api/push/subscribe
40pub async fn unsubscribe(
41 AuthUser(user_id): AuthUser,
42 State(state): State<AppState>,
43) -> Result<Json<serde_json::Value>, AppError> {
44 sqlx::query("DELETE FROM push_subscriptions WHERE user_id = ?")
45 .bind(&user_id)
46 .execute(&state.db)
47 .await?;
48
49 Ok(Json(json!({ "ok": true })))
50}
51
52/// GET /api/push/preferences
53pub async fn get_preferences(
54 AuthUser(user_id): AuthUser,
55 State(state): State<AppState>,
56) -> Result<Json<PushPreferencesResponse>, AppError> {
57 let row = sqlx::query_as::<_, (i32, String)>(
58 "SELECT COALESCE(reminder_enabled, 0), COALESCE(reminder_time, '20:00') FROM user_stats WHERE user_id = ?",
59 )
60 .bind(&user_id)
61 .fetch_optional(&state.db)
62 .await?;
63
64 match row {
65 Some((enabled, time)) => Ok(Json(PushPreferencesResponse {
66 reminder_enabled: enabled != 0,
67 reminder_time: time,
68 })),
69 None => Ok(Json(PushPreferencesResponse {
70 reminder_enabled: false,
71 reminder_time: "20:00".to_string(),
72 })),
73 }
74}
75
76/// PUT /api/push/preferences
77pub async fn update_preferences(
78 AuthUser(user_id): AuthUser,
79 State(state): State<AppState>,
80 Json(req): Json<PushPreferencesRequest>,
81) -> Result<Json<serde_json::Value>, AppError> {
82 let enabled = i32::from(req.reminder_enabled);
83
84 sqlx::query("UPDATE user_stats SET reminder_enabled = ?, reminder_time = ? WHERE user_id = ?")
85 .bind(enabled)
86 .bind(&req.reminder_time)
87 .bind(&user_id)
88 .execute(&state.db)
89 .await?;
90
91 Ok(Json(json!({ "ok": true })))
92}