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

0xmichalis / nftbk / 18659805528

20 Oct 2025 05:25PM UTC coverage: 37.563% (+1.5%) from 36.045%
18659805528

push

github

0xmichalis
chore: more log cleanup

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

129 existing lines in 4 files now uncovered.

1714 of 4563 relevant lines covered (37.56%)

7.05 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!(
NEW
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✔
NEW
62
                info!("Loaded x402 config (facilitator: {})", cfg.facilitator.url);
×
63
                Some(cfg)
64
            }
65
            Err(e) => {
1✔
66
                return Err(format!(
2✔
67
                    "Failed to compile x402 config from '{}': {}",
2✔
68
                    config_path.display(),
1✔
69
                    e
1✔
70
                ));
71
            }
72
        }
73
    } else {
74
        None
5✔
75
    };
76

77
    Ok(AuthConfig {
78
        jwt_credentials,
79
        x402_config,
80
    })
81
}
82

83
#[cfg(test)]
84
mod load_auth_config_tests {
85
    use super::*;
86
    use std::io::Write;
87
    use tempfile::NamedTempFile;
88

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

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

105
        let result = load_auth_config(temp_file.path());
106
        assert!(result.is_ok());
107

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

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

124
[[jwt]]
125
issuer = "issuer2"
126
audience = "audience2"
127
verification_key = "key2"
128
"#;
129
        let temp_file = create_temp_config(config_content);
130

131
        let result = load_auth_config(temp_file.path());
132
        assert!(result.is_ok());
133

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

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

150
        let result = load_auth_config(temp_file.path());
151
        assert!(result.is_ok());
152

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

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

170
[x402]
171
asset_symbol = "USDC"
172
base_url = "http://localhost:8080/"
173
recipient_address = "0x1234567890123456789012345678901234567890"
174
max_timeout_seconds = 300
175

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

182
        let result = load_auth_config(temp_file.path());
183
        assert!(result.is_ok());
184

185
        let auth_config = result.unwrap();
186
        assert_eq!(auth_config.jwt_credentials.len(), 1);
187
        assert!(auth_config.x402_config.is_some());
188
    }
189

190
    #[test]
191
    fn handles_empty_jwt_section() {
192
        let config_content = r#"
193
jwt = []
194
"#;
195
        let temp_file = create_temp_config(config_content);
196

197
        let result = load_auth_config(temp_file.path());
198
        assert!(result.is_ok());
199

200
        let auth_config = result.unwrap();
201
        assert_eq!(auth_config.jwt_credentials.len(), 0);
202
        assert!(auth_config.x402_config.is_none());
203
    }
204

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

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

220
        let result = load_auth_config(temp_file.path());
221
        assert!(result.is_ok());
222

223
        let auth_config = result.unwrap();
224
        assert_eq!(auth_config.jwt_credentials.len(), 0);
225
        assert!(auth_config.x402_config.is_some());
226
    }
227

228
    #[test]
229
    fn handles_empty_config_file() {
230
        let config_content = "";
231
        let temp_file = create_temp_config(config_content);
232

233
        let result = load_auth_config(temp_file.path());
234
        assert!(result.is_ok());
235

236
        let auth_config = result.unwrap();
237
        assert_eq!(auth_config.jwt_credentials.len(), 0);
238
        assert!(auth_config.x402_config.is_none());
239
    }
240

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

245
        let result = load_auth_config(nonexistent_path);
246
        assert!(result.is_err());
247

248
        let error = result.unwrap_err();
249
        assert!(error.contains("Failed to read auth config file"));
250
    }
251

252
    #[test]
253
    fn returns_error_for_invalid_toml() {
254
        let config_content = "invalid toml content {";
255
        let temp_file = create_temp_config(config_content);
256

257
        let result = load_auth_config(temp_file.path());
258
        assert!(result.is_err());
259

260
        let error = result.unwrap_err();
261
        assert!(error.contains("Failed to parse auth config file"));
262
    }
263

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

272
[x402]
273
asset_symbol = "USDC"
274
base_url = "http://localhost:8080/"
275
recipient_address = "0x1234567890123456789012345678901234567890"
276
max_timeout_seconds = 300
277

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

284
        let result = load_auth_config(temp_file.path());
285
        assert!(result.is_err());
286

287
        let error = result.unwrap_err();
288
        assert!(error.contains("Failed to compile x402 config"));
289
    }
290

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

300
        let result = load_auth_config(temp_file.path());
301
        assert!(result.is_err());
302

303
        let error = result.unwrap_err();
304
        assert!(error.contains("Failed to parse auth config file"));
305
    }
306
}
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

© 2025 Coveralls, Inc