Browse Source

Move feature flag parsing to util

pull/4168/head
Philipp Kolberg 2 years ago
parent
commit
646cedeea6
No known key found for this signature in database GPG Key ID: 4C58CB0448FF9061
  1. 16
      src/api/core/mod.rs
  2. 18
      src/config.rs
  3. 16
      src/util.rs

16
src/api/core/mod.rs

@ -47,15 +47,14 @@ pub fn events_routes() -> Vec<Route> {
// //
// Move this somewhere else // Move this somewhere else
// //
use rocket::{serde::json::Json, Catcher, Route}; use rocket::{serde::json::Json, serde::json::Value, Catcher, Route};
use serde_json::Value;
use crate::{ use crate::{
api::{JsonResult, JsonUpcase, Notify, UpdateType}, api::{JsonResult, JsonUpcase, Notify, UpdateType},
auth::Headers, auth::Headers,
db::DbConn, db::DbConn,
error::Error, error::Error,
util::get_reqwest_client, util::{get_reqwest_client, parse_feature_flags},
}; };
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -193,9 +192,7 @@ fn version() -> Json<&'static str> {
#[get("/config")] #[get("/config")]
fn config() -> Json<Value> { fn config() -> Json<Value> {
let domain = crate::CONFIG.domain(); let domain = crate::CONFIG.domain();
let feature_flags = crate::CONFIG.feature_flags().to_lowercase(); let feature_states = parse_feature_flags(&crate::CONFIG.feature_flags());
let features = feature_flags.split(',').map(|f| f.trim()).collect::<Vec<_>>();
let mut feature_states = json!({});
let mut config = json!({ let mut config = json!({
// Note: The clients use this version to handle backwards compatibility concerns // Note: The clients use this version to handle backwards compatibility concerns
// This means they expect a version that closely matches the Bitwarden server version // This means they expect a version that closely matches the Bitwarden server version
@ -218,12 +215,7 @@ fn config() -> Json<Value> {
}, },
"object": "config", "object": "config",
}); });
// Disabled because it is causing issues https://github.com/dani-garcia/vaultwarden/discussions/4052 config["featureStates"] = serde_json::to_value(feature_states).unwrap();
feature_states["autofill-v2"] = serde_json::Value::Bool(false);
for feature in features {
feature_states[feature.to_string()] = serde_json::Value::Bool(true);
}
config["featureStates"] = feature_states;
Json(config) Json(config)
} }

18
src/config.rs

@ -9,7 +9,7 @@ use reqwest::Url;
use crate::{ use crate::{
db::DbConnType, db::DbConnType,
error::Error, error::Error,
util::{get_env, get_env_bool}, util::{get_env, get_env_bool, parse_feature_flags},
}; };
static CONFIG_FILE: Lazy<String> = Lazy::new(|| { static CONFIG_FILE: Lazy<String> = Lazy::new(|| {
@ -547,8 +547,10 @@ make_config! {
/// TOTP codes of the previous and next 30 seconds will be invalid. /// TOTP codes of the previous and next 30 seconds will be invalid.
authenticator_disable_time_drift: bool, true, def, false; authenticator_disable_time_drift: bool, true, def, false;
/// Customize the enabled feature flags on the clients |> This is a comma separated list of feature flags to enable. /// Customize the enabled feature flags on the clients |> This is a comma separated list of feature flags to en-/disable.
feature_flags: String, false, def, "fido2-vault-credentials".to_string(); /// Features are enabled by default which can be overridden by prefixing the feature with a `!`.
/// Autofill v2 is disabled by default because it is causing issues https://github.com/dani-garcia/vaultwarden/discussions/4052
feature_flags: String, false, def, "!autofill-v2,fido2-vault-credentials".to_string();
/// Require new device emails |> When a user logs in an email is required to be sent. /// Require new device emails |> When a user logs in an email is required to be sent.
/// If sending the email fails the login attempt will fail. /// If sending the email fails the login attempt will fail.
@ -754,9 +756,7 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
) )
} }
let feature_flags = cfg.feature_flags.to_lowercase(); const SUPPORTED_FLAGS: &[&str] = &[
let features = feature_flags.split(',').map(|f| f.trim()).collect::<Vec<_>>();
let supported_flags = vec![
"display-kdf-iteration-warning", "display-kdf-iteration-warning",
"fido2-vault-credentials", "fido2-vault-credentials",
"trusted-device-encryption", "trusted-device-encryption",
@ -769,9 +769,9 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
"flexible-collections-v-1", "flexible-collections-v-1",
"bulk-collection-access", "bulk-collection-access",
]; ];
for feature in features { for flag in parse_feature_flags(&cfg.feature_flags).keys() {
if !supported_flags.contains(&feature) { if !SUPPORTED_FLAGS.contains(&flag.as_str()) {
err!(format!("Feature flag {feature:?} is not supported.")); err!(format!("Feature flag {flag:?} is not supported."));
} }
} }

16
src/util.rs

@ -2,6 +2,7 @@
// Web Headers and caching // Web Headers and caching
// //
use std::{ use std::{
collections::HashMap,
io::{Cursor, ErrorKind}, io::{Cursor, ErrorKind},
ops::Deref, ops::Deref,
}; };
@ -747,3 +748,18 @@ pub fn convert_json_key_lcase_first(src_json: Value) -> Value {
value => value, value => value,
} }
} }
/// Parses the feature flags string into a HashMap.
pub fn parse_feature_flags(feature_flags: &str) -> HashMap<String, bool> {
let feature_flags_lowercase = feature_flags.to_lowercase();
let features = feature_flags_lowercase.split(',').map(|f| f.trim()).collect::<Vec<_>>();
let mut feature_states: HashMap<String, bool> = HashMap::new();
for feature in features {
let is_enabled = !feature.starts_with('!');
let flag = if is_enabled { feature } else { &feature[1..] };
feature_states.insert(flag.to_string(), is_enabled);
}
feature_states
}
Loading…
Cancel
Save