chore: track version files, docs, web app split, scripts (missed commits from March work)

This commit is contained in:
2026-09-13 08:41:35 +08:00
parent 84c709bbcc
commit edf76db56b
33 changed files with 3082 additions and 504 deletions
+64
View File
@@ -3,6 +3,7 @@ package server
import (
"net/http"
"strconv"
"strings"
)
type AccessContext struct {
@@ -63,3 +64,66 @@ func (s *Server) ResolveTenantAccessToken(tok string) (*AccessContext, bool) {
return nil, false
}
// TenantCan implements action-level RBAC for tenant-scoped APIs.
func TenantCan(ac *AccessContext, action string) bool {
if ac == nil {
return false
}
switch action {
case "view":
return (ac.Kind == "session" && (ac.Role == "admin" || ac.Role == "operator")) || ac.Kind == "apikey"
case "mutate_node_meta", "mutate_sdwan", "mutate_connect", "mutate_node_control":
return ac.Kind == "session" && (ac.Role == "admin" || ac.Role == "operator")
case "enroll_manage":
return ac.Kind == "session" && ac.Role == "admin"
default:
return false
}
}
func settingOn(v string) bool {
v = strings.TrimSpace(strings.ToLower(v))
return v == "1" || v == "true" || v == "on" || v == "yes"
}
// TenantCanWithOverride evaluates baseline RBAC then optional advanced override switches.
// Return values: allowed, usedOverride
func (s *Server) TenantCanWithOverride(ac *AccessContext, action string) (bool, bool) {
if TenantCan(ac, action) {
return true, false
}
if ac == nil || s == nil || s.store == nil || ac.TenantID <= 0 {
return false, false
}
if ac.Kind == "master" {
return false, false
}
// global override gate
if v, _, err := s.store.GetSetting("advanced_override_enabled"); err != nil || !settingOn(v) {
return false, false
}
switch action {
case "mutate_sdwan":
if ac.Kind == "apikey" {
if v, _, err := s.store.GetSetting("allow_apikey_mutate_sdwan"); err == nil && settingOn(v) {
return true, true
}
}
case "mutate_connect":
if ac.Kind == "session" && ac.Role == "operator" {
if v, _, err := s.store.GetSetting("allow_connect_cross_tenant"); err == nil && settingOn(v) {
return true, true
}
}
case "mutate_node_control":
if ac.Kind == "session" && ac.Role == "operator" {
if v, _, err := s.store.GetSetting("allow_operator_kick_cross_node"); err == nil && settingOn(v) {
return true, true
}
}
}
return false, false
}