Introduce lms_personas table, repoint practice persona_id FKs off users, validate persona refs on LMS and exam-prep practice flows, personas.* RBAC permissions, and OpenAPI docs. Co-authored-by: Cursor <cursoragent@cursor.com>
92 lines
2.2 KiB
Go
92 lines
2.2 KiB
Go
package personas
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
"Yimaru-Backend/internal/domain"
|
|
"Yimaru-Backend/internal/ports"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
var ErrPersonaNotFound = domain.ErrPersonaNotFound
|
|
|
|
// ErrNameRequired indicates a missing trim-empty name on create.
|
|
var ErrNameRequired = errors.New("name is required")
|
|
|
|
// ErrNameEmptyUpdate indicates an update attempted to clear the persona name.
|
|
var ErrNameEmptyUpdate = errors.New("name cannot be empty")
|
|
|
|
type Service struct {
|
|
store ports.LmsPersonaStore
|
|
}
|
|
|
|
func NewService(store ports.LmsPersonaStore) *Service {
|
|
return &Service{store: store}
|
|
}
|
|
|
|
func clampPage(limit, offset int32) (int32, int32) {
|
|
if limit <= 0 {
|
|
limit = 20
|
|
}
|
|
if limit > 200 {
|
|
limit = 200
|
|
}
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
return limit, offset
|
|
}
|
|
|
|
func (s *Service) Create(ctx context.Context, in domain.CreateLmsPersonaInput) (domain.LmsPersona, error) {
|
|
name := strings.TrimSpace(in.Name)
|
|
if name == "" {
|
|
return domain.LmsPersona{}, ErrNameRequired
|
|
}
|
|
in.Name = name
|
|
return s.store.CreateLmsPersona(ctx, in)
|
|
}
|
|
|
|
func (s *Service) GetByID(ctx context.Context, id int64) (domain.LmsPersona, error) {
|
|
p, err := s.store.GetLmsPersonaByID(ctx, id)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return domain.LmsPersona{}, ErrPersonaNotFound
|
|
}
|
|
return domain.LmsPersona{}, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
func (s *Service) Update(ctx context.Context, id int64, in domain.UpdateLmsPersonaInput) (domain.LmsPersona, error) {
|
|
if in.Name != nil {
|
|
t := strings.TrimSpace(*in.Name)
|
|
if t == "" {
|
|
return domain.LmsPersona{}, ErrNameEmptyUpdate
|
|
}
|
|
in.Name = &t
|
|
}
|
|
p, err := s.store.UpdateLmsPersona(ctx, id, in)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return domain.LmsPersona{}, ErrPersonaNotFound
|
|
}
|
|
return domain.LmsPersona{}, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
func (s *Service) Delete(ctx context.Context, id int64) error {
|
|
if err := s.store.DeleteLmsPersona(ctx, id); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) List(ctx context.Context, activeOnly bool, limit, offset int32) ([]domain.LmsPersona, int64, error) {
|
|
limit, offset = clampPage(limit, offset)
|
|
return s.store.ListLmsPersonas(ctx, activeOnly, limit, offset)
|
|
}
|