mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-28 16:32:06 +00:00
- Apply black formatting to 17 files. - Fix F821 undefined name errors in: - src/main.py: Add missing `queue` import. - src/seedpass/core/encryption.py: Fix `JSONDecodeError` reference. - src/utils/__init__.py: Fix exception variable scope in fallback code. - src/utils/key_derivation.py: Add `TYPE_CHECKING` imports. - src/seedpass/core/config_manager.py: Add `TYPE_CHECKING` imports. - Initialize torch environment and TODO file. Co-authored-by: PR0M3TH3AN <[email protected]>
99 lines
3.1 KiB
Python
99 lines
3.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
import typer
|
|
|
|
from .common import (
|
|
_get_services,
|
|
ChangePasswordRequest,
|
|
UnlockRequest,
|
|
BackupParentSeedRequest,
|
|
)
|
|
|
|
app = typer.Typer(help="Manage the entire vault")
|
|
|
|
|
|
@app.command("export")
|
|
def vault_export(
|
|
ctx: typer.Context, file: str = typer.Option(..., help="Output file")
|
|
) -> None:
|
|
"""Export the vault profile to an encrypted file."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
data = vault_service.export_profile()
|
|
Path(file).write_bytes(data)
|
|
typer.echo(str(file))
|
|
|
|
|
|
@app.command("import")
|
|
def vault_import(
|
|
ctx: typer.Context, file: str = typer.Option(..., help="Input file")
|
|
) -> None:
|
|
"""Import a vault profile from an encrypted file."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
data = Path(file).read_bytes()
|
|
vault_service.import_profile(data)
|
|
typer.echo(str(file))
|
|
|
|
|
|
@app.command("change-password")
|
|
def vault_change_password(ctx: typer.Context) -> None:
|
|
"""Change the master password used for encryption."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
old_pw = typer.prompt("Current password", hide_input=True)
|
|
new_pw = typer.prompt("New password", hide_input=True, confirmation_prompt=True)
|
|
try:
|
|
vault_service.change_password(
|
|
ChangePasswordRequest(old_password=old_pw, new_password=new_pw)
|
|
)
|
|
except Exception as exc: # pragma: no cover - pass through errors
|
|
typer.echo(f"Error: {exc}")
|
|
raise typer.Exit(code=1)
|
|
typer.echo("Password updated")
|
|
|
|
|
|
@app.command("unlock")
|
|
def vault_unlock(ctx: typer.Context) -> None:
|
|
"""Unlock the vault for the active profile."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
password = typer.prompt("Master password", hide_input=True)
|
|
try:
|
|
resp = vault_service.unlock(UnlockRequest(password=password))
|
|
except Exception as exc: # pragma: no cover - pass through errors
|
|
typer.echo(f"Error: {exc}")
|
|
raise typer.Exit(code=1)
|
|
typer.echo(f"Unlocked in {resp.duration:.2f}s")
|
|
|
|
|
|
@app.command("lock")
|
|
def vault_lock(ctx: typer.Context) -> None:
|
|
"""Lock the vault and clear sensitive data from memory."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
vault_service.lock()
|
|
typer.echo("locked")
|
|
|
|
|
|
@app.command("stats")
|
|
def vault_stats(ctx: typer.Context) -> None:
|
|
"""Display statistics about the current seed profile."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
stats = vault_service.stats()
|
|
typer.echo(json.dumps(stats, indent=2))
|
|
|
|
|
|
@app.command("reveal-parent-seed")
|
|
def vault_reveal_parent_seed(
|
|
ctx: typer.Context,
|
|
file: Optional[str] = typer.Option(
|
|
None, "--file", help="Save encrypted seed to this path"
|
|
),
|
|
) -> None:
|
|
"""Display the parent seed and optionally write an encrypted backup file."""
|
|
vault_service, _profile, _sync = _get_services(ctx)
|
|
password = typer.prompt("Master password", hide_input=True)
|
|
vault_service.backup_parent_seed(
|
|
BackupParentSeedRequest(path=Path(file) if file else None, password=password)
|
|
)
|