Skip to main content

aster_forge_config/
avatar.rs

1//! Gravatar configuration helpers.
2//!
3//! This module owns the configuration-facing parts of Gravatar handling:
4//! normalization of the stored base URL and runtime fallback to the conventional
5//! default base URL. Product crates still own avatar source policy, upload
6//! routes, cache headers, and which sizes they expose.
7
8use crate::{ConfigCoreError, Result};
9
10use aster_forge_utils::url::{HttpBaseUrlOptions, normalize_http_base_url};
11
12/// Default Gravatar base URL used by Aster services.
13pub const DEFAULT_GRAVATAR_BASE_URL: &str = "https://www.gravatar.com/avatar";
14
15/// Normalizes a Gravatar base URL configuration value.
16///
17/// Empty values fall back to [`DEFAULT_GRAVATAR_BASE_URL`]. Non-empty values
18/// must be absolute HTTP(S) base URLs without query or fragment components.
19pub fn normalize_gravatar_base_url_config_value(value: &str) -> Result<String> {
20    normalize_http_base_url(
21        value,
22        "gravatar_base_url",
23        HttpBaseUrlOptions::optional_without_query_fragment(),
24    )
25    .map_err(|error| ConfigCoreError::invalid_value(error.to_string()))
26    .map(|normalized| normalized.unwrap_or_else(|| DEFAULT_GRAVATAR_BASE_URL.to_string()))
27}
28
29/// Returns a normalized Gravatar base URL or [`DEFAULT_GRAVATAR_BASE_URL`].
30pub fn gravatar_base_url_or_default(value: Option<&str>) -> String {
31    let normalized = value
32        .unwrap_or(DEFAULT_GRAVATAR_BASE_URL)
33        .trim()
34        .trim_end_matches('/')
35        .to_string();
36    if normalized.is_empty() {
37        DEFAULT_GRAVATAR_BASE_URL.to_string()
38    } else {
39        normalized
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::{
46        DEFAULT_GRAVATAR_BASE_URL, gravatar_base_url_or_default,
47        normalize_gravatar_base_url_config_value,
48    };
49
50    #[test]
51    fn gravatar_base_url_normalization_accepts_empty_and_http_base_urls() {
52        assert_eq!(
53            normalize_gravatar_base_url_config_value("  ").unwrap(),
54            DEFAULT_GRAVATAR_BASE_URL
55        );
56        assert_eq!(
57            normalize_gravatar_base_url_config_value(" https://mirror.example/avatar/ ").unwrap(),
58            "https://mirror.example/avatar"
59        );
60        assert!(normalize_gravatar_base_url_config_value("ftp://example.com/avatar").is_err());
61        assert!(
62            normalize_gravatar_base_url_config_value("https://example.com/avatar?x=1").is_err()
63        );
64        assert!(
65            normalize_gravatar_base_url_config_value("https://example.com/avatar#frag").is_err()
66        );
67    }
68
69    #[test]
70    fn gravatar_base_url_reader_defaults_blank_values() {
71        assert_eq!(
72            gravatar_base_url_or_default(None),
73            DEFAULT_GRAVATAR_BASE_URL
74        );
75        assert_eq!(
76            gravatar_base_url_or_default(Some("   ")),
77            DEFAULT_GRAVATAR_BASE_URL
78        );
79        assert_eq!(
80            gravatar_base_url_or_default(Some("https://mirror.example/avatar/")),
81            "https://mirror.example/avatar"
82        );
83    }
84}