94 lines
2.4 KiB
Rust
94 lines
2.4 KiB
Rust
use axum::{
|
|
extract::{Path, State},
|
|
middleware,
|
|
routing::{get, post},
|
|
Extension, Json, Router,
|
|
};
|
|
|
|
use crate::{
|
|
db,
|
|
server::{
|
|
error::{AppError, AppResult},
|
|
gpodder::{
|
|
auth_middleware,
|
|
format::{Format, StringWithFormat},
|
|
models::{Device, DevicePatch, DeviceType},
|
|
},
|
|
Context,
|
|
},
|
|
};
|
|
|
|
pub fn router(ctx: Context) -> Router<Context> {
|
|
Router::new()
|
|
.route("/{username}", get(get_devices))
|
|
.route("/{username}/{id}", post(post_device))
|
|
.layer(middleware::from_fn_with_state(ctx.clone(), auth_middleware))
|
|
}
|
|
|
|
async fn get_devices(
|
|
State(ctx): State<Context>,
|
|
Path(username): Path<StringWithFormat>,
|
|
Extension(user): Extension<db::User>,
|
|
) -> AppResult<Json<Vec<Device>>> {
|
|
if username.format != Format::Json {
|
|
return Err(AppError::NotFound);
|
|
}
|
|
|
|
if *username != user.username {
|
|
return Err(AppError::BadRequest);
|
|
}
|
|
|
|
let devices = tokio::task::spawn_blocking(move || db::Device::for_user(&ctx.pool, user.id))
|
|
.await
|
|
.unwrap()?
|
|
.into_iter()
|
|
.map(|d| Device {
|
|
id: d.device_id,
|
|
caption: d.caption,
|
|
r#type: d.type_.into(),
|
|
// TODO implement subscription count
|
|
subscriptions: 0,
|
|
})
|
|
.collect();
|
|
|
|
Ok(Json(devices))
|
|
}
|
|
|
|
async fn post_device(
|
|
State(ctx): State<Context>,
|
|
Path((_username, id)): Path<(String, StringWithFormat)>,
|
|
Extension(user): Extension<db::User>,
|
|
Json(patch): Json<DevicePatch>,
|
|
) -> AppResult<()> {
|
|
if id.format != Format::Json {
|
|
return Err(AppError::NotFound);
|
|
}
|
|
|
|
tokio::task::spawn_blocking(move || {
|
|
if let Some(mut device) = db::Device::by_device_id(&ctx.pool, user.id, &id)? {
|
|
if let Some(caption) = patch.caption {
|
|
device.caption = caption;
|
|
}
|
|
|
|
if let Some(type_) = patch.r#type {
|
|
device.type_ = type_.into();
|
|
}
|
|
|
|
device.update(&ctx.pool)
|
|
} else {
|
|
db::NewDevice::new(
|
|
user.id,
|
|
id.to_string(),
|
|
patch.caption.unwrap_or(String::new()),
|
|
patch.r#type.unwrap_or(DeviceType::Other).into(),
|
|
)
|
|
.insert(&ctx.pool)
|
|
.map(|_| ())
|
|
}
|
|
})
|
|
.await
|
|
.unwrap()?;
|
|
|
|
Ok(())
|
|
}
|