Files
k-tv/crates/presentation/src/handlers/channels.rs

156 lines
5.3 KiB
Rust

use axum::Json;
use axum::extract::{Path, State};
use api_types::{
ChannelResponse, ConfigSnapshotResponse, CreateChannelRequest, PatchSnapshotRequest,
UpdateChannelRequest,
};
use application::channels::{CreateChannelCommand, DeleteChannelCommand, UpdateChannelCommand};
use application::config_snapshots::{RestoreSnapshotCommand, SaveSnapshotCommand};
use domain::DomainError;
use crate::errors::AppError;
use crate::extractors::CurrentUser;
use crate::state::AppState;
pub async fn list_channels(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
) -> Result<Json<Vec<ChannelResponse>>, AppError> {
let channels = state.channel_query.find_all().await?;
Ok(Json(channels.into_iter().map(ChannelResponse::from).collect()))
}
pub async fn list_my_channels(
State(state): State<AppState>,
CurrentUser(user): CurrentUser,
) -> Result<Json<Vec<ChannelResponse>>, AppError> {
let channels = state.channel_query.find_by_owner(user.id()).await?;
Ok(Json(channels.into_iter().map(ChannelResponse::from).collect()))
}
pub async fn create_channel(
State(state): State<AppState>,
CurrentUser(user): CurrentUser,
Json(req): Json<CreateChannelRequest>,
) -> Result<Json<ChannelResponse>, AppError> {
let cmd = CreateChannelCommand {
owner_id: user.id(),
name: req.name,
timezone: req.timezone,
};
let channel = application::channels::create::execute(&state.channel_command_deps, cmd).await?;
Ok(Json(ChannelResponse::from(channel)))
}
pub async fn get_channel(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
Path(id): Path<uuid::Uuid>,
) -> Result<Json<ChannelResponse>, AppError> {
let channel = state
.channel_query
.find_by_id(id.into())
.await?
.ok_or_else(|| AppError(DomainError::NotFound(format!("Channel {id} not found"))))?;
Ok(Json(ChannelResponse::from(channel)))
}
pub async fn update_channel(
State(state): State<AppState>,
CurrentUser(user): CurrentUser,
Path(id): Path<uuid::Uuid>,
Json(req): Json<UpdateChannelRequest>,
) -> Result<Json<ChannelResponse>, AppError> {
let cmd = UpdateChannelCommand {
channel_id: id.into(),
owner_id: user.id(),
name: req.name,
description: req.description.map(Some),
timezone: req.timezone,
schedule_config: req.schedule_config.map(Into::into),
rotation_policy: req.rotation_policy,
auto_schedule: req.auto_schedule,
gap_filler: req.gap_filler,
};
let channel = application::channels::update::execute(&state.channel_command_deps, cmd).await?;
Ok(Json(ChannelResponse::from(channel)))
}
pub async fn delete_channel(
State(state): State<AppState>,
CurrentUser(user): CurrentUser,
Path(id): Path<uuid::Uuid>,
) -> Result<axum::http::StatusCode, AppError> {
let cmd = DeleteChannelCommand {
channel_id: id.into(),
owner_id: user.id(),
};
application::channels::delete::execute(&state.channel_command_deps, cmd).await?;
Ok(axum::http::StatusCode::NO_CONTENT)
}
pub async fn save_snapshot(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
Path(id): Path<uuid::Uuid>,
) -> Result<Json<ConfigSnapshotResponse>, AppError> {
let cmd = SaveSnapshotCommand {
channel_id: id.into(),
label: None,
};
let snap = application::config_snapshots::save::execute(&state.config_snapshot_deps, cmd).await?;
Ok(Json(ConfigSnapshotResponse::from(snap)))
}
pub async fn list_snapshots(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
Path(id): Path<uuid::Uuid>,
) -> Result<Json<Vec<ConfigSnapshotResponse>>, AppError> {
let snaps = state.channel_query.list_config_snapshots(id.into()).await?;
Ok(Json(snaps.into_iter().map(ConfigSnapshotResponse::from).collect()))
}
pub async fn get_snapshot(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
Path((id, snapshot_id)): Path<(uuid::Uuid, uuid::Uuid)>,
) -> Result<Json<ConfigSnapshotResponse>, AppError> {
let snap = state
.channel_query
.get_config_snapshot(id.into(), snapshot_id.into())
.await?
.ok_or_else(|| AppError(DomainError::NotFound("Snapshot not found".into())))?;
Ok(Json(ConfigSnapshotResponse::from(snap)))
}
pub async fn patch_snapshot(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
Path((id, snapshot_id)): Path<(uuid::Uuid, uuid::Uuid)>,
Json(req): Json<PatchSnapshotRequest>,
) -> Result<Json<ConfigSnapshotResponse>, AppError> {
let snap = state
.channel_command_deps
.channel_command
.patch_config_snapshot_label(id.into(), snapshot_id.into(), req.label)
.await?
.ok_or_else(|| AppError(DomainError::NotFound("Snapshot not found".into())))?;
Ok(Json(ConfigSnapshotResponse::from(snap)))
}
pub async fn restore_snapshot(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
Path((id, snapshot_id)): Path<(uuid::Uuid, uuid::Uuid)>,
) -> Result<Json<ChannelResponse>, AppError> {
let cmd = RestoreSnapshotCommand {
channel_id: id.into(),
snapshot_id: snapshot_id.into(),
};
let channel =
application::config_snapshots::restore::execute(&state.config_snapshot_deps, cmd).await?;
Ok(Json(ChannelResponse::from(channel)))
}