edgee_sdk/token.rs
1/// Generates a token from a hostname.
2///
3/// This function generates a token by computing the MD5 hash of the provided hostname
4/// and formatting it as a lowercase hexadecimal string.
5///
6/// # Arguments
7///
8/// * `hostname` - A string slice containing the hostname to generate a token for
9///
10/// # Returns
11///
12/// * `String` - The generated token as a 32-character lowercase hexadecimal string
13///
14/// # Examples
15///
16/// ```
17/// let hostname = "example.com";
18/// let token = edgee_sdk::token::generate(hostname);
19/// assert_eq!(token.len(), 32);
20/// ```
21pub fn generate(hostname: &str) -> String {
22 format!("{:x}", md5::compute(hostname))
23}
24
25/// Validates a token from an authorization header against a hostname.
26///
27/// This function checks if a given authorization header contains a valid token for the specified hostname.
28/// The token must be in the format "Bearer <token>" where <token> is a 32-character MD5 hash of the hostname.
29///
30/// # Arguments
31///
32/// * `hostname` - A string slice containing the hostname to validate against
33/// * `authorization_header` - A string slice containing the full authorization header value
34///
35/// # Returns
36///
37/// * `bool` - Returns true if the token is valid for the hostname, false otherwise
38///
39/// # Examples
40///
41/// ```
42/// let hostname = "example.com";
43/// let auth_header = "Bearer d41d8cd98f00b204e9800998ecf8427e";
44/// let is_valid = edgee_sdk::token::validate(hostname, auth_header);
45/// ```
46pub fn validate(hostname: &str, authorization_header: &str) -> bool {
47 if !authorization_header.starts_with("Bearer ") {
48 return false;
49 }
50
51 let token = &authorization_header["Bearer ".len()..];
52
53 if token.len() != 32 {
54 return false;
55 }
56
57 let token_md5 = format!("{:x}", md5::compute(hostname));
58
59 token == token_md5
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_generate_token() {
68 let hostname = "example.com";
69 let token = generate(hostname);
70
71 // Check token length
72 assert_eq!(token.len(), 32);
73
74 // Check deterministic output
75 assert_eq!(generate(hostname), generate(hostname));
76
77 // Known value test
78 assert_eq!(
79 generate("test.com"),
80 "c97c1b3671fef2055e175ca2154d217a".to_string()
81 );
82 }
83
84 #[test]
85 fn test_validate_token() {
86 let hostname = "example.com";
87 let token = generate(hostname);
88 let valid_header = format!("Bearer {}", token);
89
90 // Test valid token
91 assert!(validate(hostname, &valid_header));
92
93 // Test invalid bearer format
94 assert!(!validate(hostname, &token));
95 assert!(!validate(hostname, "bearer 123"));
96 assert!(!validate(hostname, "Basic 123"));
97 assert!(!validate(hostname, ""));
98
99 // Test invalid token length
100 assert!(!validate(hostname, "Bearer 123"));
101 assert!(!validate(
102 hostname,
103 "Bearer 123456789012345678901234567890123"
104 )); // 33 chars
105
106 // Test wrong token
107 assert!(!validate(
108 hostname,
109 "Bearer 0000000000000000000000000000000"
110 ));
111
112 // Test different hostname
113 let other_token = generate("other.com");
114 assert!(!validate(hostname, &format!("Bearer {}", other_token)));
115 }
116}