diff --git a/config.yaml b/config.yaml index abe37c0..e64350b 100644 --- a/config.yaml +++ b/config.yaml @@ -76,6 +76,26 @@ rtc-relay: # Admin URL admin-url: http://localhost:3001 +# Global banner. It can be used to notify about an upcoming maintenance operation for example +banner: + # Specify whether the banner should be shown or not + enabled: true + + # Optional expiration time for the banner. Set to 0 to show the message forever + expire: 1641801081 + + # Nature of the banner. It can be either "information", "warning", "success" + nature: warning + + # The message of the banner, available in different languages + message: + fr: Une maintenance planifiée va provoquer une interruption de service de quelques minutes. + en: A planned maintenance will provoke a short unavailability of the service. + + # Optional URL to "learn more" about the message. Leave an empty value to disable + link: https://about.communiquons.org/ + + # List of #Forez groups # # This option allows to enable some extra features for these groups diff --git a/src/api_data/server_config.rs b/src/api_data/server_config.rs index 1037495..c701161 100644 --- a/src/api_data/server_config.rs +++ b/src/api_data/server_config.rs @@ -7,7 +7,7 @@ use crate::constants::{conservation_policy, MIN_SUPPORTED_MOBILE_VERSION, passwo use crate::constants::accounts_info_policy::{MAX_FIRST_NAME_LENGTH, MAX_LAST_NAME_LENGTH, MAX_LOCATION_LENGTH, MIN_FIRST_NAME_LENGTH, MIN_LAST_NAME_LENGTH}; use crate::constants::conversations::{ALLOWED_CONVERSATION_FILES_TYPES, CONVERSATION_FILES_MAX_SIZE, CONVERSATION_WRITING_EVENT_INTERVAL, CONVERSATION_WRITING_EVENT_LIFETIME, MAX_CONV_IMAGE_MESSAGE_WIDTH, MAX_CONV_LOGO_HEIGHT, MAX_CONV_LOGO_WIDTH, MAX_CONV_MESSAGE_THUMBNAIL_HEIGHT, MAX_CONV_MESSAGE_THUMBNAIL_WIDTH, MAX_CONVERSATION_MESSAGE_LENGTH, MAX_CONVERSATION_NAME_LENGTH, MIN_CONVERSATION_MESSAGE_LENGTH}; use crate::data::api_client::APIClient; -use crate::data::config::conf; +use crate::data::config::{Banner, conf}; #[derive(Serialize)] struct NotificationsConfig { @@ -72,6 +72,7 @@ pub struct ServerConfig { play_store_url: &'static str, android_direct_download_url: String, + banner: Option<&'static Banner>, push_notifications: NotificationsConfig, password_policy: PasswordPolicy, data_conservation_policy: DataConservationPolicy, @@ -89,6 +90,11 @@ impl ServerConfig { play_store_url: &conf().play_store_url, android_direct_download_url: conf().android_direct_download_url.clone(), + banner: match conf().banner.as_ref().map(|b| b.is_visible()).unwrap_or(false) { + true => conf().banner.as_ref(), + false => None, + }, + push_notifications: NotificationsConfig { has_firebase: c.is_firebase_available(), has_independent: conf().is_independent_push_notifications_service_enabled(), diff --git a/src/data/config.rs b/src/data/config.rs index eb09144..379dd23 100644 --- a/src/data/config.rs +++ b/src/data/config.rs @@ -1,8 +1,10 @@ +use std::collections::HashMap; use std::error::Error; use yaml_rust::{Yaml, YamlLoader}; use crate::data::group_id::GroupID; +use crate::utils::date_utils::time; /// Server configuration /// @@ -35,6 +37,31 @@ pub struct IndependentPushService { pub public_url: String, } + +#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum BannerNature { + Information, + Warning, + Success, +} + +#[derive(Debug, serde::Serialize)] +pub struct Banner { + pub enabled: bool, + pub expire: Option, + pub nature: BannerNature, + pub message: HashMap, + pub link: Option, +} + +impl Banner { + pub fn is_visible(&self) -> bool { + self.enabled && + self.expire.map(|v| v < 1 || v > time()).unwrap_or(true) + } +} + #[derive(Debug)] pub struct Config { pub port: u64, @@ -54,6 +81,7 @@ pub struct Config { pub database: DatabaseConfig, pub rtc_relay: Option, pub admin_url: String, + pub banner: Option, pub forez_groups: Vec, } @@ -140,6 +168,28 @@ impl Config { }) }; + let parsed_banner = &parsed["banner"]; + let banner = match parsed_banner.is_badvalue() { + true => None, + false => Some(Banner { + enabled: Self::yaml_bool(parsed_banner, "enabled"), + expire: match Self::yaml_u64(parsed_banner, "expire") { + 0 => None, + v => Some(v) + }, + nature: match Self::yaml_str(parsed_banner, "nature").as_str() { + "information" => BannerNature::Information, + "warning" => BannerNature::Warning, + "success" => BannerNature::Success, + v => panic!("Invalid banner nature: {} !", v) + }, + message: parsed_banner["message"].as_hash().unwrap().iter() + .map(|(k, v)| (k.as_str().unwrap().to_string(), v.as_str().unwrap().to_string())) + .collect(), + link: parsed_banner["link"].as_str().map(|s| s.to_string()), + }) + }; + let forez_groups = match &parsed["forez_groups"] { Yaml::BadValue => vec![], _ => { @@ -183,6 +233,8 @@ impl Config { admin_url: Self::yaml_str(parsed, "admin-url"), + banner, + forez_groups, };