• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

0xmichalis / nftbk / 18683453038

21 Oct 2025 12:14PM UTC coverage: 40.026% (+0.3%) from 39.734%
18683453038

push

github

0xmichalis
chore: log network on x402 config load

0 of 1 new or added line in 1 file covered. (0.0%)

19 existing lines in 2 files now uncovered.

1846 of 4612 relevant lines covered (40.03%)

7.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/src/server/auth/mod.rs
1
pub mod jwt;
2
pub mod x402;
3

4
use std::path::Path;
5
use toml;
6
use tracing::info;
7

8
use crate::server::auth::x402::{X402Config, X402ConfigRaw};
9

10
#[derive(serde::Deserialize, Clone, Debug)]
11
pub struct JwtCredential {
12
    pub issuer: String,
13
    pub audience: String,
14
    pub verification_key: String,
15
}
16

17
#[derive(serde::Deserialize)]
18
struct AuthFile {
19
    #[serde(default)]
20
    jwt: Vec<JwtCredential>,
21
    #[serde(default)]
22
    x402: Option<X402ConfigRaw>,
23
}
24

25
#[derive(Debug)]
26
pub struct AuthConfig {
27
    pub jwt_credentials: Vec<JwtCredential>,
28
    pub x402_config: Option<X402Config>,
29
}
30

31
pub fn load_auth_config(config_path: &Path) -> Result<AuthConfig, String> {
11✔
32
    let contents = std::fs::read_to_string(config_path).map_err(|e| {
44✔
33
        format!(
1✔
34
            "Failed to read auth config file '{}': {}",
1✔
35
            config_path.display(),
2✔
36
            e
37
        )
38
    })?;
39

40
    let mut file: AuthFile = toml::from_str(&contents).map_err(|e| {
10✔
41
        format!(
2✔
42
            "Failed to parse auth config file '{}': {}",
2✔
43
            config_path.display(),
4✔
44
            e
45
        )
46
    })?;
47

48
    let mut jwt_credentials: Vec<JwtCredential> = Vec::new();
49
    for cred in file.jwt.drain(..) {
6✔
50
        let mut normalized = cred.clone();
51
        normalized.verification_key = normalized.verification_key.replace("\\n", "\n");
52
        jwt_credentials.push(normalized.clone());
53
        info!(
54
            "Loaded JWT credential set (issuer: {}, audience: {})",
×
55
            normalized.issuer, normalized.audience
56
        );
57
    }
58

59
    let x402_config = if let Some(raw) = file.x402.take() {
10✔
60
        match X402Config::compile(raw) {
61
            Ok(cfg) => {
2✔
62
                info!(
NEW
63
                    "Loaded x402 config (network: {}, facilitator: {})",
×
64
                    cfg.facilitator.network, cfg.facilitator.url
65
                );
66
                Some(cfg)
67
            }
68
            Err(e) => {
1✔
69
                return Err(format!(
2✔
70
                    "Failed to compile x402 config from '{}': {}",
2✔
71
                    config_path.display(),
1✔
72
                    e
1✔
73
                ));
74
            }
75
        }
76
    } else {
77
        None
5✔
78
    };
79

80
    Ok(AuthConfig {
81
        jwt_credentials,
82
        x402_config,
83
    })
84
}
85

86
#[cfg(test)]
87
mod load_auth_config_tests {
88
    use super::*;
89
    use std::io::Write;
90
    use tempfile::NamedTempFile;
91

92
    fn create_temp_config(content: &str) -> NamedTempFile {
93
        let mut file = NamedTempFile::new().unwrap();
94
        write!(file, "{}", content).unwrap();
95
        file
96
    }
97

98
    #[test]
99
    fn loads_jwt_credentials_successfully() {
100
        let config_content = r#"
101
[[jwt]]
102
issuer = "test-issuer"
103
audience = "test-audience"
104
verification_key = "test-key"
105
"#;
106
        let temp_file = create_temp_config(config_content);
107

108
        let result = load_auth_config(temp_file.path());
109
        assert!(result.is_ok());
110

111
        let auth_config = result.unwrap();
112
        assert_eq!(auth_config.jwt_credentials.len(), 1);
113
        assert_eq!(auth_config.jwt_credentials[0].issuer, "test-issuer");
114
        assert_eq!(auth_config.jwt_credentials[0].audience, "test-audience");
115
        assert_eq!(auth_config.jwt_credentials[0].verification_key, "test-key");
116
        assert!(auth_config.x402_config.is_none());
117
    }
118

119
    #[test]
120
    fn loads_multiple_jwt_credentials() {
121
        let config_content = r#"
122
[[jwt]]
123
issuer = "issuer1"
124
audience = "audience1"
125
verification_key = "key1"
126

127
[[jwt]]
128
issuer = "issuer2"
129
audience = "audience2"
130
verification_key = "key2"
131
"#;
132
        let temp_file = create_temp_config(config_content);
133

134
        let result = load_auth_config(temp_file.path());
135
        assert!(result.is_ok());
136

137
        let auth_config = result.unwrap();
138
        assert_eq!(auth_config.jwt_credentials.len(), 2);
139
        assert_eq!(auth_config.jwt_credentials[0].issuer, "issuer1");
140
        assert_eq!(auth_config.jwt_credentials[1].issuer, "issuer2");
141
    }
142

143
    #[test]
144
    fn normalizes_verification_key_newlines() {
145
        let config_content = r#"
146
[[jwt]]
147
issuer = "test-issuer"
148
audience = "test-audience"
149
verification_key = "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\n-----END PUBLIC KEY-----"
150
"#;
151
        let temp_file = create_temp_config(config_content);
152

153
        let result = load_auth_config(temp_file.path());
154
        assert!(result.is_ok());
155

156
        let auth_config = result.unwrap();
157
        assert!(auth_config.jwt_credentials[0]
158
            .verification_key
159
            .contains('\n'));
160
        assert!(!auth_config.jwt_credentials[0]
161
            .verification_key
162
            .contains("\\n"));
163
    }
164

165
    #[test]
166
    fn loads_x402_config_successfully() {
167
        let config_content = r#"
168
[[jwt]]
169
issuer = "test-issuer"
170
audience = "test-audience"
171
verification_key = "test-key"
172

173
[x402]
174
asset_symbol = "USDC"
175
base_url = "http://localhost:8080/"
176
recipient_address = "0x1234567890123456789012345678901234567890"
177
max_timeout_seconds = 300
178

179
[x402.facilitator]
180
url = "https://x402.org/facilitator"
181
network = "base-sepolia"
182
"#;
183
        let temp_file = create_temp_config(config_content);
184

185
        let result = load_auth_config(temp_file.path());
186
        assert!(result.is_ok());
187

188
        let auth_config = result.unwrap();
189
        assert_eq!(auth_config.jwt_credentials.len(), 1);
190
        assert!(auth_config.x402_config.is_some());
191
    }
192

193
    #[test]
194
    fn handles_empty_jwt_section() {
195
        let config_content = r#"
196
jwt = []
197
"#;
198
        let temp_file = create_temp_config(config_content);
199

200
        let result = load_auth_config(temp_file.path());
201
        assert!(result.is_ok());
202

203
        let auth_config = result.unwrap();
204
        assert_eq!(auth_config.jwt_credentials.len(), 0);
205
        assert!(auth_config.x402_config.is_none());
206
    }
207

208
    #[test]
209
    fn handles_missing_jwt_section() {
210
        let config_content = r#"
211
[x402]
212
asset_symbol = "USDC"
213
base_url = "http://localhost:8080/"
214
recipient_address = "0x1234567890123456789012345678901234567890"
215
max_timeout_seconds = 300
216

217
[x402.facilitator]
218
url = "https://x402.org/facilitator"
219
network = "base-sepolia"
220
"#;
221
        let temp_file = create_temp_config(config_content);
222

223
        let result = load_auth_config(temp_file.path());
224
        assert!(result.is_ok());
225

226
        let auth_config = result.unwrap();
227
        assert_eq!(auth_config.jwt_credentials.len(), 0);
228
        assert!(auth_config.x402_config.is_some());
229
    }
230

231
    #[test]
232
    fn handles_empty_config_file() {
233
        let config_content = "";
234
        let temp_file = create_temp_config(config_content);
235

236
        let result = load_auth_config(temp_file.path());
237
        assert!(result.is_ok());
238

239
        let auth_config = result.unwrap();
240
        assert_eq!(auth_config.jwt_credentials.len(), 0);
241
        assert!(auth_config.x402_config.is_none());
242
    }
243

244
    #[test]
245
    fn returns_error_for_nonexistent_file() {
246
        let nonexistent_path = std::path::Path::new("/nonexistent/path/config.toml");
247

248
        let result = load_auth_config(nonexistent_path);
249
        assert!(result.is_err());
250

251
        let error = result.unwrap_err();
252
        assert!(error.contains("Failed to read auth config file"));
253
    }
254

255
    #[test]
256
    fn returns_error_for_invalid_toml() {
257
        let config_content = "invalid toml content {";
258
        let temp_file = create_temp_config(config_content);
259

260
        let result = load_auth_config(temp_file.path());
261
        assert!(result.is_err());
262

263
        let error = result.unwrap_err();
264
        assert!(error.contains("Failed to parse auth config file"));
265
    }
266

267
    #[test]
268
    fn returns_error_for_invalid_x402_config() {
269
        let config_content = r#"
270
[[jwt]]
271
issuer = "test-issuer"
272
audience = "test-audience"
273
verification_key = "test-key"
274

275
[x402]
276
asset_symbol = "USDC"
277
base_url = "http://localhost:8080/"
278
recipient_address = "0x1234567890123456789012345678901234567890"
279
max_timeout_seconds = 300
280

281
[x402.facilitator]
282
url = "https://x402.org/facilitator"
283
network = "invalid-network"
284
"#;
285
        let temp_file = create_temp_config(config_content);
286

287
        let result = load_auth_config(temp_file.path());
288
        assert!(result.is_err());
289

290
        let error = result.unwrap_err();
291
        assert!(error.contains("Failed to compile x402 config"));
292
    }
293

294
    #[test]
295
    fn handles_missing_required_jwt_fields() {
296
        let config_content = r#"
297
[[jwt]]
298
issuer = "test-issuer"
299
# Missing audience and verification_key
300
"#;
301
        let temp_file = create_temp_config(config_content);
302

303
        let result = load_auth_config(temp_file.path());
304
        assert!(result.is_err());
305

306
        let error = result.unwrap_err();
307
        assert!(error.contains("Failed to parse auth config file"));
308
    }
309
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc