feat: implement advanced subscription changes POST request
This commit is contained in:
parent
6d439783b5
commit
c50e24089e
6 changed files with 186 additions and 4 deletions
|
|
@ -1,12 +1,14 @@
|
|||
mod auth;
|
||||
mod devices;
|
||||
mod subscriptions;
|
||||
|
||||
use axum::Router;
|
||||
|
||||
use crate::server::Context;
|
||||
|
||||
mod auth;
|
||||
mod devices;
|
||||
|
||||
pub fn router(ctx: Context) -> Router<Context> {
|
||||
Router::new()
|
||||
.nest("/auth", auth::router())
|
||||
.nest("/devices", devices::router(ctx.clone()))
|
||||
.nest("/subscriptions", subscriptions::router(ctx.clone()))
|
||||
}
|
||||
|
|
|
|||
72
src/server/gpodder/advanced/subscriptions.rs
Normal file
72
src/server/gpodder/advanced/subscriptions.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use axum::{
|
||||
extract::{Path, State},
|
||||
middleware,
|
||||
routing::post,
|
||||
Extension, Json, Router,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
db,
|
||||
server::{
|
||||
error::{AppError, AppResult},
|
||||
gpodder::{
|
||||
auth_middleware,
|
||||
format::{Format, StringWithFormat},
|
||||
models::{DeviceType, SubscriptionChangeResponse, SubscriptionDelta},
|
||||
},
|
||||
Context,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn router(ctx: Context) -> Router<Context> {
|
||||
Router::new()
|
||||
.route("/{username}/{id}", post(post_subscription_changes))
|
||||
.layer(middleware::from_fn_with_state(ctx.clone(), auth_middleware))
|
||||
}
|
||||
|
||||
pub async fn post_subscription_changes(
|
||||
State(ctx): State<Context>,
|
||||
Path((username, id)): Path<(String, StringWithFormat)>,
|
||||
Extension(user): Extension<db::User>,
|
||||
Json(delta): Json<SubscriptionDelta>,
|
||||
) -> AppResult<Json<SubscriptionChangeResponse>> {
|
||||
if id.format != Format::Json {
|
||||
return Err(AppError::NotFound);
|
||||
}
|
||||
|
||||
if username != user.username {
|
||||
return Err(AppError::BadRequest);
|
||||
}
|
||||
|
||||
let timestamp = chrono::Utc::now().timestamp_millis();
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let device = if let Some(device) = db::Device::by_device_id(&ctx.pool, user.id, &id)? {
|
||||
device
|
||||
} else {
|
||||
db::NewDevice::new(
|
||||
user.id,
|
||||
id.to_string(),
|
||||
String::new(),
|
||||
DeviceType::Other.into(),
|
||||
)
|
||||
.insert(&ctx.pool)?
|
||||
};
|
||||
|
||||
db::Subscription::update_for_device(
|
||||
&ctx.pool,
|
||||
device.id,
|
||||
delta.add,
|
||||
delta.remove,
|
||||
timestamp,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
|
||||
Ok(Json(SubscriptionChangeResponse {
|
||||
timestamp: timestamp + 1,
|
||||
// TODO implement URL sanitization
|
||||
update_urls: vec![],
|
||||
}))
|
||||
}
|
||||
|
|
@ -49,3 +49,15 @@ pub struct DevicePatch {
|
|||
pub caption: Option<String>,
|
||||
pub r#type: Option<DeviceType>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SubscriptionDelta {
|
||||
pub add: Vec<String>,
|
||||
pub remove: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct SubscriptionChangeResponse {
|
||||
pub timestamp: i64,
|
||||
pub update_urls: Vec<(String, String)>,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue