feat: refresh content workflow and verification settings
All checks were successful
docker-images / build-and-push (admin, admin, termi-astro-admin, admin/Dockerfile) (push) Successful in 43s
docker-images / build-and-push (backend, backend, termi-astro-backend, backend/Dockerfile) (push) Successful in 25m9s
docker-images / build-and-push (frontend, frontend, termi-astro-frontend, frontend/Dockerfile) (push) Successful in 51s

This commit is contained in:
2026-04-01 18:47:17 +08:00
parent f2c07df320
commit 7de4ddc3ee
66 changed files with 1455 additions and 2759 deletions

View File

@@ -1,6 +1,6 @@
use axum::{
extract::{Multipart, Query},
http::{header, HeaderMap},
http::{HeaderMap, header},
};
use loco_rs::prelude::*;
use sea_orm::{
@@ -170,7 +170,9 @@ pub struct AdminSiteSettingsResponse {
pub music_playlist: Vec<site_settings::MusicTrackPayload>,
pub ai_enabled: bool,
pub paragraph_comments_enabled: bool,
pub comment_verification_mode: String,
pub comment_turnstile_enabled: bool,
pub subscription_verification_mode: String,
pub subscription_turnstile_enabled: bool,
pub web_push_enabled: bool,
pub turnstile_site_key: Option<String>,
@@ -686,9 +688,7 @@ fn build_media_object_response(
title: metadata.and_then(|entry| entry.title.clone()),
alt_text: metadata.and_then(|entry| entry.alt_text.clone()),
caption: metadata.and_then(|entry| entry.caption.clone()),
tags: metadata
.map(media_assets::tag_list)
.unwrap_or_default(),
tags: metadata.map(media_assets::tag_list).unwrap_or_default(),
notes: metadata.and_then(|entry| entry.notes.clone()),
}
}
@@ -724,6 +724,14 @@ fn build_settings_response(
) -> AdminSiteSettingsResponse {
let ai_providers = site_settings::ai_provider_configs(&item);
let ai_active_provider_id = site_settings::active_ai_provider_id(&item);
let comment_verification_mode = crate::services::turnstile::selected_mode(
&item,
crate::services::turnstile::TurnstileScope::Comment,
);
let subscription_verification_mode = crate::services::turnstile::selected_mode(
&item,
crate::services::turnstile::TurnstileScope::Subscription,
);
let turnstile_site_key = crate::services::turnstile::site_key(&item);
let turnstile_secret_key = crate::services::turnstile::secret_key(&item);
let web_push_vapid_public_key = crate::services::web_push::public_key(&item);
@@ -751,8 +759,16 @@ fn build_settings_response(
music_playlist: music_playlist_values(&item.music_playlist),
ai_enabled: item.ai_enabled.unwrap_or(false),
paragraph_comments_enabled: item.paragraph_comments_enabled.unwrap_or(true),
comment_turnstile_enabled: item.comment_turnstile_enabled.unwrap_or(false),
subscription_turnstile_enabled: item.subscription_turnstile_enabled.unwrap_or(false),
comment_verification_mode: comment_verification_mode.as_str().to_string(),
comment_turnstile_enabled: matches!(
comment_verification_mode,
crate::services::turnstile::VerificationMode::Turnstile
),
subscription_verification_mode: subscription_verification_mode.as_str().to_string(),
subscription_turnstile_enabled: matches!(
subscription_verification_mode,
crate::services::turnstile::VerificationMode::Turnstile
),
web_push_enabled: item.web_push_enabled.unwrap_or(false),
turnstile_site_key,
turnstile_secret_key,
@@ -887,7 +903,6 @@ pub async fn session_logout(headers: HeaderMap, State(ctx): State<AppContext>) -
#[debug_handler]
pub async fn dashboard(headers: HeaderMap, State(ctx): State<AppContext>) -> Result<Response> {
check_auth(&headers)?;
content::sync_markdown_posts(&ctx).await?;
let all_posts = posts::Entity::find().all(&ctx.db).await?;
let total_posts = all_posts.len() as u64;
@@ -1190,8 +1205,8 @@ pub async fn list_media_objects(
check_auth(&headers)?;
let settings = storage::require_r2_settings(&ctx).await?;
let objects = storage::list_objects(&ctx, query.prefix.as_deref(), query.limit.unwrap_or(200))
.await?;
let objects =
storage::list_objects(&ctx, query.prefix.as_deref(), query.limit.unwrap_or(200)).await?;
let keys = objects
.iter()
.map(|item| item.key.clone())
@@ -1228,7 +1243,11 @@ pub async fn delete_media_object(
storage::delete_object(&ctx, key).await?;
if let Err(error) = media_assets::delete_by_key(&ctx, key).await {
tracing::warn!(?error, key, "failed to delete media metadata after object deletion");
tracing::warn!(
?error,
key,
"failed to delete media metadata after object deletion"
);
}
format::json(AdminMediaDeleteResponse {
@@ -1325,7 +1344,11 @@ pub async fn batch_delete_media_objects(
match storage::delete_object(&ctx, &key).await {
Ok(()) => {
if let Err(error) = media_assets::delete_by_key(&ctx, &key).await {
tracing::warn!(?error, key, "failed to delete media metadata after batch removal");
tracing::warn!(
?error,
key,
"failed to delete media metadata after batch removal"
);
}
deleted.push(key)
}
@@ -1955,7 +1978,10 @@ pub fn routes() -> Routes {
"/storage/media/batch-delete",
post(batch_delete_media_objects),
)
.add("/storage/media/metadata", patch(update_media_object_metadata))
.add(
"/storage/media/metadata",
patch(update_media_object_metadata),
)
.add("/storage/media/replace", post(replace_media_object))
.add(
"/comments/blacklist",