get stuff ready for deployment!

This commit is contained in:
Schrottkatze 2024-11-06 16:19:47 +01:00
parent 00a584c8f0
commit 66b14ed855
Signed by: schrottkatze
SSH key fingerprint: SHA256:hXb3t1vINBFCiDCmhRABHX5ocdbLiKyCdKI4HK2Rbbc
4 changed files with 87 additions and 55 deletions

View file

@ -1,44 +1,49 @@
use std::io; // use std::io;
use app::App; // use app::App;
use crossterm::event::{self, KeyCode, KeyEventKind}; // use crossterm::event::{self, KeyCode, KeyEventKind};
use ratatui::{style::Stylize, widgets::Paragraph, DefaultTerminal}; // use ratatui::{style::Stylize, widgets::Paragraph, DefaultTerminal};
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let mut term = ratatui::init(); // let mut term = ratatui::init();
term.clear()?; // term.clear()?;
let r = App::default().run(&mut term); // let r = App::default().run(&mut term);
ratatui::restore(); // ratatui::restore();
r // r
let mut teststr = String::from("Hello! ää");
} }
mod app { fn rev_in_place(s: &mut String) {
s.ch
use std::io;
use ratatui::{DefaultTerminal, Frame};
#[derive(Default)]
pub struct App {
exit: bool,
} }
impl App { // mod app {
pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
while !self.exit {
terminal.draw(|frame| self.draw(frame))?;
self.handle_events()?;
}
Ok(())
}
fn draw(&self, frame: &mut Frame) { // use std::io;
todo!()
}
fn handle_events(&mut self) -> io::Result<()> { // use ratatui::{DefaultTerminal, Frame};
todo!()
} // #[derive(Default)]
} // pub struct App {
} // exit: bool,
// }
// impl App {
// pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
// while !self.exit {
// terminal.draw(|frame| self.draw(frame))?;
// self.handle_events()?;
// }
// Ok(())
// }
// fn draw(&self, frame: &mut Frame) {
// todo!()
// }
// fn handle_events(&mut self) -> io::Result<()> {
// todo!()
// }
// }
// }

View file

@ -1,19 +1,62 @@
use axum::{ use axum::{
extract::{Path, State}, extract::{Path, Request, State},
middleware::{self, Next},
response::{IntoResponse, Response},
routing::get, routing::get,
Json, Router, Json, Router,
}; };
use http::{HeaderMap, HeaderValue, StatusCode};
use rand::distributions::{Alphanumeric, DistString}; use rand::distributions::{Alphanumeric, DistString};
use sqlx::{Pool, Postgres, QueryBuilder}; use sqlx::{Pool, Postgres, QueryBuilder};
use crate::{model::Chat, state::AppState}; use crate::{markup_response::simple_error_page, model::Chat, state::AppState, ADMIN_TOK};
pub fn router(state: AppState) -> Router { pub fn router(state: AppState) -> Router {
Router::new() Router::new()
.route("/new/:amount", get(create)) .route("/new/:amount", get(create))
.nest("/stat", stat::router(state.clone()))
.route_layer(middleware::from_fn_with_state(
state.clone(),
auth_middleware,
))
.with_state(state) .with_state(state)
} }
async fn auth_middleware(
State(state): State<AppState>,
headers: HeaderMap,
req: Request,
next: Next,
) -> Response {
let admin_tok = headers.get("x-admin-tok");
if headers.get("x-admin-tok") == Some(&HeaderValue::from_static(ADMIN_TOK)) {
let res = next.run(req).await;
return res;
}
simple_error_page(StatusCode::UNAUTHORIZED).into_response()
}
mod stat {
use axum::{extract::State, routing::get, Json, Router};
use crate::{model::Chat, state::AppState};
// TODO: /stat/* should require authentication
pub fn router(state: AppState) -> Router<AppState> {
Router::new().route("/chats", get(chats)).with_state(state)
}
async fn chats(State(state): State<AppState>) -> Json<Vec<Chat>> {
let r = sqlx::query_as!(Chat, "select * from chats;")
.fetch_all(state.pool())
.await
.unwrap();
Json(r)
}
}
async fn create(Path(amount): Path<u8>, State(state): State<AppState>) -> Json<Vec<Chat>> { async fn create(Path(amount): Path<u8>, State(state): State<AppState>) -> Json<Vec<Chat>> {
let paths: Vec<String> = (0..amount) let paths: Vec<String> = (0..amount)
.map(|_| Alphanumeric.sample_string(&mut rand::thread_rng(), 6)) .map(|_| Alphanumeric.sample_string(&mut rand::thread_rng(), 6))

View file

@ -10,7 +10,6 @@ mod admin;
mod chat; mod chat;
mod markup_response; mod markup_response;
mod model; mod model;
mod stat;
mod state; mod state;
mod ws; mod ws;
@ -28,7 +27,6 @@ async fn main() -> anyhow::Result<()> {
.route("/:path", get(chat::get).post(chat::post)) .route("/:path", get(chat::get).post(chat::post))
.route("/poll/:msg", get(chat::poll)) .route("/poll/:msg", get(chat::poll))
.with_state(state.clone()) .with_state(state.clone())
.nest("/stat", stat::router(state.clone()))
.nest("/admin", admin::router(state.clone())) .nest("/admin", admin::router(state.clone()))
.nest("/static", axum_static::static_router("static")); .nest("/static", axum_static::static_router("static"));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap(); let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();

View file

@ -4,17 +4,3 @@ use axum::{extract::State, routing::get, Json, Router};
use sqlx::{types::Uuid, Pool, Postgres}; use sqlx::{types::Uuid, Pool, Postgres};
use crate::{model::Chat, state::AppState}; use crate::{model::Chat, state::AppState};
// TODO: /stat/* should require authentication
pub fn router(state: AppState) -> Router {
Router::new().route("/chats", get(chats)).with_state(state)
}
async fn chats(State(state): State<AppState>) -> Json<Vec<Chat>> {
let r = sqlx::query_as!(Chat, "select * from chats;")
.fetch_all(state.pool())
.await
.unwrap();
Json(r)
}