feat(channels): gate available channels behind feature switch (backend)
Add a DB-backed soft switch "available_channels_enabled" controlling the user-facing /channels/available endpoint and sidebar entry. Default to false (opt-in) — the feature stays invisible until an admin enables it under Admin Settings > Features. - domain_constants: SettingKeyAvailableChannelsEnabled - settings_view: AllSettings/PublicSettings + AvailableChannelsEnabled - setting_service: public+all read/write, seed default "false", GetAvailableChannelsRuntime helper (fail-closed on read error) - admin setting_handler: UpdateSettingsRequest *bool + update branch + audit diff entry - public setting_handler: expose via GET /api/v1/settings - available_channel_handler: featureEnabled() guard — returns empty list after auth when disabled (401 precedes the feature check to preserve existing behavior)
This commit is contained in:
@@ -21,19 +21,30 @@ import (
|
||||
type AvailableChannelHandler struct {
|
||||
channelService *service.ChannelService
|
||||
apiKeyService *service.APIKeyService
|
||||
settingService *service.SettingService
|
||||
}
|
||||
|
||||
// NewAvailableChannelHandler 创建用户侧可用渠道 handler。
|
||||
func NewAvailableChannelHandler(
|
||||
channelService *service.ChannelService,
|
||||
apiKeyService *service.APIKeyService,
|
||||
settingService *service.SettingService,
|
||||
) *AvailableChannelHandler {
|
||||
return &AvailableChannelHandler{
|
||||
channelService: channelService,
|
||||
apiKeyService: apiKeyService,
|
||||
settingService: settingService,
|
||||
}
|
||||
}
|
||||
|
||||
// featureEnabled 返回 available-channels 开关是否启用。默认关闭(opt-in)。
|
||||
func (h *AvailableChannelHandler) featureEnabled(c *gin.Context) bool {
|
||||
if h.settingService == nil {
|
||||
return false
|
||||
}
|
||||
return h.settingService.GetAvailableChannelsRuntime(c.Request.Context()).Enabled
|
||||
}
|
||||
|
||||
// userAvailableGroup 用户可见的分组概要(白名单字段)。
|
||||
type userAvailableGroup struct {
|
||||
ID int64 `json:"id"`
|
||||
@@ -89,6 +100,13 @@ func (h *AvailableChannelHandler) List(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Feature 未启用时返回空数组(不暴露渠道信息)。检查放在认证之后,
|
||||
// 保持与未开关前的 401 行为一致:未登录先 401,登录后再按开关决定。
|
||||
if !h.featureEnabled(c) {
|
||||
response.Success(c, []userAvailableChannel{})
|
||||
return
|
||||
}
|
||||
|
||||
userGroups, err := h.apiKeyService.GetAvailableGroups(c.Request.Context(), subject.UserID)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
|
||||
Reference in New Issue
Block a user