feat(config): add security feature toggle support
Implements a master toggle for security features across config, CLI, and application logic. This allows granular control over whether the advanced security middleware and protections are active globally.
This commit is contained in:
@@ -22,6 +22,9 @@ func TestDefaults(t *testing.T) {
|
||||
if !cfg.GuestUploadsEnabled || !cfg.APIEnabled || !cfg.ZipDownloadsEnabled || !cfg.OneTimeDownloadsEnabled {
|
||||
t.Fatal("expected default guest/API/download toggles to be enabled")
|
||||
}
|
||||
if !cfg.SecurityEnabled {
|
||||
t.Fatal("expected security features to be enabled by default")
|
||||
}
|
||||
if cfg.AdminUsername != "admin" {
|
||||
t.Fatalf("unexpected admin username: %s", cfg.AdminUsername)
|
||||
}
|
||||
@@ -39,6 +42,7 @@ func TestEnvironmentOverrides(t *testing.T) {
|
||||
t.Setenv("WARPBOX_BOX_POLL_INTERVAL_MS", "2000")
|
||||
t.Setenv("WARPBOX_ADMIN_USERNAME", "root")
|
||||
t.Setenv("WARPBOX_ONE_TIME_DOWNLOAD_RETRY_ON_FAILURE", "true")
|
||||
t.Setenv("WARPBOX_SECURITY_ENABLED", "false")
|
||||
|
||||
cfg, err := Load()
|
||||
if err != nil {
|
||||
@@ -63,6 +67,9 @@ func TestEnvironmentOverrides(t *testing.T) {
|
||||
if !cfg.OneTimeDownloadRetryOnFailure {
|
||||
t.Fatal("expected one-time retry-on-failure env override to be applied")
|
||||
}
|
||||
if cfg.SecurityEnabled {
|
||||
t.Fatal("expected security features toggle from environment to be applied")
|
||||
}
|
||||
if cfg.Source(SettingAPIEnabled) != SourceEnv {
|
||||
t.Fatalf("expected API setting source to be env, got %s", cfg.Source(SettingAPIEnabled))
|
||||
}
|
||||
@@ -191,6 +198,7 @@ func clearConfigEnv(t *testing.T) {
|
||||
"WARPBOX_BOX_POLL_INTERVAL_MS",
|
||||
"WARPBOX_THUMBNAIL_BATCH_SIZE",
|
||||
"WARPBOX_THUMBNAIL_INTERVAL_SECONDS",
|
||||
"WARPBOX_SECURITY_ENABLED",
|
||||
} {
|
||||
t.Setenv(name, "")
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ var Definitions = []SettingDefinition{
|
||||
{Key: SettingThumbnailBatchSize, EnvName: "WARPBOX_THUMBNAIL_BATCH_SIZE", Label: "Thumbnail batch size", Type: SettingTypeInt, Editable: true, Minimum: 1},
|
||||
{Key: SettingThumbnailIntervalSeconds, EnvName: "WARPBOX_THUMBNAIL_INTERVAL_SECONDS", Label: "Thumbnail interval seconds", Type: SettingTypeInt, Editable: true, Minimum: 1},
|
||||
{Key: SettingActivityRetentionSeconds, EnvName: "WARPBOX_ACTIVITY_RETENTION_SECONDS", Label: "Activity retention seconds", Type: SettingTypeInt64, Editable: true, Minimum: 60},
|
||||
{Key: SettingSecurityEnabled, EnvName: "WARPBOX_SECURITY_ENABLED", Label: "Security features enabled", Type: SettingTypeBool, Editable: true},
|
||||
{Key: SettingSecurityIPWhitelist, EnvName: "WARPBOX_SECURITY_IP_WHITELIST", Label: "Security IP whitelist", Type: SettingTypeText, Editable: true},
|
||||
{Key: SettingSecurityAdminIPWhitelist, EnvName: "WARPBOX_SECURITY_ADMIN_IP_WHITELIST", Label: "Security admin IP whitelist", Type: SettingTypeText, Editable: true},
|
||||
{Key: SettingTrustedProxyCIDRs, EnvName: "WARPBOX_TRUSTED_PROXY_CIDRS", Label: "Trusted proxy CIDRs", Type: SettingTypeText, Editable: true},
|
||||
|
||||
@@ -27,6 +27,7 @@ func Load() (*Config, error) {
|
||||
ThumbnailBatchSize: 10,
|
||||
ThumbnailIntervalSeconds: 30,
|
||||
ActivityRetentionSeconds: 7 * 24 * 60 * 60,
|
||||
SecurityEnabled: true,
|
||||
SecurityLoginWindowSeconds: 10 * 60,
|
||||
SecurityLoginMaxAttempts: 8,
|
||||
SecurityBanSeconds: 30 * 60,
|
||||
@@ -91,6 +92,7 @@ func Load() (*Config, error) {
|
||||
{SettingOneTimeDownloadRetryFail, "WARPBOX_ONE_TIME_DOWNLOAD_RETRY_ON_FAILURE", &cfg.OneTimeDownloadRetryOnFailure},
|
||||
{SettingRenewOnAccessEnabled, "WARPBOX_RENEW_ON_ACCESS_ENABLED", &cfg.RenewOnAccessEnabled},
|
||||
{SettingRenewOnDownloadEnabled, "WARPBOX_RENEW_ON_DOWNLOAD_ENABLED", &cfg.RenewOnDownloadEnabled},
|
||||
{SettingSecurityEnabled, "WARPBOX_SECURITY_ENABLED", &cfg.SecurityEnabled},
|
||||
}
|
||||
for _, item := range envBools {
|
||||
if err := cfg.applyBoolEnv(item.key, item.name, item.target); err != nil {
|
||||
@@ -209,6 +211,7 @@ func (cfg *Config) captureDefaults() {
|
||||
cfg.captureDefaultValue(SettingThumbnailBatchSize, strconv.Itoa(cfg.ThumbnailBatchSize))
|
||||
cfg.captureDefaultValue(SettingThumbnailIntervalSeconds, strconv.Itoa(cfg.ThumbnailIntervalSeconds))
|
||||
cfg.captureDefaultValue(SettingActivityRetentionSeconds, strconv.FormatInt(cfg.ActivityRetentionSeconds, 10))
|
||||
cfg.captureDefaultValue(SettingSecurityEnabled, formatBool(cfg.SecurityEnabled))
|
||||
cfg.captureDefaultValue(SettingSecurityIPWhitelist, cfg.SecurityIPWhitelist)
|
||||
cfg.captureDefaultValue(SettingSecurityAdminIPWhitelist, cfg.SecurityAdminIPWhitelist)
|
||||
cfg.captureDefaultValue(SettingTrustedProxyCIDRs, cfg.TrustedProxyCIDRs)
|
||||
|
||||
@@ -37,6 +37,7 @@ const (
|
||||
SettingThumbnailIntervalSeconds = "thumbnail_interval_seconds"
|
||||
SettingDataDir = "data_dir"
|
||||
SettingActivityRetentionSeconds = "activity_retention_seconds"
|
||||
SettingSecurityEnabled = "security_enabled"
|
||||
SettingSecurityIPWhitelist = "security_ip_whitelist"
|
||||
SettingSecurityAdminIPWhitelist = "security_admin_ip_whitelist"
|
||||
SettingTrustedProxyCIDRs = "trusted_proxy_cidrs"
|
||||
@@ -108,6 +109,7 @@ type Config struct {
|
||||
ThumbnailBatchSize int
|
||||
ThumbnailIntervalSeconds int
|
||||
ActivityRetentionSeconds int64
|
||||
SecurityEnabled bool
|
||||
SecurityIPWhitelist string
|
||||
SecurityAdminIPWhitelist string
|
||||
TrustedProxyCIDRs string
|
||||
|
||||
@@ -95,6 +95,8 @@ func (cfg *Config) assignBool(key string, value bool, source Source) {
|
||||
cfg.RenewOnAccessEnabled = value
|
||||
case SettingRenewOnDownloadEnabled:
|
||||
cfg.RenewOnDownloadEnabled = value
|
||||
case SettingSecurityEnabled:
|
||||
cfg.SecurityEnabled = value
|
||||
}
|
||||
cfg.setValue(key, formatBool(value), source)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user