implement bare basic functionality!!!

This commit is contained in:
Schrottkatze 2024-10-04 20:18:36 +02:00
parent 5f9bb732b8
commit ed87d3fb51
Signed by: schrottkatze
SSH key fingerprint: SHA256:hXb3t1vINBFCiDCmhRABHX5ocdbLiKyCdKI4HK2Rbbc
7 changed files with 238 additions and 13 deletions

135
Cargo.lock generated
View file

@ -53,6 +53,21 @@ version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.15" version = "0.6.15"
@ -208,7 +223,9 @@ dependencies = [
"anyhow", "anyhow",
"axum", "axum",
"axum-macros", "axum-macros",
"chrono",
"chrono-tz", "chrono-tz",
"http",
"maud", "maud",
"rand", "rand",
"serde", "serde",
@ -263,6 +280,12 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -311,7 +334,13 @@ version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [ dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits", "num-traits",
"serde",
"wasm-bindgen",
"windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -410,6 +439,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.14" version = "0.2.14"
@ -842,6 +877,29 @@ dependencies = [
"tower-service", "tower-service",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.5.0" version = "0.5.0"
@ -893,6 +951,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
dependencies = [
"wasm-bindgen",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -1701,6 +1768,7 @@ dependencies = [
"atoi", "atoi",
"byteorder", "byteorder",
"bytes", "bytes",
"chrono",
"crc", "crc",
"crossbeam-queue", "crossbeam-queue",
"either", "either",
@ -1785,6 +1853,7 @@ dependencies = [
"bitflags", "bitflags",
"byteorder", "byteorder",
"bytes", "bytes",
"chrono",
"crc", "crc",
"digest", "digest",
"dotenvy", "dotenvy",
@ -1827,6 +1896,7 @@ dependencies = [
"base64", "base64",
"bitflags", "bitflags",
"byteorder", "byteorder",
"chrono",
"crc", "crc",
"dotenvy", "dotenvy",
"etcetera", "etcetera",
@ -1863,6 +1933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680"
dependencies = [ dependencies = [
"atoi", "atoi",
"chrono",
"flume", "flume",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -2256,6 +2327,61 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.26.6" version = "0.26.6"
@ -2297,6 +2423,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"

View file

@ -4,14 +4,16 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
http = "1"
axum = { version = "0.7.5", features = [ "json", "macros" ] } axum = { version = "0.7.5", features = [ "json", "macros" ] }
axum-macros = "0.4.1" axum-macros = "0.4.1"
chrono = { version = "0.4", features = [ "serde" ] }
chrono-tz = "0.10.0" chrono-tz = "0.10.0"
maud = "0.26.0" maud = "0.26.0"
sqlx = { version = "0.8.2", features = ["postgres", "runtime-tokio", "tls-rustls-ring", "uuid" ] } sqlx = { version = "0.8.2", features = [ "postgres", "runtime-tokio", "tls-rustls-ring", "uuid", "chrono" ] }
tokio = { version = "1.40.0", features = ["full"] } tokio = { version = "1.40.0", features = [ "full" ] }
tokio-tungstenite = "0.24.0" tokio-tungstenite = "0.24.0"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = [ "derive" ] }
anyhow = "1" anyhow = "1"
uuid = { version = "1.10.0", features = ["serde"] } uuid = { version = "1.10.0", features = [ "serde" ] }
rand = "0.8.5" rand = "0.8.5"

View file

@ -10,8 +10,10 @@ create table chats (
create table messages ( create table messages (
id uuid default (gen_random_uuid()) primary key, id uuid default (gen_random_uuid()) primary key,
timestamp timestamptz default (now()), timestamp timestamptz not null default (now()),
chat_id uuid not null references chats(id), chat_id uuid not null references chats(id),
content varchar(2000) not null, content varchar(2000) not null,
from_admin boolean not null from_admin boolean not null
) );
insert into chats (url_path) values ('tstcht');

View file

@ -1,18 +1,28 @@
use axum::{ use axum::{
extract::{Path, State}, extract::{FromRef, Path, State},
response::Html, http::{
Json, header::{ACCEPT, CONTENT_TYPE},
HeaderMap, HeaderValue, StatusCode,
},
response::{Html, IntoResponse, Redirect},
Form, Json,
}; };
use maud::{html, Render}; use maud::{html, Render};
use serde::{Deserialize, Serialize};
use sqlx::{Pool, Postgres}; use sqlx::{Pool, Postgres};
use uuid::Uuid; use uuid::Uuid;
use crate::model::{Chat, Message}; use crate::{
model::{Chat, Message},
ADMIN_TOK,
};
pub async fn get( pub async fn get(
Path(url_path): Path<String>, Path(url_path): Path<String>,
headers: HeaderMap,
State(pool): State<Pool<Postgres>>, State(pool): State<Pool<Postgres>>,
) -> Json<Vec<Message>> { ) -> impl IntoResponse {
println!("headers: {headers:#?}");
let chat = sqlx::query_as!(Chat, r#"select * from chats where url_path = $1"#, url_path) let chat = sqlx::query_as!(Chat, r#"select * from chats where url_path = $1"#, url_path)
.fetch_one(&pool) .fetch_one(&pool)
.await .await
@ -25,5 +35,74 @@ pub async fn get(
.fetch_all(&pool) .fetch_all(&pool)
.await .await
.unwrap(); .unwrap();
Json(messages)
if Some(&HeaderValue::from_static("application/json")) == headers.get(ACCEPT) {
Json(messages).into_response()
} else {
Html(
html! {
main {
div #history {
@for msg in &messages {
div.message.(if msg.from_admin { "from_admin" } else { "from_user" }) {
p { (msg.content) "(" (msg.timestamp) ")" }
}
}
}
form #send method="post"{
textarea #msgcontent name="msgcontent" rows="1" cols="80" {}
button type="submit" { "Send!" }
}
}
}
.into_string(),
)
.into_response()
}
}
// TODO:
// - validation of msg length
// - fix terrible returns lmao
pub async fn post(
Path(url_path): Path<String>,
headers: HeaderMap,
State(pool): State<Pool<Postgres>>,
Form(FormMessageBody { msgcontent: body }): Form<FormMessageBody>,
) -> impl IntoResponse {
let chat = sqlx::query_as!(Chat, r#"select * from chats where url_path = $1"#, url_path)
.fetch_one(&pool)
.await
.unwrap();
if body.len() > 2000 {
return StatusCode::BAD_REQUEST.into_response();
}
if headers.get("x-admin-tok") == Some(&HeaderValue::from_static(ADMIN_TOK)) {
sqlx::query!(
r#"insert into messages (chat_id, content, from_admin) values ($1, $2, true);"#,
chat.id,
body
)
.execute(&pool)
.await
.unwrap();
StatusCode::OK.into_response()
} else {
sqlx::query!(
r#"insert into messages (chat_id, content, from_admin) values ($1, $2, false);"#,
chat.id,
body
)
.execute(&pool)
.await
.unwrap();
Redirect::to(&format!("/{url_path}")).into_response()
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FormMessageBody {
msgcontent: String,
} }

View file

@ -17,7 +17,7 @@ async fn main() -> anyhow::Result<()> {
let app = Router::new() let app = Router::new()
.route("/", get(|| async { "<h1>gay</h1>" })) .route("/", get(|| async { "<h1>gay</h1>" }))
.route("/:path", get(chat::get)) .route("/:path", get(chat::get).post(chat::post))
.with_state(pool.clone()) .with_state(pool.clone())
.nest("/stat", stat::router(pool.clone())) .nest("/stat", stat::router(pool.clone()))
.nest("/admin", admin::router(pool.clone())); .nest("/admin", admin::router(pool.clone()));

View file

@ -1,3 +1,4 @@
use chrono::{DateTime, FixedOffset, Local, Utc};
use serde::Serialize; use serde::Serialize;
use sqlx::{prelude::FromRow, Decode, Encode}; use sqlx::{prelude::FromRow, Decode, Encode};
use uuid::Uuid; use uuid::Uuid;
@ -15,6 +16,7 @@ pub struct Message {
// Uuid but sqlx doesnt impl serde traits for them // Uuid but sqlx doesnt impl serde traits for them
pub id: Uuid, pub id: Uuid,
pub chat_id: Uuid, pub chat_id: Uuid,
pub timestamp: DateTime<Utc>,
pub content: String, pub content: String,
pub from_admin: bool, pub from_admin: bool,

5
justfile Normal file
View file

@ -0,0 +1,5 @@
[no-cd]
reset-db:
#!/usr/bin/env nu
cd crates/backend
sqlx database reset