initial commit. Cloned timetracker repository
This commit is contained in:
177
app/delivery/web/init.go
Normal file
177
app/delivery/web/init.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.ma-al.com/goc_marek/timetracker/app/config"
|
||||
"git.ma-al.com/goc_marek/timetracker/app/delivery/handler"
|
||||
"git.ma-al.com/goc_marek/timetracker/app/delivery/middleware"
|
||||
"git.ma-al.com/goc_marek/timetracker/app/delivery/web/public"
|
||||
|
||||
// "github.com/gofiber/fiber/v2/middleware/filesystem"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
// "github.com/gofiber/fiber/v3/middleware/filesystem"
|
||||
"github.com/gofiber/fiber/v3/middleware/logger"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
)
|
||||
|
||||
// Server represents the web server
|
||||
type Server struct {
|
||||
app *fiber.App
|
||||
cfg *config.Config
|
||||
api fiber.Router
|
||||
}
|
||||
|
||||
// App returns the fiber app
|
||||
func (s *Server) App() *fiber.App {
|
||||
return s.app
|
||||
}
|
||||
|
||||
// Cfg returns the config
|
||||
func (s *Server) Cfg() *config.Config {
|
||||
return s.cfg
|
||||
}
|
||||
|
||||
// New creates a new server instance
|
||||
func New() *Server {
|
||||
return &Server{
|
||||
app: fiber.New(fiber.Config{
|
||||
ErrorHandler: customErrorHandler,
|
||||
}),
|
||||
cfg: config.Get(),
|
||||
}
|
||||
}
|
||||
|
||||
// Setup configures the server with routes and middleware
|
||||
func (s *Server) Setup() error {
|
||||
// Global middleware
|
||||
s.app.Use(recover.New())
|
||||
s.app.Use(logger.New())
|
||||
|
||||
// CORS middleware
|
||||
s.app.Use(middleware.CORSMiddleware())
|
||||
|
||||
// Language middleware - discovers client's language and stores in context
|
||||
s.app.Use(middleware.LanguageMiddleware())
|
||||
|
||||
// initialize healthcheck
|
||||
public.InitHealth(s.App(), s.Cfg())
|
||||
|
||||
// serve favicon
|
||||
public.Favicon(s.app, s.cfg)
|
||||
|
||||
// API routes
|
||||
s.api = s.app.Group("/api/v1")
|
||||
|
||||
// initialize swagger endpoints
|
||||
public.InitSwagger(s.App())
|
||||
|
||||
// Auth routes (public)
|
||||
auth := s.api.Group("/auth")
|
||||
handler.AuthHandlerRoutes(auth)
|
||||
|
||||
// Repo routes (public)
|
||||
repo := s.api.Group("/repo")
|
||||
repo.Use(middleware.AuthMiddleware())
|
||||
handler.RepoHandlerRoutes(repo)
|
||||
|
||||
// Protected routes example
|
||||
protected := s.api.Group("/restricted")
|
||||
protected.Use(middleware.AuthMiddleware())
|
||||
protected.Get("/dashboard", func(c fiber.Ctx) error {
|
||||
user := middleware.GetUser(c)
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Welcome to the protected area",
|
||||
"user": user,
|
||||
})
|
||||
})
|
||||
|
||||
// Admin routes example
|
||||
admin := s.api.Group("/admin")
|
||||
admin.Use(middleware.AuthMiddleware())
|
||||
admin.Use(middleware.RequireAdmin())
|
||||
admin.Get("/users", func(c fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Admin area - user management",
|
||||
})
|
||||
})
|
||||
|
||||
public.NewLangHandler().InitLanguage(s.api, s.cfg)
|
||||
|
||||
// Settings endpoint
|
||||
public.NewSettingsHandler().InitSettings(s.api, s.cfg)
|
||||
|
||||
// keep this at the end because its wilderange
|
||||
public.InitBo(s.App())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run starts the server
|
||||
func (s *Server) Run() error {
|
||||
// Run database migrations
|
||||
// if err := db.RunMigrations(); err != nil {
|
||||
// log.Printf("⚠️ Database migrations failed: %v", err)
|
||||
// } else {
|
||||
// log.Println("✓ Database migrations completed")
|
||||
// }
|
||||
|
||||
// // Seed admin user
|
||||
// if err := db.SeedAdminUser("admin@example.com", "admin123"); err != nil {
|
||||
// log.Printf("⚠️ Admin user seeding failed: %v", err)
|
||||
// }
|
||||
|
||||
addr := s.cfg.Server.Host + ":" + strconv.Itoa(s.cfg.Server.Port)
|
||||
log.Printf("Starting server on %s", addr)
|
||||
log.Printf("Swagger UI available at http://%s/swagger/index.html", addr)
|
||||
log.Printf("OpenAPI JSON available at http://%s/openapi.json", addr)
|
||||
|
||||
go func() {
|
||||
if err := s.app.Listen(":3000"); err != nil {
|
||||
log.Println("Server stopped:", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for shutdown signal
|
||||
quit := make(chan os.Signal, 1)
|
||||
|
||||
signal.Notify(
|
||||
quit,
|
||||
syscall.SIGINT, // Ctrl+C
|
||||
syscall.SIGTERM, // docker stop
|
||||
)
|
||||
|
||||
<-quit
|
||||
|
||||
log.Println("Shutting down server...")
|
||||
|
||||
// graceful shutdown with timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := s.app.ShutdownWithContext(ctx); err != nil {
|
||||
log.Fatal("Shutdown error:", err)
|
||||
}
|
||||
|
||||
log.Println("Server exited cleanly")
|
||||
return nil
|
||||
}
|
||||
|
||||
// customErrorHandler handles errors
|
||||
func customErrorHandler(c fiber.Ctx, err error) error {
|
||||
code := fiber.StatusInternalServerError
|
||||
|
||||
if e, ok := err.(*fiber.Error); ok {
|
||||
code = e.Code
|
||||
}
|
||||
|
||||
return c.Status(code).JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user