mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-16 04:05:48 -07:00
Added Device API Endpoints (Partway)
This commit is contained in:
@@ -55,6 +55,7 @@ CREATE TABLE IF NOT EXISTS enrollment_install_codes (
|
||||
id TEXT PRIMARY KEY,
|
||||
code TEXT UNIQUE,
|
||||
expires_at TEXT,
|
||||
created_by_user_id TEXT,
|
||||
used_at TEXT,
|
||||
used_by_guid TEXT,
|
||||
max_uses INTEGER,
|
||||
@@ -94,17 +95,28 @@ CREATE TABLE IF NOT EXISTS device_list_views (
|
||||
CREATE TABLE IF NOT EXISTS sites (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT,
|
||||
description TEXT
|
||||
description TEXT,
|
||||
created_at INTEGER
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS device_sites (
|
||||
device_hostname TEXT,
|
||||
device_hostname TEXT PRIMARY KEY,
|
||||
site_id INTEGER,
|
||||
PRIMARY KEY (device_hostname, site_id)
|
||||
assigned_at INTEGER
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS github_token (
|
||||
id INTEGER PRIMARY KEY,
|
||||
token TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE,
|
||||
display_name TEXT,
|
||||
password_sha512 TEXT,
|
||||
role TEXT,
|
||||
last_login INTEGER,
|
||||
created_at INTEGER,
|
||||
updated_at INTEGER
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
@@ -210,12 +222,54 @@ def engine_harness(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Iterator[
|
||||
),
|
||||
)
|
||||
cur.execute(
|
||||
"INSERT INTO sites (id, name, description) VALUES (?, ?, ?)",
|
||||
(1, "Main Lab", "Primary integration site"),
|
||||
"INSERT INTO sites (id, name, description, created_at) VALUES (?, ?, ?, ?)",
|
||||
(1, "Main Lab", "Primary integration site", 1_700_000_000),
|
||||
)
|
||||
cur.execute(
|
||||
"INSERT INTO device_sites (device_hostname, site_id) VALUES (?, ?)",
|
||||
("test-device", 1),
|
||||
"INSERT INTO device_sites (device_hostname, site_id, assigned_at) VALUES (?, ?, ?)",
|
||||
("test-device", 1, 1_700_000_500),
|
||||
)
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO users (id, username, display_name, password_sha512, role, last_login, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(1, "admin", "Administrator", "test", "Admin", 0, 0, 0),
|
||||
)
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO device_approvals (
|
||||
id,
|
||||
approval_reference,
|
||||
guid,
|
||||
hostname_claimed,
|
||||
ssl_key_fingerprint_claimed,
|
||||
enrollment_code_id,
|
||||
status,
|
||||
client_nonce,
|
||||
server_nonce,
|
||||
agent_pubkey_der,
|
||||
created_at,
|
||||
updated_at,
|
||||
approved_by_user_id
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
"approval-1",
|
||||
"APP-REF-1",
|
||||
None,
|
||||
"pending-device",
|
||||
"aa:bb:cc:dd",
|
||||
None,
|
||||
"pending",
|
||||
"client-nonce",
|
||||
"server-nonce",
|
||||
None,
|
||||
"2025-01-01T00:00:00Z",
|
||||
"2025-01-01T00:00:00Z",
|
||||
None,
|
||||
),
|
||||
)
|
||||
conn.commit()
|
||||
finally:
|
||||
|
||||
@@ -120,3 +120,67 @@ def test_agent_hash_list_permissions(engine_harness: EngineTestHarness) -> None:
|
||||
assert allowed.status_code == 200
|
||||
agents = allowed.get_json()["agents"]
|
||||
assert agents and agents[0]["hostname"] == "test-device"
|
||||
|
||||
|
||||
def test_sites_lifecycle(engine_harness: EngineTestHarness) -> None:
|
||||
client = _client_with_admin_session(engine_harness)
|
||||
create_resp = client.post(
|
||||
"/api/sites",
|
||||
json={"name": "Edge", "description": "Edge location"},
|
||||
)
|
||||
assert create_resp.status_code == 201
|
||||
site_id = create_resp.get_json()["id"]
|
||||
|
||||
list_resp = client.get("/api/sites")
|
||||
sites = list_resp.get_json()["sites"]
|
||||
assert any(site["id"] == site_id for site in sites)
|
||||
|
||||
assign_resp = client.post(
|
||||
"/api/sites/assign",
|
||||
json={"site_id": site_id, "hostnames": ["test-device"]},
|
||||
)
|
||||
assert assign_resp.status_code == 200
|
||||
|
||||
mapping_resp = client.get("/api/sites/device_map")
|
||||
mapping = mapping_resp.get_json()["mapping"]
|
||||
assert mapping["test-device"]["site_id"] == site_id
|
||||
|
||||
rename_resp = client.post(
|
||||
"/api/sites/rename",
|
||||
json={"id": site_id, "new_name": "Edge-Renamed"},
|
||||
)
|
||||
assert rename_resp.status_code == 200
|
||||
assert rename_resp.get_json()["name"] == "Edge-Renamed"
|
||||
|
||||
delete_resp = client.post("/api/sites/delete", json={"ids": [site_id]})
|
||||
assert delete_resp.status_code == 200
|
||||
|
||||
|
||||
def test_admin_enrollment_code_flow(engine_harness: EngineTestHarness) -> None:
|
||||
client = _client_with_admin_session(engine_harness)
|
||||
create_resp = client.post(
|
||||
"/api/admin/enrollment-codes",
|
||||
json={"ttl_hours": 1, "max_uses": 2},
|
||||
)
|
||||
assert create_resp.status_code == 201
|
||||
code_id = create_resp.get_json()["id"]
|
||||
|
||||
list_resp = client.get("/api/admin/enrollment-codes")
|
||||
codes = list_resp.get_json()["codes"]
|
||||
assert any(code["id"] == code_id for code in codes)
|
||||
|
||||
delete_resp = client.delete(f"/api/admin/enrollment-codes/{code_id}")
|
||||
assert delete_resp.status_code == 200
|
||||
|
||||
|
||||
def test_admin_device_approvals(engine_harness: EngineTestHarness) -> None:
|
||||
client = _client_with_admin_session(engine_harness)
|
||||
list_resp = client.get("/api/admin/device-approvals")
|
||||
approvals = list_resp.get_json()["approvals"]
|
||||
assert approvals and approvals[0]["status"] == "pending"
|
||||
|
||||
approve_resp = client.post(
|
||||
"/api/admin/device-approvals/approval-1/approve",
|
||||
json={"conflict_resolution": "overwrite"},
|
||||
)
|
||||
assert approve_resp.status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user