mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
8.9 KiB
8.9 KiB
Utility Controllers - Quick Reference Card
🚀 Quick Setup
# 1. Install dependency
go get github.com/go-playground/validator/v10
# 2. Add to main.go AutoMigrate
&models.AuditLog{},
# 3. Initialize after database init
controllers.InitAuditLogger(dbInstance)
controllers.InitBatchOperations(dbInstance)
📦 Global Variables
controllers.Respond // Response helper
controllers.Paginator // Pagination helper
controllers.QueryParser // Query/filter helper
controllers.Validator // Validation helper
controllers.AuditLogger // Audit logging
controllers.BatchOps // Batch operations
controllers.Exporter // Export CSV/JSON
💡 Common Patterns
Standard List Endpoint
func (ctrl *Controller) List(c *gin.Context) {
query := controllers.QueryParser.BuildQueryChain(c, db.Model(&Model{})).
WithSearch("field1", "field2").
WithSort("created_at", "desc").
WithBoolFilter("published", "published").
Build()
var items []Model
meta, _ := controllers.Paginator.Paginate(c, query, &items)
controllers.Respond.SuccessWithMeta(c, items, meta, "Success")
}
Standard Get Endpoint
func (ctrl *Controller) Get(c *gin.Context) {
id := c.Param("id")
var item Model
if err := db.First(&item, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
controllers.Respond.NotFound(c, "Not found")
return
}
controllers.Respond.InternalError(c, "Database error")
return
}
controllers.Respond.Success(c, item, "Success")
}
Standard Create Endpoint
func (ctrl *Controller) Create(c *gin.Context) {
type Request struct {
Field string `json:"field" validate:"required,min=3"`
}
var req Request
if err := c.ShouldBindJSON(&req); err != nil {
controllers.Respond.BadRequest(c, "Invalid JSON")
return
}
if !controllers.Validator.ValidateAndRespond(c, req) {
return
}
item := Model{Field: controllers.Validator.SanitizeString(req.Field)}
if err := db.Create(&item).Error; err != nil {
controllers.Respond.InternalError(c, "Failed to create")
return
}
controllers.AuditLogger.LogCreate(c, "Model", item.ID, "Created")
controllers.Respond.Created(c, item, "Created successfully")
}
Standard Update Endpoint
func (ctrl *Controller) Update(c *gin.Context) {
id := c.Param("id")
var item Model
if err := db.First(&item, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
controllers.Respond.NotFound(c, "Not found")
return
}
controllers.Respond.InternalError(c, "Database error")
return
}
oldValue := item.Field
type Request struct {
Field string `json:"field" validate:"omitempty,min=3"`
}
var req Request
if err := c.ShouldBindJSON(&req); err != nil {
controllers.Respond.BadRequest(c, "Invalid JSON")
return
}
if !controllers.Validator.ValidateAndRespond(c, req) {
return
}
if req.Field != "" {
item.Field = controllers.Validator.SanitizeString(req.Field)
}
if err := db.Save(&item).Error; err != nil {
controllers.Respond.InternalError(c, "Failed to update")
return
}
controllers.AuditLogger.LogUpdate(c, "Model", item.ID, "Updated",
map[string]interface{}{"field": oldValue},
map[string]interface{}{"field": item.Field})
controllers.Respond.Success(c, item, "Updated successfully")
}
Standard Delete Endpoint
func (ctrl *Controller) Delete(c *gin.Context) {
id := c.Param("id")
var item Model
if err := db.First(&item, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
controllers.Respond.NotFound(c, "Not found")
return
}
controllers.Respond.InternalError(c, "Database error")
return
}
itemID := item.ID
description := item.Name
if err := db.Delete(&item).Error; err != nil {
controllers.Respond.InternalError(c, "Failed to delete")
return
}
controllers.AuditLogger.LogDelete(c, "Model", itemID, "Deleted: "+description)
controllers.Respond.NoContent(c)
}
🔍 Query Parameters Reference
GET /api/v1/items?
search=term # Search across fields
&q=term # Alternative search param
&sort=field:desc # Sort by field (asc/desc)
&published=true # Boolean filter
&category_ids=1,2,3 # Multiple IDs filter
&from=2024-01-01 # Date range start
&to=2024-12-31 # Date range end
&page=1 # Page number
&page_size=20 # Items per page
📝 Validation Tags
type Request struct {
Field1 string `validate:"required"` // Required
Field2 string `validate:"required,min=3,max=50"` // Length constraints
Email string `validate:"required,email"` // Email validation
URL string `validate:"omitempty,url"` // URL validation
Slug string `validate:"omitempty,slug"` // Slug validation
Color string `validate:"omitempty,color"` // Hex color validation
Status string `validate:"oneof=draft published"` // Enum validation
Age int `validate:"gte=0,lte=120"` // Number range
}
🎯 Response Methods
// Success responses
Respond.Success(c, data, "Success")
Respond.SuccessWithMeta(c, data, meta, "Success")
Respond.Created(c, data, "Created")
Respond.NoContent(c)
// Error responses
Respond.BadRequest(c, "Invalid input")
Respond.Unauthorized(c, "Not authenticated")
Respond.Forbidden(c, "No permission")
Respond.NotFound(c, "Not found")
Respond.Conflict(c, "Already exists")
Respond.InternalError(c, "Server error")
Respond.ValidationError(c, errors)
🔄 Batch Operations
// Batch delete
BatchOps.BatchDelete(c, &Model{}, "table_name")
// Batch update
allowedFields := []string{"published", "featured"}
BatchOps.BatchUpdate(c, &Model{}, "table_name", allowedFields)
// Batch publish/unpublish
BatchOps.BatchPublish(c, &Model{}, "table_name", true)
// Batch reorder
BatchOps.BatchReorder(c, &Model{}, "table_name")
📊 Export Data
// Export to CSV
headers := []string{"ID", "Name", "Created"}
Exporter.ExportToCSV(c, items, "export.csv", headers)
// Export to JSON
Exporter.ExportToJSON(c, items, "export.json")
🔐 Audit Logging
// Log actions
AuditLogger.LogCreate(c, "EntityType", entityID, "Description")
AuditLogger.LogUpdate(c, "EntityType", entityID, "Description", before, after)
AuditLogger.LogDelete(c, "EntityType", entityID, "Description")
AuditLogger.LogLogin(c, userID, success)
AuditLogger.LogLogout(c, userID)
// Custom log
AuditLogger.LogEntry(c, "CUSTOM_ACTION", "EntityType", &entityID, "Description", changes)
🧹 Sanitization
// Sanitize string (trim, normalize spaces)
clean := Validator.SanitizeString(input)
// Sanitize email (lowercase, trim)
email := Validator.SanitizeEmail(input)
// Sanitize slug (lowercase, hyphens, alphanumeric)
slug := Validator.SanitizeSlug(input)
🧪 Individual Validation
// Check validity
isValid := Validator.IsValidEmail(email)
isValid := Validator.IsValidURL(url)
isValid := Validator.IsValidSlug(slug)
// Get validation errors
errors := Validator.Validate(struct)
📁 Files Created
internal/controllers/
├── response_helper.go (Standardized responses)
├── pagination_helper.go (Auto pagination)
├── query_helper.go (Filtering & sorting)
├── validation_helper.go (Input validation)
├── audit_log_controller.go (Audit trail)
├── batch_operations_controller.go (Bulk operations)
├── export_helper.go (CSV/JSON export)
├── example_usage_controller.go (Usage examples)
└── poll_controller_refactored.go (Real refactoring)
internal/models/
└── audit_log.go (Audit log model)
DOCS/
└── NEW_UTILITY_CONTROLLERS_GUIDE.md (Complete guide)
Root:
├── UTILITY_CONTROLLERS_README.md (Summary)
└── QUICK_REFERENCE.md (This file)
🎓 Learning Path
- Start here:
UTILITY_CONTROLLERS_README.md - Deep dive:
DOCS/NEW_UTILITY_CONTROLLERS_GUIDE.md - See examples:
example_usage_controller.go - Real refactor:
poll_controller_refactored.go - Quick lookup:
QUICK_REFERENCE.md(this file)
💪 Benefits
- ✅ 70% less code for common operations
- ✅ Consistent API responses everywhere
- ✅ Built-in pagination, search, filtering
- ✅ Automatic validation and sanitization
- ✅ Complete audit trail for compliance
- ✅ Efficient batch operations
- ✅ Easy data export to CSV/JSON
Bookmark this file for quick reference while coding! 📌