hvz/endpoints/
notifications.rs1use actix_web::{HttpRequest, HttpResponse, Responder, delete, post, web};
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 notifications::{Notification, PlayerGroups, PushSubscription},
6 player::Player,
7 token::Token,
8};
9
10#[derive(Debug, Serialize, Deserialize)]
12pub struct PushSubscriptionRequest {
13 endpoint: String,
14 p256dh: String,
15 auth: String,
16}
17
18#[derive(Debug, Serialize, Deserialize)]
20pub struct PushNotificationRequest {
21 title: String,
22 content: String,
23 player_groups: PlayerGroups,
24}
25
26#[post("/notifications/subscribe/{url_id}")]
28pub async fn subscribe(
29 url_id: web::Path<String>,
30 req: HttpRequest,
31 form: web::Json<PushSubscriptionRequest>,
32) -> impl Responder {
33 if let Err(e) = Token::check_token(&req, &url_id).await {
34 return HttpResponse::Forbidden().body(e);
35 }
36
37 let player = match Player::get_player(url_id.into_inner()).await {
38 Ok(Some(player)) => player,
39 Ok(None) => return HttpResponse::NotFound().body("Player not found"),
40 Err(err) => return HttpResponse::Forbidden().body(err),
41 };
42
43 let subscription = PushSubscription::new(
44 player.id.clone(),
45 form.endpoint.clone(),
46 form.p256dh.clone(),
47 form.auth.clone(),
48 )
49 .await;
50
51 match subscription.save().await {
52 Ok(sub) => HttpResponse::Ok().json(sub),
53 Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
54 }
55}
56
57#[delete("/subscriptions/unsubscribe/{url_id}")]
59pub async fn unsubscribe(url_id: web::Path<String>, req: HttpRequest) -> impl Responder {
60 if let Err(e) = Token::check_token(&req, &url_id).await {
61 return HttpResponse::Forbidden().body(e);
62 }
63
64 let player = match Player::get_player(url_id.into_inner()).await {
65 Ok(Some(player)) => player,
66 Ok(None) => return HttpResponse::NotFound().body("Player not found"),
67 Err(err) => return HttpResponse::InternalServerError().body(err.to_string()),
68 };
69
70 match PushSubscription::unsubscribe(player.id).await {
71 Ok(_) => HttpResponse::NoContent().finish(),
72 Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
73 }
74}
75
76#[post("/notifications/send/{url_id}")]
78pub async fn send_notification(
79 url_id: web::Path<String>,
80 req: HttpRequest,
81 form: web::Json<PushNotificationRequest>,
82) -> impl Responder {
83 if let Err(e) = Token::check_token(&req, &url_id).await {
84 return HttpResponse::Forbidden().body(e);
85 }
86
87 let player = match Player::get_player(url_id.into_inner()).await {
88 Ok(Some(player)) => {
89 if let Err(err) = player.ensure_admin().await {
90 return HttpResponse::Unauthorized().body(err);
91 };
92 player
93 }
94 Ok(None) => return HttpResponse::NotFound().body("Player not found"),
95 Err(err) => return HttpResponse::Forbidden().body(err),
96 };
97
98 let notification = Notification::new(
99 player.id,
100 form.title.clone(),
101 form.content.clone(),
102 PlayerGroups::All,
103 )
104 .await;
105
106 match notification.save().await {
107 Ok(_) => {}
108 Err(err) => return HttpResponse::InternalServerError().body(err.to_string()),
109 }
110
111 match notification.send_push_notification().await {
112 Ok(response) => HttpResponse::Ok().json(response),
113 Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
114 }
115}