backend/service/
application_settings.rs

1//! Service layer for [`ApplicationSetting`].
2
3use crate::error::ServiceError;
4use crate::model::dto::ApplicationSettingDto;
5use crate::model::entity::ApplicationSetting;
6use diesel_async::AsyncPgConnection;
7use reqwest::StatusCode;
8
9/// RGB value of one color
10type Rgb = (u8, u8, u8);
11
12/// RGB values of all four heatmap colors (red, orange, green, black)
13pub type HeatmapColors = (Rgb, Rgb, Rgb, Rgb);
14
15/// Find an application setting by key
16///
17/// # Errors
18/// If the connection to the database could not be established.
19/// If no application setting with the key `key` exists.
20pub async fn find_by_key(
21    key: &str,
22    conn: &mut AsyncPgConnection,
23) -> Result<ApplicationSettingDto, ServiceError> {
24    let result = ApplicationSetting::find_by_key(key, conn).await?;
25    Ok(result)
26}
27
28/// Convert a hex color code to RGB.
29/// Hex code must be 6 characters long (case-insensitive).
30///
31/// # Errors
32/// If the hex code is not 6 characters long.
33/// If the hex code is not valid.
34pub fn hex_to_rgb(hex: &str) -> Result<(u8, u8, u8), ServiceError> {
35    let error_msg = "Invalid heatmap color hex code";
36    if hex.len() != 6 {
37        return Err(ServiceError::new(
38            StatusCode::INTERNAL_SERVER_ERROR,
39            error_msg,
40        ));
41    }
42
43    let red_slice = hex.get(0..2);
44    let red = match red_slice {
45        Some(red) => u8::from_str_radix(red, 16)
46            .map_err(|_| ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, error_msg))?,
47        None => {
48            return Err(ServiceError::new(
49                StatusCode::INTERNAL_SERVER_ERROR,
50                error_msg,
51            ));
52        }
53    };
54
55    let green_slice = hex.get(2..4);
56    let green = match green_slice {
57        Some(green) => u8::from_str_radix(green, 16)
58            .map_err(|_| ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, error_msg))?,
59        None => {
60            return Err(ServiceError::new(
61                StatusCode::INTERNAL_SERVER_ERROR,
62                error_msg,
63            ));
64        }
65    };
66
67    let blue_slice = hex.get(4..6);
68    let blue = match blue_slice {
69        Some(blue) => u8::from_str_radix(blue, 16)
70            .map_err(|_| ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, error_msg))?,
71        None => {
72            return Err(ServiceError::new(
73                StatusCode::INTERNAL_SERVER_ERROR,
74                error_msg,
75            ));
76        }
77    };
78
79    Ok((red, green, blue))
80}
81
82/// Get all four heatmap colors (red, orange, green, black) from the application settings.
83///
84/// # Errors
85/// If the connection to the database could not be established.
86/// If the colors in the database are not valid hex codes.
87/// If there are no colors in the database.
88pub async fn get_heatmap_colors(
89    conn: &mut AsyncPgConnection,
90) -> Result<HeatmapColors, ServiceError> {
91    let red_hex = find_by_key("heatmap_red", conn).await?;
92    let orange_hex = find_by_key("heatmap_orange", conn).await?;
93    let green_hex = find_by_key("heatmap_green", conn).await?;
94    let black_hex = find_by_key("heatmap_black", conn).await?;
95
96    let red = hex_to_rgb(&red_hex.value)?;
97    let orange = hex_to_rgb(&orange_hex.value)?;
98    let green = hex_to_rgb(&green_hex.value)?;
99    let black = hex_to_rgb(&black_hex.value)?;
100
101    Ok((red, orange, green, black))
102}