mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Add change-password command and endpoint
This commit is contained in:
@@ -68,6 +68,7 @@ Manage the entire vault for a profile.
|
|||||||
| Action | Command | Examples |
|
| Action | Command | Examples |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| Export the vault | `vault export` | `seedpass vault export --file backup.json` |
|
| Export the vault | `vault export` | `seedpass vault export --file backup.json` |
|
||||||
|
| Change the master password | `vault change-password` | `seedpass vault change-password` |
|
||||||
|
|
||||||
### Nostr Commands
|
### Nostr Commands
|
||||||
|
|
||||||
@@ -147,6 +148,7 @@ Code: 123456
|
|||||||
### `vault` Commands
|
### `vault` Commands
|
||||||
|
|
||||||
- **`seedpass vault export`** – Export the entire vault to an encrypted JSON file.
|
- **`seedpass vault export`** – Export the entire vault to an encrypted JSON file.
|
||||||
|
- **`seedpass vault change-password`** – Change the master password used for encryption.
|
||||||
|
|
||||||
### `nostr` Commands
|
### `nostr` Commands
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@ Keep this token secret. Every request must include it in the `Authorization` hea
|
|||||||
- `DELETE /api/v1/fingerprint/{fp}` – Remove a fingerprint.
|
- `DELETE /api/v1/fingerprint/{fp}` – Remove a fingerprint.
|
||||||
- `POST /api/v1/fingerprint/select` – Switch the active fingerprint.
|
- `POST /api/v1/fingerprint/select` – Switch the active fingerprint.
|
||||||
- `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/change-password` – Change the master password for the active profile.
|
||||||
- `POST /api/v1/shutdown` – Stop the server gracefully.
|
- `POST /api/v1/shutdown` – Stop the server gracefully.
|
||||||
|
|
||||||
## Example Requests
|
## Example Requests
|
||||||
|
@@ -311,6 +311,15 @@ def get_nostr_pubkey(authorization: str | None = Header(None)) -> Any:
|
|||||||
return {"npub": _pm.nostr_client.key_manager.get_npub()}
|
return {"npub": _pm.nostr_client.key_manager.get_npub()}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/api/v1/change-password")
|
||||||
|
def change_password(authorization: str | None = Header(None)) -> dict[str, str]:
|
||||||
|
"""Change the master password for the active profile."""
|
||||||
|
_check_token(authorization)
|
||||||
|
assert _pm is not None
|
||||||
|
_pm.change_password()
|
||||||
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/v1/shutdown")
|
@app.post("/api/v1/shutdown")
|
||||||
async def shutdown_server(authorization: str | None = Header(None)) -> dict[str, str]:
|
async def shutdown_server(authorization: str | None = Header(None)) -> dict[str, str]:
|
||||||
_check_token(authorization)
|
_check_token(authorization)
|
||||||
|
@@ -324,6 +324,13 @@ def vault_export(
|
|||||||
typer.echo(str(file))
|
typer.echo(str(file))
|
||||||
|
|
||||||
|
|
||||||
|
@vault_app.command("change-password")
|
||||||
|
def vault_change_password(ctx: typer.Context) -> None:
|
||||||
|
"""Change the master password used for encryption."""
|
||||||
|
pm = _get_pm(ctx)
|
||||||
|
pm.change_password()
|
||||||
|
|
||||||
|
|
||||||
@nostr_app.command("sync")
|
@nostr_app.command("sync")
|
||||||
def nostr_sync(ctx: typer.Context) -> None:
|
def nostr_sync(ctx: typer.Context) -> None:
|
||||||
"""Sync with configured Nostr relays."""
|
"""Sync with configured Nostr relays."""
|
||||||
|
@@ -158,6 +158,19 @@ def test_update_config(client):
|
|||||||
assert res.headers.get("access-control-allow-origin") == "http://example.com"
|
assert res.headers.get("access-control-allow-origin") == "http://example.com"
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_password_route(client):
|
||||||
|
cl, token = client
|
||||||
|
called = {}
|
||||||
|
|
||||||
|
api._pm.change_password = lambda: called.setdefault("called", True)
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Origin": "http://example.com"}
|
||||||
|
res = cl.post("/api/v1/change-password", headers=headers)
|
||||||
|
assert res.status_code == 200
|
||||||
|
assert res.json() == {"status": "ok"}
|
||||||
|
assert called.get("called") is True
|
||||||
|
assert res.headers.get("access-control-allow-origin") == "http://example.com"
|
||||||
|
|
||||||
|
|
||||||
def test_update_config_unknown_key(client):
|
def test_update_config_unknown_key(client):
|
||||||
cl, token = client
|
cl, token = client
|
||||||
headers = {"Authorization": f"Bearer {token}", "Origin": "http://example.com"}
|
headers = {"Authorization": f"Bearer {token}", "Origin": "http://example.com"}
|
||||||
@@ -206,6 +219,7 @@ def test_shutdown(client, monkeypatch):
|
|||||||
("put", "/api/v1/config/inactivity_timeout"),
|
("put", "/api/v1/config/inactivity_timeout"),
|
||||||
("post", "/api/v1/entry/1/archive"),
|
("post", "/api/v1/entry/1/archive"),
|
||||||
("post", "/api/v1/entry/1/unarchive"),
|
("post", "/api/v1/entry/1/unarchive"),
|
||||||
|
("post", "/api/v1/change-password"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_invalid_token_other_endpoints(client, method, path):
|
def test_invalid_token_other_endpoints(client, method, path):
|
||||||
|
@@ -81,6 +81,19 @@ def test_vault_export(monkeypatch, tmp_path):
|
|||||||
assert called["path"] == out_path
|
assert called["path"] == out_path
|
||||||
|
|
||||||
|
|
||||||
|
def test_vault_change_password(monkeypatch):
|
||||||
|
called = {}
|
||||||
|
|
||||||
|
def change_pw():
|
||||||
|
called["called"] = True
|
||||||
|
|
||||||
|
pm = SimpleNamespace(change_password=change_pw, select_fingerprint=lambda fp: None)
|
||||||
|
monkeypatch.setattr(cli, "PasswordManager", lambda: pm)
|
||||||
|
result = runner.invoke(app, ["vault", "change-password"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert called.get("called") is True
|
||||||
|
|
||||||
|
|
||||||
def test_nostr_get_pubkey(monkeypatch):
|
def test_nostr_get_pubkey(monkeypatch):
|
||||||
pm = SimpleNamespace(
|
pm = SimpleNamespace(
|
||||||
nostr_client=SimpleNamespace(
|
nostr_client=SimpleNamespace(
|
||||||
|
Reference in New Issue
Block a user