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:
72
crates/presentation/src/handlers/providers.rs
Normal file
72
crates/presentation/src/handlers/providers.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
//! Provider configuration CRUD handlers.
|
||||
|
||||
use axum::Json;
|
||||
use axum::extract::{Path, State};
|
||||
|
||||
use api_types::{ProviderConfigRequest, ProviderConfigResponse};
|
||||
use application::providers::{
|
||||
DeleteProviderCommand, GetProviderQuery, ListProvidersQuery, UpsertProviderCommand,
|
||||
};
|
||||
|
||||
use crate::errors::ApiError;
|
||||
use crate::extractors::AdminUser;
|
||||
use crate::state::AppState;
|
||||
|
||||
/// GET /admin/providers
|
||||
pub async fn list_providers(
|
||||
State(state): State<AppState>,
|
||||
AdminUser(_user): AdminUser,
|
||||
) -> Result<Json<Vec<ProviderConfigResponse>>, ApiError> {
|
||||
let providers =
|
||||
application::providers::list::execute(&state.provider_deps, ListProvidersQuery).await?;
|
||||
Ok(Json(
|
||||
providers
|
||||
.into_iter()
|
||||
.map(ProviderConfigResponse::from)
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
/// GET /admin/providers/:id
|
||||
pub async fn get_provider(
|
||||
State(state): State<AppState>,
|
||||
AdminUser(_user): AdminUser,
|
||||
Path(id): Path<String>,
|
||||
) -> Result<Json<ProviderConfigResponse>, ApiError> {
|
||||
let query = GetProviderQuery { id: id.clone() };
|
||||
let provider = application::providers::get::execute(&state.provider_deps, query)
|
||||
.await?
|
||||
.ok_or_else(|| ApiError::not_found(format!("Provider {id} not found")))?;
|
||||
Ok(Json(ProviderConfigResponse::from(provider)))
|
||||
}
|
||||
|
||||
/// PUT /admin/providers/:id
|
||||
pub async fn upsert_provider(
|
||||
State(state): State<AppState>,
|
||||
AdminUser(_user): AdminUser,
|
||||
Path(id): Path<String>,
|
||||
Json(req): Json<ProviderConfigRequest>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
let config_json = serde_json::to_string(&req.config)
|
||||
.map_err(|e| ApiError::validation(format!("Invalid config JSON: {e}")))?;
|
||||
|
||||
let cmd = UpsertProviderCommand {
|
||||
id,
|
||||
provider_type: req.provider_type,
|
||||
config_json,
|
||||
enabled: req.enabled,
|
||||
};
|
||||
application::providers::upsert::execute(&state.provider_deps, cmd).await?;
|
||||
Ok(Json(serde_json::json!({"status": "ok"})))
|
||||
}
|
||||
|
||||
/// DELETE /admin/providers/:id
|
||||
pub async fn delete_provider(
|
||||
State(state): State<AppState>,
|
||||
AdminUser(_user): AdminUser,
|
||||
Path(id): Path<String>,
|
||||
) -> Result<axum::http::StatusCode, ApiError> {
|
||||
let cmd = DeleteProviderCommand { id };
|
||||
application::providers::delete::execute(&state.provider_deps, cmd).await?;
|
||||
Ok(axum::http::StatusCode::NO_CONTENT)
|
||||
}
|
||||
Reference in New Issue
Block a user