Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/cordiale-ui/lang/de/LC_MESSAGES/cordiale-ui.po
Original file line number Diff line number Diff line change
Expand Up @@ -2729,8 +2729,8 @@ msgid "Delete {} for good? Its whole scrollback goes with it, for every account.
msgstr "{} endgültig löschen? Der gesamte Verlauf geht damit verloren, für jedes Konto. Gelöschte Nachrichten: {}"

msgctxt "AppWindow"
msgid "Delete {} for good? Its whole scrollback goes with it, for every account; the server couldn't say how many messages that is."
msgstr "{} endgültig löschen? Der gesamte Verlauf geht damit verloren, für jedes Konto; der Server konnte nicht sagen, wie viele Nachrichten das sind."
msgid "Can't delete {}: the server couldn't say how many messages that would remove. Cancel and try again."
msgstr "{} kann nicht gelöscht werden: Der Server konnte nicht sagen, wie viele Nachrichten entfernt würden. Abbrechen und erneut versuchen."

msgctxt "AppWindow"
msgid "Delete network and scrollback"
Expand Down
4 changes: 2 additions & 2 deletions crates/cordiale-ui/lang/es/LC_MESSAGES/cordiale-ui.po
Original file line number Diff line number Diff line change
Expand Up @@ -2729,8 +2729,8 @@ msgid "Delete {} for good? Its whole scrollback goes with it, for every account.
msgstr "¿Eliminar {} definitivamente? Todo su historial se va con ella, para todas las cuentas. Mensajes eliminados: {}"

msgctxt "AppWindow"
msgid "Delete {} for good? Its whole scrollback goes with it, for every account; the server couldn't say how many messages that is."
msgstr "¿Eliminar {} definitivamente? Todo su historial se va con ella, para todas las cuentas; el servidor no pudo decir cuántos mensajes son."
msgid "Can't delete {}: the server couldn't say how many messages that would remove. Cancel and try again."
msgstr "No se puede eliminar {}: el servidor no pudo decir cuántos mensajes se eliminarían. Cancela e inténtalo de nuevo."

msgctxt "AppWindow"
msgid "Delete network and scrollback"
Expand Down
4 changes: 2 additions & 2 deletions crates/cordiale-ui/lang/fr/LC_MESSAGES/cordiale-ui.po
Original file line number Diff line number Diff line change
Expand Up @@ -2729,8 +2729,8 @@ msgid "Delete {} for good? Its whole scrollback goes with it, for every account.
msgstr "Supprimer {} définitivement ? Tout son historique disparaît avec, pour chaque compte. Messages supprimés : {}"

msgctxt "AppWindow"
msgid "Delete {} for good? Its whole scrollback goes with it, for every account; the server couldn't say how many messages that is."
msgstr "Supprimer {} définitivement ? Tout son historique disparaît avec, pour chaque compte ; le serveur n'a pas pu dire combien de messages cela représente."
msgid "Can't delete {}: the server couldn't say how many messages that would remove. Cancel and try again."
msgstr "Impossible de supprimer {} : le serveur n'a pas pu dire combien de messages seraient supprimés. Annulez et réessayez."

msgctxt "AppWindow"
msgid "Delete network and scrollback"
Expand Down
4 changes: 2 additions & 2 deletions crates/cordiale-ui/lang/it/LC_MESSAGES/cordiale-ui.po
Original file line number Diff line number Diff line change
Expand Up @@ -2729,8 +2729,8 @@ msgid "Delete {} for good? Its whole scrollback goes with it, for every account.
msgstr "Eliminare {} definitivamente? Con la rete va via tutto lo storico, per ogni account. Messaggi eliminati: {}"

msgctxt "AppWindow"
msgid "Delete {} for good? Its whole scrollback goes with it, for every account; the server couldn't say how many messages that is."
msgstr "Eliminare {} definitivamente? Con la rete va via tutto lo storico, per ogni account; il server non ha saputo dire quanti messaggi siano."
msgid "Can't delete {}: the server couldn't say how many messages that would remove. Cancel and try again."
msgstr "Impossibile eliminare {}: il server non ha saputo dire quanti messaggi verrebbero rimossi. Annulla e riprova."

msgctxt "AppWindow"
msgid "Delete network and scrollback"
Expand Down
12 changes: 11 additions & 1 deletion crates/cordiale-ui/src/admin_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,10 +546,11 @@ pub(crate) async fn push_admin_featured(
/// confirmation. A 404 or any failure is "can't say", never zero, and the
/// answer is dropped if the confirmation moved on to another network.
pub(crate) async fn handle_admin_network_count(
state: &WorkerState,
state: &mut WorkerState,
ui: &slint::Weak<AppWindow>,
network_id: String,
) {
state.panels.admin_network_count_for = None;
let (Some(client), Some(token)) = (&state.conn.client, &state.conn.token) else {
return;
};
Expand All @@ -563,6 +564,9 @@ pub(crate) async fn handle_admin_network_count(
None
}
};
if count.is_some() {
state.panels.admin_network_count_for = Some(network_id.clone());
}
let _ = ui.upgrade_in_event_loop(move |ui| {
if ui.get_admin_network_confirm_id() != network_id.as_str() {
return;
Expand All @@ -577,6 +581,12 @@ pub(crate) async fn handle_admin_network_count(
});
}

/// A network may only be deleted once the server has answered its
/// scrollback count (zero included); a stale or forged request is refused.
pub(crate) fn admin_network_delete_armed(state: &WorkerState, network_id: &str) -> bool {
state.panels.admin_network_count_for.as_deref() == Some(network_id)
}

pub(crate) fn admin_overview_text(overview: &cordiale_core::admin::AdminOverview) -> String {
format!(
"{} session(s) · {}/{} visitors live · {} · v{}",
Expand Down
14 changes: 12 additions & 2 deletions crates/cordiale-ui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,9 @@ struct PanelState {
/// The last `GET /admin/uploads` answer, which decides what may be
/// deleted.
admin_uploads: Option<cordiale_core::admin::AdminUploadsResponse>,
/// The network id whose scrollback count the server last answered; only
/// that network may be deleted.
admin_network_count_for: Option<String>,
/// `/kb` requests waiting for their `resolve_userhost` reply, by ref.
pending_kickbans: HashMap<String, PendingKickBan>,
/// Identity-recovery panel driven entirely by server pushes; `None`
Expand Down Expand Up @@ -1448,6 +1451,7 @@ impl WorkerState {
admin_events: Vec::new(),
admin_settings: None,
admin_uploads: None,
admin_network_count_for: None,
pending_kickbans: HashMap::new(),
recover_panel: None,
reply_view: None,
Expand Down Expand Up @@ -2116,7 +2120,7 @@ async fn run_worker(
run_admin_featured_delete(&mut state, &ui, network_id, featured_id).await;
}
Some(WorkerCommand::AdminNetworkCount(network_id)) => {
handle_admin_network_count(&state, &ui, network_id).await;
handle_admin_network_count(&mut state, &ui, network_id).await;
}
Some(WorkerCommand::AdminCredentialEdit {
user_id,
Expand Down Expand Up @@ -2168,7 +2172,13 @@ async fn run_worker(
run_admin_settings_save(&mut state, &ui, form).await;
}
Some(WorkerCommand::AdminNetworkDelete(network_id)) => {
handle_admin_write(&state, &ui, AdminWrite::DeleteNetwork(network_id)).await;
if admin_network_delete_armed(&state, &network_id) {
state.panels.admin_network_count_for = None;
handle_admin_write(&state, &ui, AdminWrite::DeleteNetwork(network_id))
.await;
} else {
persistence::log_line("admin network delete refused: no count");
}
}
Some(WorkerCommand::AdminNetworkSave {
slug,
Expand Down
14 changes: 14 additions & 0 deletions crates/cordiale-ui/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4657,6 +4657,20 @@ fn a_refused_admin_write_is_told_apart() {
assert_eq!(admin_failure_kind(None, true), "admin-action-failed");
}

#[test]
fn network_delete_needs_a_count_for_that_network() {
let mut state = WorkerState::new();
// No count answered yet (counting, 404 or any failure): refused.
assert!(!admin_network_delete_armed(&state, "7"));
// A successful count, zero included, arms only its own network.
state.panels.admin_network_count_for = Some("7".to_string());
assert!(admin_network_delete_armed(&state, "7"));
assert!(!admin_network_delete_armed(&state, "8"));
// A new count request clears the previous answer.
state.panels.admin_network_count_for = None;
assert!(!admin_network_delete_armed(&state, "7"));
}

fn pending_kickban(ban_type: cordiale_core::ban::BanType) -> PendingKickBan {
PendingKickBan {
network: "libera".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions crates/cordiale-ui/ui/appwindow.slint
Original file line number Diff line number Diff line change
Expand Up @@ -6223,7 +6223,7 @@ export component AppWindow inherits Window {
? @tr("Counting the messages of {}…", admin-network-confirm-slug)
: (admin-network-count-state == "known"
? @tr("Delete {} for good? Its whole scrollback goes with it, for every account. Messages deleted: {}", admin-network-confirm-slug, admin-network-count)
: @tr("Delete {} for good? Its whole scrollback goes with it, for every account; the server couldn't say how many messages that is.", admin-network-confirm-slug));
: @tr("Can't delete {}: the server couldn't say how many messages that would remove. Cancel and try again.", admin-network-confirm-slug));
wrap: word-wrap;
horizontal-stretch: 1;
vertical-alignment: center;
Expand All @@ -6238,7 +6238,7 @@ export component AppWindow inherits Window {
}
Button {
text: @tr("Delete network and scrollback");
enabled: admin-network-count-state != "counting";
enabled: admin-network-count-state == "known";
clicked => {
admin-network-delete(admin-network-confirm-id);
admin-network-confirm-id = "";
Expand Down
Loading