mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-15 23:22:59 +08:00
feat(admin): let admins restrict which public groups a user may access
Public groups have always been bindable by every user: CanBindGroup returned true for any non-exclusive group, and user_allowed_groups only ever carried the exclusive groups an admin had granted. Admins had no way to hand a single user a subset of the public groups short of converting a group to exclusive, which changes it for everyone already using it. A user now carries restrict_public_groups. While it is false, which is the default and what every existing row migrates to, nothing changes: every public group stays bindable. Once an admin turns it on for a user, that user's public groups are narrowed to the ones listed in user_allowed_groups, the same table that already gates exclusive groups. The flag is an administrative control, so it rides on the admin user DTO only and leaves the shape of the end-user endpoints alone. The model plaza filter honours the flag as well, so a restricted user is not shown groups they would be refused when binding a key. Anonymous visitors have no user record and keep the previous view. Enforcement rides on the existing CanBindGroup choke point, so it covers key creation, key updates, and per-request authorization together. An API key bound to a group that is later withdrawn stops working at request time rather than lingering as a key that can be listed but not used. The admin dialog gains a toggle over the public group list. Turning it off re-checks every public group, so an admin cannot save a list that reads as restrictive while the restriction itself is disabled. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
efb46db0a9
commit
b56c61eccd
+12
-1
@@ -53,6 +53,8 @@ type User struct {
|
||||
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
|
||||
// LastActiveAt holds the value of the "last_active_at" field.
|
||||
LastActiveAt *time.Time `json:"last_active_at,omitempty"`
|
||||
// RestrictPublicGroups holds the value of the "restrict_public_groups" field.
|
||||
RestrictPublicGroups bool `json:"restrict_public_groups,omitempty"`
|
||||
// BalanceNotifyEnabled holds the value of the "balance_notify_enabled" field.
|
||||
BalanceNotifyEnabled bool `json:"balance_notify_enabled,omitempty"`
|
||||
// BalanceNotifyThresholdType holds the value of the "balance_notify_threshold_type" field.
|
||||
@@ -237,7 +239,7 @@ func (*User) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case user.FieldTotpEnabled, user.FieldBalanceNotifyEnabled:
|
||||
case user.FieldTotpEnabled, user.FieldRestrictPublicGroups, user.FieldBalanceNotifyEnabled:
|
||||
values[i] = new(sql.NullBool)
|
||||
case user.FieldBalance, user.FieldFrozenBalance, user.FieldBalanceNotifyThreshold, user.FieldTotalRecharged:
|
||||
values[i] = new(sql.NullFloat64)
|
||||
@@ -381,6 +383,12 @@ func (_m *User) assignValues(columns []string, values []any) error {
|
||||
_m.LastActiveAt = new(time.Time)
|
||||
*_m.LastActiveAt = value.Time
|
||||
}
|
||||
case user.FieldRestrictPublicGroups:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field restrict_public_groups", values[i])
|
||||
} else if value.Valid {
|
||||
_m.RestrictPublicGroups = value.Bool
|
||||
}
|
||||
case user.FieldBalanceNotifyEnabled:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field balance_notify_enabled", values[i])
|
||||
@@ -588,6 +596,9 @@ func (_m *User) String() string {
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("restrict_public_groups=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.RestrictPublicGroups))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("balance_notify_enabled=")
|
||||
builder.WriteString(fmt.Sprintf("%v", _m.BalanceNotifyEnabled))
|
||||
builder.WriteString(", ")
|
||||
|
||||
Reference in New Issue
Block a user