feat(build): add unlock rescue script and build command
- Introduced a new PowerShell script `build-unlock-rescue.ps1` to facilitate the unlocking process for NyaTerm. - Added a corresponding build command `build:unlock-rescue` in package.json to streamline the execution of the unlock rescue script. - Implemented functionality in the script to create a backup of the database and disable screen lock settings.
This commit is contained in:
1 parent
0eed179446
commit
1412f314ab
3 files changed
+131
No files matched your search
@@ -20,6 +20,7 @@
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"release": "node scripts/sync-version.mjs --commit && tsc && vite build && tauri build",
|
||||
"build:unlock-rescue": "powershell -ExecutionPolicy Bypass -File scripts/build-unlock-rescue.ps1",
|
||||
"preview": "vite preview",
|
||||
"tauri": "tauri",
|
||||
"lint": "node scripts/check-no-console.mjs && biome check src/",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||
$manifestPath = Join-Path $repoRoot "src-tauri/Cargo.toml"
|
||||
$artifactDir = Join-Path $repoRoot "dist/rescue"
|
||||
$sourceExe = Join-Path $repoRoot "src-tauri/target/release/nyaterm-unlock-rescue.exe"
|
||||
$targetExe = Join-Path $artifactDir "nyaterm-unlock-rescue.exe"
|
||||
$targetZip = Join-Path $artifactDir "nyaterm-unlock-rescue-windows-x64.zip"
|
||||
|
||||
cargo build --release --manifest-path $manifestPath --bin nyaterm-unlock-rescue
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $artifactDir | Out-Null
|
||||
Copy-Item -Force -Path $sourceExe -Destination $targetExe
|
||||
Compress-Archive -Force -Path $targetExe -DestinationPath $targetZip
|
||||
|
||||
Write-Host "Built rescue tool:"
|
||||
Write-Host $targetExe
|
||||
Write-Host $targetZip
|
||||
@@ -0,0 +1,112 @@
|
||||
use redb::{Database, ReadableTable, TableDefinition};
|
||||
use serde_json::Value;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const SETTINGS_TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("settings");
|
||||
const SETTINGS_KEY: &str = "settings/default";
|
||||
|
||||
fn main() {
|
||||
if let Err(error) = run() {
|
||||
eprintln!("NyaTerm unlock rescue failed: {error}");
|
||||
wait_for_enter();
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
wait_for_enter();
|
||||
}
|
||||
|
||||
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let db_path = std::env::args()
|
||||
.nth(1)
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(default_db_path);
|
||||
|
||||
if !db_path.exists() {
|
||||
return Err(format!("database not found: {}", db_path.display()).into());
|
||||
}
|
||||
|
||||
let backup_path = db_path.with_extension(format!(
|
||||
"redb.screen-lock-rescue-{}.bak",
|
||||
unix_timestamp_seconds()
|
||||
));
|
||||
std::fs::copy(&db_path, &backup_path)?;
|
||||
|
||||
let db = Database::open(&db_path)?;
|
||||
let txn = db.begin_write()?;
|
||||
let changed = {
|
||||
let mut table = txn.open_table(SETTINGS_TABLE)?;
|
||||
let (mut settings, was_enabled, old_idle): (Value, bool, u64) = {
|
||||
let Some(raw) = table.get(SETTINGS_KEY)? else {
|
||||
return Err(format!("settings document not found: {SETTINGS_KEY}").into());
|
||||
};
|
||||
|
||||
let mut settings: Value = serde_json::from_slice(raw.value())?;
|
||||
let security = settings
|
||||
.as_object_mut()
|
||||
.and_then(|root| root.get_mut("security"))
|
||||
.and_then(Value::as_object_mut)
|
||||
.ok_or("settings.security is missing or not an object")?;
|
||||
|
||||
let was_enabled = security
|
||||
.get("enable_screen_lock")
|
||||
.and_then(Value::as_bool)
|
||||
.unwrap_or(false);
|
||||
let old_idle = security
|
||||
.get("idle_lock_minutes")
|
||||
.and_then(Value::as_u64)
|
||||
.unwrap_or(0);
|
||||
|
||||
(settings, was_enabled, old_idle)
|
||||
};
|
||||
|
||||
let security = settings
|
||||
.as_object_mut()
|
||||
.and_then(|root| root.get_mut("security"))
|
||||
.and_then(Value::as_object_mut)
|
||||
.ok_or("settings.security is missing or not an object")?;
|
||||
|
||||
security.insert("enable_screen_lock".to_string(), Value::Bool(false));
|
||||
security.insert(
|
||||
"idle_lock_minutes".to_string(),
|
||||
Value::Number(serde_json::Number::from(0)),
|
||||
);
|
||||
|
||||
let content = serde_json::to_vec(&settings)?;
|
||||
table.insert(SETTINGS_KEY, content.as_slice())?;
|
||||
was_enabled || old_idle != 0
|
||||
};
|
||||
txn.commit()?;
|
||||
|
||||
println!("NyaTerm unlock rescue completed.");
|
||||
println!("Database: {}", db_path.display());
|
||||
println!("Backup: {}", backup_path.display());
|
||||
println!("Screen lock disabled: {changed}");
|
||||
println!("Master password was left unchanged.");
|
||||
println!("You can start NyaTerm again now.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn default_db_path() -> PathBuf {
|
||||
std::env::var_os("USERPROFILE")
|
||||
.or_else(|| std::env::var_os("HOME"))
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join(".nyaterm")
|
||||
.join("nyaterm.redb")
|
||||
}
|
||||
|
||||
fn unix_timestamp_seconds() -> u64 {
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map(|duration| duration.as_secs())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn wait_for_enter() {
|
||||
println!();
|
||||
println!("Press Enter to close this window.");
|
||||
|
||||
let mut input = String::new();
|
||||
let _ = std::io::stdin().read_line(&mut input);
|
||||
}
|
||||
Reference in new issue
Block a user