2024-02-16 21:31:00 +00:00
|
|
|
package server
|
2024-02-10 11:59:58 +00:00
|
|
|
|
|
|
|
import (
|
2024-02-16 21:31:00 +00:00
|
|
|
"context"
|
2024-02-10 11:59:58 +00:00
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"code.tjo.space/mentos1386/zdravko/internal"
|
2024-02-15 22:47:56 +00:00
|
|
|
"code.tjo.space/mentos1386/zdravko/internal/config"
|
2024-02-11 19:28:00 +00:00
|
|
|
"code.tjo.space/mentos1386/zdravko/internal/handlers"
|
2024-02-16 21:31:00 +00:00
|
|
|
"code.tjo.space/mentos1386/zdravko/internal/temporal"
|
2024-02-11 19:28:00 +00:00
|
|
|
"code.tjo.space/mentos1386/zdravko/web/static"
|
2024-02-20 10:24:04 +00:00
|
|
|
"code.tjo.space/mentos1386/zdravko/web/templates"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
|
|
"github.com/labstack/echo/v4/middleware"
|
2024-02-10 11:59:58 +00:00
|
|
|
)
|
|
|
|
|
2024-02-16 21:31:00 +00:00
|
|
|
type Server struct {
|
2024-02-21 09:41:20 +00:00
|
|
|
echo *echo.Echo
|
|
|
|
cfg *config.ServerConfig
|
2024-02-16 21:31:00 +00:00
|
|
|
}
|
|
|
|
|
2024-02-19 09:09:30 +00:00
|
|
|
func NewServer(cfg *config.ServerConfig) (*Server, error) {
|
2024-02-16 21:31:00 +00:00
|
|
|
return &Server{
|
2024-02-21 09:41:20 +00:00
|
|
|
cfg: cfg,
|
|
|
|
echo: echo.New(),
|
2024-02-16 21:31:00 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) Name() string {
|
|
|
|
return "HTTP WEB and API Server"
|
|
|
|
}
|
2024-02-11 09:15:00 +00:00
|
|
|
|
2024-02-16 21:31:00 +00:00
|
|
|
func (s *Server) Start() error {
|
2024-02-21 09:41:20 +00:00
|
|
|
s.echo.Renderer = templates.NewTemplates()
|
|
|
|
s.echo.Use(middleware.Logger())
|
|
|
|
s.echo.Use(middleware.Recover())
|
2024-02-10 11:59:58 +00:00
|
|
|
|
2024-02-16 21:31:00 +00:00
|
|
|
db, query, err := internal.ConnectToDatabase(s.cfg.DatabasePath)
|
2024-02-11 10:56:21 +00:00
|
|
|
if err != nil {
|
2024-02-16 21:31:00 +00:00
|
|
|
return err
|
2024-02-11 10:56:21 +00:00
|
|
|
}
|
|
|
|
log.Println("Connected to database")
|
|
|
|
|
2024-02-18 21:37:17 +00:00
|
|
|
temporalClient, err := temporal.ConnectServerToTemporal(s.cfg)
|
2024-02-16 12:07:29 +00:00
|
|
|
if err != nil {
|
2024-02-16 21:31:00 +00:00
|
|
|
return err
|
2024-02-16 12:07:29 +00:00
|
|
|
}
|
2024-02-18 21:37:17 +00:00
|
|
|
log.Println("Connected to Temporal")
|
2024-02-16 12:07:29 +00:00
|
|
|
|
2024-02-16 21:31:00 +00:00
|
|
|
h := handlers.NewBaseHandler(db, query, temporalClient, s.cfg)
|
2024-02-11 19:28:00 +00:00
|
|
|
|
|
|
|
// Health
|
2024-02-21 09:41:20 +00:00
|
|
|
s.echo.GET("/health", func(c echo.Context) error {
|
2024-02-11 19:28:00 +00:00
|
|
|
d, err := db.DB()
|
|
|
|
if err != nil {
|
2024-02-20 10:24:04 +00:00
|
|
|
return err
|
2024-02-11 19:28:00 +00:00
|
|
|
}
|
|
|
|
err = d.Ping()
|
|
|
|
if err != nil {
|
2024-02-20 10:24:04 +00:00
|
|
|
return err
|
2024-02-11 19:28:00 +00:00
|
|
|
}
|
2024-02-20 10:24:04 +00:00
|
|
|
|
|
|
|
return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
|
2024-02-11 19:28:00 +00:00
|
|
|
})
|
2024-02-11 10:56:21 +00:00
|
|
|
|
2024-02-10 11:59:58 +00:00
|
|
|
// Server static files
|
2024-02-21 09:41:20 +00:00
|
|
|
stat := s.echo.Group("/static")
|
2024-02-20 10:24:04 +00:00
|
|
|
stat.Use(middleware.StaticWithConfig(middleware.StaticConfig{
|
|
|
|
Filesystem: http.FS(static.Static),
|
|
|
|
}))
|
2024-02-10 11:59:58 +00:00
|
|
|
|
2024-02-20 10:24:04 +00:00
|
|
|
// Public
|
2024-02-21 09:41:20 +00:00
|
|
|
s.echo.GET("", h.Index)
|
2024-02-23 08:36:13 +00:00
|
|
|
s.echo.GET("/incidents", h.Incidents)
|
2024-02-11 22:48:37 +00:00
|
|
|
|
2024-02-19 14:23:17 +00:00
|
|
|
// Settings
|
2024-02-21 09:41:20 +00:00
|
|
|
settings := s.echo.Group("/settings")
|
2024-02-20 10:24:04 +00:00
|
|
|
settings.Use(h.Authenticated)
|
|
|
|
settings.GET("", h.SettingsOverviewGET)
|
|
|
|
settings.GET("/healthchecks", h.SettingsHealthchecksGET)
|
|
|
|
settings.GET("/healthchecks/create", h.SettingsHealthchecksCreateGET)
|
|
|
|
settings.POST("/healthchecks/create", h.SettingsHealthchecksCreatePOST)
|
|
|
|
settings.GET("/healthchecks/:slug", h.SettingsHealthchecksDescribeGET)
|
|
|
|
settings.GET("/workers", h.SettingsWorkersGET)
|
|
|
|
settings.GET("/workers/create", h.SettingsWorkersCreateGET)
|
|
|
|
settings.POST("/workers/create", h.SettingsWorkersCreatePOST)
|
|
|
|
settings.GET("/workers/:slug", h.SettingsWorkersDescribeGET)
|
|
|
|
settings.GET("/workers/:slug/token", h.SettingsWorkersTokenGET)
|
|
|
|
settings.Match([]string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"}, "/temporal*", h.Temporal)
|
2024-02-11 19:28:00 +00:00
|
|
|
|
|
|
|
// OAuth2
|
2024-02-21 09:41:20 +00:00
|
|
|
oauth2 := s.echo.Group("/oauth2")
|
2024-02-20 10:24:04 +00:00
|
|
|
oauth2.GET("/login", h.OAuth2LoginGET)
|
|
|
|
oauth2.GET("/callback", h.OAuth2CallbackGET)
|
|
|
|
oauth2.GET("/logout", h.OAuth2LogoutGET, h.Authenticated)
|
2024-02-10 11:59:58 +00:00
|
|
|
|
2024-02-19 09:09:30 +00:00
|
|
|
// API
|
2024-02-21 09:41:20 +00:00
|
|
|
apiv1 := s.echo.Group("/api/v1")
|
2024-02-20 10:24:04 +00:00
|
|
|
apiv1.Use(h.Authenticated)
|
|
|
|
apiv1.GET("/workers/connect", h.ApiV1WorkersConnectGET)
|
2024-02-21 22:15:21 +00:00
|
|
|
apiv1.POST("/healthchecks/:slug/history", h.ApiV1HealthchecksHistoryPOST)
|
2024-02-20 10:24:04 +00:00
|
|
|
|
|
|
|
// Error handler
|
2024-02-21 09:41:20 +00:00
|
|
|
s.echo.HTTPErrorHandler = func(err error, c echo.Context) {
|
2024-02-20 10:24:04 +00:00
|
|
|
code := http.StatusInternalServerError
|
|
|
|
if he, ok := err.(*echo.HTTPError); ok {
|
|
|
|
code = he.Code
|
|
|
|
}
|
2024-02-12 10:22:14 +00:00
|
|
|
|
2024-02-20 10:24:04 +00:00
|
|
|
if code == http.StatusNotFound {
|
|
|
|
_ = h.Error404(c)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
_ = c.String(code, err.Error())
|
2024-02-16 21:31:00 +00:00
|
|
|
}
|
|
|
|
|
2024-02-21 09:41:20 +00:00
|
|
|
return s.echo.Start(":" + s.cfg.Port)
|
2024-02-16 21:31:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) Stop() error {
|
|
|
|
ctx := context.Background()
|
2024-02-21 09:41:20 +00:00
|
|
|
return s.echo.Shutdown(ctx)
|
2024-02-10 11:59:58 +00:00
|
|
|
}
|