feat: add worker config reader with secret decryption
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
import psycopg
|
||||||
|
|
||||||
|
from lyra_worker.crypto import decrypt_secret
|
||||||
|
|
||||||
|
|
||||||
|
def get_config(conn: psycopg.Connection) -> dict[str, str]:
|
||||||
|
"""Return all config as {key: value}, decrypting rows marked secret."""
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute('SELECT key, value, secret FROM "Config"')
|
||||||
|
rows = cur.fetchall()
|
||||||
|
out: dict[str, str] = {}
|
||||||
|
for key, value, secret in rows:
|
||||||
|
out[key] = decrypt_secret(value) if secret else value
|
||||||
|
return out
|
||||||
@@ -12,12 +12,14 @@ def conn():
|
|||||||
with connection.cursor() as cur:
|
with connection.cursor() as cur:
|
||||||
cur.execute('DELETE FROM "Job"')
|
cur.execute('DELETE FROM "Job"')
|
||||||
cur.execute('DELETE FROM "Request"')
|
cur.execute('DELETE FROM "Request"')
|
||||||
|
cur.execute('DELETE FROM "Config"')
|
||||||
connection.commit()
|
connection.commit()
|
||||||
yield connection
|
yield connection
|
||||||
# Clean up rows created during the test (Job cascades from Request).
|
# Clean up rows created during the test (Job cascades from Request).
|
||||||
with connection.cursor() as cur:
|
with connection.cursor() as cur:
|
||||||
cur.execute('DELETE FROM "Job"')
|
cur.execute('DELETE FROM "Job"')
|
||||||
cur.execute('DELETE FROM "Request"')
|
cur.execute('DELETE FROM "Request"')
|
||||||
|
cur.execute('DELETE FROM "Config"')
|
||||||
connection.commit()
|
connection.commit()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from lyra_worker.config import get_config
|
||||||
|
from lyra_worker.crypto import encrypt_secret
|
||||||
|
|
||||||
|
TEST_KEY = "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY="
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def _key(monkeypatch):
|
||||||
|
monkeypatch.setenv("LYRA_SECRET_KEY", TEST_KEY)
|
||||||
|
|
||||||
|
|
||||||
|
def _put(conn, key, value, secret):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
'INSERT INTO "Config" (key, value, secret, "updatedAt") VALUES (%s, %s, %s, now()) '
|
||||||
|
'ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, secret = EXCLUDED.secret',
|
||||||
|
(key, value, secret),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def test_reads_plain_and_decrypts_secret(conn):
|
||||||
|
_put(conn, "slskd.url", "http://slskd:5030", False)
|
||||||
|
_put(conn, "slskd.api_key", encrypt_secret("topsecret"), True)
|
||||||
|
|
||||||
|
cfg = get_config(conn)
|
||||||
|
assert cfg["slskd.url"] == "http://slskd:5030"
|
||||||
|
assert cfg["slskd.api_key"] == "topsecret" # decrypted
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_keys_absent(conn):
|
||||||
|
cfg = get_config(conn)
|
||||||
|
assert "qobuz.password" not in cfg
|
||||||
Reference in New Issue
Block a user