upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs74
1 files changed, 26 insertions, 48 deletions
diff --git a/src/config.rs b/src/config.rs
index 271a340..dd7b1e3 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -109,22 +109,25 @@ impl WhitelistEntry {
109} 109}
110 110
111/// GRASP-05 Archive mode configuration 111/// GRASP-05 Archive mode configuration
112#[derive(Debug, Clone, Serialize, Deserialize)] 112#[derive(Debug, Clone, Serialize, Deserialize, Default)]
113pub struct ArchiveConfig { 113pub struct ArchiveConfig {
114 /// Accept all repository announcements (no filtering) 114 /// Accept all repository announcements (no filtering)
115 /// 115 ///
116 /// WARNING: Setting this to true allows anyone to mirror any repository 116 /// WARNING: Setting this to true allows anyone to mirror any repository
117 /// to this relay, potentially causing storage/bandwidth exhaustion. 117 /// to this relay, potentially causing storage/bandwidth exhaustion.
118 #[serde(default)]
118 pub archive_all: bool, 119 pub archive_all: bool,
119 120
120 /// Whitelist entries for selective archiving 121 /// Whitelist entries for selective archiving
121 /// 122 ///
122 /// If empty and archive_all is false, GRASP-05 is disabled (GRASP-01 strict mode). 123 /// If empty and archive_all is false, GRASP-05 is disabled (GRASP-01 strict mode).
124 #[serde(default)]
123 pub whitelist: Vec<WhitelistEntry>, 125 pub whitelist: Vec<WhitelistEntry>,
124 126
125 /// GRASP server domains to archive (archive all repositories from these domains) 127 /// GRASP server domains to archive (archive all repositories from these domains)
126 /// 128 ///
127 /// If non-empty, archives all repositories from the specified GRASP server domains. 129 /// If non-empty, archives all repositories from the specified GRASP server domains.
130 #[serde(default)]
128 pub grasp_services: Vec<String>, 131 pub grasp_services: Vec<String>,
129 132
130 /// Read-only archive mode: relay is a read-only sync of archived repositories 133 /// Read-only archive mode: relay is a read-only sync of archived repositories
@@ -132,6 +135,7 @@ pub struct ArchiveConfig {
132 /// When true, the relay ONLY accepts announcements matching the archive whitelist/all. 135 /// When true, the relay ONLY accepts announcements matching the archive whitelist/all.
133 /// Announcements listing the relay but not in the whitelist are rejected. 136 /// Announcements listing the relay but not in the whitelist are rejected.
134 /// When false, the relay operates in GRASP-01 mode for unwhitelisted repos. 137 /// When false, the relay operates in GRASP-01 mode for unwhitelisted repos.
138 #[serde(default)]
135 pub read_only: bool, 139 pub read_only: bool,
136} 140}
137 141
@@ -146,6 +150,7 @@ impl ArchiveConfig {
146 /// Returns true if: 150 /// Returns true if:
147 /// - archive_all is true, OR 151 /// - archive_all is true, OR
148 /// - announcement matches any whitelist entry 152 /// - announcement matches any whitelist entry
153 ///
149 /// Note: grasp_services matching is handled via matches_grasp_services() 154 /// Note: grasp_services matching is handled via matches_grasp_services()
150 pub fn matches(&self, npub: &str, identifier: &str) -> bool { 155 pub fn matches(&self, npub: &str, identifier: &str) -> bool {
151 if self.archive_all { 156 if self.archive_all {
@@ -171,23 +176,13 @@ impl ArchiveConfig {
171 } 176 }
172} 177}
173 178
174impl Default for ArchiveConfig {
175 fn default() -> Self {
176 Self {
177 archive_all: false,
178 whitelist: Vec::new(),
179 grasp_services: Vec::new(),
180 read_only: false,
181 }
182 }
183}
184
185/// Repository whitelist configuration 179/// Repository whitelist configuration
186#[derive(Debug, Clone, Serialize, Deserialize)] 180#[derive(Debug, Clone, Serialize, Deserialize, Default)]
187pub struct RepositoryConfig { 181pub struct RepositoryConfig {
188 /// Whitelist entries for selective repository acceptance 182 /// Whitelist entries for selective repository acceptance
189 /// 183 ///
190 /// If empty, all repositories listing the service are accepted (GRASP-01 mode). 184 /// If empty, all repositories listing the service are accepted (GRASP-01 mode).
185 #[serde(default)]
191 pub whitelist: Vec<WhitelistEntry>, 186 pub whitelist: Vec<WhitelistEntry>,
192} 187}
193 188
@@ -207,21 +202,14 @@ impl RepositoryConfig {
207 } 202 }
208} 203}
209 204
210impl Default for RepositoryConfig {
211 fn default() -> Self {
212 Self {
213 whitelist: Vec::new(),
214 }
215 }
216}
217
218/// Repository blacklist configuration 205/// Repository blacklist configuration
219#[derive(Debug, Clone, Serialize, Deserialize)] 206#[derive(Debug, Clone, Serialize, Deserialize, Default)]
220pub struct BlacklistConfig { 207pub struct BlacklistConfig {
221 /// Blacklist entries for blocking specific repositories 208 /// Blacklist entries for blocking specific repositories
222 /// 209 ///
223 /// If empty, no repositories are blacklisted. 210 /// If empty, no repositories are blacklisted.
224 /// Blacklist takes precedence over both archive and repository whitelists. 211 /// Blacklist takes precedence over both archive and repository whitelists.
212 #[serde(default)]
225 pub blacklist: Vec<WhitelistEntry>, 213 pub blacklist: Vec<WhitelistEntry>,
226} 214}
227 215
@@ -256,21 +244,14 @@ impl BlacklistConfig {
256 } 244 }
257} 245}
258 246
259impl Default for BlacklistConfig {
260 fn default() -> Self {
261 Self {
262 blacklist: Vec::new(),
263 }
264 }
265}
266
267/// Event blacklist configuration for blocking events by author npub 247/// Event blacklist configuration for blocking events by author npub
268#[derive(Debug, Clone, Serialize, Deserialize)] 248#[derive(Debug, Clone, Serialize, Deserialize, Default)]
269pub struct EventBlacklistConfig { 249pub struct EventBlacklistConfig {
270 /// Blacklisted npubs - events from these authors are rejected 250 /// Blacklisted npubs - events from these authors are rejected
271 /// 251 ///
272 /// If empty, no events are blacklisted by author. 252 /// If empty, no events are blacklisted by author.
273 /// Applies to ALL event types, preventing events from reaching both the relay and purgatory. 253 /// Applies to ALL event types, preventing events from reaching both the relay and purgatory.
254 #[serde(default)]
274 pub blacklisted_npubs: Vec<String>, 255 pub blacklisted_npubs: Vec<String>,
275} 256}
276 257
@@ -292,14 +273,6 @@ impl EventBlacklistConfig {
292 } 273 }
293} 274}
294 275
295impl Default for EventBlacklistConfig {
296 fn default() -> Self {
297 Self {
298 blacklisted_npubs: Vec::new(),
299 }
300 }
301}
302
303/// Database backend type for the relay 276/// Database backend type for the relay
304#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default, ValueEnum)] 277#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default, ValueEnum)]
305#[serde(rename_all = "lowercase")] 278#[serde(rename_all = "lowercase")]
@@ -500,6 +473,10 @@ pub struct Config {
500 /// Prevents connection exhaustion DoS attacks 473 /// Prevents connection exhaustion DoS attacks
501 #[arg(long, env = "NGIT_MAX_CONNECTIONS", default_value_t = 4096)] 474 #[arg(long, env = "NGIT_MAX_CONNECTIONS", default_value_t = 4096)]
502 pub max_connections: usize, 475 pub max_connections: usize,
476
477 /// Log level for application logging
478 #[arg(long, env = "NGIT_LOG_LEVEL", default_value = "info")]
479 pub log_level: String,
503} 480}
504 481
505impl Config { 482impl Config {
@@ -782,6 +759,7 @@ impl Config {
782 repository_blacklist: String::new(), 759 repository_blacklist: String::new(),
783 event_blacklist: String::new(), 760 event_blacklist: String::new(),
784 max_connections: 500, 761 max_connections: 500,
762 log_level: "debug".to_string(),
785 } 763 }
786 } 764 }
787} 765}
@@ -1103,14 +1081,14 @@ mod tests {
1103 fn test_archive_read_only_defaults() { 1081 fn test_archive_read_only_defaults() {
1104 // Default: false when no archive mode 1082 // Default: false when no archive mode
1105 let config = Config::for_testing(); 1083 let config = Config::for_testing();
1106 assert_eq!(config.archive_config().read_only, false); 1084 assert!(!config.archive_config().read_only);
1107 1085
1108 // Default: true when archive_all is set 1086 // Default: true when archive_all is set
1109 let config = Config { 1087 let config = Config {
1110 archive_all: true, 1088 archive_all: true,
1111 ..Config::for_testing() 1089 ..Config::for_testing()
1112 }; 1090 };
1113 assert_eq!(config.archive_config().read_only, true); 1091 assert!(config.archive_config().read_only);
1114 1092
1115 // Default: true when archive_whitelist is set 1093 // Default: true when archive_whitelist is set
1116 let keys = Keys::generate(); 1094 let keys = Keys::generate();
@@ -1119,7 +1097,7 @@ mod tests {
1119 archive_whitelist: test_npub, 1097 archive_whitelist: test_npub,
1120 ..Config::for_testing() 1098 ..Config::for_testing()
1121 }; 1099 };
1122 assert_eq!(config.archive_config().read_only, true); 1100 assert!(config.archive_config().read_only);
1123 } 1101 }
1124 1102
1125 #[test] 1103 #[test]
@@ -1130,7 +1108,7 @@ mod tests {
1130 archive_read_only: Some(true), 1108 archive_read_only: Some(true),
1131 ..Config::for_testing() 1109 ..Config::for_testing()
1132 }; 1110 };
1133 assert_eq!(config.archive_config().read_only, true); 1111 assert!(config.archive_config().read_only);
1134 1112
1135 // Explicit false with archive_all (unusual but allowed) 1113 // Explicit false with archive_all (unusual but allowed)
1136 let config = Config { 1114 let config = Config {
@@ -1138,14 +1116,14 @@ mod tests {
1138 archive_read_only: Some(false), 1116 archive_read_only: Some(false),
1139 ..Config::for_testing() 1117 ..Config::for_testing()
1140 }; 1118 };
1141 assert_eq!(config.archive_config().read_only, false); 1119 assert!(!config.archive_config().read_only);
1142 1120
1143 // Explicit false without archive mode 1121 // Explicit false without archive mode
1144 let config = Config { 1122 let config = Config {
1145 archive_read_only: Some(false), 1123 archive_read_only: Some(false),
1146 ..Config::for_testing() 1124 ..Config::for_testing()
1147 }; 1125 };
1148 assert_eq!(config.archive_config().read_only, false); 1126 assert!(!config.archive_config().read_only);
1149 } 1127 }
1150 1128
1151 #[test] 1129 #[test]
@@ -1548,7 +1526,7 @@ mod tests {
1548 }; 1526 };
1549 let archive_config = config.archive_config(); 1527 let archive_config = config.archive_config();
1550 assert!(archive_config.enabled()); 1528 assert!(archive_config.enabled());
1551 assert_eq!(archive_config.read_only, true); // Default to true 1529 assert!(archive_config.read_only); // Default to true
1552 } 1530 }
1553 1531
1554 #[test] 1532 #[test]
@@ -1558,7 +1536,7 @@ mod tests {
1558 archive_grasp_services: "git.example.com".to_string(), 1536 archive_grasp_services: "git.example.com".to_string(),
1559 ..Config::for_testing() 1537 ..Config::for_testing()
1560 }; 1538 };
1561 assert_eq!(config.archive_config().read_only, true); 1539 assert!(config.archive_config().read_only);
1562 } 1540 }
1563 1541
1564 #[test] 1542 #[test]
@@ -1569,7 +1547,7 @@ mod tests {
1569 archive_read_only: Some(false), 1547 archive_read_only: Some(false),
1570 ..Config::for_testing() 1548 ..Config::for_testing()
1571 }; 1549 };
1572 assert_eq!(config.archive_config().read_only, false); 1550 assert!(!config.archive_config().read_only);
1573 } 1551 }
1574 1552
1575 #[test] 1553 #[test]