add config options via env vars and file

This commit is contained in:
Schrottkatze 2024-11-13 16:03:10 +01:00
parent 7754599e72
commit 283b702c56
Signed by: schrottkatze
SSH key fingerprint: SHA256:hXb3t1vINBFCiDCmhRABHX5ocdbLiKyCdKI4HK2Rbbc
5 changed files with 95 additions and 28 deletions

View file

@ -28,8 +28,7 @@ async fn auth_middleware(
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)) {
if state.check_admin_tok(&headers) {
let res = next.run(req).await;
return res;
}

View file

@ -114,25 +114,21 @@ pub async fn post(
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(state.pool())
.await
.unwrap();
let is_admin = state.check_admin_tok(&headers);
sqlx::query!(
r#"insert into messages (chat_id, content, from_admin) values ($1, $2, $3);"#,
chat.id,
body,
is_admin
)
.execute(state.pool())
.await
.unwrap();
if is_admin {
StatusCode::OK.into_response()
} else {
sqlx::query!(
r#"insert into messages (chat_id, content, from_admin) values ($1, $2, false);"#,
chat.id,
body
)
.execute(state.pool())
.await
.unwrap();
Redirect::to(&format!("/{url_path}")).into_response()
}
}

View file

@ -1,5 +1,8 @@
use std::sync::Arc;
use axum::response::IntoResponse;
use http::StatusCode;
use config::Config;
use http::{HeaderMap, HeaderValue, StatusCode};
use sqlx::{Pool, Postgres};
use thiserror::Error;
@ -9,23 +12,85 @@ type Result<T> = std::result::Result<T, AppStateError>;
const DB_URL: &str = "postgres://chatdings@localhost/chatdings";
#[derive(Debug, Clone)]
pub struct AppState {
pub struct AppState(Arc<AppStateInner>);
#[derive(Debug)]
pub struct AppStateInner {
pool: Pool<Postgres>,
config: Config,
}
mod config {
use std::{env, fs};
#[derive(Debug)]
pub(super) struct Config {
db_url: String,
admin_token: String,
}
impl Config {
pub fn read_from_env() -> Self {
let db_url = env::var("CHATDINGS_DB_URL")
.expect("environment variable CHATDINGS_DB_URL has to exist");
let admin_token_path = env::var("CHATDINGS_ADMIN_TOKEN_PATH")
.expect("environment variable CHATDINGS_ADMIN_TOKEN has to exist");
let admin_token = fs::read_to_string(&admin_token_path)
.expect(&format!("failed to read '{admin_token_path:?}'"))
.trim()
.to_string();
Self {
db_url,
admin_token,
}
}
pub fn db_url(&self) -> &str {
&self.db_url
}
pub fn admin_tok(&self) -> &str {
&self.admin_token
}
}
}
impl AppState {
pub async fn init() -> Result<Self> {
let pool = Pool::<Postgres>::connect(DB_URL).await?;
Ok(Self(Arc::new(AppStateInner::init().await?)))
}
pub async fn fetch_chat_by_url_path(&self, url_path: &str) -> Result<Chat> {
self.0.fetch_chat_by_url_path(url_path).await
}
pub async fn fetch_messages(&self, chat: &Chat) -> Result<Vec<Message>> {
self.0.fetch_messages(chat).await
}
pub async fn send_message(&self, chat: &Chat, content: String, from_admin: bool) -> Result<()> {
self.0.send_message(chat, content, from_admin).await
}
pub fn check_admin_tok(&self, headers: &HeaderMap) -> bool {
self.0.check_admin_tok(headers)
}
pub fn pool(&self) -> &Pool<Postgres> {
self.0.pool()
}
}
impl AppStateInner {
async fn init() -> Result<Self> {
let config = Config::read_from_env();
let pool = Pool::<Postgres>::connect(config.db_url()).await?;
sqlx::migrate!()
.run(&pool)
.await
.expect("migration should not fail");
Ok(Self { pool })
Ok(Self { pool, config })
}
pub async fn fetch_chat_by_url_path(&self, url_path: &str) -> Result<Chat> {
async fn fetch_chat_by_url_path(&self, url_path: &str) -> Result<Chat> {
Ok(
sqlx::query_as!(Chat, r#"select * from chats where url_path = $1"#, url_path)
.fetch_one(&self.pool)
@ -33,7 +98,7 @@ impl AppState {
)
}
pub async fn fetch_messages(&self, chat: &Chat) -> Result<Vec<Message>> {
async fn fetch_messages(&self, chat: &Chat) -> Result<Vec<Message>> {
Ok(sqlx::query_as!(
Message,
r#"select * from messages where chat_id = $1"#,
@ -43,11 +108,15 @@ impl AppState {
.await?)
}
pub async fn send_message(&self, chat: &Chat, content: String, from_admin: bool) -> Result<()> {
async fn send_message(&self, chat: &Chat, content: String, from_admin: bool) -> Result<()> {
todo!()
}
pub fn pool(&self) -> &Pool<Postgres> {
fn check_admin_tok(&self, headers: &HeaderMap) -> bool {
headers.get("x-admin-tok") == Some(&HeaderValue::from_str(self.config.admin_tok()).unwrap())
}
fn pool(&self) -> &Pool<Postgres> {
&self.pool
}
}

View file

@ -59,8 +59,10 @@
listen_addresses = "127.0.0.1";
};
env = {
env = rec {
DATABASE_URL = "postgres://localhost/chatdings";
CHATDINGS_DB_URL = DATABASE_URL;
CHATDINGS_ADMIN_TOKEN_PATH = "./test_admin_tok.txt";
};
})
];

1
test_admin_tok.txt Normal file
View file

@ -0,0 +1 @@
miauu