170 lines
3.6 KiB
Go
170 lines
3.6 KiB
Go
package repo
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"trustcontact/internal/models"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type UserRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
type UserListParams struct {
|
|
Query string
|
|
Sort string
|
|
Dir string
|
|
Page int
|
|
PageSize int
|
|
}
|
|
|
|
func NewUserRepo(db *gorm.DB) *UserRepo {
|
|
return &UserRepo{db: db}
|
|
}
|
|
|
|
func (r *UserRepo) FindByID(id string) (*models.User, error) {
|
|
var user models.User
|
|
if err := r.db.Preload("Properties").Where("id = ?", id).First(&user).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
func (r *UserRepo) FindByEmail(email string) (*models.User, error) {
|
|
var user models.User
|
|
if err := r.db.Preload("Properties").Where("email = ?", email).First(&user).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
func (r *UserRepo) Create(user *models.User) error {
|
|
return r.db.Create(user).Error
|
|
}
|
|
|
|
func (r *UserRepo) SetEmailVerified(userID string, verified bool) error {
|
|
return r.db.Model(&models.User{}).
|
|
Where("id = ?", userID).
|
|
Update("email_verified", verified).Error
|
|
}
|
|
|
|
func (r *UserRepo) UpdatePasswordHash(userID string, passwordHash string) error {
|
|
return r.db.Model(&models.User{}).
|
|
Where("id = ?", userID).
|
|
Update("password_hash", passwordHash).Error
|
|
}
|
|
|
|
func (r *UserRepo) UpsertLanguagePreference(userID string, lang string) error {
|
|
var existing models.UserProperties
|
|
err := r.db.Where("user_id = ?", userID).First(&existing).Error
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return err
|
|
}
|
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
props := models.UserProperties{
|
|
UserId: userID,
|
|
Lang: lang,
|
|
}
|
|
return r.db.Create(&props).Error
|
|
}
|
|
|
|
return r.db.Model(&models.UserProperties{}).
|
|
Where("user_id = ?", userID).
|
|
Update("lang", lang).Error
|
|
}
|
|
|
|
func (r *UserRepo) UpsertDarkPreference(userID string, dark bool) error {
|
|
var existing models.UserProperties
|
|
err := r.db.Where("user_id = ?", userID).First(&existing).Error
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return err
|
|
}
|
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
props := models.UserProperties{
|
|
UserId: userID,
|
|
Dark: dark,
|
|
}
|
|
return r.db.Create(&props).Error
|
|
}
|
|
|
|
return r.db.Model(&models.UserProperties{}).
|
|
Where("user_id = ?", userID).
|
|
Update("dark", dark).Error
|
|
}
|
|
|
|
func (r *UserRepo) List(params UserListParams) ([]models.User, int64, error) {
|
|
query := r.db.Model(&models.User{})
|
|
|
|
search := strings.TrimSpace(params.Query)
|
|
if search != "" {
|
|
like := "%" + strings.ToLower(search) + "%"
|
|
query = query.Where("LOWER(name) LIKE ? OR LOWER(email) LIKE ?", like, like)
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
orderBy := sanitizeSort(params.Sort)
|
|
orderDir := sanitizeDir(params.Dir)
|
|
orderClause := fmt.Sprintf("%s %s", orderBy, orderDir)
|
|
|
|
page := params.Page
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
pageSize := params.PageSize
|
|
if pageSize <= 0 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 500 {
|
|
pageSize = 500
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
|
|
var users []models.User
|
|
if err := query.Order(orderClause).Limit(pageSize).Offset(offset).Find(&users).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return users, total, nil
|
|
}
|
|
|
|
func sanitizeSort(sort string) string {
|
|
switch strings.ToLower(strings.TrimSpace(sort)) {
|
|
case "id":
|
|
return "id"
|
|
case "name":
|
|
return "name"
|
|
case "email":
|
|
return "email"
|
|
default:
|
|
return "id"
|
|
}
|
|
}
|
|
|
|
func sanitizeDir(dir string) string {
|
|
switch strings.ToLower(strings.TrimSpace(dir)) {
|
|
case "desc":
|
|
return "desc"
|
|
default:
|
|
return "asc"
|
|
}
|
|
}
|