Skip to main content

hvz/endpoints/
admin.rs

1use actix_web::{HttpRequest, HttpResponse, Responder, get, post, web};
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    player::{Player, PlayerState},
6    token::Token,
7};
8
9/// Struct representing a request to recover a player's password
10#[derive(Debug, Serialize, Deserialize)]
11pub struct RecoverPassword {
12    pub username: String,
13    pub password: String,
14}
15
16#[derive(Debug, Serialize, Deserialize)]
17pub struct FeedPlayersForm {
18    pub n: i32,
19    pub time: i32,
20}
21
22/// Struct used to set the checkpoint
23#[derive(Debug, Serialize, Deserialize)]
24pub struct SetCheckpoint {
25    pub x: String,
26    pub y: String,
27}
28
29/// **POST /admin/recover_password/{url_id}** - Recover a player's password
30#[post("/admin/recover_password/{url_id}")]
31pub async fn recover_password(
32    url_id: web::Path<String>,
33    req: HttpRequest,
34    form: web::Json<RecoverPassword>,
35) -> impl Responder {
36    if let Err(e) = Token::check_token(&req, &url_id).await {
37        return HttpResponse::Forbidden().body(e);
38    }
39
40    let admin = match Player::get_player(url_id.into_inner()).await {
41        Ok(Some(player)) => {
42            if let Err(err) = player.ensure_admin().await {
43                return HttpResponse::Unauthorized().body(err);
44            };
45            player
46        }
47        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
48        Err(err) => return HttpResponse::InternalServerError().body(err),
49    };
50
51    let RecoverPassword { username, password } = form.into_inner();
52    let result = admin.recover_password(username, password).await;
53
54    match result {
55        Ok(()) => HttpResponse::Ok().body("Password recovered"),
56        Err(err) => HttpResponse::InternalServerError().body(err),
57    }
58}
59
60/// **GET /admin/player_count/{url_id}** - Get the count of players
61#[get("/admin/player_count/{url_id}")]
62pub async fn player_count(url_id: web::Path<String>, req: HttpRequest) -> impl Responder {
63    if let Err(e) = Token::check_token(&req, &url_id).await {
64        return HttpResponse::Forbidden().body(e);
65    }
66
67    let admin = match Player::get_player(url_id.into_inner()).await {
68        Ok(Some(player)) => {
69            if let Err(err) = player.ensure_admin().await {
70                return HttpResponse::Unauthorized().body(err);
71            };
72            player
73        }
74        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
75        Err(err) => return HttpResponse::InternalServerError().body(err),
76    };
77
78    let result = admin.count_player().await;
79
80    match result {
81        Ok(count) => HttpResponse::Ok().body(count),
82        Err(err) => HttpResponse::InternalServerError().body(err),
83    }
84}
85
86/// **GET /admin/get_players/{url_id}** - Get all players
87#[get("/admin/get_players/{url_id}")]
88pub async fn get_all_players(url_id: web::Path<String>, req: HttpRequest) -> impl Responder {
89    if let Err(e) = Token::check_token(&req, &url_id).await {
90        return HttpResponse::Forbidden().body(e);
91    }
92
93    let admin = match Player::get_player(url_id.into_inner()).await {
94        Ok(Some(player)) => {
95            if let Err(err) = player.ensure_admin().await {
96                return HttpResponse::Unauthorized().body(err);
97            };
98            player
99        }
100        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
101        Err(err) => return HttpResponse::InternalServerError().body(err),
102    };
103
104    let result = admin.admin_get_players().await;
105
106    match result {
107        Ok(players) => {
108            let player_response = players.into_iter().map(|p| {
109                if p.state == PlayerState::Zombie0 {
110                    Player { state: PlayerState::Human, next_feeding: None, ..p }
111                } else {
112                    p
113                }
114            }).collect::<Vec<Player>>();
115            HttpResponse::Ok().json(player_response)
116        }
117        Err(err) => HttpResponse::InternalServerError().body(err),
118    }
119}
120
121/// **POST /admin/player_at_checkpoint/{url_id}** - Register a player that has gone through the checkpoint
122#[post("/admin/player_at_checkpoint/{url_id}")]
123pub async fn player_at_checkpoint(
124    url_id: web::Path<String>,
125    req: HttpRequest,
126    form: web::Json<String>,
127) -> impl Responder {
128    if let Err(e) = Token::check_token(&req, &url_id).await {
129        return HttpResponse::Forbidden().body(e);
130    }
131
132    let admin = match Player::get_player(url_id.into_inner()).await {
133        Ok(Some(player)) => {
134            if let Err(err) = player.ensure_admin().await {
135                return HttpResponse::Unauthorized().body(err);
136            };
137            player
138        }
139        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
140        Err(err) => return HttpResponse::InternalServerError().body(err),
141    };
142
143    let id = form.into_inner();
144    let result = admin.player_at_checkpoint(id).await;
145
146    match result {
147        Ok(result) => HttpResponse::Ok().body(result),
148        Err(err) => HttpResponse::InternalServerError().body(err),
149    }
150}
151
152/// **POST /admin/kill_all_not_at_checkpoint/{url_id}** - Kill all players that didn't go through the checkpoint
153#[post("/admin/kill_all_not_at_checkpoint/{url_id}")]
154pub async fn kill_all_not_at_checkpoint(
155    url_id: web::Path<String>,
156    req: HttpRequest,
157) -> impl Responder {
158    if let Err(e) = Token::check_token(&req, &url_id).await {
159        return HttpResponse::Forbidden().body(e);
160    }
161
162    let admin = match Player::get_player(url_id.into_inner()).await {
163        Ok(Some(player)) => {
164            if let Err(err) = player.ensure_admin().await {
165                return HttpResponse::Unauthorized().body(err);
166            };
167            player
168        }
169        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
170        Err(err) => return HttpResponse::InternalServerError().body(err),
171    };
172
173    let result = admin.kill_all_not_at_checkpoint().await;
174
175    match result {
176        Ok(_) => HttpResponse::Ok().body("All players killed"),
177        Err(err) => HttpResponse::InternalServerError().body(err),
178    }
179}
180
181/// **POST /admin/inject_sql/{url_id}** - Inject SQL query
182#[post("/admin/inject_sql/{url_id}")]
183pub async fn inject_sql(
184    url_id: web::Path<String>,
185    req: HttpRequest,
186    form: web::Json<String>,
187) -> impl Responder {
188    if let Err(e) = Token::check_token(&req, &url_id).await {
189        return HttpResponse::Forbidden().body(e);
190    }
191
192    let admin = match Player::get_player(url_id.into_inner()).await {
193        Ok(Some(player)) => {
194            if let Err(err) = player.ensure_admin().await {
195                return HttpResponse::Unauthorized().body(err);
196            };
197            player
198        }
199        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
200        Err(err) => return HttpResponse::InternalServerError().body(err),
201    };
202
203    let sql_query = form.into_inner();
204    let result = admin.inject_sql(sql_query).await;
205
206    match result {
207        Ok(_) => HttpResponse::Ok().body("SQL injected successfully"),
208        Err(err) => HttpResponse::InternalServerError().body(err),
209    }
210}
211
212/// **GET /admin/get_logs/{url_id}** - Get logs
213#[get("/admin/get_logs/{url_id}")]
214pub async fn get_logs(url_id: web::Path<String>, req: HttpRequest) -> impl Responder {
215    if let Err(e) = Token::check_token(&req, &url_id).await {
216        return HttpResponse::Forbidden().body(e);
217    }
218
219    let admin = match Player::get_player(url_id.into_inner()).await {
220        Ok(Some(player)) => {
221            if let Err(err) = player.ensure_admin().await {
222                return HttpResponse::Unauthorized().body(err);
223            };
224            player
225        }
226        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
227        Err(err) => return HttpResponse::InternalServerError().body(err),
228    };
229
230    let result = admin.get_logs().await;
231
232    match result {
233        Ok(logs) => HttpResponse::Ok().body(logs),
234        Err(err) => HttpResponse::InternalServerError().body(err),
235    }
236}
237
238/// **POST /admin/feed/{url_id}** - Feed the first n players
239#[post("/admin/feed/{url_id}")]
240pub async fn feed_players(
241    url_id: web::Path<String>,
242    req: HttpRequest,
243    form: web::Json<FeedPlayersForm>,
244) -> impl Responder {
245    if let Err(e) = Token::check_token(&req, &url_id).await {
246        return HttpResponse::Forbidden().body(e);
247    }
248
249    let admin = match Player::get_player(url_id.into_inner()).await {
250        Ok(Some(player)) => {
251            if let Err(err) = player.ensure_admin().await {
252                return HttpResponse::Unauthorized().body(err);
253            };
254            player
255        }
256        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
257        Err(err) => return HttpResponse::InternalServerError().body(err),
258    };
259
260    let form = form.into_inner();
261    let (n, time) = (form.n, form.time);
262    let result = admin.feed_players(n, time).await;
263
264    match result {
265        Ok(_) => HttpResponse::Ok().body("Players fed successfully"),
266        Err(err) => HttpResponse::InternalServerError().body(err),
267    }
268}
269
270/// **POST /admin/feed_player/{url_id}** - Feed player
271#[post("/admin/feed_player/{url_id}")]
272pub async fn feed_player(
273    url_id: web::Path<String>,
274    req: HttpRequest,
275    form: web::Json<String>,
276) -> impl Responder {
277    if let Err(e) = Token::check_token(&req, &url_id).await {
278        return HttpResponse::Forbidden().body(e);
279    }
280
281    let admin = match Player::get_player(url_id.into_inner()).await {
282        Ok(Some(player)) => {
283            if let Err(err) = player.ensure_admin().await {
284                return HttpResponse::Unauthorized().body(err);
285            };
286            player
287        }
288        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
289        Err(err) => return HttpResponse::InternalServerError().body(err),
290    };
291
292    let result = admin.admin_feed(form.into_inner()).await;
293
294    match result {
295        Ok(_) => HttpResponse::Ok().body("Player fed successfully"),
296        Err(err) => HttpResponse::InternalServerError().body(err),
297    }
298}
299
300/// **POST /admin/zombies_add_day/{url_id}** - Feeds all zombies for a day
301#[post("/admin/zombies_add_day/{url_id}")]
302pub async fn zombies_add_day(url_id: web::Path<String>, req: HttpRequest) -> impl Responder {
303    if let Err(e) = Token::check_token(&req, &url_id).await {
304        return HttpResponse::Forbidden().body(e);
305    }
306
307    let admin = match Player::get_player(url_id.into_inner()).await {
308        Ok(Some(player)) => {
309            if let Err(err) = player.ensure_admin().await {
310                return HttpResponse::Unauthorized().body(err);
311            };
312            player
313        }
314        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
315        Err(err) => return HttpResponse::InternalServerError().body(err),
316    };
317
318    let result = admin.feed_zombies_day().await;
319
320    match result {
321        Ok(_) => HttpResponse::Ok().body("Zombies fed successfully"),
322        Err(err) => HttpResponse::InternalServerError().body(err),
323    }
324}
325
326/// **POST /admin/zombify/{url_id}** - Zombify a player
327#[post("/admin/zombify/{url_id}")]
328pub async fn zombify(
329    url_id: web::Path<String>,
330    req: HttpRequest,
331    form: web::Json<String>,
332) -> impl Responder {
333    if let Err(e) = Token::check_token(&req, &url_id).await {
334        return HttpResponse::Forbidden().body(e);
335    }
336
337    let admin = match Player::get_player(url_id.into_inner()).await {
338        Ok(Some(player)) => {
339            if let Err(err) = player.ensure_admin().await {
340                return HttpResponse::Unauthorized().body(err);
341            }
342            player
343        }
344        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
345        Err(err) => return HttpResponse::InternalServerError().body(err),
346    };
347
348    let result = admin
349        .transform(form.into_inner(), PlayerState::Zombie)
350        .await;
351
352    match result {
353        Ok(_) => HttpResponse::Ok().body("Zombified successfully"),
354        Err(e) => HttpResponse::InternalServerError().body(e),
355    }
356}
357
358/// **POST /admin/corpsify/{url_id}** - Kill a player
359#[post("/admin/corpsify/{url_id}")]
360pub async fn corpsify(
361    url_id: web::Path<String>,
362    req: HttpRequest,
363    form: web::Json<String>,
364) -> impl Responder {
365    if let Err(e) = Token::check_token(&req, &url_id).await {
366        return HttpResponse::Forbidden().body(e);
367    }
368
369    let admin = match Player::get_player(url_id.into_inner()).await {
370        Ok(Some(player)) => {
371            if let Err(err) = player.ensure_admin().await {
372                return HttpResponse::Unauthorized().body(err);
373            };
374            player
375        }
376        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
377        Err(err) => return HttpResponse::InternalServerError().body(err),
378    };
379
380    let result = admin
381        .transform(form.into_inner(), PlayerState::Corpse)
382        .await;
383
384    match result {
385        Ok(_) => HttpResponse::Ok().body("Player killed successfully"),
386        Err(err) => HttpResponse::InternalServerError().body(err),
387    }
388}
389
390/// **POST /admin/cure/{url_id}** - Cure a zombie
391#[post("/admin/cure/{url_id}")]
392pub async fn cure_zombie(
393    url_id: web::Path<String>,
394    req: HttpRequest,
395    form: web::Json<String>,
396) -> impl Responder {
397    if let Err(e) = Token::check_token(&req, &url_id).await {
398        return HttpResponse::Forbidden().body(e);
399    }
400
401    let admin = match Player::get_player(url_id.into_inner()).await {
402        Ok(Some(player)) => {
403            if let Err(err) = player.ensure_admin().await {
404                return HttpResponse::Unauthorized().body(err);
405            };
406            player
407        }
408        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
409        Err(err) => return HttpResponse::InternalServerError().body(err),
410    };
411
412    let result = admin.cure(form.into_inner()).await;
413
414    match result {
415        Ok(_) => HttpResponse::Ok().body("Player cured successfully"),
416        Err(err) => HttpResponse::InternalServerError().body(err),
417    }
418}
419
420/// **POST /admin/revive_h/{url_id}** - Revive a corpse to human
421#[post("/admin/revive_h/{url_id}")]
422pub async fn revive_human(
423    url_id: web::Path<String>,
424    req: HttpRequest,
425    form: web::Json<String>,
426) -> impl Responder {
427    if let Err(e) = Token::check_token(&req, &url_id).await {
428        return HttpResponse::Forbidden().body(e);
429    }
430
431    let admin = match Player::get_player(url_id.into_inner()).await {
432        Ok(Some(player)) => {
433            if let Err(err) = player.ensure_admin().await {
434                return HttpResponse::Unauthorized().body(err);
435            };
436            player
437        }
438        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
439        Err(err) => return HttpResponse::InternalServerError().body(err),
440    };
441
442    let result = admin.transform(form.into_inner(), PlayerState::Human).await;
443
444    match result {
445        Ok(_) => HttpResponse::Ok().body("Player revived successfully"),
446        Err(err) => HttpResponse::InternalServerError().body(err),
447    }
448}
449
450/// **POST /admin/revive_z/{url_id}** - Revive a corpse to zombie
451#[post("/admin/revive_z/{url_id}")]
452pub async fn revive_zombie(
453    url_id: web::Path<String>,
454    req: HttpRequest,
455    form: web::Json<String>,
456) -> impl Responder {
457    if let Err(e) = Token::check_token(&req, &url_id).await {
458        return HttpResponse::Forbidden().body(e);
459    }
460
461    let admin = match Player::get_player(url_id.into_inner()).await {
462        Ok(Some(player)) => {
463            if let Err(err) = player.ensure_admin().await {
464                return HttpResponse::Unauthorized().body(err);
465            };
466            player
467        }
468        Ok(None) => return HttpResponse::NotFound().body("Player not found"),
469        Err(err) => return HttpResponse::InternalServerError().body(err),
470    };
471
472    let result = admin
473        .transform(form.into_inner(), PlayerState::Zombie)
474        .await;
475
476    match result {
477        Ok(_) => HttpResponse::Ok().body("Player revived successfully"),
478        Err(err) => HttpResponse::InternalServerError().body(err),
479    }
480}