feat: sync deployed v1.0.0-rc.38-custom.42

Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
cneicy committed 2026-09-26 04:49:11 +08:00
1 parent aa6c3f50f4
commit ceddfd3d6b
828 files changed
+122253 -13702

No files matched your search

+24 -17
View File
@@ -1,8 +1,9 @@
package authz
import (
"strings"
"fmt"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/model"
casbinmodel "github.com/casbin/casbin/v2/model"
"github.com/casbin/casbin/v2/persist"
@@ -24,7 +25,28 @@ func (a *gormAdapter) LoadPolicy(m casbinmodel.Model) error {
return err
}
for _, rule := range rules {
if err := persist.LoadPolicyLine(ruleToLine(rule), m); err != nil {
if rule.Ptype != "p" {
// This model has no role-inheritance or other policy sections.
continue
}
if rule.V0 == "" || rule.V1 == "" || rule.V2 == "" {
return fmt.Errorf("authorization policy %d is missing a subject, resource or action", rule.Id)
}
effect := rule.V3
if effect == "" {
effect = EffectAllow
}
if effect != EffectAllow && effect != EffectDeny {
return fmt.Errorf("authorization policy %d has an invalid effect", rule.Id)
}
if rule.V5 != "" || (rule.V4 != "" && rule.V4 != "all") {
// The current model cannot enforce legacy own/other scopes. Keep
// the stored rule for review and deny this permission in memory.
// Skipping a per-user rule would expose the admin role baseline.
effect = EffectDeny
common.SysLog(fmt.Sprintf("authorization policy %d has an unsupported legacy scope; loaded as deny; review the stored policy before granting access", rule.Id))
}
if err := persist.LoadPolicyArray([]string{rule.Ptype, rule.V0, rule.V1, rule.V2, effect}, m); err != nil {
return err
}
}
@@ -104,18 +126,3 @@ func newRule(ptype string, policy []string) model.CasbinRule {
}
return rule
}
func ruleToLine(rule model.CasbinRule) string {
parts := []string{rule.Ptype}
values := []string{rule.V0, rule.V1, rule.V2, rule.V3, rule.V4, rule.V5}
if rule.Ptype == "p" && rule.V0 != "" && rule.V1 != "" && rule.V2 != "" && rule.V3 == "" {
values[3] = EffectAllow
}
for _, value := range values {
if value == "" {
continue
}
parts = append(parts, value)
}
return strings.Join(parts, ", ")
}
+49
View File
@@ -77,6 +77,55 @@ func TestInitOnSlaveOnlyLoadsPolicies(t *testing.T) {
assert.False(t, Can(2, common.RoleAdminUser, ChannelRead))
}
func TestLegacyScopedPoliciesDoNotExpandPermissions(t *testing.T) {
for _, master := range []bool{true, false} {
name := "master"
if !master {
name = "slave"
}
t.Run(name, func(t *testing.T) {
db := newAuthzTestDB(t)
common.IsMasterNode = master
rules := []model.CasbinRule{
{Ptype: "p", V0: "role:vendor", V1: "channel", V2: "read", V3: "allow", V4: "own"},
{Ptype: "p", V0: UserSubject(42), V1: "channel", V2: "read", V3: "allow", V4: "own"},
{Ptype: "p", V0: UserSubject(43), V1: "channel", V2: "sensitive_write", V3: "allow", V4: "all"},
{Ptype: "p", V0: UserSubject(44), V1: "channel", V2: "secret_view", V3: "deny", V4: "all"},
{Ptype: "p", V0: UserSubject(45), V1: "channel", V2: "read"},
{Ptype: "p", V0: UserSubject(46), V1: "channel", V2: "read", V3: "allow", V4: "unknown-scope"},
{Ptype: "p", V0: UserSubject(47), V1: "channel", V2: "read", V3: "allow", V5: "own"},
{Ptype: "p", V0: UserSubject(48), V1: "channel", V2: "read", V3: "allow", V4: "own"},
{Ptype: "p", V0: UserSubject(48), V1: "channel", V2: "read", V3: "allow", V4: "all"},
{Ptype: "p", V0: RoleSubject(BuiltInRoleAdmin), V1: "channel", V2: "operate", V3: "allow", V4: "own"},
{Ptype: "p", V0: UserSubject(50), V1: "channel", V2: "sensitive_write", V3: "allow"},
{Ptype: "g", V0: UserSubject(99), V1: RoleSubject(BuiltInRoleAdmin)},
}
require.NoError(t, db.Create(&rules).Error)
ids := make([]uint, len(rules))
for i := range rules {
ids[i] = rules[i].Id
}
for range 2 {
require.NoError(t, Init(db))
require.NoError(t, ReloadPolicy())
assert.False(t, Can(42, common.RoleAdminUser, ChannelRead), "own must not fall back to the admin allow baseline")
assert.True(t, Can(43, common.RoleAdminUser, ChannelSensitiveWrite))
assert.False(t, Can(44, common.RoleAdminUser, ChannelSecretView))
assert.True(t, Can(45, common.RoleAdminUser, ChannelRead))
for _, userID := range []int{46, 47, 48} {
assert.False(t, Can(userID, common.RoleAdminUser, ChannelRead))
}
assert.False(t, Can(51, common.RoleAdminUser, ChannelOperate), "reseed must not erase a scoped role restriction")
assert.True(t, Can(50, common.RoleAdminUser, ChannelSensitiveWrite))
assert.False(t, Can(99, common.RoleCommonUser, ChannelRead))
var stored []model.CasbinRule
require.NoError(t, db.Where("id IN ?", ids).Order("id").Find(&stored).Error)
assert.Equal(t, rules, stored, "legacy rows must remain available for administrator review")
}
})
}
}
func TestSetUserPermissionsStoresOnlyOverrides(t *testing.T) {
db := newAuthzTestDB(t)
require.NoError(t, Init(db))
+5 -1
View File
@@ -39,7 +39,11 @@ func resetBuiltInRolePolicies(db *gorm.DB) error {
for _, spec := range builtInRoles {
subjects = append(subjects, RoleSubject(spec.Key))
}
return db.Where("ptype = ? AND v0 IN ?", "p", subjects).Delete(&model.CasbinRule{}).Error
// Scoped legacy rules must survive baseline reseeding so the adapter can
// retain their restrictions instead of replacing them with global grants.
return db.Where("ptype = ? AND v0 IN ?", "p", subjects).
Where("(v4 = ? OR v4 IS NULL) AND (v5 = ? OR v5 IS NULL)", "", "").
Delete(&model.CasbinRule{}).Error
}
func seedDefaultPolicies() error {