stato intermedio
This commit is contained in:
@@ -208,3 +208,63 @@ func (ac *AuthController) ResetPassword(c *fiber.Ctx) error {
|
||||
}
|
||||
return c.Redirect("/login")
|
||||
}
|
||||
|
||||
func (ac *AuthController) UpdateLanguage(c *fiber.Ctx) error {
|
||||
currentUser, ok := httpmw.CurrentUserFromContext(c)
|
||||
if !ok {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
type langRequest struct {
|
||||
Lang string `json:"lang" form:"lang"`
|
||||
}
|
||||
|
||||
var req langRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
req.Lang = c.FormValue("lang")
|
||||
}
|
||||
|
||||
lang := services.NormalizeLanguage(req.Lang)
|
||||
if !services.IsSupportedLanguage(lang) {
|
||||
return c.Status(fiber.StatusBadRequest).SendString("invalid language")
|
||||
}
|
||||
|
||||
if err := ac.authService.UpdateUserLanguage(currentUser.ID, lang); err != nil {
|
||||
if errors.Is(err, services.ErrInvalidLanguage) {
|
||||
return c.Status(fiber.StatusBadRequest).SendString("invalid language")
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).SendString("cannot update language")
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func (ac *AuthController) UpdateTheme(c *fiber.Ctx) error {
|
||||
currentUser, ok := httpmw.CurrentUserFromContext(c)
|
||||
if !ok {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
type themeRequest struct {
|
||||
Theme string `json:"theme" form:"theme"`
|
||||
}
|
||||
|
||||
var req themeRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
req.Theme = c.FormValue("theme")
|
||||
}
|
||||
|
||||
theme := services.NormalizeTheme(req.Theme)
|
||||
if theme != "dark" && theme != "light" {
|
||||
return c.Status(fiber.StatusBadRequest).SendString("invalid theme")
|
||||
}
|
||||
|
||||
if err := ac.authService.UpdateUserTheme(currentUser.ID, theme); err != nil {
|
||||
if errors.Is(err, services.ErrInvalidTheme) {
|
||||
return c.Status(fiber.StatusBadRequest).SendString("invalid theme")
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).SendString("cannot update theme")
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
@@ -68,12 +68,12 @@ func (uc *UsersController) Table(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
func (uc *UsersController) Modal(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
id := strings.TrimSpace(c.Params("id"))
|
||||
if id == "" {
|
||||
return c.Status(fiber.StatusBadRequest).SendString("invalid user id")
|
||||
}
|
||||
|
||||
user, err := uc.usersService.GetByID(uint(id))
|
||||
user, err := uc.usersService.GetByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@ func Migrate(database *gorm.DB) error {
|
||||
&models.User{},
|
||||
&models.EmailVerificationToken{},
|
||||
&models.PasswordResetToken{},
|
||||
&models.UserProperties{},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@ func Seed(database *gorm.DB) error {
|
||||
Role: models.RoleAdmin,
|
||||
EmailVerified: true,
|
||||
PasswordHash: passwordHash,
|
||||
Properties: models.UserProperties{
|
||||
Lang: "en",
|
||||
Dark: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Normal User",
|
||||
@@ -30,6 +34,10 @@ func Seed(database *gorm.DB) error {
|
||||
Role: models.RoleUser,
|
||||
EmailVerified: true,
|
||||
PasswordHash: passwordHash,
|
||||
Properties: models.UserProperties{
|
||||
Lang: "it",
|
||||
Dark: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Demo One",
|
||||
@@ -37,6 +45,10 @@ func Seed(database *gorm.DB) error {
|
||||
Role: models.RoleUser,
|
||||
EmailVerified: true,
|
||||
PasswordHash: passwordHash,
|
||||
Properties: models.UserProperties{
|
||||
Lang: "en",
|
||||
Dark: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Demo Two",
|
||||
@@ -44,6 +56,10 @@ func Seed(database *gorm.DB) error {
|
||||
Role: models.RoleUser,
|
||||
EmailVerified: true,
|
||||
PasswordHash: passwordHash,
|
||||
Properties: models.UserProperties{
|
||||
Lang: "en",
|
||||
Dark: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Demo Three",
|
||||
@@ -51,11 +67,20 @@ func Seed(database *gorm.DB) error {
|
||||
Role: models.RoleUser,
|
||||
EmailVerified: true,
|
||||
PasswordHash: passwordHash,
|
||||
Properties: models.UserProperties{
|
||||
Lang: "en",
|
||||
Dark: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, user := range seedUsers {
|
||||
if err := upsertUser(database, user); err != nil {
|
||||
userID, err := upsertUser(database, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.Properties.UserId = userID
|
||||
if err := upsertUserProperties(database, user.Properties, user.Email); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -63,7 +88,7 @@ func Seed(database *gorm.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func upsertUser(database *gorm.DB, user models.User) error {
|
||||
func upsertUser(database *gorm.DB, user models.User) (string, error) {
|
||||
result := database.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "email"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{
|
||||
@@ -73,9 +98,26 @@ func upsertUser(database *gorm.DB, user models.User) error {
|
||||
"password_hash",
|
||||
"updated_at",
|
||||
}),
|
||||
}).Create(&user)
|
||||
}).Omit("Properties").Create(&user)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("seed user %s: %w", user.Email, result.Error)
|
||||
return "", fmt.Errorf("seed user %s: %w", user.Email, result.Error)
|
||||
}
|
||||
|
||||
var persisted models.User
|
||||
if err := database.Select("id").Where("email = ?", user.Email).First(&persisted).Error; err != nil {
|
||||
return "", fmt.Errorf("load seeded user %s: %w", user.Email, err)
|
||||
}
|
||||
|
||||
return persisted.ID, nil
|
||||
}
|
||||
|
||||
func upsertUserProperties(database *gorm.DB, props models.UserProperties, userEmail string) error {
|
||||
result := database.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "user_id"}},
|
||||
DoNothing: true,
|
||||
}).Create(&props)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("seed user properties %s: %w", userEmail, result.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -31,7 +31,7 @@ func RequireAdmin() fiber.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
func SetSessionUserID(c *fiber.Ctx, userID uint) error {
|
||||
func SetSessionUserID(c *fiber.Ctx, userID string) error {
|
||||
store, ok := c.Locals(contextStoreKey).(*session.Store)
|
||||
if !ok || store == nil {
|
||||
return errors.New("session store not available")
|
||||
|
||||
@@ -2,7 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"trustcontact/internal/models"
|
||||
"trustcontact/internal/repo"
|
||||
@@ -37,6 +37,21 @@ func CurrentUserMiddleware(store *session.Store, database *gorm.DB) fiber.Handle
|
||||
|
||||
c.Locals(contextUserKey, user)
|
||||
setTemplateData(c, "CurrentUser", user)
|
||||
if user != nil {
|
||||
setTemplateData(c, "UserLang", strings.TrimSpace(user.Properties.Lang))
|
||||
if user.Properties.UserId != "" {
|
||||
if user.Properties.Dark {
|
||||
setTemplateData(c, "UserTheme", "dark")
|
||||
} else {
|
||||
setTemplateData(c, "UserTheme", "light")
|
||||
}
|
||||
} else {
|
||||
setTemplateData(c, "UserTheme", "")
|
||||
}
|
||||
} else {
|
||||
setTemplateData(c, "UserLang", "")
|
||||
setTemplateData(c, "UserTheme", "")
|
||||
}
|
||||
return c.Next()
|
||||
}
|
||||
}
|
||||
@@ -49,7 +64,7 @@ func CurrentUser(c *fiber.Ctx, store *session.Store, userRepo *repo.UserRepo) (*
|
||||
|
||||
uidRaw := sess.Get(sessionUserIDKey)
|
||||
uid, ok := normalizeUserID(uidRaw)
|
||||
if !ok || uid == 0 {
|
||||
if !ok || uid == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -77,37 +92,16 @@ func CurrentUserFromContext(c *fiber.Ctx) (*models.User, bool) {
|
||||
return user, true
|
||||
}
|
||||
|
||||
func normalizeUserID(v any) (uint, bool) {
|
||||
func normalizeUserID(v any) (string, bool) {
|
||||
switch value := v.(type) {
|
||||
case uint:
|
||||
return value, true
|
||||
case uint64:
|
||||
return uint(value), true
|
||||
case uint32:
|
||||
return uint(value), true
|
||||
case int:
|
||||
if value <= 0 {
|
||||
return 0, false
|
||||
}
|
||||
return uint(value), true
|
||||
case int64:
|
||||
if value <= 0 {
|
||||
return 0, false
|
||||
}
|
||||
return uint(value), true
|
||||
case int32:
|
||||
if value <= 0 {
|
||||
return 0, false
|
||||
}
|
||||
return uint(value), true
|
||||
case string:
|
||||
parsed, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil || parsed == 0 {
|
||||
return 0, false
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if trimmed == "" {
|
||||
return "", false
|
||||
}
|
||||
return uint(parsed), true
|
||||
return trimmed, true
|
||||
default:
|
||||
return 0, false
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ func RegisterRoutes(app *fiber.App, store *session.Store, database *gorm.DB, cfg
|
||||
app.Post("/reset-password", authController.ResetPassword)
|
||||
app.Get("/forbidden", authController.ShowForbidden)
|
||||
app.Get("/welcome", httpmw.RequireAuth(), authController.ShowWelcome)
|
||||
app.Post("/preferences/lang", httpmw.RequireAuth(), authController.UpdateLanguage)
|
||||
app.Post("/preferences/theme", httpmw.RequireAuth(), authController.UpdateTheme)
|
||||
|
||||
private := app.Group("/private", httpmw.RequireAuth(), httpmw.RequireAdmin())
|
||||
private.Get("/", func(c *fiber.Ctx) error {
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type EmailVerificationToken struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
UserID uint `gorm:"not null;index"`
|
||||
ID string `gorm:"primaryKey"`
|
||||
UserID string `gorm:"not null;index"`
|
||||
TokenHash string `gorm:"size:64;uniqueIndex;not null"`
|
||||
ExpiresAt time.Time `gorm:"not null;index"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (token *EmailVerificationToken) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// UUID version 4
|
||||
token.ID = uuid.NewString()
|
||||
return
|
||||
}
|
||||
|
||||
type PasswordResetToken struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
UserID uint `gorm:"not null;index"`
|
||||
ID string `gorm:"primaryKey"`
|
||||
UserID string `gorm:"not null;index"`
|
||||
TokenHash string `gorm:"size:64;uniqueIndex;not null"`
|
||||
ExpiresAt time.Time `gorm:"not null;index"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (token *PasswordResetToken) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// UUID version 4
|
||||
token.ID = uuid.NewString()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
RoleAdmin = "admin"
|
||||
@@ -8,12 +13,25 @@ const (
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
Name string `gorm:"size:120;index"`
|
||||
Email string `gorm:"size:320;uniqueIndex;not null"`
|
||||
PasswordHash string `gorm:"size:255;not null"`
|
||||
EmailVerified bool `gorm:"not null;default:false"`
|
||||
Role string `gorm:"size:32;index;not null;default:user"`
|
||||
ID string `gorm:"primaryKey"`
|
||||
Name string `gorm:"size:120;index"`
|
||||
Email string `gorm:"size:320;uniqueIndex;not null"`
|
||||
PasswordHash string `gorm:"size:255;not null"`
|
||||
EmailVerified bool `gorm:"not null;default:false"`
|
||||
Role string `gorm:"size:32;index;not null;default:user"`
|
||||
Properties UserProperties `gorm:"foreignKey:UserId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// UUID version 4
|
||||
user.ID = uuid.NewString()
|
||||
return
|
||||
}
|
||||
|
||||
type UserProperties struct {
|
||||
UserId string `json:"user_id" gorm:"uniqueIndex"`
|
||||
Lang string `json:"lang"`
|
||||
Dark bool `json:"dark"`
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ func (r *EmailVerificationTokenRepo) FindValidByHash(tokenHash string, now time.
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
func (r *EmailVerificationTokenRepo) DeleteByID(id uint) error {
|
||||
func (r *EmailVerificationTokenRepo) DeleteByID(id string) error {
|
||||
return r.db.Delete(&models.EmailVerificationToken{}, id).Error
|
||||
}
|
||||
|
||||
func (r *EmailVerificationTokenRepo) DeleteByUserID(userID uint) error {
|
||||
func (r *EmailVerificationTokenRepo) DeleteByUserID(userID string) error {
|
||||
return r.db.Where("user_id = ?", userID).Delete(&models.EmailVerificationToken{}).Error
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ func (r *PasswordResetTokenRepo) FindValidByHash(tokenHash string, now time.Time
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
func (r *PasswordResetTokenRepo) DeleteByID(id uint) error {
|
||||
func (r *PasswordResetTokenRepo) DeleteByID(id string) error {
|
||||
return r.db.Delete(&models.PasswordResetToken{}, id).Error
|
||||
}
|
||||
|
||||
func (r *PasswordResetTokenRepo) DeleteByUserID(userID uint) error {
|
||||
func (r *PasswordResetTokenRepo) DeleteByUserID(userID string) error {
|
||||
return r.db.Where("user_id = ?", userID).Delete(&models.PasswordResetToken{}).Error
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ func NewUserRepo(db *gorm.DB) *UserRepo {
|
||||
return &UserRepo{db: db}
|
||||
}
|
||||
|
||||
func (r *UserRepo) FindByID(id uint) (*models.User, error) {
|
||||
func (r *UserRepo) FindByID(id string) (*models.User, error) {
|
||||
var user models.User
|
||||
if err := r.db.First(&user, id).Error; err != nil {
|
||||
if err := r.db.Preload("Properties").Where("id = ?", id).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func (r *UserRepo) FindByID(id uint) (*models.User, error) {
|
||||
|
||||
func (r *UserRepo) FindByEmail(email string) (*models.User, error) {
|
||||
var user models.User
|
||||
if err := r.db.Where("email = ?", email).First(&user).Error; err != nil {
|
||||
if err := r.db.Preload("Properties").Where("email = ?", email).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -54,18 +54,58 @@ func (r *UserRepo) Create(user *models.User) error {
|
||||
return r.db.Create(user).Error
|
||||
}
|
||||
|
||||
func (r *UserRepo) SetEmailVerified(userID uint, verified bool) 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 uint, passwordHash string) 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{})
|
||||
|
||||
@@ -92,8 +132,8 @@ func (r *UserRepo) List(params UserListParams) ([]models.User, int64, error) {
|
||||
if pageSize <= 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
if pageSize > 100 {
|
||||
pageSize = 100
|
||||
if pageSize > 500 {
|
||||
pageSize = 500
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
@@ -22,8 +22,20 @@ var (
|
||||
ErrInvalidCredentials = errors.New("invalid credentials")
|
||||
ErrEmailNotVerified = errors.New("email not verified")
|
||||
ErrInvalidOrExpiredToken = errors.New("invalid or expired token")
|
||||
ErrInvalidLanguage = errors.New("invalid language")
|
||||
ErrInvalidTheme = errors.New("invalid theme")
|
||||
)
|
||||
|
||||
var supportedLanguages = map[string]struct{}{
|
||||
"it": {},
|
||||
"en": {},
|
||||
"en_us": {},
|
||||
"de": {},
|
||||
"fr": {},
|
||||
"de_ch": {},
|
||||
"fr_ch": {},
|
||||
}
|
||||
|
||||
type AuthService struct {
|
||||
cfg *config.Config
|
||||
users *repo.UserRepo
|
||||
@@ -187,6 +199,23 @@ func (s *AuthService) ResetPassword(token, newPassword string) error {
|
||||
return s.resetTokens.DeleteByID(record.ID)
|
||||
}
|
||||
|
||||
func (s *AuthService) UpdateUserLanguage(userID string, lang string) error {
|
||||
normalized := NormalizeLanguage(lang)
|
||||
if !IsSupportedLanguage(normalized) {
|
||||
return ErrInvalidLanguage
|
||||
}
|
||||
|
||||
return s.users.UpsertLanguagePreference(userID, normalized)
|
||||
}
|
||||
|
||||
func (s *AuthService) UpdateUserTheme(userID string, theme string) error {
|
||||
normalized := NormalizeTheme(theme)
|
||||
if normalized != "dark" && normalized != "light" {
|
||||
return ErrInvalidTheme
|
||||
}
|
||||
return s.users.UpsertDarkPreference(userID, normalized == "dark")
|
||||
}
|
||||
|
||||
func (s *AuthService) issueVerifyEmail(ctx context.Context, user *models.User) error {
|
||||
plainToken, err := auth.NewToken()
|
||||
if err != nil {
|
||||
@@ -245,3 +274,17 @@ func (s *AuthService) sendResetEmail(ctx context.Context, user *models.User, pla
|
||||
func normalizeEmail(email string) string {
|
||||
return strings.ToLower(strings.TrimSpace(email))
|
||||
}
|
||||
|
||||
func NormalizeLanguage(lang string) string {
|
||||
normalized := strings.ToLower(strings.TrimSpace(lang))
|
||||
return strings.ReplaceAll(normalized, "-", "_")
|
||||
}
|
||||
|
||||
func IsSupportedLanguage(lang string) bool {
|
||||
_, ok := supportedLanguages[NormalizeLanguage(lang)]
|
||||
return ok
|
||||
}
|
||||
|
||||
func NormalizeTheme(theme string) string {
|
||||
return strings.ToLower(strings.TrimSpace(theme))
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ func (s *UsersService) List(query UsersQuery) (*UsersPage, error) {
|
||||
if pageSize <= 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
if pageSize > 100 {
|
||||
pageSize = 100
|
||||
if pageSize > 500 {
|
||||
pageSize = 500
|
||||
}
|
||||
|
||||
sort := normalizeSort(query.Sort)
|
||||
@@ -104,7 +104,7 @@ func (s *UsersService) List(query UsersQuery) (*UsersPage, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *UsersService) GetByID(id uint) (*models.User, error) {
|
||||
func (s *UsersService) GetByID(id string) (*models.User, error) {
|
||||
return s.users.FindByID(id)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user