1package httpserve
2
3import (
4 "github.com/bnema/gordon/internal/httpserve/handler"
5 "github.com/bnema/gordon/internal/httpserve/middleware"
6 "github.com/bnema/gordon/internal/server"
7 _ "github.com/joho/godotenv/autoload"
8 "github.com/labstack/echo/v4"
9 echomid "github.com/labstack/echo/v4/middleware"
10)
11
12// RegisterRoutes registers all routes and middlewares
13func RegisterRoutes(e *echo.Echo, a *server.App) *echo.Echo {
14 // e.Use(echomid.Logger()) too verbose
15 e.Use(echomid.Recover())
16 // Initiate the session middleware
17 e.Use(middleware.InitSessionMiddleware(a))
18
19 // Language detection
20 e.Use(middleware.LanguageDetection)
21
22 AdminPath := a.Config.Admin.Path
23 bindLoginRoute(e, a, AdminPath)
24 bindAPIEndpoints(e, a)
25
26 // SetCommonDataMiddleware will pass data to the renderer
27 e.Use(middleware.SetCommonDataMiddleware(a))
28
29 // Error handler middleware
30 e.Use(middleware.ErrorHandler)
31
32 // Use middlewares
33 e.Use(middleware.SecureRoutes(a))
34
35 // Color scheme detection for dark/light mode
36 e.Use(middleware.ColorSchemeDetection)
37
38 bindAdminRoute(e, a, AdminPath)
39 bindStaticRoute(e, a, "/*")
40 bindHTMXEndpoints(e, a)
41
42 // Protect the root path with a 403
43 e.GET("/", func(c echo.Context) error {
44 return c.String(403, "403 Forbidden")
45 })
46
47 return e
48}
49
50// bindAPIEndpoints expose /api endpoints and speaks only JSON
51func bindAPIEndpoints(e *echo.Echo, a *server.App) {
52 apiGroup := e.Group("/api")
53 apiGroup.Use(middleware.RequireToken(a))
54 apiGroup.GET("/ping", func(c echo.Context) error {
55 return handler.GetInfos(c, a)
56 })
57 apiGroup.POST("/deploy", func(c echo.Context) error {
58 return handler.PostDeploy(c, a)
59 })
60 apiGroup.POST("/push", func(c echo.Context) error {
61 return handler.PostPush(c, a)
62 })
63}
64
65// bindStaticRoute bind static path
66func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
67 e.GET(path, func(c echo.Context) error {
68 return handler.StaticRoute(c, a)
69 }, echomid.Gzip())
70}
71
72// bindLoginRoute binds all login routes
73func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
74 e.GET(adminPath+"/login", func(c echo.Context) error {
75 return handler.RenderLoginPage(c, a)
76 })
77 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
78 return handler.StartOAuthGithub(c, a)
79 })
80 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
81 return handler.OAuthCallback(c, a)
82 })
83 e.GET(adminPath+"/logout", func(c echo.Context) error {
84 return handler.Logout(c, a)
85 })
86}
87
88// bindAdminRoute binds all admin routes
89func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
90 adminGroup := e.Group(adminPath)
91 // Since login is behind the admin path, we cannot use group middleware
92 adminGroup.GET("", func(c echo.Context) error {
93 return c.Redirect(302, adminPath+"/manager")
94 }, middleware.RequireLogin(a))
95
96 adminGroup.GET("/manager", func(c echo.Context) error {
97 return handler.AdminManagerRoute(c, a)
98 }, middleware.RequireLogin(a))
99}
100
101// bindHTMXEndpoints binds all HTMX endpoints
102func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
103 // Create a group for /htmx endpoints
104 htmxGroup := e.Group("/htmx")
105
106 // Apply middleware to the group, so all endpoints are protected
107 htmxGroup.Use(middleware.RequireLogin(a))
108
109 // List all images component
110 htmxGroup.GET("/image-manager", func(c echo.Context) error {
111 return handler.ImageManagerComponent(c, a)
112 })
113 // Delete an image
114 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
115 return handler.ImageManagerDelete(c, a)
116 })
117
118 // List all containers
119 htmxGroup.GET("/container-manager", func(c echo.Context) error {
120 return handler.ContainerManagerComponent(c, a)
121 })
122 // Stop a container
123 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
124 return handler.ContainerManagerStop(c, a)
125 })
126 // Delete a container
127 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
128 return handler.ContainerManagerDelete(c, a)
129 })
130 // Start a container
131 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
132 return handler.ContainerManagerStart(c, a)
133 })
134 // Edit a container view
135 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
136 return handler.ContainerManagerEditGET(c, a)
137 })
138 // Edit a container action
139 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
140 return handler.ContainerManagerEditPOST(c, a)
141 })
142
143 // Display upload-image component
144 htmxGroup.GET("/upload-image", func(c echo.Context) error {
145 return handler.UploadImageGETHandler(c, a)
146 })
147 // Upload image
148 htmxGroup.POST("/upload-image", func(c echo.Context) error {
149 return handler.UploadImagePOSTHandler(c, a)
150 })
151 // Display create-container component
152 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
153 return handler.CreateContainerGET(c, a)
154 })
155 // Create container
156 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
157 return handler.CreateContainerPOST(c, a)
158 })
159}