slack-auth-1770277167/services/auth-api/internal/api/handlers/example.go
jordan 45269dc680
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Add service component: auth-api
2026-02-05 07:39:35 +00:00

204 lines
5.5 KiB
Go

package handlers
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"git.threesix.ai/jordan/slack-auth-1770277167/pkg/app"
"git.threesix.ai/jordan/slack-auth-1770277167/pkg/httperror"
"git.threesix.ai/jordan/slack-auth-1770277167/pkg/httpresponse"
"git.threesix.ai/jordan/slack-auth-1770277167/pkg/logging"
)
// Example demonstrates the Wrap pattern for error-returning handlers.
type Example struct {
logger *logging.Logger
}
// NewExample creates a new Example handler.
func NewExample(logger *logging.Logger) *Example {
return &Example{logger: logger}
}
// CreateRequest is the request body for creating an example.
type CreateRequest struct {
Name string `json:"name" validate:"required,min=1,max=100"`
Description string `json:"description" validate:"max=500"`
}
// UpdateRequest is the request body for updating an example.
type UpdateRequest struct {
Name string `json:"name" validate:"omitempty,min=1,max=100"`
Description string `json:"description" validate:"max=500"`
}
// ExampleResponse is the response for an example resource.
type ExampleResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// List returns a paginated list of examples.
// Demonstrates pagination query params and list responses.
func (h *Example) List(w http.ResponseWriter, r *http.Request) error {
// Example: Parse pagination query params
// page := r.URL.Query().Get("page")
// perPage := r.URL.Query().Get("per_page")
// Example: Fetch from database
// items, total, err := h.repo.List(r.Context(), page, perPage)
// if err != nil {
// return err
// }
// Placeholder response
items := []ExampleResponse{
{
ID: "550e8400-e29b-41d4-a716-446655440000",
Name: "Example Item 1",
Description: "First example item",
CreatedAt: "2024-01-15T10:30:00Z",
UpdatedAt: "2024-01-15T10:30:00Z",
},
{
ID: "550e8400-e29b-41d4-a716-446655440001",
Name: "Example Item 2",
Description: "Second example item",
CreatedAt: "2024-01-16T12:00:00Z",
UpdatedAt: "2024-01-16T12:00:00Z",
},
}
httpresponse.OK(w, r, items)
return nil
}
// Get returns an example by ID.
// Demonstrates returning HTTPErrors for common error cases.
func (h *Example) Get(w http.ResponseWriter, r *http.Request) error {
id := chi.URLParam(r, "id")
// Validate UUID format
if _, err := uuid.Parse(id); err != nil {
return httperror.BadRequest("invalid id format")
}
// Example: Fetch from database
// item, err := h.repo.Get(r.Context(), id)
// if err != nil {
// if errors.Is(err, ErrNotFound) {
// return httperror.NotFoundf("example %s not found", id)
// }
// return err
// }
// Placeholder response
httpresponse.OK(w, r, ExampleResponse{
ID: id,
Name: "Example Item",
Description: "This is an example item",
CreatedAt: "2024-01-15T10:30:00Z",
UpdatedAt: "2024-01-15T10:30:00Z",
})
return nil
}
// Create creates a new example.
// Demonstrates using BindAndValidate for request parsing and validation.
func (h *Example) Create(w http.ResponseWriter, r *http.Request) error {
var req CreateRequest
// Bind and validate request body
if err := app.BindAndValidate(r, &req); err != nil {
return err
}
// Example: Check for duplicates
// if exists, _ := h.repo.GetByName(r.Context(), req.Name); exists != nil {
// return httperror.Conflict("example with this name already exists")
// }
// Example: Create in database
// item, err := h.repo.Create(r.Context(), req)
// if err != nil {
// return err
// }
// Example: Access authenticated user
// user := auth.GetUser(r.Context())
// h.logger.Info("example created", "by", user.ID, "name", req.Name)
id := uuid.New().String()
httpresponse.Created(w, r, ExampleResponse{
ID: id,
Name: req.Name,
Description: req.Description,
CreatedAt: "2024-01-15T10:30:00Z",
UpdatedAt: "2024-01-15T10:30:00Z",
})
return nil
}
// Update updates an existing example.
// Demonstrates partial updates with BindAndValidate.
func (h *Example) Update(w http.ResponseWriter, r *http.Request) error {
id := chi.URLParam(r, "id")
if _, err := uuid.Parse(id); err != nil {
return httperror.BadRequest("invalid id format")
}
var req UpdateRequest
if err := app.BindAndValidate(r, &req); err != nil {
return err
}
// Example: Fetch existing, apply updates, save
// item, err := h.repo.Get(r.Context(), id)
// if err != nil {
// if errors.Is(err, ErrNotFound) {
// return httperror.NotFoundf("example %s not found", id)
// }
// return err
// }
// if err := h.repo.Update(r.Context(), id, req); err != nil {
// return err
// }
httpresponse.OK(w, r, ExampleResponse{
ID: id,
Name: req.Name,
Description: req.Description,
CreatedAt: "2024-01-15T10:30:00Z",
UpdatedAt: "2024-01-16T14:00:00Z",
})
return nil
}
// Delete deletes an example by ID.
// Demonstrates no-content response.
func (h *Example) Delete(w http.ResponseWriter, r *http.Request) error {
id := chi.URLParam(r, "id")
if _, err := uuid.Parse(id); err != nil {
return httperror.BadRequest("invalid id format")
}
// Example: Delete from database
// if err := h.repo.Delete(r.Context(), id); err != nil {
// if errors.Is(err, ErrNotFound) {
// return httperror.NotFoundf("example %s not found", id)
// }
// return err
// }
httpresponse.NoContent(w)
return nil
}