milestone 21: abp list exceptions and a regex rule kind
This commit is contained in:
+32
-8
@@ -1,6 +1,9 @@
|
||||
//! The one configuration model. Bootstrap, import, export, the repositories and
|
||||
//! the running server all speak this struct; nothing else describes nxdns
|
||||
//! configuration.
|
||||
//! The one *declarative* configuration model: loading, reconciliation, import,
|
||||
//! export and the running server all speak this struct, and it is the whole
|
||||
//! shape of a config file. It is not the only shape the repositories accept —
|
||||
//! the API edits rows one at a time through narrower inputs such as
|
||||
//! `RuleInput`, `ClientInput` and `ClientEdit`, so a field added here does not
|
||||
//! reach those paths by itself.
|
||||
//!
|
||||
//! Pure: no `std.Io` value is a parameter anywhere, no SQLite, no clock. The
|
||||
//! only `std.Io` types that appear are `std.Io.Duration` as a conversion result.
|
||||
@@ -8,11 +11,21 @@
|
||||
//! Runtime columns are deliberately absent. `clients.first_seen`,
|
||||
//! `clients.last_seen`, `rules.created_at` and
|
||||
//! `blocklist_sources.{last_updated, domain_count, wildcard_count,
|
||||
//! skipped_regex_count, checksum}` are facts a running server produces, not
|
||||
//! configuration. Including them would make two exports taken minutes apart
|
||||
//! differ, which would make the byte-stable round trip untestable against a
|
||||
//! live server. Import sets the timestamps to the import time and leaves the
|
||||
//! counters at their column defaults.
|
||||
//! exception_count, skipped_regex_count, checksum}` are facts a running server
|
||||
//! produces, not configuration. Including them would make two exports taken
|
||||
//! minutes apart differ, which would make the byte-stable round trip untestable
|
||||
//! against a live server.
|
||||
//!
|
||||
//! Declarative configuration reaches the database through exactly one path:
|
||||
//! `config/reconcile.zig`. `nxdns import` is a thin wrapper over it, and so is
|
||||
//! `run --config`. Reconciliation asks what changed rather than replacing
|
||||
//! wholesale, so a row the input still names keeps the runtime state attached
|
||||
//! to it: a source matched by url keeps its id, checksum and counters, a rule
|
||||
//! keeps its `created_at`, and a client keeps its first-seen and last-seen
|
||||
//! stamps. The source id and checksum are the two that decide whether a
|
||||
//! file-mode restart reuses the compiled bodies or downloads them again:
|
||||
//! `loadSource` names the files after the id and accepts them only against the
|
||||
//! stored checksum. The counters ride along as reported state.
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
@@ -256,20 +269,25 @@ pub const BlocklistSource = struct {
|
||||
|
||||
pub const GroupSource = struct { group: []const u8, source_url: []const u8 };
|
||||
|
||||
/// The three spellings `CHECK(kind IN ('exact','wildcard','regex'))` admits
|
||||
/// after migration step 4.
|
||||
pub const RuleKind = enum {
|
||||
exact,
|
||||
wildcard,
|
||||
regex,
|
||||
|
||||
pub fn toDb(self: RuleKind) []const u8 {
|
||||
return switch (self) {
|
||||
.exact => "exact",
|
||||
.wildcard => "wildcard",
|
||||
.regex => "regex",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fromDb(text: []const u8) ?RuleKind {
|
||||
if (std.mem.eql(u8, text, "exact")) return .exact;
|
||||
if (std.mem.eql(u8, text, "wildcard")) return .wildcard;
|
||||
if (std.mem.eql(u8, text, "regex")) return .regex;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -789,6 +807,12 @@ test "every toDb and fromDb enum pair round-trips over all tags" {
|
||||
try expectEnumRoundTrip(RecordType);
|
||||
}
|
||||
|
||||
test "RuleKind carries the third kind through export and import" {
|
||||
try testing.expectEqualStrings("regex", RuleKind.regex.toDb());
|
||||
try testing.expectEqual(RuleKind.regex, RuleKind.fromDb("regex").?);
|
||||
try testing.expect(RuleKind.fromDb("Regex") == null);
|
||||
}
|
||||
|
||||
test "RecordType stores the uppercase DDL spelling" {
|
||||
try testing.expectEqualStrings("A", RecordType.a.toDb());
|
||||
try testing.expectEqualStrings("AAAA", RecordType.aaaa.toDb());
|
||||
|
||||
Reference in New Issue
Block a user