v3 : relecture de cf634c2 — renouvellement sans effet sur la réponse, lien en attente fermé avec les sessions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-23 09:02:26 +02:00
co-authored by Claude Opus 5.5
parent cf634c25d2
commit decbc0ba7b
9 changed files with 107 additions and 30 deletions
+26 -7
View File
@@ -222,7 +222,8 @@ pub async fn set_admin(
}
/// A lost device, a person who left: every session of this identity closes,
/// but the one this request comes with.
/// but the one this request comes with, and so does a sign-in link still
/// waiting for it (it may sit on the lost device).
pub async fn close_sessions(
State(state): State<AppState>,
headers: HeaderMap,
@@ -231,14 +232,32 @@ pub async fn close_sessions(
) -> AppResult<Json<serde_json::Value>> {
admin_only(&user)?;
auth::load_identity(&state, &id).await?;
let closed = sqlx::query("DELETE FROM sessions WHERE identity_id = ? AND token_hash != ?")
let current = auth::session_hash(&state, &headers).unwrap_or_default();
// Counted as the overview counts them; the expired ones go too.
let open: i64 = sqlx::query_scalar(
"SELECT COUNT(*) FROM sessions WHERE identity_id = ? AND token_hash != ? AND expires_at > ?",
)
.bind(&id)
.bind(&current)
.bind(util::now())
.fetch_one(&state.db)
.await?;
sqlx::query("DELETE FROM sessions WHERE identity_id = ? AND token_hash != ?")
.bind(&id)
.bind(auth::session_hash(&state, &headers).unwrap_or_default())
.bind(&current)
.execute(&state.db)
.await?
.rows_affected();
tracing::info!(identity = %id, closed, by = %user.id, "sessions closed");
Ok(Json(json!({ "closed": closed })))
.await?;
let links = sqlx::query(
"UPDATE invitations SET expires_at = ? WHERE identity_id = ? AND used_at IS NULL AND expires_at > ?",
)
.bind(util::now())
.bind(&id)
.bind(util::now())
.execute(&state.db)
.await?
.rows_affected();
tracing::info!(identity = %id, closed = open, links, by = %user.id, "sessions closed");
Ok(Json(json!({ "closed": open, "links": links })))
}
#[derive(Deserialize)]