204 lines
5.5 KiB
Go
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
|
|
}
|