mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-07 14:58:56 +00:00
require password for sensitive read endpoints
This commit is contained in:
@@ -19,7 +19,7 @@ Keep this token secret and avoid logging it. Tokens expire after a few minutes a
|
||||
## Endpoints
|
||||
|
||||
- `GET /api/v1/entry?query=<text>` – Search entries matching a query.
|
||||
- `GET /api/v1/entry/{id}` – Retrieve a single entry by its index.
|
||||
- `GET /api/v1/entry/{id}` – Retrieve a single entry by its index. Requires an `X-SeedPass-Password` header.
|
||||
- `POST /api/v1/entry` – Create a new entry of any supported type.
|
||||
- `PUT /api/v1/entry/{id}` – Modify an existing entry.
|
||||
- `PUT /api/v1/config/{key}` – Update a configuration value.
|
||||
@@ -31,8 +31,8 @@ Keep this token secret and avoid logging it. Tokens expire after a few minutes a
|
||||
- `POST /api/v1/fingerprint` – Add a new seed fingerprint.
|
||||
- `DELETE /api/v1/fingerprint/{fp}` – Remove a 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` – Return current TOTP codes and remaining time.
|
||||
- `GET /api/v1/totp/export` – Export all TOTP entries as JSON. Requires an `X-SeedPass-Password` header.
|
||||
- `GET /api/v1/totp` – Return current TOTP codes and remaining time. Requires an `X-SeedPass-Password` header.
|
||||
- `GET /api/v1/stats` – Return statistics about the active seed profile.
|
||||
- `GET /api/v1/notifications` – Retrieve and clear queued notifications. Messages appear in the persistent notification box but remain queued until fetched.
|
||||
- `GET /api/v1/nostr/pubkey` – Fetch the Nostr public key for the active seed.
|
||||
|
@@ -139,8 +139,13 @@ def search_entry(query: str, authorization: str | None = Header(None)) -> List[A
|
||||
|
||||
|
||||
@app.get("/api/v1/entry/{entry_id}")
|
||||
def get_entry(entry_id: int, authorization: str | None = Header(None)) -> Any:
|
||||
def get_entry(
|
||||
entry_id: int,
|
||||
authorization: str | None = Header(None),
|
||||
password: str | None = Header(None, alias="X-SeedPass-Password"),
|
||||
) -> Any:
|
||||
_check_token(authorization)
|
||||
_require_password(password)
|
||||
assert _pm is not None
|
||||
entry = _pm.entry_manager.retrieve_entry(entry_id)
|
||||
if entry is None:
|
||||
@@ -417,17 +422,25 @@ def select_fingerprint(
|
||||
|
||||
|
||||
@app.get("/api/v1/totp/export")
|
||||
def export_totp(authorization: str | None = Header(None)) -> dict:
|
||||
def export_totp(
|
||||
authorization: str | None = Header(None),
|
||||
password: str | None = Header(None, alias="X-SeedPass-Password"),
|
||||
) -> dict:
|
||||
"""Return all stored TOTP entries in JSON format."""
|
||||
_check_token(authorization)
|
||||
_require_password(password)
|
||||
assert _pm is not None
|
||||
return _pm.entry_manager.export_totp_entries(_pm.parent_seed)
|
||||
|
||||
|
||||
@app.get("/api/v1/totp")
|
||||
def get_totp_codes(authorization: str | None = Header(None)) -> dict:
|
||||
def get_totp_codes(
|
||||
authorization: str | None = Header(None),
|
||||
password: str | None = Header(None, alias="X-SeedPass-Password"),
|
||||
) -> dict:
|
||||
"""Return active TOTP codes with remaining seconds."""
|
||||
_check_token(authorization)
|
||||
_require_password(password)
|
||||
assert _pm is not None
|
||||
entries = _pm.entry_manager.list_entries(
|
||||
filter_kind=EntryType.TOTP.value, include_archived=False
|
||||
|
@@ -78,6 +78,7 @@ def test_get_entry_by_id(client):
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Origin": "http://example.com",
|
||||
"X-SeedPass-Password": "pw",
|
||||
}
|
||||
res = cl.get("/api/v1/entry/1", headers=headers)
|
||||
assert res.status_code == 200
|
||||
|
@@ -136,7 +136,7 @@ def test_totp_export_endpoint(client):
|
||||
cl, token = client
|
||||
api._pm.entry_manager.export_totp_entries = lambda seed: {"entries": ["x"]}
|
||||
api._pm.parent_seed = "seed"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
headers = {"Authorization": f"Bearer {token}", "X-SeedPass-Password": "pw"}
|
||||
res = cl.get("/api/v1/totp/export", headers=headers)
|
||||
assert res.status_code == 200
|
||||
assert res.json() == {"entries": ["x"]}
|
||||
@@ -148,7 +148,7 @@ def test_totp_codes_endpoint(client):
|
||||
api._pm.entry_manager.get_totp_code = lambda i, s: "123456"
|
||||
api._pm.entry_manager.get_totp_time_remaining = lambda i: 30
|
||||
api._pm.parent_seed = "seed"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
headers = {"Authorization": f"Bearer {token}", "X-SeedPass-Password": "pw"}
|
||||
res = cl.get("/api/v1/totp", headers=headers)
|
||||
assert res.status_code == 200
|
||||
assert res.json() == {
|
||||
|
Reference in New Issue
Block a user