Dorian 486fc39249 feat: complete Phase 1 foundation hardening + three-mode UI design doc
Phase 1a — Gradient Removal:
- Replaced all gradient-button/gradient-card with glass-button/path-option-card
- Removed banned gradient CSS classes

Phase 1b — Security Hardening:
- SecretsManager: AES-256-GCM encryption (core/security)
- electrs_status: credentials from env vars instead of hardcoded
- port_manager: RwLock proper error handling (no unwrap)
- Pinned all 11 :latest manifest images to specific versions
- parmanode converter: pinned inferred image versions

Phase 1c — Code Quality:
- Split rpc.rs (1795 lines) into 6 handler modules (auth, node, container, package, peers)
- Removed sideload code (UI, store, RPC client, 3 doc files)
- Fixed body background flash on logout/refresh
- Replaced 30 TypeScript `any` types with proper types
- Deleted HelloWorld.vue, removed TODO comments
- Added set -euo pipefail to all shell scripts
- Made deploy script verbose with timestamps and elapsed time

Also adds:
- CLAUDE.md project guide
- docs/three-mode-ui-design.md — design spec for Easy/Pro/Chat UI modes
- OnlineStatusPill component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 05:23:42 +00:00

78 lines
2.7 KiB
Rust

use super::{RpcHandler, DEV_DEFAULT_PASSWORD};
use anyhow::Result;
impl RpcHandler {
pub(super) async fn handle_auth_login(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let password = params
.get("password")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing password"))?;
let is_setup = self.auth_manager.is_setup().await?;
if !is_setup {
// Dev mode: allow default password so UI can log in without running setup
if self.config.dev_mode && password == DEV_DEFAULT_PASSWORD {
return Ok(serde_json::Value::Null);
}
return Err(anyhow::anyhow!(
"User not set up. Please complete setup first."
));
}
let valid = self.auth_manager.verify_password(password).await?;
if !valid {
return Err(anyhow::anyhow!("Password Incorrect"));
}
Ok(serde_json::Value::Null)
}
pub(super) async fn handle_auth_logout(&self) -> Result<serde_json::Value> {
Ok(serde_json::Value::Null)
}
pub(super) async fn handle_auth_change_password(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let current_password = params
.get("currentPassword")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing currentPassword"))?;
let new_password = params
.get("newPassword")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing newPassword"))?;
let also_change_ssh = params
.get("alsoChangeSsh")
.and_then(|v| v.as_bool())
.unwrap_or(true);
self.auth_manager
.change_password(current_password, new_password, also_change_ssh)
.await?;
Ok(serde_json::json!({ "success": true }))
}
pub(super) async fn handle_auth_onboarding_complete(&self) -> Result<serde_json::Value> {
self.auth_manager.complete_onboarding().await?;
Ok(serde_json::json!(true))
}
pub(super) async fn handle_auth_is_onboarding_complete(&self) -> Result<serde_json::Value> {
let complete = self.auth_manager.is_onboarding_complete().await?;
Ok(serde_json::json!(complete))
}
pub(super) async fn handle_auth_reset_onboarding(&self) -> Result<serde_json::Value> {
self.auth_manager.reset_onboarding().await?;
Ok(serde_json::json!(true))
}
}