Skip to content

Commit 2a3f6f1

Browse files
maltesanderclaude
andcommitted
feat: Add security.properties builder
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent eeeb836 commit 2a3f6f1

1 file changed

Lines changed: 82 additions & 1 deletion

File tree

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,82 @@
1-
//! placeholder — implemented in a later task
1+
//! Builder for `security.properties` (the JVM security properties file).
2+
//!
3+
//! Reproduces the product-config behaviour: `networkaddress.cache.ttl` and
4+
//! `networkaddress.cache.negative.ttl` are `required` properties with recommended
5+
//! values, so they are always emitted; user `security.properties` overrides win.
6+
7+
use std::collections::BTreeMap;
8+
9+
const NETWORKADDRESS_CACHE_TTL: &str = "networkaddress.cache.ttl";
10+
const NETWORKADDRESS_CACHE_NEGATIVE_TTL: &str = "networkaddress.cache.negative.ttl";
11+
12+
const DEFAULT_NETWORKADDRESS_CACHE_TTL: &str = "30";
13+
const DEFAULT_NETWORKADDRESS_CACHE_NEGATIVE_TTL: &str = "0";
14+
15+
/// Build the `security.properties` key/value pairs.
16+
///
17+
/// `overrides` are the resolved user overrides for `security.properties`
18+
/// (highest precedence). Values are wrapped in `Some` for the writer.
19+
pub fn build(overrides: BTreeMap<String, String>) -> BTreeMap<String, Option<String>> {
20+
let mut props: BTreeMap<String, Option<String>> = BTreeMap::new();
21+
22+
// 1. Defaults (recommended values for the required properties).
23+
props.insert(
24+
NETWORKADDRESS_CACHE_TTL.to_string(),
25+
Some(DEFAULT_NETWORKADDRESS_CACHE_TTL.to_string()),
26+
);
27+
props.insert(
28+
NETWORKADDRESS_CACHE_NEGATIVE_TTL.to_string(),
29+
Some(DEFAULT_NETWORKADDRESS_CACHE_NEGATIVE_TTL.to_string()),
30+
);
31+
32+
// 2. No automatic operator-injected values.
33+
// 3. No merged_config contribution.
34+
// 4. User overrides (highest precedence).
35+
for (k, v) in overrides {
36+
props.insert(k, Some(v));
37+
}
38+
39+
props
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use super::*;
45+
46+
#[test]
47+
fn defaults_present_without_overrides() {
48+
let props = build(BTreeMap::new());
49+
assert_eq!(
50+
props.get("networkaddress.cache.ttl"),
51+
Some(&Some("30".to_string()))
52+
);
53+
assert_eq!(
54+
props.get("networkaddress.cache.negative.ttl"),
55+
Some(&Some("0".to_string()))
56+
);
57+
}
58+
59+
#[test]
60+
fn user_override_wins() {
61+
let overrides = [("networkaddress.cache.ttl".to_string(), "60".to_string())]
62+
.into_iter()
63+
.collect();
64+
let props = build(overrides);
65+
assert_eq!(
66+
props.get("networkaddress.cache.ttl"),
67+
Some(&Some("60".to_string()))
68+
);
69+
}
70+
71+
#[test]
72+
fn extra_user_override_key_is_added() {
73+
let overrides = [("custom.security.prop".to_string(), "x".to_string())]
74+
.into_iter()
75+
.collect();
76+
let props = build(overrides);
77+
assert_eq!(
78+
props.get("custom.security.prop"),
79+
Some(&Some("x".to_string()))
80+
);
81+
}
82+
}

0 commit comments

Comments
 (0)