feat(reports): store and browse report artifacts
This commit is contained in:
1 parent
5967a43eb5
commit
6f2e479958
13 files changed
+875
-93
No files matched your search
@@ -47,7 +47,7 @@ class SchemaTest(unittest.TestCase):
|
||||
"blocklist_reasons", "whitelist_entries",
|
||||
"whitelist_sources", "firewall_snapshots",
|
||||
"firewall_address_list_entries", "firewall_rule_entries",
|
||||
"whois_info", "log_sources"):
|
||||
"whois_info", "log_sources", "report_artifacts"):
|
||||
self.assertIn(t, tables, f"missing table {t}")
|
||||
conn.close()
|
||||
|
||||
@@ -195,5 +195,54 @@ class FirewallTest(unittest.TestCase):
|
||||
"SELECT COUNT(*) FROM firewall_rule_entries").fetchone()[0], 1)
|
||||
|
||||
|
||||
class ReportArtifactTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.conn = _new_conn()
|
||||
|
||||
def tearDown(self):
|
||||
self.conn.close()
|
||||
|
||||
def test_artifact_insert_is_idempotent_and_detail_decodes_payload(self):
|
||||
kwargs = {
|
||||
"source": "copyparty", "report_type": "analyzer_summary",
|
||||
"generated_at": "2026-11-01T10:00:00+00:00",
|
||||
"payload": {"summary": {"requests": 12}},
|
||||
"original_path": "reports/copyparty/2026-11-01.txt",
|
||||
"content_sha256": "a" * 64,
|
||||
}
|
||||
first_id = repo.insert_report_artifact(self.conn, **kwargs)
|
||||
duplicate_id = repo.insert_report_artifact(self.conn, **kwargs)
|
||||
|
||||
self.assertEqual(first_id, duplicate_id)
|
||||
self.assertEqual(self.conn.execute(
|
||||
"SELECT COUNT(*) FROM report_artifacts").fetchone()[0], 1)
|
||||
self.assertEqual(repo.get_report_artifact(self.conn, first_id)["payload"],
|
||||
kwargs["payload"])
|
||||
|
||||
def test_artifact_cursor_orders_stably_and_filters_source(self):
|
||||
for day, source in (("01", "npm"), ("02", "copyparty"),
|
||||
("03", "npm")):
|
||||
repo.insert_report_artifact(
|
||||
self.conn, source=source, report_type="summary",
|
||||
generated_at=f"2026-11-{day}T00:00:00+00:00",
|
||||
payload={"day": day}, original_path=f"reports/{day}.txt",
|
||||
content_sha256=day * 64,
|
||||
)
|
||||
|
||||
first = repo.list_report_artifacts(self.conn, source="npm", limit=1)
|
||||
self.assertEqual(len(first["items"]), 1)
|
||||
self.assertIsNotNone(first["next_cursor"])
|
||||
second = repo.list_report_artifacts(
|
||||
self.conn, source="npm", limit=1, cursor=first["next_cursor"])
|
||||
self.assertEqual(len(second["items"]), 1)
|
||||
self.assertIsNone(second["next_cursor"])
|
||||
self.assertGreater(first["items"][0]["generated_at"],
|
||||
second["items"][0]["generated_at"])
|
||||
|
||||
def test_artifact_cursor_rejects_invalid_token(self):
|
||||
with self.assertRaises(ValueError):
|
||||
repo.list_report_artifacts(self.conn, cursor="invalid")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user