Skip to content
Snippets Groups Projects
Forked from an inaccessible project.
config.rs 2.84 KiB
/* Copyright 2021 Dominik George <dominik.george@teckids.org>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::BASE_NAME;

use serde::de::Deserialize;

extern crate config;

pub fn get_config(conf_args: Option<config::Config>) -> config::Config {
    // Preset default configuration
    let mut conf = config::Config::default();
    conf.set("pam.flow", "password").ok();

    // Unwrap passed arguments or use empty fallback
    let conf_args = conf_args.unwrap_or_default();

    // Determine config file from args if provided and load config file
    let config_file = match conf_args.get_str("config") {
        Ok(filename) => filename.to_string(),
        Err(_) => "/etc/".to_string() + BASE_NAME,
    };
    conf.merge(config::File::with_name(&config_file)).ok();

    // Override configuration from environment variables
    conf.merge(config::Environment::with_prefix(BASE_NAME.to_string().to_uppercase().as_str())).ok();

    // Override configuration from args passed on module loading (e.g. args in PAM stack)
    conf.merge(conf_args).ok();

    return conf;
}

pub fn argv_to_config(argv: &Vec<String>) -> config::Config {
    let mut conf = config::Config::default();

    for arg in argv {
        if arg.contains("=") {
            let split: Vec<&str> = arg.split("=").collect();
            conf.set(split[0], split[1]).ok();
        } else {
            conf.set(arg, true).ok();
        }
    }
    return conf;
}

pub fn get_optional<'de, T: Deserialize<'de>>(conf: &config::Config, key: &str) -> Option<T> {
    debug!("Looking up key {} in config", key);
    match conf.get(key) {
        Ok(v) => Some(v),
        Err(_) => {
            // Try falling back to parent block
            match key.find('.') {
                Some(i) => {
                    debug!("Key {} not found in config, trying parent block", key);
                    get_optional(conf, &key[i+1..])
                },
                None => None,
            }
        },
    }
}

pub fn get_or_error<'de, T: Deserialize<'de>, E>(config: &config::Config, key: &str, error_value: E) -> Result<T, E> {
    match get_optional(config, key) {
        Some(v) => {
            debug!("Configuration key found: {}", key);
            return Ok(v);
        },
        None => {
            error!("Configuration key not found: {}", key);
            return Err(error_value);
        },
    }
}