otter/otter/src/server/gpodder/advanced/sync.rs

92 lines
2.3 KiB
Rust

use axum::{
extract::{Path, State},
middleware,
routing::get,
Extension, Json, Router,
};
use crate::server::{
error::{AppError, AppResult},
gpodder::{
auth_api_middleware,
format::{Format, StringWithFormat},
models::{SyncStatus, SyncStatusDelta},
},
Context,
};
pub fn router(ctx: Context) -> Router<Context> {
Router::new()
.route(
"/{username}",
get(get_sync_status).post(post_sync_status_changes),
)
.layer(middleware::from_fn_with_state(
ctx.clone(),
auth_api_middleware,
))
}
pub async fn get_sync_status(
State(ctx): State<Context>,
Path(username): Path<StringWithFormat>,
Extension(user): Extension<gpodder::User>,
) -> AppResult<Json<SyncStatus>> {
if username.format != Format::Json {
return Err(AppError::NotFound);
}
if *username != user.username {
return Err(AppError::BadRequest);
}
Ok(
tokio::task::spawn_blocking(move || ctx.store.devices_by_sync_group(&user))
.await
.unwrap()
.map(|(not_synchronized, synchronized)| {
Json(SyncStatus {
synchronized,
not_synchronized,
})
})?,
)
}
pub async fn post_sync_status_changes(
State(ctx): State<Context>,
Path(username): Path<StringWithFormat>,
Extension(user): Extension<gpodder::User>,
Json(delta): Json<SyncStatusDelta>,
) -> AppResult<Json<SyncStatus>> {
if username.format != Format::Json {
return Err(AppError::NotFound);
}
if *username != user.username {
return Err(AppError::BadRequest);
}
Ok(tokio::task::spawn_blocking(move || {
ctx.store.update_device_sync_status(
&user,
delta
.synchronize
.iter()
.map(|v| v.iter().map(|s| s.as_ref()).collect())
.collect(),
delta.stop_synchronize.iter().map(|s| s.as_ref()).collect(),
)?;
ctx.store.devices_by_sync_group(&user)
})
.await
.unwrap()
.map(|(not_synchronized, synchronized)| {
Json(SyncStatus {
synchronized,
not_synchronized,
})
})?)
}