Feat v0.2.6 admin settings audit (#10)
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #10.
This commit is contained in:
@@ -335,15 +335,13 @@ func TruncateAll(t *testing.T) {
|
||||
INSERT INTO global_settings (key, value) VALUES
|
||||
('registration', '{"enabled": true}'),
|
||||
('site', '{"name": "Switchboard Core", "tagline": "Self-hosted extension platform"}'),
|
||||
('banner', '{"enabled": false, "text": "", "bg": "#007a33", "fg": "#ffffff"}'),
|
||||
('model_roles', '{"utility":{"primary":null,"fallback":null},"embedding":{"primary":null,"fallback":null},"generation":{"primary":null,"fallback":null}}')
|
||||
('banner', '{"enabled": false, "text": "", "bg": "#007a33", "fg": "#ffffff"}')
|
||||
ON CONFLICT (key) DO NOTHING
|
||||
`)
|
||||
DB.Exec(`
|
||||
INSERT INTO platform_policies (key, value) VALUES
|
||||
('allow_user_byok', 'false'),
|
||||
('allow_user_personas', 'false'),
|
||||
('allow_raw_model_access', 'true'),
|
||||
('allow_registration', 'true'),
|
||||
('default_user_active', 'false'),
|
||||
('allow_team_providers', 'true')
|
||||
@@ -354,19 +352,13 @@ func TruncateAll(t *testing.T) {
|
||||
INSERT INTO global_settings (key, value) VALUES
|
||||
('registration', '{"enabled": true}'::jsonb),
|
||||
('site', '{"name": "Switchboard Core", "tagline": "Self-hosted extension platform"}'::jsonb),
|
||||
('banner', '{"enabled": false, "text": "", "bg": "#007a33", "fg": "#ffffff"}'::jsonb),
|
||||
('model_roles', '{
|
||||
"utility": { "primary": null, "fallback": null },
|
||||
"embedding": { "primary": null, "fallback": null },
|
||||
"generation": { "primary": null, "fallback": null }
|
||||
}'::jsonb)
|
||||
('banner', '{"enabled": false, "text": "", "bg": "#007a33", "fg": "#ffffff"}'::jsonb)
|
||||
ON CONFLICT (key) DO NOTHING
|
||||
`)
|
||||
DB.Exec(`
|
||||
INSERT INTO platform_policies (key, value) VALUES
|
||||
('allow_user_byok', 'false'),
|
||||
('allow_user_personas', 'false'),
|
||||
('allow_raw_model_access', 'true'),
|
||||
('allow_registration', 'true'),
|
||||
('default_user_active', 'false'),
|
||||
('allow_team_providers', 'true')
|
||||
|
||||
@@ -361,47 +361,15 @@ func (h *AdminHandler) PublicSettings(c *gin.Context) {
|
||||
// Banner config, branding, etc. — safe subset for non-admin users
|
||||
banner, _ := h.stores.GlobalConfig.Get(c.Request.Context(), "banner")
|
||||
branding, _ := h.stores.GlobalConfig.Get(c.Request.Context(), "branding")
|
||||
systemPrompt, _ := h.stores.GlobalConfig.Get(c.Request.Context(), "system_prompt")
|
||||
policies, _ := h.stores.Policies.GetAll(c.Request.Context())
|
||||
|
||||
// Paste-to-file threshold (admin-configurable via storage.paste_to_file_chars, default 2000)
|
||||
pasteChars := 2000
|
||||
if storageSettings, err := h.stores.GlobalConfig.Get(c.Request.Context(), "storage"); err == nil {
|
||||
if v, ok := storageSettings["paste_to_file_chars"]; ok {
|
||||
switch n := v.(type) {
|
||||
case float64:
|
||||
pasteChars = int(n)
|
||||
case int:
|
||||
pasteChars = n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only tell the user whether admin prompt exists — don't expose content
|
||||
hasAdminPrompt := false
|
||||
if content, ok := systemPrompt["content"].(string); ok && content != "" {
|
||||
hasAdminPrompt = true
|
||||
}
|
||||
|
||||
// Retention TTL (v0.37.14 — days before purge for global/team channels)
|
||||
retentionTTL := 0
|
||||
if ttlCfg, err := h.stores.GlobalConfig.Get(c.Request.Context(), "retention_ttl_days"); err == nil {
|
||||
if v, ok := ttlCfg["value"].(float64); ok {
|
||||
retentionTTL = int(v)
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"banner": banner,
|
||||
"branding": branding,
|
||||
"has_admin_prompt": hasAdminPrompt,
|
||||
"storage_configured": storageConfigured,
|
||||
"paste_to_file_chars": pasteChars,
|
||||
"banner": banner,
|
||||
"branding": branding,
|
||||
"storage_configured": storageConfigured,
|
||||
"policies": gin.H{
|
||||
"allow_registration": policies["allow_registration"],
|
||||
"allow_user_byok": policies["allow_user_byok"],
|
||||
"allow_user_personas": policies["allow_user_personas"],
|
||||
"retention_ttl_days": retentionTTL,
|
||||
"allow_registration": policies["allow_registration"],
|
||||
"allow_user_byok": policies["allow_user_byok"],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -86,8 +86,6 @@ func (h *ProfileBootstrapHandler) GetBootstrap(c *gin.Context) {
|
||||
if ps := h.stores.Policies; ps != nil {
|
||||
policies["allow_user_byok"], _ = ps.GetBool(ctx, "allow_user_byok")
|
||||
policies["allow_user_personas"], _ = ps.GetBool(ctx, "allow_user_personas")
|
||||
policies["allow_raw_model_access"], _ = ps.GetBool(ctx, "allow_raw_model_access")
|
||||
policies["kb_direct_access"], _ = ps.GetBool(ctx, "kb_direct_access")
|
||||
}
|
||||
|
||||
// ── Settings ────────────────────────────
|
||||
|
||||
@@ -67,8 +67,6 @@ func (h *ProfilePermissionsHandler) GetMyPermissions(c *gin.Context) {
|
||||
if ps := h.stores.Policies; ps != nil {
|
||||
policies["allow_user_byok"], _ = ps.GetBool(ctx, "allow_user_byok")
|
||||
policies["allow_user_personas"], _ = ps.GetBool(ctx, "allow_user_personas")
|
||||
policies["allow_raw_model_access"], _ = ps.GetBool(ctx, "allow_raw_model_access")
|
||||
policies["kb_direct_access"], _ = ps.GetBool(ctx, "kb_direct_access")
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
|
||||
@@ -84,13 +84,11 @@ type TeamMember struct {
|
||||
// PLATFORM POLICIES
|
||||
|
||||
var PolicyDefaults = map[string]string{
|
||||
"allow_user_byok": "false",
|
||||
"allow_user_personas": "false",
|
||||
"allow_raw_model_access": "false",
|
||||
"allow_registration": "true",
|
||||
"default_user_active": "false",
|
||||
"allow_team_providers": "true",
|
||||
"default_model": "",
|
||||
"allow_user_byok": "false",
|
||||
"allow_user_personas": "false",
|
||||
"allow_registration": "true",
|
||||
"default_user_active": "false",
|
||||
"allow_team_providers": "true",
|
||||
}
|
||||
|
||||
// HandleFromName generates a URL-safe @mention handle from a display name.
|
||||
|
||||
@@ -79,16 +79,14 @@ func sectionCategory(section string) string {
|
||||
switch section {
|
||||
case "users", "teams", "groups":
|
||||
return "people"
|
||||
case "providers", "models", "personas", "roles", "knowledgeBases", "memory":
|
||||
return "ai"
|
||||
case "health", "routing", "capabilities":
|
||||
return "routing"
|
||||
case "settings", "storage", "packages", "channels", "broadcast":
|
||||
case "workflows":
|
||||
return "workflows"
|
||||
case "settings", "storage", "packages", "broadcast":
|
||||
return "system"
|
||||
case "usage", "audit", "stats":
|
||||
return "monitoring"
|
||||
default:
|
||||
return "ai" // default landing
|
||||
return "system"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user