presentation: HTTP server crate w/ handlers, routes, background tasks

Axum binary that wires all clean-arch crates together:
- AppState holds pre-built Deps structs (auth, channels, schedule, library, etc.)
- JWT extractors (CurrentUser, AdminUser, OptionalCurrentUser)
- Handlers delegate to application use cases, map to api-types DTOs
- Routes: auth, channels, schedule, library, admin, providers, config, iptv
- Background: auto-scheduler, broadcast poller, webhook consumer, library sync
- Factory builds everything from Config + DbPool
- SimpleProviderRegistry impl of IProviderRegistry trait
- NoopMediaProvider fallback
This commit is contained in:
2026-07-12 03:23:20 +02:00
parent afed5c01b4
commit 56d742a74c
25 changed files with 3186 additions and 5 deletions

View File

@@ -0,0 +1,66 @@
//! Admin handlers.
use axum::Json;
use axum::extract::{Query, State};
use serde::Deserialize;
use std::collections::HashMap;
use api_types::{ActivityEventResponse, SettingsResponse};
use application::admin::{GetActivityLogQuery, GetSettingsQuery, UpdateSettingsCommand};
use crate::errors::ApiError;
use crate::extractors::AdminUser;
use crate::state::AppState;
/// GET /admin/settings
pub async fn get_settings(
State(state): State<AppState>,
AdminUser(_user): AdminUser,
) -> Result<Json<SettingsResponse>, ApiError> {
let pairs =
application::admin::get_settings::execute(&state.admin_deps, GetSettingsQuery).await?;
let settings: HashMap<String, String> = pairs.into_iter().collect();
Ok(Json(SettingsResponse { settings }))
}
/// PUT /admin/settings
pub async fn update_settings(
State(state): State<AppState>,
AdminUser(_user): AdminUser,
Json(body): Json<HashMap<String, String>>,
) -> Result<Json<SettingsResponse>, ApiError> {
let settings_vec: Vec<(String, String)> = body.into_iter().collect();
let cmd = UpdateSettingsCommand {
settings: settings_vec,
};
application::admin::update_settings::execute(&state.admin_deps, cmd).await?;
// Re-read after update
let pairs =
application::admin::get_settings::execute(&state.admin_deps, GetSettingsQuery).await?;
let settings: HashMap<String, String> = pairs.into_iter().collect();
Ok(Json(SettingsResponse { settings }))
}
#[derive(Debug, Deserialize)]
pub struct ActivityLogParams {
pub limit: Option<u32>,
}
/// GET /admin/activity
pub async fn get_activity_log(
State(state): State<AppState>,
AdminUser(_user): AdminUser,
Query(params): Query<ActivityLogParams>,
) -> Result<Json<Vec<ActivityEventResponse>>, ApiError> {
let query = GetActivityLogQuery {
limit: params.limit.unwrap_or(50),
};
let events = application::admin::activity_log::execute(&state.admin_deps, query).await?;
Ok(Json(
events
.into_iter()
.map(ActivityEventResponse::from)
.collect(),
))
}