mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 15:58:48 +00:00
Validate entry type fields
This commit is contained in:
@@ -723,6 +723,93 @@ class EntryManager:
|
|||||||
|
|
||||||
entry_type = entry.get("type", entry.get("kind", EntryType.PASSWORD.value))
|
entry_type = entry.get("type", entry.get("kind", EntryType.PASSWORD.value))
|
||||||
|
|
||||||
|
provided_fields = {
|
||||||
|
"username": username,
|
||||||
|
"url": url,
|
||||||
|
"archived": archived,
|
||||||
|
"notes": notes,
|
||||||
|
"label": label,
|
||||||
|
"period": period,
|
||||||
|
"digits": digits,
|
||||||
|
"value": value,
|
||||||
|
"custom_fields": custom_fields,
|
||||||
|
"tags": tags,
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed = {
|
||||||
|
EntryType.PASSWORD.value: {
|
||||||
|
"username",
|
||||||
|
"url",
|
||||||
|
"label",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.TOTP.value: {
|
||||||
|
"label",
|
||||||
|
"period",
|
||||||
|
"digits",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.KEY_VALUE.value: {
|
||||||
|
"label",
|
||||||
|
"value",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.MANAGED_ACCOUNT.value: {
|
||||||
|
"label",
|
||||||
|
"value",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.SSH.value: {
|
||||||
|
"label",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.PGP.value: {
|
||||||
|
"label",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.NOSTR.value: {
|
||||||
|
"label",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
EntryType.SEED.value: {
|
||||||
|
"label",
|
||||||
|
"archived",
|
||||||
|
"notes",
|
||||||
|
"custom_fields",
|
||||||
|
"tags",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed_fields = allowed.get(entry_type, set())
|
||||||
|
invalid = {
|
||||||
|
k for k, v in provided_fields.items() if v is not None
|
||||||
|
} - allowed_fields
|
||||||
|
if invalid:
|
||||||
|
raise ValueError(
|
||||||
|
f"Entry type '{entry_type}' does not support fields: {', '.join(sorted(invalid))}"
|
||||||
|
)
|
||||||
|
|
||||||
if entry_type == EntryType.TOTP.value:
|
if entry_type == EntryType.TOTP.value:
|
||||||
if label is not None:
|
if label is not None:
|
||||||
entry["label"] = label
|
entry["label"] = label
|
||||||
@@ -796,6 +883,7 @@ class EntryManager:
|
|||||||
print(
|
print(
|
||||||
colored(f"Error: Failed to modify entry at index {index}: {e}", "red")
|
colored(f"Error: Failed to modify entry at index {index}: {e}", "red")
|
||||||
)
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
def archive_entry(self, index: int) -> None:
|
def archive_entry(self, index: int) -> None:
|
||||||
"""Mark the specified entry as archived."""
|
"""Mark the specified entry as archived."""
|
||||||
|
@@ -207,6 +207,7 @@ def update_entry(
|
|||||||
"""
|
"""
|
||||||
_check_token(authorization)
|
_check_token(authorization)
|
||||||
assert _pm is not None
|
assert _pm is not None
|
||||||
|
try:
|
||||||
_pm.entry_manager.modify_entry(
|
_pm.entry_manager.modify_entry(
|
||||||
entry_id,
|
entry_id,
|
||||||
username=entry.get("username"),
|
username=entry.get("username"),
|
||||||
@@ -217,6 +218,8 @@ def update_entry(
|
|||||||
digits=entry.get("digits"),
|
digits=entry.get("digits"),
|
||||||
value=entry.get("value"),
|
value=entry.get("value"),
|
||||||
)
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
return {"status": "ok"}
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -306,6 +306,7 @@ def entry_modify(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Modify an existing entry."""
|
"""Modify an existing entry."""
|
||||||
pm = _get_pm(ctx)
|
pm = _get_pm(ctx)
|
||||||
|
try:
|
||||||
pm.entry_manager.modify_entry(
|
pm.entry_manager.modify_entry(
|
||||||
entry_id,
|
entry_id,
|
||||||
username=username,
|
username=username,
|
||||||
@@ -316,6 +317,9 @@ def entry_modify(
|
|||||||
digits=digits,
|
digits=digits,
|
||||||
value=value,
|
value=value,
|
||||||
)
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
typer.echo(str(e))
|
||||||
|
raise typer.Exit(code=1)
|
||||||
pm.sync_vault()
|
pm.sync_vault()
|
||||||
|
|
||||||
|
|
||||||
|
@@ -93,6 +93,19 @@ def test_create_and_modify_ssh_entry(client):
|
|||||||
assert calls["modify"][1]["notes"] == "x"
|
assert calls["modify"][1]["notes"] == "x"
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_entry_error(client):
|
||||||
|
cl, token = client
|
||||||
|
|
||||||
|
def modify(*a, **k):
|
||||||
|
raise ValueError("nope")
|
||||||
|
|
||||||
|
api._pm.entry_manager.modify_entry = modify
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
res = cl.put("/api/v1/entry/1", json={"username": "x"}, headers=headers)
|
||||||
|
assert res.status_code == 400
|
||||||
|
assert res.json() == {"detail": "nope"}
|
||||||
|
|
||||||
|
|
||||||
def test_update_config_secret_mode(client):
|
def test_update_config_secret_mode(client):
|
||||||
cl, token = client
|
cl, token = client
|
||||||
called = {}
|
called = {}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||||
|
import pytest
|
||||||
|
|
||||||
from password_manager.entry_management import EntryManager
|
from password_manager.entry_management import EntryManager
|
||||||
from password_manager.backup import BackupManager
|
from password_manager.backup import BackupManager
|
||||||
@@ -18,3 +19,14 @@ def test_modify_totp_entry_period_digits_and_archive(tmp_path):
|
|||||||
assert entry["period"] == 60
|
assert entry["period"] == 60
|
||||||
assert entry["digits"] == 8
|
assert entry["digits"] == 8
|
||||||
assert entry["archived"] is True
|
assert entry["archived"] is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_modify_totp_entry_invalid_field(tmp_path):
|
||||||
|
vault, _ = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
|
||||||
|
cfg_mgr = ConfigManager(vault, tmp_path)
|
||||||
|
backup_mgr = BackupManager(tmp_path, cfg_mgr)
|
||||||
|
em = EntryManager(vault, backup_mgr)
|
||||||
|
|
||||||
|
em.add_totp("Example", TEST_SEED)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
em.modify_entry(0, username="alice")
|
||||||
|
@@ -396,6 +396,21 @@ def test_entry_modify(monkeypatch):
|
|||||||
assert called["args"][:5] == (1, "alice", None, None, None)
|
assert called["args"][:5] == (1, "alice", None, None, None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_entry_modify_invalid(monkeypatch):
|
||||||
|
def modify_entry(*a, **k):
|
||||||
|
raise ValueError("bad")
|
||||||
|
|
||||||
|
pm = SimpleNamespace(
|
||||||
|
entry_manager=SimpleNamespace(modify_entry=modify_entry),
|
||||||
|
select_fingerprint=lambda fp: None,
|
||||||
|
sync_vault=lambda: None,
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(cli, "PasswordManager", lambda: pm)
|
||||||
|
result = runner.invoke(app, ["entry", "modify", "1", "--username", "alice"])
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "bad" in result.stdout
|
||||||
|
|
||||||
|
|
||||||
def test_entry_archive(monkeypatch):
|
def test_entry_archive(monkeypatch):
|
||||||
called = {}
|
called = {}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user