Files
gitea/models/user/admin_grant.go
T
petru 1e13af4d6e
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
Modified - Added install-time admin management policy choices with direct-grantor and inherited-grantor enforcement.
Modified - Updated the example app.ini documentation for the new administrator management policies.
2026-04-30 21:07:08 +00:00

107 lines
2.5 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package user
import (
"context"
"strconv"
)
const BootstrapAdminActorName = "GOOD"
func getUserSettingInt64(ctx context.Context, userID int64, key string) (int64, bool, error) {
value, err := GetUserSetting(ctx, userID, key)
if err != nil {
if IsErrUserSettingIsNotExist(err) {
return 0, false, nil
}
return 0, false, err
}
if value == "" {
return 0, false, nil
}
parsed, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0, false, err
}
return parsed, true, nil
}
func GetAdminGrantorID(ctx context.Context, userID int64) (int64, bool, error) {
return getUserSettingInt64(ctx, userID, SettingsKeyAdminGrantedBy)
}
func GetSuperAdminGrantorID(ctx context.Context, userID int64) (int64, bool, error) {
return getUserSettingInt64(ctx, userID, SettingsKeySuperAdminGrantedBy)
}
func HasBootstrapAdminGrant(ctx context.Context, userID int64) (bool, error) {
for _, key := range []string{SettingsKeyAdminGrantedByName, SettingsKeySuperAdminGrantedByName} {
value, err := GetUserSetting(ctx, userID, key)
if err != nil {
if IsErrUserSettingIsNotExist(err) {
continue
}
return false, err
}
if value == BootstrapAdminActorName {
return true, nil
}
}
return false, nil
}
func IsGrantorOf(ctx context.Context, grantedUserID, possibleGrantorID int64) (bool, error) {
for _, getter := range []func(context.Context, int64) (int64, bool, error){GetAdminGrantorID, GetSuperAdminGrantorID} {
grantorID, has, err := getter(ctx, grantedUserID)
if err != nil {
return false, err
}
if has && grantorID == possibleGrantorID {
return true, nil
}
}
return false, nil
}
func IsEligibleAdminGrantor(ctx context.Context, userID int64) (bool, error) {
u, err := GetUserByID(ctx, userID)
if err != nil {
if IsErrUserNotExist(err) {
return false, nil
}
return false, err
}
return u.IsAdmin && u.IsActive && !u.ProhibitLogin, nil
}
func GetEffectiveAdminGrantorID(ctx context.Context, userID int64) (int64, bool, error) {
visited := map[int64]struct{}{userID: {}}
currentUserID := userID
for {
grantorID, has, err := GetAdminGrantorID(ctx, currentUserID)
if err != nil {
return 0, false, err
}
if !has {
return 0, false, nil
}
if _, ok := visited[grantorID]; ok {
return 0, false, nil
}
visited[grantorID] = struct{}{}
eligible, err := IsEligibleAdminGrantor(ctx, grantorID)
if err != nil {
return 0, false, err
}
if eligible {
return grantorID, true, nil
}
currentUserID = grantorID
}
}