Files
sm-user-plugin/user.go
Jakub Zych 5530fa4ebf feat(03-01): serve seeded genres behind JWT middleware
golem15.user registers jwt.auth, golem15.fonoteka mounts GET /_fonoteka/api/v1/genres
through that guard, and a smoke test reads the 15 migrated rows with a test-only token.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 20:04:18 +02:00

57 lines
1.5 KiB
Go

package user
import (
"context"
"errors"
"fmt"
"strings"
"git.golem15.com/golem15/summercms/backpack"
"git.golem15.com/golem15/summercms/bouncer"
"gorm.io/gorm"
)
// User is the minimal users row the JWT guard loads.
type User struct {
ID uint `gorm:"column:id;primaryKey"`
Email string `gorm:"column:email"`
Password string `gorm:"column:password"`
MustChangePassword bool `gorm:"column:must_change_password"`
}
func (User) TableName() string { return "users" }
type gormUsers struct {
app *backpack.App
}
func (g gormUsers) FindByID(ctx context.Context, id uint) (*bouncer.Principal, error) {
if g.app == nil {
return nil, fmt.Errorf("golem15.user: app is nil")
}
gdb, ok := g.app.Lookup[*gorm.DB]()
if !ok || gdb == nil {
return nil, fmt.Errorf("golem15.user: gorm handle is missing")
}
var row User
err := gdb.WithContext(ctx).Where("id = ?", id).Take(&row).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
return &bouncer.Principal{ID: row.ID, MustChangePassword: row.MustChangePassword}, nil
}
func jwtSecret(app *backpack.App) (string, error) {
if app == nil || app.Config == nil {
return "", fmt.Errorf("golem15.user: jwt.secret is empty (set SUMMER_GOLEM15__USER__JWT__SECRET)")
}
secret := strings.TrimSpace(app.Config.String("golem15.user.jwt.secret"))
if secret == "" {
return "", fmt.Errorf("golem15.user: jwt.secret is empty (set SUMMER_GOLEM15__USER__JWT__SECRET)")
}
return secret, nil
}