use anyhow::Result; use axum::{ Form, extract::Query, response::{IntoResponse, Redirect}, }; use axum_htmx::{HxRedirect, HxRequest}; use axum_template::RenderHtml; use http::StatusCode; use minijinja::context as template_context; use serde::Deserialize; use std::borrow::Cow; use crate::{ contextual_error, http::{ context::{AdminRequestContext, admin_template_context}, errors::WebError, }, select_template, storage::{ denylist::denylist_add_or_update, private_event_content::{private_event_content_delete, private_event_content_get}, }, }; #[derive(Deserialize)] pub(crate) struct ContentRecordQuery { pub(crate) aturi: String, } pub(crate) async fn handle_admin_content_view( admin_ctx: AdminRequestContext, Query(query): Query, ) -> Result { let canonical_url = format!( "https://{}/admin/content/view", admin_ctx.web_context.config.external_base ); let default_context = admin_template_context(&admin_ctx, &canonical_url, "content"); let language = admin_ctx.language; let web_context = admin_ctx.web_context; let render_template = select_template!("admin_content_view", false, false, language); let error_template = select_template!(false, false, language); // Get the content record by AT-URI let content = private_event_content_get(&web_context.pool, &query.aturi).await; if let Err(err) = content { return contextual_error!( web_context, language.0, error_template, default_context, err ); } let content = content.unwrap(); if content.is_none() { return contextual_error!( web_context, language.0, error_template, default_context, "Content not found" ); } let content = content.unwrap(); // Convert to JSON for display let content_json = serde_json::to_string_pretty(&content) .unwrap_or_else(|_| "Error formatting JSON".to_string()); Ok(RenderHtml( &render_template, web_context.engine.clone(), template_context! { ..default_context, ..template_context! { aturi => query.aturi.clone(), content => content, content_json => content_json, }}, ) .into_response()) } #[derive(Deserialize)] pub(crate) struct NukeContentForm { aturi: String, } pub(crate) async fn handle_admin_content_nuke( admin_ctx: AdminRequestContext, HxRequest(hx_request): HxRequest, Form(form): Form, ) -> Result { let error_template = select_template!(false, false, admin_ctx.language); // Delete the content record if let Err(err) = private_event_content_delete(&admin_ctx.web_context.pool, &form.aturi).await { return contextual_error!( admin_ctx.web_context, admin_ctx.language, error_template, template_context! {}, err ); } // Add content AT-URI to denylist let reason = format!( "Content nuked by admin {}", admin_ctx.admin_handle.did.replace('\'', "") ); if let Err(err) = denylist_add_or_update( &admin_ctx.web_context.pool, Cow::Borrowed(&form.aturi), Cow::Owned(reason), ) .await { return contextual_error!( admin_ctx.web_context, admin_ctx.language, error_template, template_context! {}, err ); } if hx_request { let hx_redirect = HxRedirect::from("/admin/content"); Ok((StatusCode::OK, hx_redirect, "").into_response()) } else { Ok(Redirect::to("/admin/content").into_response()) } }