Leave a removed account's feeds as unsubscribing does (#157)
Removing an account deleted the user, and the foreign keys took their subscriptions with them, but nothing did what unsubscribing does next: a feed nobody subscribes to any more leaves the catalogue (or stays, if listed, for the Directory). A feed only that person read stayed with no subscribers, and a feed with none downloads by its own settings, so it went on fetching each new episode, daily, for no one, until it had been quiet for a year. remove_feed's body is now leave(), and remove_user() leaves each of the person's feeds with it before deleting the account, from the page and from `ipx user rm` alike; a feed inside a group of theirs goes with the group. `ipx user rm` now tells a running daemon to reload, as add and rm do (#120), since it can change the catalogue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
31
src/web.rs
31
src/web.rs
@@ -558,7 +558,7 @@ async fn remove_user(
|
||||
target.name
|
||||
)));
|
||||
}
|
||||
state.ctx.db.delete_user(id).await?;
|
||||
crate::remove_user(&state.ctx, id).await?;
|
||||
tracing::info!(by = %user.name, user = %target.name, "account removed");
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
@@ -1662,34 +1662,7 @@ async fn remove_feed(
|
||||
Path(id): Path<String>,
|
||||
user: crate::db::User,
|
||||
) -> Result<StatusCode, ApiError> {
|
||||
// Unsubscribing is personal: it takes the feed off your list and leaves everyone
|
||||
// else's alone.
|
||||
state.ctx.db.unsubscribe(user.id, &id).await?;
|
||||
for child in crate::subscriptions(&state.ctx).await?
|
||||
.iter()
|
||||
.filter(|s| s.cfg.group.as_deref() == Some(id.as_str()))
|
||||
{
|
||||
state.ctx.db.unsubscribe(user.id, &child.id).await?;
|
||||
}
|
||||
if state.ctx.db.subscriber_counts().await?.contains_key(&id) {
|
||||
return Ok(StatusCode::NO_CONTENT);
|
||||
}
|
||||
|
||||
// Nobody is left: the feed stops being scanned. Its files and history stay, so if
|
||||
// someone subscribes again they do not pull the back catalogue a second time. A feed an
|
||||
// admin listed stays in the Directory, for the next person.
|
||||
let mut cfg = state.ctx.edit_cfg().await;
|
||||
if cfg.feeds.get(&id).is_some_and(|f| f.listed) {
|
||||
return Ok(StatusCode::NO_CONTENT);
|
||||
}
|
||||
if cfg.feeds.remove(&id).is_none() {
|
||||
// A derived feed: forget it here, though the OPML will list it again on the next
|
||||
// read unless you unsubscribe from the OPML itself.
|
||||
state.ctx.db.drop_managed(&id).await?;
|
||||
return Ok(StatusCode::NO_CONTENT);
|
||||
}
|
||||
state.ctx.store_cfg(cfg).await?;
|
||||
crate::retire_group(&state.ctx, &id).await?;
|
||||
crate::leave(&state.ctx, user.id, &id).await?;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user