this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

changed the locking around some

+57 -38
+1 -1
shared/src/advent/mod.rs
··· 52 52 Two, 53 53 } 54 54 55 - #[derive(Clone, Copy, Debug)] 55 + #[derive(Clone, Copy, Debug, PartialEq)] 56 56 pub enum CompletionStatus { 57 57 ///None of the day's challenges have been completed 58 58 None,
+24 -15
web/src/main.rs
··· 258 258 "/day/{id}", 259 259 match prod { 260 260 true => get(handlers::day::view_day_handler) 261 - .route_layer(middleware::from_fn(unlock::unlock)), 261 + .route_layer(middleware::from_fn_with_state(app_state.postgres_pool.clone(), unlock::unlock)), 262 262 false => get(handlers::day::view_day_handler), 263 263 }, 264 264 ) ··· 266 266 "/day/{id}", 267 267 match prod { 268 268 true => post(handlers::day::post_day_handler) 269 - .route_layer(middleware::from_fn(unlock::unlock)), 269 + .route_layer(middleware::from_fn_with_state(app_state.postgres_pool.clone(), unlock::unlock)), 270 270 false => post(handlers::day::post_day_handler), 271 271 }, 272 272 ) ··· 296 296 297 297 /// The default handler that will be used during the advent month, but not during amtosphere conf 298 298 async fn home_handler(State(pool): State<PgPool>, session: AxumSessionStore) -> impl IntoResponse { 299 - //TODO make a helper function for this since it is similar to the middleware 300 - let now = chrono::Utc::now(); 301 299 let mut unlocked: Vec<u8> = Vec::new(); 302 300 301 + let did = session.get_did(); 302 + let is_logged_in = session.logged_in(); 303 + let all_statuses = get_all_days_completion_status(&pool, did.as_ref()) 304 + .await 305 + .unwrap_or_else(|_| (1..=25).map(|day| (day, CompletionStatus::None)).collect()); 306 + 303 307 //HACK Yeah I don't like it either - bt 304 308 let prod: bool = env::var("PROD") 305 309 .map(|val| val == "true") 306 310 .unwrap_or_else(|_| true); 307 311 if prod { 308 - if now.month() == 12 { 309 - let today = now.day().min(25); 310 - for d in 1..=today { 311 - unlocked.push(d as u8); 312 + // Only show implemented days, progressively unlocked as users complete them 313 + let implemented_days: Vec<u8> = vec![1, 2, 3]; 314 + if let Some(&first) = implemented_days.first() { 315 + unlocked.push(first); 316 + } 317 + for window in implemented_days.windows(2) { 318 + let prev = window[0]; 319 + let prev_status = all_statuses 320 + .iter() 321 + .find(|(d, _)| *d == prev) 322 + .map(|(_, s)| s) 323 + .unwrap_or(&CompletionStatus::None); 324 + if *prev_status == CompletionStatus::Both { 325 + unlocked.push(window[1]); 326 + } else { 327 + break; 312 328 } 313 329 } 314 330 } else { ··· 316 332 unlocked.push(d as u8); 317 333 } 318 334 } 319 - 320 - // Get completion status for all days at once 321 - let did = session.get_did(); 322 - let is_logged_in = session.logged_in(); 323 - let all_statuses = get_all_days_completion_status(&pool, did.as_ref()) 324 - .await 325 - .unwrap_or_else(|_| (1..=25).map(|day| (day, CompletionStatus::None)).collect()); 326 335 327 336 // Filter to only include unlocked days 328 337 let unlocked_with_status: Vec<DayStatus> = all_statuses
+32 -22
web/src/unlock.rs
··· 1 - use axum::extract::{Path, Request}; 1 + use crate::session::AxumSessionStore; 2 + use axum::extract::{Path, Request, State}; 2 3 use axum::http; 3 4 use axum::{ 4 5 middleware, 5 6 response::{self, IntoResponse}, 6 7 }; 7 - use chrono::Datelike; 8 + use shared::advent::{CompletionStatus, get_all_days_completion_status}; 9 + use sqlx::PgPool; 8 10 9 11 pub async fn unlock( 12 + State(pool): State<PgPool>, 10 13 Path(mut day): Path<u8>, 14 + session: AxumSessionStore, 11 15 request: Request, 12 16 next: middleware::Next, 13 17 ) -> response::Response { ··· 35 39 .into_response(); 36 40 } 37 41 38 - let now = chrono::Utc::now(); 39 - let current_day = now.day(); 40 - let month = now.month(); 42 + let implemented_days: Vec<u8> = vec![1, 2, 3]; 41 43 42 - if month != 12 { 44 + if !implemented_days.contains(&day) { 43 45 return ( 44 46 http::StatusCode::FORBIDDEN, 45 - "It's not December yet! NO PEAKING", 47 + "This day hasn't been created yet!", 46 48 ) 47 49 .into_response(); 48 50 } 49 51 50 - //Show any day previous to the current day and current day 51 - if day as u32 <= current_day { 52 - return next.run(request).await; 53 - } 52 + // First implemented day is always accessible 53 + let pos = implemented_days.iter().position(|&d| d == day).unwrap(); 54 + if pos > 0 { 55 + let prev_day = implemented_days[pos - 1]; 56 + let did = session.get_did(); 54 57 55 - ( 56 - http::StatusCode::FORBIDDEN, 57 - "Now just hold on a minute. It ain't time yet.", 58 - ) 59 - .into_response() 58 + let all_statuses = get_all_days_completion_status(&pool, did.as_ref()) 59 + .await 60 + .unwrap_or_else(|_| (1..=25).map(|d| (d, CompletionStatus::None)).collect()); 60 61 61 - // Just commenting out for now if we do want a json endpoint and i forgot easiest way to return it 62 - // let error_response = axum::Json(serde_json::json!({ 63 - // "error": "Route Locked", 64 - // "time_remaining_seconds": time_remaining.as_secs(), 65 - // })); 62 + let prev_status = all_statuses 63 + .iter() 64 + .find(|(d, _)| *d == prev_day) 65 + .map(|(_, s)| s) 66 + .unwrap_or(&CompletionStatus::None); 67 + 68 + if *prev_status != CompletionStatus::Both { 69 + return ( 70 + http::StatusCode::FORBIDDEN, 71 + "Now just hold on a minute. It ain't time yet.", 72 + ) 73 + .into_response(); 74 + } 75 + } 66 76 67 - // (http::StatusCode::FORBIDDEN, error_response).into_response() 77 + next.run(request).await 68 78 }