fix: improve play profile input validation, error responses, and HTTP status codes

- createPlayProfileHandler: return 201 Created (not 200) on success
- create/update handlers: return 500 for infra errors, 400 only for
  validation errors (using new ErrPlayProfileValidation sentinel)
- deletePlayProfileHandler: validate JSON body (was silently ignored)
- verifyPlayProfilePINHandler: validate JSON body (was silently ignored)
- verify handler catch-all: return 500 (not 400) for unexpected errors
- Service layer: wrap validation errors with ErrPlayProfileValidation
  so handlers can distinguish client vs server errors

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
soldosluka857
2026-05-30 02:08:16 +00:00
committed by Shuke
parent 5bbc9fadfe
commit 2c45fa596a
2 changed files with 29 additions and 11 deletions
+9 -5
View File
@@ -14,6 +14,7 @@ import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
@@ -36,6 +37,7 @@ var (
ErrPlayProfileForbidden = errors.New("profile forbidden")
ErrPlayProfilePINInvalid = errors.New("pin invalid")
ErrPlayProfileLimit = errors.New("profile limit reached")
ErrPlayProfileValidation = errors.New("validation error")
)
// NewPlayProfileService is the constructor.
@@ -194,7 +196,7 @@ func (s *PlayProfileService) updateExisting(ctx context.Context, row *model.Play
if in.RequirePIN && in.PIN != "" {
patch["pin_hash"] = hashPIN(in.PIN)
} else if in.RequirePIN && row.PINHash == "" {
return nil, errors.New("pin required")
return nil, fmt.Errorf("%w: pin required", ErrPlayProfileValidation)
}
if !in.RequirePIN {
patch["pin_hash"] = ""
@@ -267,19 +269,21 @@ func (s *PlayProfileService) TouchActive(ctx context.Context, id string) error {
// validateProfileInput rejects malformed payloads. On create we require
// user_id; on update we allow it to be empty (caller supplies it via URL).
// Errors wrap ErrPlayProfileValidation so handlers can distinguish
// validation failures (400) from infrastructure errors (500).
func validateProfileInput(in PlayProfileInput, requireUser bool) error {
if strings.TrimSpace(in.Name) == "" {
return errors.New("name required")
return fmt.Errorf("%w: name required", ErrPlayProfileValidation)
}
if requireUser && strings.TrimSpace(in.UserID) == "" {
return errors.New("user_id required")
return fmt.Errorf("%w: user_id required", ErrPlayProfileValidation)
}
if requireUser && in.RequirePIN && strings.TrimSpace(in.PIN) == "" {
return errors.New("pin required")
return fmt.Errorf("%w: pin required", ErrPlayProfileValidation)
}
if in.RequirePIN && in.PIN != "" {
if len(in.PIN) < 4 || len(in.PIN) > 8 {
return errors.New("pin must be 4-8 characters")
return fmt.Errorf("%w: pin must be 4-8 characters", ErrPlayProfileValidation)
}
}
return nil