cli: avoid data-dir initialization for version; create db parent dirs; redact generated passwords in CLI output
- Prevent 'nx9-wg version' from creating data directories by avoiding database initialization. - Create parent directories when an explicit --database path is provided. - Redact printed generated administrator passwords; announce file path or redact instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
commit
2ac6c81dfe
140 files changed
+31342
No files matched your search
@@ -0,0 +1,111 @@
|
||||
//! Single Administrator account, password, API tokens, and session management view model.
|
||||
|
||||
use chrono::NaiveDateTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Active session view row.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SessionRowView {
|
||||
pub id: String,
|
||||
pub ip_address: String,
|
||||
pub user_agent: String,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub expires_at: NaiveDateTime,
|
||||
pub is_current: bool,
|
||||
}
|
||||
|
||||
/// Active API token view row.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ApiTokenRowView {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub expires_at: Option<NaiveDateTime>,
|
||||
pub last_used_at: Option<NaiveDateTime>,
|
||||
pub is_revoked: bool,
|
||||
}
|
||||
|
||||
/// Administrator management view state.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AdministratorState {
|
||||
// Card 1: Account
|
||||
pub username: String,
|
||||
pub last_login_at: Option<NaiveDateTime>,
|
||||
pub last_login_ip: Option<String>,
|
||||
pub totp_enabled: bool,
|
||||
pub active_session_count: usize,
|
||||
|
||||
// Card 2: Password change
|
||||
pub current_password: String,
|
||||
pub new_password: String,
|
||||
pub confirm_password: String,
|
||||
|
||||
// Card 3: API Tokens
|
||||
pub new_token_name: String,
|
||||
pub new_token_expires_days: Option<u32>,
|
||||
pub created_token_plaintext: Option<String>,
|
||||
pub tokens: Vec<ApiTokenRowView>,
|
||||
|
||||
// Card 4: Sessions
|
||||
pub sessions: Vec<SessionRowView>,
|
||||
|
||||
// Feedback
|
||||
pub success_message: Option<String>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for AdministratorState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
username: "admin".to_string(),
|
||||
last_login_at: None,
|
||||
last_login_ip: None,
|
||||
totp_enabled: false,
|
||||
active_session_count: 1,
|
||||
current_password: String::new(),
|
||||
new_password: String::new(),
|
||||
confirm_password: String::new(),
|
||||
new_token_name: String::new(),
|
||||
new_token_expires_days: Some(30),
|
||||
created_token_plaintext: None,
|
||||
tokens: Vec::new(),
|
||||
sessions: Vec::new(),
|
||||
success_message: None,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AdministratorState {
|
||||
pub fn validate_password_change(&self) -> Result<(), &'static str> {
|
||||
if self.current_password.is_empty() {
|
||||
return Err("Current password is required");
|
||||
}
|
||||
if self.new_password.len() < 8 {
|
||||
return Err("New password must be at least 8 characters long");
|
||||
}
|
||||
if self.new_password != self.confirm_password {
|
||||
return Err("New password and confirmation do not match");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_admin_password_validation() {
|
||||
let mut state = AdministratorState::default();
|
||||
assert!(state.validate_password_change().is_err());
|
||||
|
||||
state.current_password = "OldPassword123!".to_string();
|
||||
state.new_password = "NewPassword123!".to_string();
|
||||
state.confirm_password = "MismatchPassword!".to_string();
|
||||
assert!(state.validate_password_change().is_err());
|
||||
|
||||
state.confirm_password = "NewPassword123!".to_string();
|
||||
assert!(state.validate_password_change().is_ok());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user