mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-30 14:26:36 +08:00
120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Package service implements domain business services and orchestration for the auth plugin.
|
|
package service
|
|
|
|
import (
|
|
"Wavelet/plugins/domain/auth/consts"
|
|
"Wavelet/plugins/domain/auth/dao"
|
|
"Wavelet/plugins/domain/auth/model/do"
|
|
"context"
|
|
"errors"
|
|
"sync/atomic"
|
|
|
|
"golang.org/x/sync/singleflight"
|
|
)
|
|
|
|
var capRuntimeConfigKeys = []string{
|
|
consts.ConfigKeyCapLoginEnabled,
|
|
consts.ConfigKeyCapChallengeCount,
|
|
consts.ConfigKeyCapChallengeSize,
|
|
consts.ConfigKeyCapChallengeDifficulty,
|
|
consts.ConfigKeyCapChallengeTTL,
|
|
consts.ConfigKeyCapTokenTTL,
|
|
}
|
|
|
|
var capRuntimeConfigKeySet = func() map[string]struct{} {
|
|
set := make(map[string]struct{}, len(capRuntimeConfigKeys))
|
|
for _, key := range capRuntimeConfigKeys {
|
|
set[key] = struct{}{}
|
|
}
|
|
return set
|
|
}()
|
|
|
|
// IsCapRuntimeConfigKey reports whether a system config key affects CAPTCHA runtime settings.
|
|
func IsCapRuntimeConfigKey(key string) bool {
|
|
_, ok := capRuntimeConfigKeySet[key]
|
|
return ok
|
|
}
|
|
|
|
// CapSettingsManager manages dynamic CAPTCHA configuration cache.
|
|
type CapSettingsManager struct {
|
|
dao *dao.DAO
|
|
snapshot atomic.Pointer[do.CapRuntimeSettings]
|
|
loadGroup singleflight.Group
|
|
}
|
|
|
|
// NewCapSettingsManager creates a new CapSettingsManager.
|
|
func NewCapSettingsManager(d *dao.DAO) *CapSettingsManager {
|
|
return &CapSettingsManager{
|
|
dao: d,
|
|
}
|
|
}
|
|
|
|
// Invalidate drops the in-process CAPTCHA settings snapshot.
|
|
func (m *CapSettingsManager) Invalidate() {
|
|
m.snapshot.Store(nil)
|
|
}
|
|
|
|
// Current returns the cached CAPTCHA runtime settings snapshot.
|
|
func (m *CapSettingsManager) Current(ctx context.Context) (do.CapRuntimeSettings, error) {
|
|
if snapshot := m.snapshot.Load(); snapshot != nil {
|
|
return *snapshot, nil
|
|
}
|
|
|
|
loaded, err, _ := m.loadGroup.Do("cap-runtime-settings", func() (any, error) {
|
|
if snapshot := m.snapshot.Load(); snapshot != nil {
|
|
return *snapshot, nil
|
|
}
|
|
|
|
settings, loadErr := m.loadSettings(ctx)
|
|
if loadErr != nil {
|
|
return do.CapRuntimeSettings{}, loadErr
|
|
}
|
|
|
|
m.snapshot.Store(&settings)
|
|
return settings, nil
|
|
})
|
|
if err != nil {
|
|
return do.CapRuntimeSettings{}, err
|
|
}
|
|
|
|
settings, ok := loaded.(do.CapRuntimeSettings)
|
|
if !ok {
|
|
return do.CapRuntimeSettings{}, errors.New("cap runtime settings loader returned unexpected type")
|
|
}
|
|
return settings, nil
|
|
}
|
|
|
|
// CapProtectionEnabled reports whether CAPTCHA verification is required for protected routes.
|
|
func (m *CapSettingsManager) CapProtectionEnabled(ctx context.Context) bool {
|
|
settings, err := m.Current(ctx)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return settings.LoginEnabled
|
|
}
|
|
|
|
// InstallTestSnapshot installs a fixed snapshot for unit tests.
|
|
func (m *CapSettingsManager) InstallTestSnapshot(settings do.CapRuntimeSettings) func() {
|
|
snapshot := settings
|
|
m.snapshot.Store(&snapshot)
|
|
return m.Invalidate
|
|
}
|
|
|
|
func (m *CapSettingsManager) loadSettings(ctx context.Context) (do.CapRuntimeSettings, error) {
|
|
if m.dao == nil {
|
|
return do.ParseCapRuntimeSettings(nil), nil
|
|
}
|
|
records, err := m.dao.ListSystemConfigsByKeys(ctx, capRuntimeConfigKeys)
|
|
if err != nil {
|
|
return do.CapRuntimeSettings{}, err
|
|
}
|
|
configs := make(map[string]string, len(records))
|
|
for _, r := range records {
|
|
configs[r.Key] = r.Value
|
|
}
|
|
return do.ParseCapRuntimeSettings(configs), nil
|
|
}
|