package models import ( "database/sql" "fmt" "time" "simple_portal/database" ) // IPBan 表示一条IP封禁记录。 type IPBan struct { ID int `json:"id"` IP string `json:"ip"` Reason string `json:"reason"` FailCount int `json:"fail_count"` BannedUntil time.Time `json:"banned_until"` CreatedAt time.Time `json:"created_at"` } // IsIPBanned 检查指定IP是否处于封禁状态(未过期)。 // 白名单IP不会被检查,需要在调用前自行判断。 func IsIPBanned(ip string) (bool, *IPBan, error) { var ban IPBan err := database.DB.QueryRow( "SELECT id, ip, reason, fail_count, banned_until, created_at FROM ip_bans WHERE ip = ? AND banned_until > ? ORDER BY banned_until DESC LIMIT 1", ip, time.Now().Format("2006-01-02 15:04:05"), ).Scan(&ban.ID, &ban.IP, &ban.Reason, &ban.FailCount, &ban.BannedUntil, &ban.CreatedAt) if err == sql.ErrNoRows { return false, nil, nil } if err != nil { return false, nil, fmt.Errorf("failed to check IP ban: %w", err) } return true, &ban, nil } // CreateIPBan 插入一条IP封禁记录。 func CreateIPBan(ip, reason string, failCount int, bannedUntil time.Time) error { _, err := database.DB.Exec( "INSERT INTO ip_bans (ip, reason, fail_count, banned_until, created_at) VALUES (?, ?, ?, ?, ?)", ip, reason, failCount, bannedUntil.Format("2006-01-02 15:04:05"), time.Now().Format("2006-01-02 15:04:05"), ) if err != nil { return fmt.Errorf("failed to create IP ban: %w", err) } return nil } // GetAllActiveBans 获取所有未过期的封禁记录。 func GetAllActiveBans() ([]IPBan, error) { rows, err := database.DB.Query( "SELECT id, ip, reason, fail_count, banned_until, created_at FROM ip_bans WHERE banned_until > ? ORDER BY banned_until DESC", time.Now().Format("2006-01-02 15:04:05"), ) if err != nil { return nil, fmt.Errorf("failed to query active bans: %w", err) } defer rows.Close() var bans []IPBan for rows.Next() { var b IPBan if err := rows.Scan(&b.ID, &b.IP, &b.Reason, &b.FailCount, &b.BannedUntil, &b.CreatedAt); err != nil { return nil, fmt.Errorf("failed to scan IP ban: %w", err) } bans = append(bans, b) } return bans, nil } // DeleteIPBan 删除一条封禁记录(手动解封)。 func DeleteIPBan(id int) error { _, err := database.DB.Exec("DELETE FROM ip_bans WHERE id = ?", id) if err != nil { return fmt.Errorf("failed to delete IP ban: %w", err) } return nil }