feat: config history — auto-snapshot on update, list/pin/restore endpoints
This commit is contained in:
72
k-tv-backend/api/src/routes/channels/config_history.rs
Normal file
72
k-tv-backend/api/src/routes/channels/config_history.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use axum::{
|
||||
Json,
|
||||
extract::{Path, State},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
dto::{ChannelResponse, ConfigSnapshotResponse, PatchSnapshotRequest},
|
||||
error::ApiError,
|
||||
extractors::CurrentUser,
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
use super::require_owner;
|
||||
|
||||
pub(super) async fn list_config_history(
|
||||
State(state): State<AppState>,
|
||||
CurrentUser(user): CurrentUser,
|
||||
Path(channel_id): Path<Uuid>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let channel = state.channel_service.find_by_id(channel_id).await?;
|
||||
require_owner(&channel, user.id)?;
|
||||
|
||||
let snapshots = state.channel_service.list_config_snapshots(channel_id).await?;
|
||||
let response: Vec<ConfigSnapshotResponse> = snapshots.into_iter().map(Into::into).collect();
|
||||
Ok(Json(response))
|
||||
}
|
||||
|
||||
pub(super) async fn patch_config_snapshot(
|
||||
State(state): State<AppState>,
|
||||
CurrentUser(user): CurrentUser,
|
||||
Path((channel_id, snap_id)): Path<(Uuid, Uuid)>,
|
||||
Json(payload): Json<PatchSnapshotRequest>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let channel = state.channel_service.find_by_id(channel_id).await?;
|
||||
require_owner(&channel, user.id)?;
|
||||
|
||||
let updated = state
|
||||
.channel_service
|
||||
.patch_config_snapshot_label(channel_id, snap_id, payload.label)
|
||||
.await?
|
||||
.ok_or_else(|| ApiError::NotFound("Snapshot not found".into()))?;
|
||||
|
||||
Ok(Json(ConfigSnapshotResponse::from(updated)))
|
||||
}
|
||||
|
||||
pub(super) async fn restore_config_snapshot(
|
||||
State(state): State<AppState>,
|
||||
CurrentUser(user): CurrentUser,
|
||||
Path((channel_id, snap_id)): Path<(Uuid, Uuid)>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let channel = state.channel_service.find_by_id(channel_id).await?;
|
||||
require_owner(&channel, user.id)?;
|
||||
|
||||
let updated = state
|
||||
.channel_service
|
||||
.restore_config_snapshot(channel_id, snap_id)
|
||||
.await
|
||||
.map_err(|e| match e {
|
||||
domain::DomainError::ChannelNotFound(_) => ApiError::NotFound("Snapshot not found".into()),
|
||||
other => ApiError::from(other),
|
||||
})?;
|
||||
|
||||
let _ = state
|
||||
.activity_log_repo
|
||||
.log("config_restored", &snap_id.to_string(), Some(channel_id))
|
||||
.await;
|
||||
|
||||
Ok((StatusCode::OK, Json(ChannelResponse::from(updated))))
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use domain::{AccessMode, User};
|
||||
use crate::{error::ApiError, state::AppState};
|
||||
|
||||
mod broadcast;
|
||||
mod config_history;
|
||||
mod crud;
|
||||
mod schedule;
|
||||
|
||||
@@ -39,6 +40,18 @@ pub fn router() -> Router<AppState> {
|
||||
.route("/{id}/now", get(broadcast::get_current_broadcast))
|
||||
.route("/{id}/epg", get(broadcast::get_epg))
|
||||
.route("/{id}/stream", get(broadcast::get_stream))
|
||||
.route(
|
||||
"/{id}/config/history",
|
||||
get(config_history::list_config_history),
|
||||
)
|
||||
.route(
|
||||
"/{id}/config/history/{snap_id}",
|
||||
axum::routing::patch(config_history::patch_config_snapshot),
|
||||
)
|
||||
.route(
|
||||
"/{id}/config/history/{snap_id}/restore",
|
||||
post(config_history::restore_config_snapshot),
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user