Files
backend/internal/repository/verification_repo.go
lafay b2b55ea52d
All checks were successful
Build Backend / build (push) Successful in 1m56s
Build Backend / build-docker (push) Successful in 1m15s
feat: enhance security with IP banning, ownership checks, and SSRF protection
Add comprehensive security improvements across the application:

- **IP-based login protection**: Implement IP ban system tracking login failures, auto-banning after threshold exceeded
- **Ownership verification**: Add userID parameter to Delete/Update operations for posts and comments to prevent unauthorized modifications
- **SSRF protection**: Add URL and resolved host validation for image URLs in chat and OpenAI client
- **SQL injection prevention**: Add EscapeLikeWildcard utility to escape special characters in LIKE queries
- **HTTP security**: Configure server timeouts and add security headers middleware
- **Rate limiting**: Refactor to support configurable duration and per-endpoint rate limits for auth routes
- **Error handling**: Standardize error responses using HandleError and proper error types
2026-04-30 12:26:25 +08:00

109 lines
3.1 KiB
Go

package repository
import (
"with_you/internal/model"
"with_you/internal/pkg/utils"
"gorm.io/gorm"
)
type VerificationRepository interface {
Create(record *model.VerificationRecord) error
GetByID(id string) (*model.VerificationRecord, error)
GetLatestByUserID(userID string) (*model.VerificationRecord, error)
GetPendingByUserID(userID string) (*model.VerificationRecord, error)
List(page, pageSize int, status, keyword string) ([]*model.VerificationRecord, int64, error)
Update(record *model.VerificationRecord) error
GetRecordsByUserID(userID string, page, pageSize int) ([]*model.VerificationRecord, int64, error)
}
type verificationRepository struct {
db *gorm.DB
}
func NewVerificationRepository(db *gorm.DB) VerificationRepository {
return &verificationRepository{db: db}
}
func (r *verificationRepository) Create(record *model.VerificationRecord) error {
return r.db.Create(record).Error
}
func (r *verificationRepository) GetByID(id string) (*model.VerificationRecord, error) {
var record model.VerificationRecord
err := r.db.First(&record, "id = ?", id).Error
if err != nil {
return nil, err
}
return &record, nil
}
func (r *verificationRepository) GetLatestByUserID(userID string) (*model.VerificationRecord, error) {
var record model.VerificationRecord
err := r.db.Where("user_id = ?", userID).
Order("created_at DESC").
First(&record).Error
if err != nil {
return nil, err
}
return &record, nil
}
func (r *verificationRepository) GetPendingByUserID(userID string) (*model.VerificationRecord, error) {
var record model.VerificationRecord
err := r.db.Where("user_id = ? AND status = ?", userID, model.VerificationStatusPending).
First(&record).Error
if err != nil {
return nil, err
}
return &record, nil
}
func (r *verificationRepository) List(page, pageSize int, status, keyword string) ([]*model.VerificationRecord, int64, error) {
var records []*model.VerificationRecord
var total int64
query := r.db.Model(&model.VerificationRecord{})
if status != "" {
query = query.Where("verification_records.status = ?", status)
}
if keyword != "" {
kw := "%" + utils.EscapeLikeWildcard(keyword) + "%"
query = query.Joins("JOIN users ON users.id = verification_records.user_id").
Where("users.username LIKE ? OR users.nickname LIKE ? OR verification_records.real_name LIKE ?",
kw, kw, kw)
}
query.Count(&total)
offset := (page - 1) * pageSize
err := query.Order("created_at DESC").
Offset(offset).
Limit(pageSize).
Find(&records).Error
return records, total, err
}
func (r *verificationRepository) Update(record *model.VerificationRecord) error {
return r.db.Save(record).Error
}
func (r *verificationRepository) GetRecordsByUserID(userID string, page, pageSize int) ([]*model.VerificationRecord, int64, error) {
var records []*model.VerificationRecord
var total int64
query := r.db.Model(&model.VerificationRecord{}).Where("user_id = ?", userID)
query.Count(&total)
offset := (page - 1) * pageSize
err := query.Order("created_at DESC").
Offset(offset).
Limit(pageSize).
Find(&records).Error
return records, total, err
}