Add PDF reports, file uploads, admin auth, and comprehensive tests
Features: - PDF service for generating task reports with ReportLab-style formatting - Storage service for file uploads (local and S3-compatible) - Admin authentication middleware with JWT support - Admin user model and repository Infrastructure: - Updated Docker configuration for admin panel builds - Email service enhancements for task notifications - Updated router with admin and file upload routes - Environment configuration updates Tests: - Unit tests for handlers (auth, residence, task) - Unit tests for models (user, residence, task) - Unit tests for repositories (user, residence, task) - Unit tests for services (residence, task) - Integration test setup - Test utilities for mocking database and services Database: - Admin user seed data - Updated test data seeds 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,81 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
_ "github.com/lib/pq" // PostgreSQL driver for GoAdmin
|
||||
|
||||
"github.com/treytartt/mycrib-api/internal/admin"
|
||||
"github.com/treytartt/mycrib-api/internal/config"
|
||||
"github.com/treytartt/mycrib-api/internal/database"
|
||||
"github.com/treytartt/mycrib-api/pkg/utils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize logger
|
||||
utils.InitLogger(true)
|
||||
|
||||
// Load configuration
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to load configuration")
|
||||
}
|
||||
|
||||
// Initialize database
|
||||
db, err := database.Connect(&cfg.Database, cfg.Server.Debug)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to connect to database")
|
||||
}
|
||||
_ = db // Database handle managed by GoAdmin
|
||||
|
||||
// Get underlying *sql.DB for cleanup
|
||||
sqlDB, _ := db.DB()
|
||||
defer sqlDB.Close()
|
||||
|
||||
// Set Gin mode
|
||||
if cfg.Server.Debug {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
// Create Gin router
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery())
|
||||
r.Use(gin.Logger())
|
||||
|
||||
// Setup GoAdmin
|
||||
eng, err := admin.Setup(r, cfg)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to setup GoAdmin")
|
||||
}
|
||||
_ = eng // Engine is used internally
|
||||
|
||||
// Determine admin port (default: 9000, or PORT+1000)
|
||||
adminPort := 9000
|
||||
if cfg.Server.Port > 0 {
|
||||
adminPort = cfg.Server.Port + 1000
|
||||
}
|
||||
|
||||
// Start server
|
||||
addr := fmt.Sprintf(":%d", adminPort)
|
||||
log.Info().Str("addr", addr).Msg("Starting MyCrib Admin Panel")
|
||||
|
||||
// Handle graceful shutdown
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
if err := r.Run(addr); err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to start admin server")
|
||||
}
|
||||
}()
|
||||
|
||||
<-quit
|
||||
log.Info().Msg("Shutting down admin server...")
|
||||
}
|
||||
@@ -9,11 +9,9 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
_ "github.com/lib/pq" // PostgreSQL driver for GoAdmin
|
||||
"github.com/rs/zerolog/log"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/treytartt/mycrib-api/internal/admin"
|
||||
"github.com/treytartt/mycrib-api/internal/config"
|
||||
"github.com/treytartt/mycrib-api/internal/database"
|
||||
"github.com/treytartt/mycrib-api/internal/router"
|
||||
@@ -93,24 +91,36 @@ func main() {
|
||||
Msg("Email service not configured - emails will not be sent")
|
||||
}
|
||||
|
||||
// Setup router with dependencies
|
||||
deps := &router.Dependencies{
|
||||
DB: db,
|
||||
Cache: cache,
|
||||
Config: cfg,
|
||||
EmailService: emailService,
|
||||
}
|
||||
r := router.SetupRouter(deps)
|
||||
|
||||
// Setup GoAdmin panel at /admin
|
||||
if db != nil {
|
||||
if _, err := admin.Setup(r, cfg); err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to setup admin panel - admin will be unavailable")
|
||||
// Initialize storage service for file uploads
|
||||
var storageService *services.StorageService
|
||||
if cfg.Storage.UploadDir != "" {
|
||||
storageService, err = services.NewStorageService(&cfg.Storage)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to initialize storage service - uploads disabled")
|
||||
} else {
|
||||
log.Info().Msg("Admin panel available at /admin")
|
||||
log.Info().
|
||||
Str("upload_dir", cfg.Storage.UploadDir).
|
||||
Str("base_url", cfg.Storage.BaseURL).
|
||||
Int64("max_file_size", cfg.Storage.MaxFileSize).
|
||||
Msg("Storage service initialized")
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize PDF service for report generation
|
||||
pdfService := services.NewPDFService()
|
||||
log.Info().Msg("PDF service initialized")
|
||||
|
||||
// Setup router with dependencies (includes admin panel at /admin)
|
||||
deps := &router.Dependencies{
|
||||
DB: db,
|
||||
Cache: cache,
|
||||
Config: cfg,
|
||||
EmailService: emailService,
|
||||
PDFService: pdfService,
|
||||
StorageService: storageService,
|
||||
}
|
||||
r := router.SetupRouter(deps)
|
||||
|
||||
// Create HTTP server
|
||||
srv := &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", cfg.Server.Port),
|
||||
|
||||
Reference in New Issue
Block a user