@ -111,6 +111,7 @@ macro_rules! make_config {
_usr : ConfigBuilder ,
_usr : ConfigBuilder ,
_overrides : Vec < & 'static str > ,
_overrides : Vec < & 'static str > ,
_config_file_status : ConfigFileStatus ,
}
}
// Custom Deserialize for ConfigBuilder, mainly based upon https://serde.rs/deserialize-struct.html
// Custom Deserialize for ConfigBuilder, mainly based upon https://serde.rs/deserialize-struct.html
@ -259,17 +260,18 @@ macro_rules! make_config {
builder
builder
}
}
async fn from_file ( ) -> Result < Self , Error > {
async fn from_file ( ) -> Result < Option < Self > , Error > {
let operator = storage ::operator_for_path ( & CONFIG_FILE_PARENT_DIR ) ? ;
let operator = storage ::operator_for_path ( & CONFIG_FILE_PARENT_DIR ) ? ;
let config_bytes = match operator . read ( & CONFIG_FILENAME ) . await {
let config_bytes = match operator . read ( & CONFIG_FILENAME ) . await {
Ok ( bytes ) = > bytes ,
Ok ( bytes ) = > bytes ,
// No config file is fine, should not return any error
// No config file is fine, should not return any error
Err ( e ) if e . kind ( ) = = opendal ::ErrorKind ::NotFound = > return Ok ( Self ::default ( ) ) ,
Err ( e ) if e . kind ( ) = = opendal ::ErrorKind ::NotFound = > return Ok ( None ) ,
// Any other error might be an issue and should be passed back to the caller
// Any other error might be an issue and should be passed back to the caller
Err ( e ) = > return Err ( e . into ( ) ) ,
Err ( e ) = > return Err ( e . into ( ) ) ,
} ;
} ;
let builder = serde_json ::from_slice ( & config_bytes . to_vec ( ) ) ? ;
println ! ( "[INFO] Using saved config from `{}` for configuration.\n" , * CONFIG_FILE ) ;
println ! ( "[INFO] Using saved config from `{}` for configuration.\n" , * CONFIG_FILE ) ;
serde_json ::from_slice ( & config_bytes . to_vec ( ) ) . map_err ( Into ::into )
Ok ( Some ( builder ) )
}
}
fn clear_non_editable ( & mut self ) {
fn clear_non_editable ( & mut self ) {
@ -446,6 +448,8 @@ macro_rules! make_config {
"domain_origin" ,
"domain_origin" ,
"domain_path" ,
"domain_path" ,
"domain" ,
"domain" ,
"duo_ikey" ,
"duo_host" ,
"helo_name" ,
"helo_name" ,
"org_creation_users" ,
"org_creation_users" ,
"signups_domains_whitelist" ,
"signups_domains_whitelist" ,
@ -457,6 +461,8 @@ macro_rules! make_config {
"sso_authority" ,
"sso_authority" ,
"sso_callback_path" ,
"sso_callback_path" ,
"sso_client_id" ,
"sso_client_id" ,
"yubico_client_id" ,
"yubico_server" ,
] ;
] ;
let cfg = {
let cfg = {
@ -489,6 +495,10 @@ macro_rules! make_config {
} ;
} ;
overrides
overrides
}
}
pub fn get_config_file_status ( & self ) -> ConfigFileStatus {
self . inner . read ( ) . unwrap ( ) . _config_file_status
}
}
}
} ;
} ;
}
}
@ -1481,23 +1491,34 @@ pub const SUPPORTED_FEATURE_FLAGS: &[&str] = &[
"pm-32009-new-item-types" ,
"pm-32009-new-item-types" ,
] ;
] ;
#[ derive(Clone, Copy, Serialize) ]
pub enum ConfigFileStatus {
NotFound ,
Loaded ,
Error ,
}
impl Config {
impl Config {
pub async fn load ( ) -> Result < Self , Error > {
pub async fn load ( ) -> Result < Self , Error > {
// Loading from env and file
// Loading from env and file
let env = ConfigBuilder ::from_env ( ) ;
let env = ConfigBuilder ::from_env ( ) ;
let usr = ConfigBuilder ::from_file ( ) . await . unwrap_or_else ( | e | {
let ( usr , config_file_status ) = match ConfigBuilder ::from_file ( ) . await {
println ! (
Ok ( Some ( usr ) ) = > ( usr , ConfigFileStatus ::Loaded ) ,
" [ ERROR ] Failed to load configuration from ` { } ` \ n \
Ok ( None ) = > ( ConfigBuilder ::default ( ) , ConfigFileStatus ::NotFound ) ,
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \
Err ( e ) = > {
# The file seems to exist but might contain invalid JSON or invalid values . # \ n \
println ! (
# Check the syntax and make sure every value is valid and within its allowed range . # \ n \
" [ ERROR ] Failed to load configuration from ` { } ` \ n \
# This file is not used until those errors are resolved . # \ n \
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \
# The file seems to exist but might contain invalid JSON or invalid values . # \ n \
# Check the syntax and make sure every value is valid and within its allowed range . # \ n \
# This file is not used until those errors are resolved . # \ n \
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \
{ e :? } \ n " ,
{ e :? } \ n " ,
* CONFIG_FILE
* CONFIG_FILE
) ;
) ;
ConfigBuilder ::default ( )
( ConfigBuilder ::default ( ) , ConfigFileStatus ::Error )
} ) ;
}
} ;
// Create merged config, config file overwrites env
// Create merged config, config file overwrites env
let mut overrides = Vec ::new ( ) ;
let mut overrides = Vec ::new ( ) ;
@ -1517,6 +1538,7 @@ impl Config {
_env : env ,
_env : env ,
_usr : usr ,
_usr : usr ,
_overrides : overrides ,
_overrides : overrides ,
_config_file_status : config_file_status ,
} ) ,
} ) ,
} )
} )
}
}
@ -1550,6 +1572,7 @@ impl Config {
writer . config = config ;
writer . config = config ;
writer . _usr = builder ;
writer . _usr = builder ;
writer . _overrides = overrides ;
writer . _overrides = overrides ;
writer . _config_file_status = ConfigFileStatus ::Loaded ;
}
}
//Save to file
//Save to file
@ -1641,6 +1664,7 @@ impl Config {
writer . config = config ;
writer . config = config ;
writer . _usr = usr ;
writer . _usr = usr ;
writer . _overrides = Vec ::new ( ) ;
writer . _overrides = Vec ::new ( ) ;
writer . _config_file_status = ConfigFileStatus ::NotFound ;
}
}
// Invalidate CSS Cache because several config items might have impact on the rendered CSS
// Invalidate CSS Cache because several config items might have impact on the rendered CSS