package system import ( "context" "kra/internal/biz/system" "time" "gorm.io/gorm" ) type loginLogPO struct { ID uint `gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` Username, IP string Status bool ErrorMessage, Agent string UserID uint } func (loginLogPO) TableName() string { return "sys_login_logs" } func (r *auditRecorderRepo) RecordLogin(ctx context.Context, v *system.LoginLog) error { if !r.data.DatabaseReady() { // The login endpoint remains reachable before database initialization; // skip the audit write until storage is ready. return nil } return r.data.DB().WithContext(ctx).Create(&loginLogPO{Username: v.Username, IP: v.IP, Status: v.Status, ErrorMessage: v.ErrorMessage, Agent: v.Agent, UserID: v.UserID}).Error } func loginFromPO(v loginLogPO) *system.LoginLog { return &system.LoginLog{ID: v.ID, CreatedAt: v.CreatedAt, UpdatedAt: v.UpdatedAt, Username: v.Username, IP: v.IP, Status: v.Status, ErrorMessage: v.ErrorMessage, Agent: v.Agent, UserID: v.UserID} } func (r *auditQueryRepo) ListLogins(ctx context.Context, page, size int, q *system.LoginLogFilter) ([]*system.LoginLog, int64, error) { db := r.data.DB().WithContext(ctx).Model(&loginLogPO{}) if q != nil { if q.Username != "" { db = db.Where("username LIKE ?", "%"+q.Username+"%") } if q.IP != "" { db = db.Where("ip LIKE ?", "%"+q.IP+"%") } if q.Status != nil { db = db.Where("status = ?", *q.Status) } if q.StartCreatedAt != nil { db = db.Where("created_at >= ?", *q.StartCreatedAt) } if q.EndCreatedAt != nil { db = db.Where("created_at <= ?", *q.EndCreatedAt) } } pos, total, err := queryRows[loginLogPO](db.Order("id desc"), page, size, true, true) if err != nil { return nil, 0, err } ids := make([]uint, 0, len(pos)) for _, value := range pos { if value.UserID != 0 { ids = append(ids, value.UserID) } } users := auditUsers(ctx, r.data.DB().WithContext(ctx), ids) out := make([]*system.LoginLog, 0, len(pos)) for _, po := range pos { value := loginFromPO(po) value.User = users[po.UserID] out = append(out, value) } return out, total, nil } func (r *auditQueryRepo) FindLogin(ctx context.Context, id uint) (*system.LoginLog, error) { var po loginLogPO if err := r.data.DB().WithContext(ctx).First(&po, id).Error; err != nil { return nil, err } return loginFromPO(po), nil } func (r *auditQueryRepo) DeleteLogins(ctx context.Context, ids []int) error { if len(ids) == 1 && ids[0] == 0 { return r.data.DB().WithContext(ctx).Delete(&loginLogPO{}).Error } return r.data.DB().WithContext(ctx).Delete(&loginLogPO{}, "id IN ?", ids).Error }