use crate::html::forms::{ActorUrlForm, BlockDomainForm, RemoveDomainForm};
use crate::html::helpers::build_page_context;
use crate::html::templates::{BlockedActorsTemplate, BlockedDomainsTemplate};
use crate::{
extractors::RequiredCookieUser, html::csrf::CsrfToken, html::render::render_page,
state::AppState,
};
use axum::{
Form,
extract::{Extension, State},
http::StatusCode,
response::{IntoResponse, Redirect},
};
pub async fn get_blocked_domains_page(
crate::extractors::AdminUser(user_id): crate::extractors::AdminUser,
State(state): State,
Extension(csrf): Extension,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, Some(user_id), csrf.0).await;
ctx.page_title = "Blocked Domains — Movies Diary".to_string();
ctx.canonical_url = format!("{}/admin/blocked-domains", state.app_ctx.config.base_url);
match state.app_ctx.ap_blocklist.get_blocked_domains().await {
Ok(domains) => {
let entries: Vec = domains
.into_iter()
.map(|d| crate::html::templates::BlockedDomainEntry {
domain: d.domain,
reason: d.reason,
blocked_at: d.blocked_at,
})
.collect();
render_page(BlockedDomainsTemplate {
ctx: &ctx,
domains: &entries,
})
.into_response()
}
Err(e) => {
tracing::error!("get_blocked_domains error: {:?}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
"Failed to load blocked domains",
)
.into_response()
}
}
}
pub async fn post_blocked_domain(
crate::extractors::AdminUser(_): crate::extractors::AdminUser,
State(state): State,
Extension(csrf): Extension,
Form(form): Form,
) -> impl IntoResponse {
if crate::html::csrf::mismatch(&csrf, &form.csrf_token) {
return StatusCode::FORBIDDEN.into_response();
}
let reason = form.reason.as_deref().filter(|s| !s.trim().is_empty());
match state
.app_ctx
.ap_blocklist
.add_blocked_domain(&form.domain, reason)
.await
{
Ok(()) => Redirect::to("/admin/blocked-domains").into_response(),
Err(e) => {
tracing::error!("add_blocked_domain error: {:?}", e);
Redirect::to("/admin/blocked-domains").into_response()
}
}
}
pub async fn post_remove_blocked_domain(
crate::extractors::AdminUser(_): crate::extractors::AdminUser,
State(state): State,
Extension(csrf): Extension,
Form(form): Form,
) -> impl IntoResponse {
if crate::html::csrf::mismatch(&csrf, &form.csrf_token) {
return StatusCode::FORBIDDEN.into_response();
}
match state
.app_ctx
.ap_blocklist
.remove_blocked_domain(&form.domain)
.await
{
Ok(()) => Redirect::to("/admin/blocked-domains").into_response(),
Err(e) => {
tracing::error!("remove_blocked_domain error: {:?}", e);
Redirect::to("/admin/blocked-domains").into_response()
}
}
}
pub async fn get_blocked_actors_page(
RequiredCookieUser(user_id): RequiredCookieUser,
State(state): State,
Extension(csrf): Extension,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, Some(user_id.clone()), csrf.0).await;
ctx.page_title = "Blocked Users — Movies Diary".to_string();
ctx.canonical_url = format!("{}/social/blocked", state.app_ctx.config.base_url);
let instance = state.app_ctx.instance.clone();
match application::social::get_blocked::execute(
&state.app_ctx.deps.social.query,
user_id.value(),
)
.await
{
Ok(blocked) => {
let entries: Vec = blocked
.into_iter()
.map(|a| crate::html::templates::BlockedActorEntry {
url: instance.actor_url_of(&a.identity),
handle: a.handle,
display_name: a.display_name,
avatar_url: a.avatar_url,
})
.collect();
render_page(BlockedActorsTemplate {
ctx: &ctx,
actors: &entries,
})
.into_response()
}
Err(e) => {
tracing::error!("get_blocked_actors error: {:?}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
"Failed to load blocked users",
)
.into_response()
}
}
}
pub async fn post_block_actor_html(
RequiredCookieUser(user_id): RequiredCookieUser,
State(state): State,
Extension(csrf): Extension,
Form(form): Form,
) -> impl IntoResponse {
if crate::html::csrf::mismatch(&csrf, &form.csrf_token) {
return StatusCode::FORBIDDEN.into_response();
}
let instance = state.app_ctx.instance.clone();
match application::social::execute::execute_command(
&state.app_ctx.deps.social.command,
application::social::commands::SocialCmd::Block {
blocker_id: user_id.value(),
target: instance.identify(&form.actor_url),
},
)
.await
{
Ok(()) => Redirect::to("/social/blocked").into_response(),
Err(e) => {
tracing::error!("block_actor html error: {:?}", e);
Redirect::to("/social/blocked").into_response()
}
}
}
pub async fn post_unblock_actor(
RequiredCookieUser(user_id): RequiredCookieUser,
State(state): State,
Extension(csrf): Extension,
Form(form): Form,
) -> impl IntoResponse {
if crate::html::csrf::mismatch(&csrf, &form.csrf_token) {
return StatusCode::FORBIDDEN.into_response();
}
let instance = state.app_ctx.instance.clone();
match application::social::execute::execute_command(
&state.app_ctx.deps.social.command,
application::social::commands::SocialCmd::Unblock {
blocker_id: user_id.value(),
target: instance.identify(&form.actor_url),
},
)
.await
{
Ok(()) => Redirect::to("/social/blocked").into_response(),
Err(e) => {
tracing::error!("unblock_actor error: {:?}", e);
Redirect::to("/social/blocked").into_response()
}
}
}