mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
更新底层架构
This commit is contained in:
117
services/log_cleanup.go
Normal file
117
services/log_cleanup.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"NetworkAuth/database"
|
||||
"NetworkAuth/models"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// StartLogCleanupTask 启动日志清理定时任务
|
||||
// 每天执行一次,且服务启动后也会尝试执行一次
|
||||
func StartLogCleanupTask() {
|
||||
go func() {
|
||||
// 启动后延迟1分钟执行首次清理,避免影响启动速度
|
||||
time.Sleep(1 * time.Minute)
|
||||
cleanupLogs()
|
||||
|
||||
// 每天执行一次
|
||||
ticker := time.NewTicker(24 * time.Hour)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
cleanupLogs()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func cleanupLogs() {
|
||||
logrus.Debug("开始执行日志清理任务...")
|
||||
|
||||
// 获取清理配置 (使用实时查询)
|
||||
loginLogDays := getSettingInt("login_log_cleanup_days", 30)
|
||||
loginLogLimit := getSettingInt("login_log_cleanup_limit", 10000)
|
||||
operationLogDays := getSettingInt("operation_log_cleanup_days", 30)
|
||||
operationLogLimit := getSettingInt("operation_log_cleanup_limit", 10000)
|
||||
|
||||
// 清理登录日志
|
||||
if err := cleanupTable(&models.LoginLog{}, loginLogDays, loginLogLimit); err != nil {
|
||||
logrus.WithError(err).Error("清理登录日志失败")
|
||||
}
|
||||
|
||||
// 清理操作日志
|
||||
if err := cleanupTable(&models.OperationLog{}, operationLogDays, operationLogLimit); err != nil {
|
||||
logrus.WithError(err).Error("清理操作日志失败")
|
||||
}
|
||||
|
||||
logrus.Debug("日志清理任务执行完成")
|
||||
}
|
||||
|
||||
// getSettingInt 获取配置整数值
|
||||
func getSettingInt(key string, defaultValue int) int {
|
||||
setting, err := GetSettingsService().GetSettingRealtime(key)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
val, err := strconv.Atoi(setting.Value)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// cleanupTable 通用清理函数
|
||||
func cleanupTable(model interface{}, retentionDays int, maxCount int) error {
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 1. 按天清理
|
||||
if retentionDays > 0 {
|
||||
cutoffDate := time.Now().AddDate(0, 0, -retentionDays)
|
||||
result := db.Unscoped().Where("created_at < ?", cutoffDate).Delete(model)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("按天清理失败: %w", result.Error)
|
||||
}
|
||||
if result.RowsAffected > 0 {
|
||||
logrus.Debugf("清理日志 (按天): 删除 %d 条记录", result.RowsAffected)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 按数量清理
|
||||
if maxCount > 0 {
|
||||
count, err := CountEntitiesByCondition(model, "", db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询总数失败: %w", err)
|
||||
}
|
||||
|
||||
if count > int64(maxCount) {
|
||||
// 找出保留范围内的最后一条记录(第 maxCount 条,按时间倒序)
|
||||
var keepRecord struct {
|
||||
ID uint
|
||||
}
|
||||
|
||||
// 假设 ID 是自增的主键,且 ID 越大代表记录越新
|
||||
if err := db.Model(model).Select("id").Order("id DESC").Offset(maxCount - 1).Limit(1).Scan(&keepRecord).Error; err != nil {
|
||||
return fmt.Errorf("查询分界记录失败: %w", err)
|
||||
}
|
||||
|
||||
if keepRecord.ID > 0 {
|
||||
result := db.Unscoped().Where("id < ?", keepRecord.ID).Delete(model)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("按数量清理失败: %w", result.Error)
|
||||
}
|
||||
if result.RowsAffected > 0 {
|
||||
logrus.Debugf("清理日志 (按数量): 删除 %d 条记录", result.RowsAffected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
33
services/operation_log.go
Normal file
33
services/operation_log.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"NetworkAuth/database"
|
||||
"NetworkAuth/models"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// RecordOperationLog 记录操作日志
|
||||
func RecordOperationLog(operationType, operator, operatorUUID, transactionID, appName, productName, details string) {
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("获取数据库连接失败,无法记录操作日志")
|
||||
return
|
||||
}
|
||||
|
||||
log := models.OperationLog{
|
||||
OperationType: operationType,
|
||||
Operator: operator,
|
||||
OperatorUUID: operatorUUID,
|
||||
TransactionID: transactionID,
|
||||
AppName: appName,
|
||||
ProductName: productName,
|
||||
Details: details,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := db.Create(&log).Error; err != nil {
|
||||
logrus.WithError(err).Error("创建操作日志失败")
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"NetworkAuth/models"
|
||||
"NetworkAuth/utils"
|
||||
"context"
|
||||
"fmt"
|
||||
"networkDev/models"
|
||||
"networkDev/utils"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -69,7 +69,11 @@ func BatchUpdateEntityStatus(model interface{}, ids []uint, status int, db *gorm
|
||||
// 返回: 数量和错误
|
||||
func CountEntitiesByCondition(model interface{}, condition string, db *gorm.DB, args ...interface{}) (int64, error) {
|
||||
var count int64
|
||||
err := db.Model(model).Where(condition, args...).Count(&count).Error
|
||||
query := db.Model(model)
|
||||
if condition != "" {
|
||||
query = query.Where(condition, args...)
|
||||
}
|
||||
err := query.Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
@@ -85,7 +89,11 @@ func CountEntitiesByCondition(model interface{}, condition string, db *gorm.DB,
|
||||
// args: 查询参数
|
||||
// 返回: 错误
|
||||
func FindEntitiesByCondition(model interface{}, result interface{}, condition string, db *gorm.DB, args ...interface{}) error {
|
||||
return db.Model(model).Where(condition, args...).Find(result).Error
|
||||
query := db.Model(model)
|
||||
if condition != "" {
|
||||
query = query.Where(condition, args...)
|
||||
}
|
||||
return query.Find(result).Error
|
||||
}
|
||||
|
||||
// CheckEntityExists 检查实体是否存在
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"networkDev/database"
|
||||
"networkDev/models"
|
||||
"NetworkAuth/database"
|
||||
"NetworkAuth/models"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
@@ -53,6 +53,10 @@ func (s *SettingsService) loadAllSettings() {
|
||||
logrus.WithError(err).Error("获取数据库连接失败")
|
||||
return
|
||||
}
|
||||
// 如果数据库未初始化,直接返回,保持缓存为空
|
||||
if db == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var settings []models.Settings
|
||||
if err := db.Find(&settings).Error; err != nil {
|
||||
@@ -67,7 +71,24 @@ func (s *SettingsService) loadAllSettings() {
|
||||
s.cache[setting.Name] = setting.Value
|
||||
}
|
||||
|
||||
logrus.WithField("count", len(settings)).Info("设置缓存加载完成")
|
||||
logrus.WithField("count", len(settings)).Debug("设置缓存加载完成")
|
||||
}
|
||||
|
||||
// Set 设置值(用于测试或运行时更新)
|
||||
func (s *SettingsService) Set(name, value string) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.cache[name] = value
|
||||
}
|
||||
|
||||
// GetSettingRealtime 实时获取设置值(优先使用Redis缓存,自动回源数据库)
|
||||
// 相比 GetString 的内存缓存,此方法能感知其他实例或直接数据库的变更(在Redis TTL过期后)
|
||||
func (s *SettingsService) GetSettingRealtime(name string) (*models.Settings, error) {
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return FindSettingByName(name, db)
|
||||
}
|
||||
|
||||
// GetString 获取字符串类型的设置值
|
||||
@@ -118,3 +139,32 @@ func (s *SettingsService) GetSessionTimeout() int {
|
||||
func (s *SettingsService) IsMaintenanceMode() bool {
|
||||
return s.GetBool("maintenance_mode", false)
|
||||
}
|
||||
|
||||
// GetJWTSecret 获取JWT密钥
|
||||
func (s *SettingsService) GetJWTSecret() string {
|
||||
return s.GetString("jwt_secret", "")
|
||||
}
|
||||
|
||||
// GetEncryptionKey 获取加密密钥
|
||||
func (s *SettingsService) GetEncryptionKey() string {
|
||||
return s.GetString("encryption_key", "")
|
||||
}
|
||||
|
||||
// GetJWTRefresh 获取JWT刷新时间(小时)
|
||||
func (s *SettingsService) GetJWTRefresh() int {
|
||||
return s.GetInt("jwt_refresh", 6)
|
||||
}
|
||||
|
||||
// GetJWTExpire 获取JWT有效期(小时)
|
||||
func (s *SettingsService) GetJWTExpire() int {
|
||||
return s.GetInt("jwt_expire", 24)
|
||||
}
|
||||
|
||||
// GetCookieConfig 获取Cookie配置
|
||||
func (s *SettingsService) GetCookieConfig() (secure bool, sameSite string, domain string, maxAge int) {
|
||||
secure = s.GetBool("cookie_secure", true)
|
||||
sameSite = s.GetString("cookie_same_site", "Lax")
|
||||
domain = s.GetString("cookie_domain", "")
|
||||
maxAge = s.GetInt("cookie_max_age", 86400)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user