mirror of
https://github.com/bitwarden/server
synced 2026-02-10 13:40:10 +00:00
All feature state access through config API (#2785)
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -9,15 +11,22 @@ namespace Bit.Api.Controllers;
|
||||
public class ConfigController : Controller
|
||||
{
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IFeatureService _featureService;
|
||||
|
||||
public ConfigController(IGlobalSettings globalSettings)
|
||||
public ConfigController(
|
||||
IGlobalSettings globalSettings,
|
||||
ICurrentContext currentContext,
|
||||
IFeatureService featureService)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
_currentContext = currentContext;
|
||||
_featureService = featureService;
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
public ConfigResponseModel GetConfigs()
|
||||
{
|
||||
return new ConfigResponseModel(_globalSettings);
|
||||
return new ConfigResponseModel(_globalSettings, _featureService.GetAll(_currentContext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,15 +10,19 @@ public class ConfigResponseModel : ResponseModel
|
||||
public string GitHash { get; set; }
|
||||
public ServerConfigResponseModel Server { get; set; }
|
||||
public EnvironmentConfigResponseModel Environment { get; set; }
|
||||
public IDictionary<string, object> FeatureStates { get; set; }
|
||||
|
||||
public ConfigResponseModel(string obj = "config") : base(obj)
|
||||
public ConfigResponseModel() : base("config")
|
||||
{
|
||||
Version = AssemblyHelpers.GetVersion();
|
||||
GitHash = AssemblyHelpers.GetGitHash();
|
||||
Environment = new EnvironmentConfigResponseModel();
|
||||
FeatureStates = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public ConfigResponseModel(IGlobalSettings globalSettings, string obj = "config") : base(obj)
|
||||
public ConfigResponseModel(
|
||||
IGlobalSettings globalSettings,
|
||||
IDictionary<string, object> featureStates) : base("config")
|
||||
{
|
||||
Version = AssemblyHelpers.GetVersion();
|
||||
GitHash = AssemblyHelpers.GetGitHash();
|
||||
@@ -30,6 +34,7 @@ public class ConfigResponseModel : ResponseModel
|
||||
Notifications = globalSettings.BaseServiceUri.Notifications,
|
||||
Sso = globalSettings.BaseServiceUri.Sso
|
||||
};
|
||||
FeatureStates = featureStates;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Bit.Core;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Bit.Core;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
@@ -26,4 +28,12 @@ public static class AuthenticationSchemes
|
||||
public static class FeatureFlagKeys
|
||||
{
|
||||
public const string SecretsManager = "secrets-manager";
|
||||
|
||||
public static List<string> GetAllKeys()
|
||||
{
|
||||
return typeof(FeatureFlagKeys).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
|
||||
.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(string))
|
||||
.Select(x => (string)x.GetRawConstantValue())
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,11 @@ public interface IFeatureService
|
||||
/// <param name="defaultValue">The default value for the feature.</param>
|
||||
/// <returns>The feature variation value.</returns>
|
||||
string GetStringVariation(string key, ICurrentContext currentContext, string defaultValue = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all feature values.
|
||||
/// </summary>
|
||||
/// <param name="currentContext">A context providing information that can be used to evaluate the feature values.</param>
|
||||
/// <returns>A dictionary of feature keys and their values.</returns>
|
||||
Dictionary<string, object> GetAll(ICurrentContext currentContext);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,38 @@ public class LaunchDarklyFeatureService : IFeatureService, IDisposable
|
||||
return _client.StringVariation(key, BuildContext(currentContext), defaultValue);
|
||||
}
|
||||
|
||||
public Dictionary<string, object> GetAll(ICurrentContext currentContext)
|
||||
{
|
||||
var results = new Dictionary<string, object>();
|
||||
|
||||
var keys = FeatureFlagKeys.GetAllKeys();
|
||||
|
||||
var values = _client.AllFlagsState(BuildContext(currentContext));
|
||||
if (values.Valid)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
var value = values.GetFlagValueJson(key);
|
||||
switch (value.Type)
|
||||
{
|
||||
case LaunchDarkly.Sdk.LdValueType.Bool:
|
||||
results.Add(key, value.AsBool);
|
||||
break;
|
||||
|
||||
case LaunchDarkly.Sdk.LdValueType.Number:
|
||||
results.Add(key, value.AsInt);
|
||||
break;
|
||||
|
||||
case LaunchDarkly.Sdk.LdValueType.String:
|
||||
results.Add(key, value.AsString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_client?.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user