forked from
oppi.li/at-advent
this repo has no description
1use crate::session::AxumSessionStore;
2use axum::extract::{Path, Request, State};
3use axum::http;
4use axum::{
5 middleware,
6 response::{self, IntoResponse},
7};
8use shared::advent::{CompletionStatus, get_all_days_completion_status, get_global_unlock_day};
9use sqlx::PgPool;
10
11pub async fn unlock(
12 State(pool): State<PgPool>,
13 Path(mut day): Path<u8>,
14 session: AxumSessionStore,
15 request: Request,
16 next: middleware::Next,
17) -> response::Response {
18 if day == 0 {
19 day = 1;
20 }
21
22 if day == 69 {
23 return (http::StatusCode::FORBIDDEN, "Really?").into_response();
24 }
25
26 if day == 42 {
27 return (
28 http::StatusCode::FORBIDDEN,
29 "Oh, you have all the answers, huh?",
30 )
31 .into_response();
32 }
33
34 if day > 25 || day < 1 {
35 return (
36 http::StatusCode::FORBIDDEN,
37 "This isn't even a day in the advent calendar????",
38 )
39 .into_response();
40 }
41 let implemented_days = shared::advent::get_implemented_days();
42 if !implemented_days.contains(&day) {
43 return (
44 http::StatusCode::FORBIDDEN,
45 "This day hasn't been created yet!",
46 )
47 .into_response();
48 }
49
50 // Check if the day is globally unlocked via the settings table
51 let global_unlock_enabled = std::env::var("GLOBAL_UNLOCK_ENABLED")
52 .map(|v| v == "true")
53 .unwrap_or(false);
54
55 if global_unlock_enabled {
56 let global_unlock_day = get_global_unlock_day(&pool).await.unwrap_or(1);
57 if day <= global_unlock_day {
58 return next.run(request).await;
59 } else {
60 return (
61 http::StatusCode::FORBIDDEN,
62 "Now just hold on a minute. It ain't time yet.",
63 )
64 .into_response();
65 }
66 }
67
68 // First implemented day is always accessible
69 let pos = implemented_days.iter().position(|&d| d == day).unwrap();
70 if pos > 0 {
71 let prev_day = implemented_days[pos - 1];
72 let did = session.get_did();
73
74 let all_statuses = get_all_days_completion_status(&pool, did.as_ref())
75 .await
76 .unwrap_or_else(|_| (1..=25).map(|d| (d, CompletionStatus::None)).collect());
77
78 let prev_status = all_statuses
79 .iter()
80 .find(|(d, _)| *d == prev_day)
81 .map(|(_, s)| s)
82 .unwrap_or(&CompletionStatus::None);
83
84 //HACK hardcoded for the workshop since we don't have a part 2 for day 4
85 if (pos == 4 || pos == 5) && *prev_status == CompletionStatus::PartOne {
86 return next.run(request).await;
87 }
88
89 if *prev_status != CompletionStatus::Both {
90 return (
91 http::StatusCode::FORBIDDEN,
92 "Now just hold on a minute. It ain't time yet.",
93 )
94 .into_response();
95 }
96 }
97
98 next.run(request).await
99}