use axum::{ extract::{Form, Path, State}, http::StatusCode, response::{IntoResponse, Redirect, Response}, }; use askama::Template; use askama_web::WebTemplate; use serde::Deserialize; use crate::auth_guard::AuthUser; use crate::db; use crate::state::AppState; pub struct KvRow { pub key: String, pub value: String, } #[derive(Template, WebTemplate)] #[template(path = "kv.html")] pub struct KvTemplate { pub bot_id: String, pub bot_name: String, pub entries: Vec, } pub async fn list( State(state): State, AuthUser(user): AuthUser, Path(bot_id): Path, ) -> Result { let bot = db::get_bot_owned(&state.db, &bot_id, &user.sub) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; let items = db::kv_list(&state.db, &bot_id) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; let entries = items .into_iter() .map(|kv| KvRow { key: kv.key, value: kv.value, }) .collect(); Ok(KvTemplate { bot_id, bot_name: bot.name, entries, }) } #[derive(Deserialize)] pub struct KvSetForm { key: String, value: String, } pub async fn set( State(state): State, AuthUser(user): AuthUser, Path(bot_id): Path, Form(form): Form, ) -> Result { let _bot = db::get_bot_owned(&state.db, &bot_id, &user.sub) .await .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "internal error").into_response())? .ok_or_else(|| StatusCode::NOT_FOUND.into_response())?; db::kv_set(&state.db, &bot_id, form.key.trim(), &form.value) .await .map_err(|e| { tracing::error!("kv set failed: {e}"); (StatusCode::INTERNAL_SERVER_ERROR, "internal error").into_response() })?; Ok(Redirect::to(&format!("/{bot_id}/kv"))) } pub async fn delete( State(state): State, AuthUser(user): AuthUser, Path((bot_id, key)): Path<(String, String)>, ) -> Result { let _bot = db::get_bot_owned(&state.db, &bot_id, &user.sub) .await .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "internal error").into_response())? .ok_or_else(|| StatusCode::NOT_FOUND.into_response())?; db::kv_delete(&state.db, &bot_id, &key) .await .map_err(|e| { tracing::error!("kv delete failed: {e}"); (StatusCode::INTERNAL_SERVER_ERROR, "internal error").into_response() })?; Ok(Redirect::to(&format!("/{bot_id}/kv"))) }