mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Add vault stats command and API endpoint
This commit is contained in:
@@ -73,6 +73,7 @@ Manage the entire vault for a profile.
|
|||||||
| Import a vault | `vault import` | `seedpass vault import --file backup.json` |
|
| Import a vault | `vault import` | `seedpass vault import --file backup.json` |
|
||||||
| Change the master password | `vault change-password` | `seedpass vault change-password` |
|
| Change the master password | `vault change-password` | `seedpass vault change-password` |
|
||||||
| Lock the vault | `vault lock` | `seedpass vault lock` |
|
| Lock the vault | `vault lock` | `seedpass vault lock` |
|
||||||
|
| Show profile statistics | `vault stats` | `seedpass vault stats` |
|
||||||
|
|
||||||
### Nostr Commands
|
### Nostr Commands
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ Code: 123456
|
|||||||
- **`seedpass vault import`** – Import a vault from an encrypted JSON file.
|
- **`seedpass vault import`** – Import a vault from an encrypted JSON file.
|
||||||
- **`seedpass vault change-password`** – Change the master password used for encryption.
|
- **`seedpass vault change-password`** – Change the master password used for encryption.
|
||||||
- **`seedpass vault lock`** – Clear sensitive data from memory and require reauthentication.
|
- **`seedpass vault lock`** – Clear sensitive data from memory and require reauthentication.
|
||||||
|
- **`seedpass vault stats`** – Display statistics about the active seed profile.
|
||||||
|
|
||||||
### `nostr` Commands
|
### `nostr` Commands
|
||||||
|
|
||||||
|
@@ -29,6 +29,7 @@ Keep this token secret. Every request must include it in the `Authorization` hea
|
|||||||
- `POST /api/v1/fingerprint/select` – Switch the active fingerprint.
|
- `POST /api/v1/fingerprint/select` – Switch the active fingerprint.
|
||||||
- `GET /api/v1/totp/export` – Export all TOTP entries as JSON.
|
- `GET /api/v1/totp/export` – Export all TOTP entries as JSON.
|
||||||
- `GET /api/v1/totp` – Return current TOTP codes and remaining time.
|
- `GET /api/v1/totp` – Return current TOTP codes and remaining time.
|
||||||
|
- `GET /api/v1/stats` – Return statistics about the active seed profile.
|
||||||
- `GET /api/v1/parent-seed` – Reveal the parent seed or save it with `?file=`.
|
- `GET /api/v1/parent-seed` – Reveal the parent seed or save it with `?file=`.
|
||||||
- `GET /api/v1/nostr/pubkey` – Fetch the Nostr public key for the active seed.
|
- `GET /api/v1/nostr/pubkey` – Fetch the Nostr public key for the active seed.
|
||||||
- `POST /api/v1/checksum/verify` – Verify the checksum of the running script.
|
- `POST /api/v1/checksum/verify` – Verify the checksum of the running script.
|
||||||
|
@@ -333,6 +333,14 @@ def get_totp_codes(authorization: str | None = Header(None)) -> dict:
|
|||||||
return {"codes": codes}
|
return {"codes": codes}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/v1/stats")
|
||||||
|
def get_profile_stats(authorization: str | None = Header(None)) -> dict:
|
||||||
|
"""Return statistics about the active seed profile."""
|
||||||
|
_check_token(authorization)
|
||||||
|
assert _pm is not None
|
||||||
|
return _pm.get_profile_stats()
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/v1/parent-seed")
|
@app.get("/api/v1/parent-seed")
|
||||||
def get_parent_seed(
|
def get_parent_seed(
|
||||||
authorization: str | None = Header(None), file: str | None = None
|
authorization: str | None = Header(None), file: str | None = None
|
||||||
|
@@ -368,6 +368,14 @@ def vault_lock(ctx: typer.Context) -> None:
|
|||||||
typer.echo("locked")
|
typer.echo("locked")
|
||||||
|
|
||||||
|
|
||||||
|
@vault_app.command("stats")
|
||||||
|
def vault_stats(ctx: typer.Context) -> None:
|
||||||
|
"""Display statistics about the current seed profile."""
|
||||||
|
pm = _get_pm(ctx)
|
||||||
|
stats = pm.get_profile_stats()
|
||||||
|
typer.echo(json.dumps(stats, indent=2))
|
||||||
|
|
||||||
|
|
||||||
@vault_app.command("reveal-parent-seed")
|
@vault_app.command("reveal-parent-seed")
|
||||||
def vault_reveal_parent_seed(
|
def vault_reveal_parent_seed(
|
||||||
ctx: typer.Context,
|
ctx: typer.Context,
|
||||||
|
13
src/tests/test_api_profile_stats.py
Normal file
13
src/tests/test_api_profile_stats.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from test_api import client
|
||||||
|
|
||||||
|
|
||||||
|
def test_profile_stats_endpoint(client):
|
||||||
|
cl, token = client
|
||||||
|
stats = {"total_entries": 1}
|
||||||
|
# monkeypatch set _pm.get_profile_stats after client fixture started
|
||||||
|
import seedpass.api as api
|
||||||
|
|
||||||
|
api._pm.get_profile_stats = lambda: stats
|
||||||
|
res = cl.get("/api/v1/stats", headers={"Authorization": f"Bearer {token}"})
|
||||||
|
assert res.status_code == 200
|
||||||
|
assert res.json() == stats
|
25
src/tests/test_cli_vault_stats.py
Normal file
25
src/tests/test_cli_vault_stats.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import json
|
||||||
|
from types import SimpleNamespace
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
from seedpass.cli import app
|
||||||
|
from seedpass import cli
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
|
||||||
|
|
||||||
|
def test_vault_stats_command(monkeypatch):
|
||||||
|
stats = {
|
||||||
|
"total_entries": 2,
|
||||||
|
"entries": {"password": 1, "totp": 1},
|
||||||
|
}
|
||||||
|
pm = SimpleNamespace(
|
||||||
|
get_profile_stats=lambda: stats, select_fingerprint=lambda fp: None
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(cli, "PasswordManager", lambda: pm)
|
||||||
|
result = runner.invoke(app, ["vault", "stats"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
out = result.stdout
|
||||||
|
# Output should be pretty JSON with the expected values
|
||||||
|
data = json.loads(out)
|
||||||
|
assert data == stats
|
Reference in New Issue
Block a user