From 86d3cbdf54acf61820f825dbc3d4e63755f1c6f8 Mon Sep 17 00:00:00 2001 From: arrelin Date: Fri, 6 Mar 2026 18:28:54 +0300 Subject: [PATCH] add admin responses endpoint --- backend/src/main.rs | 64 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/backend/src/main.rs b/backend/src/main.rs index 3c89a56..5f372f3 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,15 +1,18 @@ use axum::{ extract::State, - http::StatusCode, + http::{HeaderMap, StatusCode}, response::Json, - routing::post, + routing::{get, post}, Router, }; +use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::{postgres::PgPoolOptions, PgPool, Row}; use tower_http::cors::{Any, CorsLayer}; use uuid::Uuid; +const ADMIN_PASSWORD: &str = "2123"; + #[derive(Clone)] struct AppState { db: PgPool, @@ -31,6 +34,19 @@ struct SubmitResponse { id: Uuid, } +#[derive(Serialize)] +struct Response { + id: Uuid, + name: String, + alcohol: Option, + food: Option, + with_partner: bool, + partner_name: Option, + partner_alcohol: Option, + partner_food: Option, + created_at: DateTime, +} + async fn submit( State(state): State, Json(body): Json, @@ -55,10 +71,51 @@ async fn submit( })?; let id: Uuid = row.get("id"); - Ok(Json(SubmitResponse { id })) } +async fn admin_responses( + State(state): State, + headers: HeaderMap, +) -> Result>, StatusCode> { + let password = headers + .get("x-admin-password") + .and_then(|v| v.to_str().ok()) + .unwrap_or(""); + + if password != ADMIN_PASSWORD { + return Err(StatusCode::UNAUTHORIZED); + } + + let rows = sqlx::query( + "SELECT id, name, alcohol, food, with_partner, partner_name, partner_alcohol, partner_food, created_at + FROM responses ORDER BY created_at DESC", + ) + .fetch_all(&state.db) + .await + .map_err(|e| { + tracing::error!("DB error: {e}"); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + let responses = rows + .iter() + .map(|r| Response { + id: r.get("id"), + name: r.get("name"), + alcohol: r.get("alcohol"), + food: r.get("food"), + with_partner: r.get("with_partner"), + partner_name: r.get("partner_name"), + partner_alcohol: r.get("partner_alcohol"), + partner_food: r.get("partner_food"), + created_at: r.get("created_at"), + }) + .collect(); + + Ok(Json(responses)) +} + #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); @@ -85,6 +142,7 @@ async fn main() { let app = Router::new() .route("/api/submit", post(submit)) + .route("/api/admin/responses", get(admin_responses)) .layer(cors) .with_state(AppState { db });