Files
license/internal/subject/service.go
2026-07-31 16:59:55 +08:00

108 lines
2.7 KiB
Go

package subject
import (
"context"
"fmt"
"strings"
"time"
"unicode"
"unicode/utf8"
"github.com/google/uuid"
)
const (
maximumSubjectFieldRunes = 128
maximumPageSize = 100
)
type Service struct {
repository *Repository
}
func NewService(repository *Repository) (*Service, error) {
if repository == nil || repository.db == nil {
return nil, ErrInvalidInput
}
return &Service{repository: repository}, nil
}
func (s *Service) Create(ctx context.Context, input UpsertInput) (Subject, error) {
if !s.usable(ctx) {
return Subject{}, ErrInvalidInput
}
normalized, err := normalizeInput(input)
if err != nil {
return Subject{}, err
}
id, err := uuid.NewRandom()
if err != nil {
return Subject{}, fmt.Errorf("生成授权对象 UUID v4: %w", err)
}
now := time.Now().UTC()
return s.repository.Create(ctx, Subject{
ID: id,
PlatformName: normalized.PlatformName,
Workspace: normalized.Workspace,
CreatedAt: now,
UpdatedAt: now,
})
}
func (s *Service) Get(ctx context.Context, id uuid.UUID) (Subject, error) {
if !s.usable(ctx) || id == uuid.Nil {
return Subject{}, ErrInvalidInput
}
return s.repository.Get(ctx, id)
}
func (s *Service) List(ctx context.Context, query string, page, pageSize int) ([]Subject, int64, error) {
if !s.usable(ctx) || page < 1 || pageSize < 1 || pageSize > maximumPageSize {
return nil, 0, ErrInvalidInput
}
return s.repository.List(ctx, strings.TrimSpace(query), page, pageSize)
}
func (s *Service) Update(ctx context.Context, id uuid.UUID, input UpsertInput) (Subject, error) {
if !s.usable(ctx) || id == uuid.Nil {
return Subject{}, ErrInvalidInput
}
normalized, err := normalizeInput(input)
if err != nil {
return Subject{}, err
}
return s.repository.UpdateIfUnsigned(ctx, id, normalized)
}
func (s *Service) Delete(ctx context.Context, id uuid.UUID) error {
if !s.usable(ctx) || id == uuid.Nil {
return ErrInvalidInput
}
return s.repository.DeleteIfUnsigned(ctx, id)
}
func (s *Service) usable(ctx context.Context) bool {
return s != nil && s.repository != nil && s.repository.db != nil && ctx != nil
}
func normalizeInput(input UpsertInput) (UpsertInput, error) {
input.PlatformName = strings.TrimSpace(input.PlatformName)
input.Workspace = strings.TrimSpace(input.Workspace)
if !validSubjectField(input.PlatformName) || !validSubjectField(input.Workspace) {
return UpsertInput{}, ErrInvalidInput
}
return input, nil
}
func validSubjectField(value string) bool {
if value == "" || !utf8.ValidString(value) || utf8.RuneCountInString(value) > maximumSubjectFieldRunes {
return false
}
for _, character := range value {
if unicode.IsControl(character) {
return false
}
}
return true
}