diff options
| author | Doan Luu Duc Tai <doan@luuduct.ai> | 2026-10-30 22:12:54 -0500 |
|---|---|---|
| committer | Doan Luu Duc Tai <doan@luuduct.ai> | 2026-10-30 22:12:54 -0500 |
| commit | be16d00a8a4750028073e018ab2c58d54af192c4 (patch) | |
| tree | 3eeabb31508f98a6753a2492238581f888769b4a /crates/chat-server/src/maintenance.rs | |
| parent | b7374fe09306c495131cf3673addb76a1dcf017d (diff) | |
Refine chat controls and add explicit owner recovery reset
Simplify the ASCII interface, expose owner setup, and load any selected number of messages using bounded history batches. Add backend-only owner reset with a matching public fingerprint and stopped-service guards, and document the loss of old history and key continuity.
Diffstat (limited to 'crates/chat-server/src/maintenance.rs')
| -rw-r--r-- | crates/chat-server/src/maintenance.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/crates/chat-server/src/maintenance.rs b/crates/chat-server/src/maintenance.rs new file mode 100644 index 0000000..eac689d --- /dev/null +++ b/crates/chat-server/src/maintenance.rs @@ -0,0 +1,61 @@ +// Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +use crate::store::Store; +use anyhow::{Context, Result, ensure}; +use std::fs::{File, OpenOptions}; +use std::io::Write; +use std::net::{SocketAddr, TcpListener}; +use std::os::unix::fs::OpenOptionsExt; +use std::path::Path; + +pub(crate) fn lock(directory: &Path) -> Result<File> { + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .mode(0o600) + .open(directory.join("server.lock"))?; + file.try_lock().context( + "Chat is already running. Stop it before starting another server or resetting the owner.", + )?; + Ok(file) +} + +pub(crate) fn fingerprint(store: &Store) -> Result<()> { + let certificate = store.owner()?.context("No owner identity is registered")?; + writeln!( + std::io::stdout().lock(), + "{}", + stack_chat_crypto::public_identity(&certificate)? + )?; + Ok(()) +} + +pub(crate) fn reset(store: &mut Store, expected: &str, address: SocketAddr) -> Result<()> { + ensure!( + address.ip().is_loopback(), + "Reset must use the local chat address" + ); + let _port = + TcpListener::bind(address).context("Stop the chat server before resetting its owner")?; + store.reset_owner(expected)?; + writeln!( + std::io::stdout().lock(), + "Owner registration and chat history cleared. Restart chat and use OWNER SETUP to create a new owner file. Existing backup archives were not changed." + )?; + Ok(()) +} |
