This commit is contained in:
WJQSERVER 2025-02-16 19:48:53 +08:00
parent bd666e08d1
commit 785a74dfeb
14 changed files with 241 additions and 126 deletions

View file

@ -18,10 +18,18 @@ var (
func Init(cfg *config.Config) {
if cfg.Blacklist.Enabled {
InitBlacklist(cfg)
err := InitBlacklist(cfg)
if err != nil {
logError(err.Error())
return
}
}
if cfg.Whitelist.Enabled {
LoadWhitelist(cfg)
err := InitWhitelist(cfg)
if err != nil {
logError(err.Error())
return
}
}
logDebug("Auth Init")
}

View file

@ -2,58 +2,90 @@ package auth
import (
"encoding/json"
"fmt"
"ghproxy/config"
"os"
"strings"
"sync"
)
type WhitelistConfig struct {
Whitelist []string `json:"whitelist"`
// Whitelist 用于存储白名单信息
type Whitelist struct {
userSet map[string]struct{} // 用户级白名单
repoSet map[string]map[string]struct{} // 仓库级白名单
initOnce sync.Once // 确保初始化只执行一次
initialized bool // 初始化状态标识
}
var (
whitelistfile = "/data/ghproxy/config/whitelist.json"
whitelist *WhitelistConfig
whitelistInstance *Whitelist
whitelistInitErr error
)
func LoadWhitelist(cfg *config.Config) {
whitelistfile = cfg.Whitelist.WhitelistFile
whitelist = &WhitelistConfig{}
// InitWhitelist 初始化白名单(线程安全,仅执行一次)
func InitWhitelist(cfg *config.Config) error {
whitelistInstance = &Whitelist{
userSet: make(map[string]struct{}),
repoSet: make(map[string]map[string]struct{}),
}
data, err := os.ReadFile(whitelistfile)
data, err := os.ReadFile(cfg.Whitelist.WhitelistFile)
if err != nil {
logError("Failed to read whitelist file: %v", err)
return fmt.Errorf("failed to read whitelist: %w", err)
}
err = json.Unmarshal(data, whitelist)
if err != nil {
logError("Failed to unmarshal whitelist JSON: %v", err)
var list struct {
Entries []string `json:"whitelist"`
}
}
func CheckWhitelist(fullrepo string, user string, repo string) bool {
return forRangeCheckWhitelist(whitelist.Whitelist, fullrepo, user)
}
func sliceRepoName_Whitelist(fullrepo string) (string, string) {
s := strings.Split(fullrepo, "/")
if len(s) != 2 {
return "", ""
if err := json.Unmarshal(data, &list); err != nil {
return fmt.Errorf("invalid whitelist format: %w", err)
}
return s[0], s[1]
}
func forRangeCheckWhitelist(wlist []string, fullrepo string, user string) bool {
for _, passd := range wlist {
users, _ := sliceRepoName_Whitelist(passd)
if users == user {
if strings.HasSuffix(passd, "/*") {
return true
}
if fullrepo == passd {
return true
for _, entry := range list.Entries {
user, repo := splitUserRepoWhitelist(entry)
switch {
case repo == "" || repo == "*":
whitelistInstance.userSet[user] = struct{}{}
default:
if _, exists := whitelistInstance.repoSet[user]; !exists {
whitelistInstance.repoSet[user] = make(map[string]struct{})
}
whitelistInstance.repoSet[user][repo] = struct{}{}
}
}
whitelistInstance.initialized = true
return nil
}
// CheckWhitelist 检查用户和仓库是否在白名单中(无锁设计)
func CheckWhitelist(username, repo string) bool {
if whitelistInstance == nil || !whitelistInstance.initialized {
return false
}
// 先检查用户级白名单
if _, exists := whitelistInstance.userSet[username]; exists {
return true
}
// 再检查仓库级白名单
if repos, userExists := whitelistInstance.repoSet[username]; userExists {
// 允许仓库名为空时的全用户仓库匹配
if repo == "" {
return true
}
_, repoExists := repos[repo]
return repoExists
}
return false
}
// splitUserRepoWhitelist 分割用户和仓库信息(仅初始化时使用)
func splitUserRepoWhitelist(fullRepo string) (user, repo string) {
if idx := strings.Index(fullRepo, "/"); idx > 0 {
return fullRepo[:idx], fullRepo[idx+1:]
}
return fullRepo, ""
}