detached 76d306e

refactor: restructure package and enhance payload handling

commit
76d306eebd2844b3e177f0af0cf21032f9716e1e
author
Brice · · 2024-10-09 06:26 UTC
parent
045b500
signature
unsigned
15 files · +121 -56
M internal/common/payload.go +63 -1
@@ -3,19 +3,21 @@ package common
33 import (
44 "encoding/json"
55 "fmt"
6-
76 "io"
87 )
98
9+// RequestPayload represents the structure of incoming requests
1010 type RequestPayload struct {
1111 Type string `json:"type"`
1212 Payload Payload `json:"payload"`
1313 }
1414
15+// Payload is an interface for different types of payloads
1516 type Payload interface {
1617 GetType() string
1718 }
1819
20+// DeployResponse represents the response structure for deployment requests
1921 type DeployResponse struct {
2022 Success bool `json:"success"`
2123 Message string `json:"message"`
@@ -23,22 +25,26 @@ type DeployResponse struct {
2325 ContainerID string `json:"container_id,omitempty"`
2426 }
2527
28+// PushResponse represents the response structure for push requests
2629 type PushResponse struct {
2730 Success bool `json:"success"`
2831 Message string `json:"message"`
2932 CreateContainerURL string `json:"create_container_url,omitempty"`
3033 }
3134
35+// DeploymentError represents an error that occurred during deployment
3236 type DeploymentError struct {
3337 StatusCode int `json:"status"`
3438 Message string `json:"message"`
3539 RawResponse string `json:"raw_response"`
3640 }
3741
42+// Error implements the error interface for DeploymentError
3843 func (e *DeploymentError) Error() string {
3944 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)
4045 }
4146
47+// DeployPayload represents the payload for deployment requests
4248 type DeployPayload struct {
4349 Port string `json:"port"`
4450 TargetDomain string `json:"targetdomain"`
@@ -47,12 +53,14 @@ type DeployPayload struct {
4753 Data io.ReadCloser
4854 }
4955
56+// PushPayload represents the payload for push requests
5057 type PushPayload struct {
5158 ImageName string `json:"imagename"`
5259 ImageID string `json:"imageid"`
5360 Data io.ReadCloser
5461 }
5562
63+// UnmarshalJSON custom unmarshaler for RequestPayload
5664 func (p *RequestPayload) UnmarshalJSON(data []byte) error {
5765 var raw map[string]json.RawMessage
5866 err := json.Unmarshal(data, &raw)
@@ -64,6 +72,7 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
6472 return err
6573 }
6674
75+ // Unmarshal the payload based on the type
6776 switch p.Type {
6877 case "ping":
6978 var payload PingPayload
@@ -83,6 +92,24 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
8392 return err
8493 }
8594 p.Payload = payload
95+ case "stop":
96+ var payload StopPayload
97+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
98+ return err
99+ }
100+ p.Payload = payload
101+ case "start":
102+ var payload StartPayload
103+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
104+ return err
105+ }
106+ p.Payload = payload
107+ case "remove":
108+ var payload RemovePayload
109+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
110+ return err
111+ }
112+ p.Payload = payload
86113 default:
87114 return fmt.Errorf("invalid type: %s", p.Type)
88115 }
@@ -90,22 +117,27 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
90117 return nil
91118 }
92119
120+// PingPayload represents the payload for ping requests
93121 type PingPayload struct {
94122 Message string `json:"message"`
95123 }
96124
125+// GetType returns the type of the PingPayload
97126 func (p PingPayload) GetType() string {
98127 return "ping"
99128 }
100129
130+// GetType returns the type of the DeployPayload
101131 func (p DeployPayload) GetType() string {
102132 return "deploy"
103133 }
104134
135+// GetType returns the type of the PushPayload
105136 func (p PushPayload) GetType() string {
106137 return "push"
107138 }
108139
140+// NewPingPayload creates a new PingPayload from a map of data
109141 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
110142 message, ok := data["message"].(string)
111143 if !ok {
@@ -113,3 +145,33 @@ func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
113145 }
114146 return PingPayload{Message: message}, nil
115147 }
148+
149+// StopPayload represents the payload for stop requests
150+type StopPayload struct {
151+ ContainerID string `json:"container_id"`
152+}
153+
154+// GetType returns the type of the StopPayload
155+func (p StopPayload) GetType() string {
156+ return "stop"
157+}
158+
159+// StartPayload represents the payload for start requests
160+type StartPayload struct {
161+ ContainerID string `json:"container_id"`
162+}
163+
164+// GetType returns the type of the StartPayload
165+func (p StartPayload) GetType() string {
166+ return "start"
167+}
168+
169+// RemovePayload represents the payload for remove requests
170+type RemovePayload struct {
171+ ContainerID string `json:"container_id"`
172+}
173+
174+// GetType returns the type of the RemovePayload
175+func (p RemovePayload) GetType() string {
176+ return "remove"
177+}
@@ -3,19 +3,21 @@ package common
3 import (3 import (
4 "encoding/json"4 "encoding/json"
5 "fmt"5 "fmt"
6-
7 "io"6 "io"
8 )7 )
9 8
9+// RequestPayload represents the structure of incoming requests
10 type RequestPayload struct {10 type RequestPayload struct {
11 Type string `json:"type"`11 Type string `json:"type"`
12 Payload Payload `json:"payload"`12 Payload Payload `json:"payload"`
13 }13 }
14 14
15+// Payload is an interface for different types of payloads
15 type Payload interface {16 type Payload interface {
16 GetType() string17 GetType() string
17 }18 }
18 19
20+// DeployResponse represents the response structure for deployment requests
19 type DeployResponse struct {21 type DeployResponse struct {
20 Success bool `json:"success"`22 Success bool `json:"success"`
21 Message string `json:"message"`23 Message string `json:"message"`
@@ -23,22 +25,26 @@ type DeployResponse struct {
23 ContainerID string `json:"container_id,omitempty"`25 ContainerID string `json:"container_id,omitempty"`
24 }26 }
25 27
28+// PushResponse represents the response structure for push requests
26 type PushResponse struct {29 type PushResponse struct {
27 Success bool `json:"success"`30 Success bool `json:"success"`
28 Message string `json:"message"`31 Message string `json:"message"`
29 CreateContainerURL string `json:"create_container_url,omitempty"`32 CreateContainerURL string `json:"create_container_url,omitempty"`
30 }33 }
31 34
35+// DeploymentError represents an error that occurred during deployment
32 type DeploymentError struct {36 type DeploymentError struct {
33 StatusCode int `json:"status"`37 StatusCode int `json:"status"`
34 Message string `json:"message"`38 Message string `json:"message"`
35 RawResponse string `json:"raw_response"`39 RawResponse string `json:"raw_response"`
36 }40 }
37 41
42+// Error implements the error interface for DeploymentError
38 func (e *DeploymentError) Error() string {43 func (e *DeploymentError) Error() string {
39 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)44 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)
40 }45 }
41 46
47+// DeployPayload represents the payload for deployment requests
42 type DeployPayload struct {48 type DeployPayload struct {
43 Port string `json:"port"`49 Port string `json:"port"`
44 TargetDomain string `json:"targetdomain"`50 TargetDomain string `json:"targetdomain"`
@@ -47,12 +53,14 @@ type DeployPayload struct {
47 Data io.ReadCloser53 Data io.ReadCloser
48 }54 }
49 55
56+// PushPayload represents the payload for push requests
50 type PushPayload struct {57 type PushPayload struct {
51 ImageName string `json:"imagename"`58 ImageName string `json:"imagename"`
52 ImageID string `json:"imageid"`59 ImageID string `json:"imageid"`
53 Data io.ReadCloser60 Data io.ReadCloser
54 }61 }
55 62
63+// UnmarshalJSON custom unmarshaler for RequestPayload
56 func (p *RequestPayload) UnmarshalJSON(data []byte) error {64 func (p *RequestPayload) UnmarshalJSON(data []byte) error {
57 var raw map[string]json.RawMessage65 var raw map[string]json.RawMessage
58 err := json.Unmarshal(data, &raw)66 err := json.Unmarshal(data, &raw)
@@ -64,6 +72,7 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
64 return err72 return err
65 }73 }
66 74
75+ // Unmarshal the payload based on the type
67 switch p.Type {76 switch p.Type {
68 case "ping":77 case "ping":
69 var payload PingPayload78 var payload PingPayload
@@ -83,6 +92,24 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
83 return err92 return err
84 }93 }
85 p.Payload = payload94 p.Payload = payload
95+ case "stop":
96+ var payload StopPayload
97+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
98+ return err
99+ }
100+ p.Payload = payload
101+ case "start":
102+ var payload StartPayload
103+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
104+ return err
105+ }
106+ p.Payload = payload
107+ case "remove":
108+ var payload RemovePayload
109+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
110+ return err
111+ }
112+ p.Payload = payload
86 default:113 default:
87 return fmt.Errorf("invalid type: %s", p.Type)114 return fmt.Errorf("invalid type: %s", p.Type)
88 }115 }
@@ -90,22 +117,27 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
90 return nil117 return nil
91 }118 }
92 119
120+// PingPayload represents the payload for ping requests
93 type PingPayload struct {121 type PingPayload struct {
94 Message string `json:"message"`122 Message string `json:"message"`
95 }123 }
96 124
125+// GetType returns the type of the PingPayload
97 func (p PingPayload) GetType() string {126 func (p PingPayload) GetType() string {
98 return "ping"127 return "ping"
99 }128 }
100 129
130+// GetType returns the type of the DeployPayload
101 func (p DeployPayload) GetType() string {131 func (p DeployPayload) GetType() string {
102 return "deploy"132 return "deploy"
103 }133 }
104 134
135+// GetType returns the type of the PushPayload
105 func (p PushPayload) GetType() string {136 func (p PushPayload) GetType() string {
106 return "push"137 return "push"
107 }138 }
108 139
140+// NewPingPayload creates a new PingPayload from a map of data
109 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {141 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
110 message, ok := data["message"].(string)142 message, ok := data["message"].(string)
111 if !ok {143 if !ok {
@@ -113,3 +145,33 @@ func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
113 }145 }
114 return PingPayload{Message: message}, nil146 return PingPayload{Message: message}, nil
115 }147 }
148+
149+// StopPayload represents the payload for stop requests
150+type StopPayload struct {
151+ ContainerID string `json:"container_id"`
152+}
153+
154+// GetType returns the type of the StopPayload
155+func (p StopPayload) GetType() string {
156+ return "stop"
157+}
158+
159+// StartPayload represents the payload for start requests
160+type StartPayload struct {
161+ ContainerID string `json:"container_id"`
162+}
163+
164+// GetType returns the type of the StartPayload
165+func (p StartPayload) GetType() string {
166+ return "start"
167+}
168+
169+// RemovePayload represents the payload for remove requests
170+type RemovePayload struct {
171+ ContainerID string `json:"container_id"`
172+}
173+
174+// GetType returns the type of the RemovePayload
175+func (p RemovePayload) GetType() string {
176+ return "remove"
177+}
D internal/httpserve/handler/htmx.go +0 -1
@@ -1,1 +0,0 @@
1-package handler
@@ -1,1 +0,0 @@
1-package handler
R internal/httpserve/handler/admin-view.go → internal/httpserve/handlers/admin-view.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/cli-endpoints.go → internal/httpserve/handlers/cli-endpoints.go +2 -2 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "encoding/json"
@@ -207,7 +207,7 @@ func PostDeploy(c echo.Context, a *server.App) error {
207207
208208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{
209209 Success: false,
210- Message: fmt.Sprintf("A container for this deploy already exists."),
210+ Message: "A container for this deploy already exists.",
211211 ContainerID: extractedID,
212212 })
213213 }
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "encoding/json"4 "encoding/json"
@@ -207,7 +207,7 @@ func PostDeploy(c echo.Context, a *server.App) error {
207 207
208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{
209 Success: false,209 Success: false,
210- Message: fmt.Sprintf("A container for this deploy already exists."),210+ Message: "A container for this deploy already exists.",
211 ContainerID: extractedID,211 ContainerID: extractedID,
212 })212 })
213 }213 }
R internal/httpserve/handler/createcontainer.go → internal/httpserve/handlers/container-crud.go +2 -1 renamed, 98% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -57,6 +57,7 @@ func CreateContainerGET(c echo.Context, a *server.App) error {
5757 "ImageName": imageName,
5858 }
5959
60+ // Render the create container page
6061 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)
6162
6263 if err != nil {
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
@@ -57,6 +57,7 @@ func CreateContainerGET(c echo.Context, a *server.App) error {
57 "ImageName": imageName,57 "ImageName": imageName,
58 }58 }
59 59
60+ // Render the create container page
60 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)61 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)
61 62
62 if err != nil {63 if err != nil {
R internal/httpserve/handler/containers.go → internal/httpserve/handlers/container-management.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/editcontainer.go → internal/httpserve/handlers/container-transaction.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/oauth.go → internal/httpserve/handlers/login.go +16 -14 renamed, 92% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "encoding/base64"
@@ -13,6 +13,7 @@ import (
1313 "github.com/bnema/gordon/internal/db/queries"
1414 "github.com/bnema/gordon/internal/server"
1515 "github.com/bnema/gordon/internal/templating/render"
16+ "github.com/charmbracelet/log"
1617 "github.com/gorilla/sessions"
1718 _ "github.com/joho/godotenv/autoload"
1819 "github.com/labstack/echo-contrib/session"
@@ -59,58 +60,59 @@ func RenderLoginPage(c echo.Context, a *server.App) error {
5960 }
6061
6162 // StartOAuthGithub starts the Github OAuth flow.
63+
6264 func StartOAuthGithub(c echo.Context, a *server.App) error {
63- fmt.Println("Attempting to get an existing session.")
65+ log.Info("Attempting to get an existing session.")
6466 sess, err := getSession(c)
6567 if err != nil || sess == nil || sess.Values == nil {
66- fmt.Println("Session retrieval failed, initiating new GitHub OAuth flow.")
68+ log.Info("Session retrieval failed, initiating new GitHub OAuth flow.")
6769 return initiateGithubOAuthFlow(c, a)
6870 }
6971
70- fmt.Println("Attempting to assert session values.")
72+ log.Info("Attempting to assert session values.")
7173 sessionID, ok1 := sess.Values["sessionID"].(string)
7274 accountID, ok2 := sess.Values["accountID"].(string)
7375 authenticated, ok3 := sess.Values["authenticated"].(bool)
7476
7577 if !ok1 || !ok2 || !ok3 || !authenticated {
76- fmt.Println("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
78+ log.Info("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
7779 return initiateGithubOAuthFlow(c, a)
7880 }
7981
80- fmt.Println("Checking if session exists in DB.")
82+ log.Info("Checking if session exists in DB.")
8183 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)
8284 if err != nil {
83- fmt.Printf("Error checking if session exists: %v\n", err)
85+ log.Info("Error checking if session exists", "error", err)
8486 return fmt.Errorf("could not check if session exists: %w", err)
8587 }
8688
8789 if !sessionExists {
88- fmt.Println("Session does not exist in DB, initiating new OAuth flow.")
90+ log.Info("Session does not exist in DB, initiating new OAuth flow.")
8991 return initiateGithubOAuthFlow(c, a)
9092 }
9193
92- fmt.Println("Getting the expiration time of the session.")
94+ log.Info("Getting the expiration time of the session.")
9395 currentTime := time.Now()
9496 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)
9597 if err != nil {
96- fmt.Printf("Error getting session expiration: %v\n", err)
98+ log.Info("Error getting session expiration", "error", err)
9799 return fmt.Errorf("could not get session expiration: %w", err)
98100 }
99101
100102 if currentTime.After(sessionExpiration) {
101- fmt.Println("Current time is after session expiration, initiating new OAuth flow.")
103+ log.Info("Current time is after session expiration, initiating new OAuth flow.")
102104 return initiateGithubOAuthFlow(c, a)
103105 }
104106
105- fmt.Println("Extending session expiration time by 30 minutes.")
107+ log.Info("Extending session expiration time by 30 minutes.")
106108 newExpirationTime := currentTime.Add(30 * time.Minute)
107109 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)
108110 if err != nil {
109- fmt.Printf("Error extending session expiration: %v\n", err)
111+ log.Info("Error extending session expiration", "error", err)
110112 return fmt.Errorf("could not extend session expiration: %w", err)
111113 }
112114
113- fmt.Println("Session is valid and extended. Redirecting to admin panel.")
115+ log.Info("Session is valid and extended. Redirecting to admin panel.")
114116 return c.Redirect(http.StatusFound, a.Config.Admin.Path)
115117 }
116118
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "encoding/base64"4 "encoding/base64"
@@ -13,6 +13,7 @@ import (
13 "github.com/bnema/gordon/internal/db/queries"13 "github.com/bnema/gordon/internal/db/queries"
14 "github.com/bnema/gordon/internal/server"14 "github.com/bnema/gordon/internal/server"
15 "github.com/bnema/gordon/internal/templating/render"15 "github.com/bnema/gordon/internal/templating/render"
16+ "github.com/charmbracelet/log"
16 "github.com/gorilla/sessions"17 "github.com/gorilla/sessions"
17 _ "github.com/joho/godotenv/autoload"18 _ "github.com/joho/godotenv/autoload"
18 "github.com/labstack/echo-contrib/session"19 "github.com/labstack/echo-contrib/session"
@@ -59,58 +60,59 @@ func RenderLoginPage(c echo.Context, a *server.App) error {
59 }60 }
60 61
61 // StartOAuthGithub starts the Github OAuth flow.62 // StartOAuthGithub starts the Github OAuth flow.
63+
62 func StartOAuthGithub(c echo.Context, a *server.App) error {64 func StartOAuthGithub(c echo.Context, a *server.App) error {
63- fmt.Println("Attempting to get an existing session.")65+ log.Info("Attempting to get an existing session.")
64 sess, err := getSession(c)66 sess, err := getSession(c)
65 if err != nil || sess == nil || sess.Values == nil {67 if err != nil || sess == nil || sess.Values == nil {
66- fmt.Println("Session retrieval failed, initiating new GitHub OAuth flow.")68+ log.Info("Session retrieval failed, initiating new GitHub OAuth flow.")
67 return initiateGithubOAuthFlow(c, a)69 return initiateGithubOAuthFlow(c, a)
68 }70 }
69 71
70- fmt.Println("Attempting to assert session values.")72+ log.Info("Attempting to assert session values.")
71 sessionID, ok1 := sess.Values["sessionID"].(string)73 sessionID, ok1 := sess.Values["sessionID"].(string)
72 accountID, ok2 := sess.Values["accountID"].(string)74 accountID, ok2 := sess.Values["accountID"].(string)
73 authenticated, ok3 := sess.Values["authenticated"].(bool)75 authenticated, ok3 := sess.Values["authenticated"].(bool)
74 76
75 if !ok1 || !ok2 || !ok3 || !authenticated {77 if !ok1 || !ok2 || !ok3 || !authenticated {
76- fmt.Println("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")78+ log.Info("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
77 return initiateGithubOAuthFlow(c, a)79 return initiateGithubOAuthFlow(c, a)
78 }80 }
79 81
80- fmt.Println("Checking if session exists in DB.")82+ log.Info("Checking if session exists in DB.")
81 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)83 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)
82 if err != nil {84 if err != nil {
83- fmt.Printf("Error checking if session exists: %v\n", err)85+ log.Info("Error checking if session exists", "error", err)
84 return fmt.Errorf("could not check if session exists: %w", err)86 return fmt.Errorf("could not check if session exists: %w", err)
85 }87 }
86 88
87 if !sessionExists {89 if !sessionExists {
88- fmt.Println("Session does not exist in DB, initiating new OAuth flow.")90+ log.Info("Session does not exist in DB, initiating new OAuth flow.")
89 return initiateGithubOAuthFlow(c, a)91 return initiateGithubOAuthFlow(c, a)
90 }92 }
91 93
92- fmt.Println("Getting the expiration time of the session.")94+ log.Info("Getting the expiration time of the session.")
93 currentTime := time.Now()95 currentTime := time.Now()
94 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)96 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)
95 if err != nil {97 if err != nil {
96- fmt.Printf("Error getting session expiration: %v\n", err)98+ log.Info("Error getting session expiration", "error", err)
97 return fmt.Errorf("could not get session expiration: %w", err)99 return fmt.Errorf("could not get session expiration: %w", err)
98 }100 }
99 101
100 if currentTime.After(sessionExpiration) {102 if currentTime.After(sessionExpiration) {
101- fmt.Println("Current time is after session expiration, initiating new OAuth flow.")103+ log.Info("Current time is after session expiration, initiating new OAuth flow.")
102 return initiateGithubOAuthFlow(c, a)104 return initiateGithubOAuthFlow(c, a)
103 }105 }
104 106
105- fmt.Println("Extending session expiration time by 30 minutes.")107+ log.Info("Extending session expiration time by 30 minutes.")
106 newExpirationTime := currentTime.Add(30 * time.Minute)108 newExpirationTime := currentTime.Add(30 * time.Minute)
107 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)109 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)
108 if err != nil {110 if err != nil {
109- fmt.Printf("Error extending session expiration: %v\n", err)111+ log.Info("Error extending session expiration", "error", err)
110 return fmt.Errorf("could not extend session expiration: %w", err)112 return fmt.Errorf("could not extend session expiration: %w", err)
111 }113 }
112 114
113- fmt.Println("Session is valid and extended. Redirecting to admin panel.")115+ log.Info("Session is valid and extended. Redirecting to admin panel.")
114 return c.Redirect(http.StatusFound, a.Config.Admin.Path)116 return c.Redirect(http.StatusFound, a.Config.Admin.Path)
115 }117 }
116 118
R internal/httpserve/handler/logout.go → internal/httpserve/handlers/logout.go +4 -3 renamed, 89% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -21,8 +21,9 @@ func Logout(c echo.Context, a *server.App) error {
2121 }
2222
2323 // Invalidate the session in the database
24- if sess != nil {
25- err := queries.InvalidateDBSession(a, sess.Values["sessionID"].(string))
24+ sessionID, ok := sess.Values["sessionID"].(string)
25+ if ok {
26+ err := queries.InvalidateDBSession(a, sessionID)
2627 if err != nil {
2728 return fmt.Errorf("failed to invalidate session: %w", err)
2829 }
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
@@ -21,8 +21,9 @@ func Logout(c echo.Context, a *server.App) error {
21 }21 }
22 22
23 // Invalidate the session in the database23 // Invalidate the session in the database
24- if sess != nil {24+ sessionID, ok := sess.Values["sessionID"].(string)
25- err := queries.InvalidateDBSession(a, sess.Values["sessionID"].(string))25+ if ok {
26+ err := queries.InvalidateDBSession(a, sessionID)
26 if err != nil {27 if err != nil {
27 return fmt.Errorf("failed to invalidate session: %w", err)28 return fmt.Errorf("failed to invalidate session: %w", err)
28 }29 }
R internal/httpserve/handler/senderror.go → internal/httpserve/handlers/send-error.go +1 -1 renamed, 96% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "net/http"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "net/http"4 "net/http"
R internal/httpserve/handler/sessiondb.go → internal/httpserve/handlers/session-db.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/static.go → internal/httpserve/handlers/static.go +1 -1 renamed, 98% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "io/fs"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "io/fs"4 "io/fs"
R internal/httpserve/handler/upload-image.go → internal/httpserve/handlers/upload-image.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
M internal/httpserve/middleware/requirelogin.go +2 -2
@@ -4,7 +4,7 @@ import (
44 "net/http"
55 "time"
66
7- "github.com/bnema/gordon/internal/httpserve/handler"
7+ "github.com/bnema/gordon/internal/httpserve/handlers"
88 "github.com/bnema/gordon/internal/server"
99
1010 "github.com/labstack/echo/v4"
@@ -20,7 +20,7 @@ func RequireLogin(a *server.App) echo.MiddlewareFunc {
2020 const maxRetries = 3
2121 var err error
2222 for i := 0; i < maxRetries; i++ {
23- err = handler.ValidateSessionAndUser(c, a)
23+ err = handlers.ValidateSessionAndUser(c, a)
2424 if err == nil {
2525 return next(c)
2626 }
@@ -4,7 +4,7 @@ import (
4 "net/http"4 "net/http"
5 "time"5 "time"
6 6
7- "github.com/bnema/gordon/internal/httpserve/handler"7+ "github.com/bnema/gordon/internal/httpserve/handlers"
8 "github.com/bnema/gordon/internal/server"8 "github.com/bnema/gordon/internal/server"
9 9
10 "github.com/labstack/echo/v4"10 "github.com/labstack/echo/v4"
@@ -20,7 +20,7 @@ func RequireLogin(a *server.App) echo.MiddlewareFunc {
20 const maxRetries = 320 const maxRetries = 3
21 var err error21 var err error
22 for i := 0; i < maxRetries; i++ {22 for i := 0; i < maxRetries; i++ {
23- err = handler.ValidateSessionAndUser(c, a)23+ err = handlers.ValidateSessionAndUser(c, a)
24 if err == nil {24 if err == nil {
25 return next(c)25 return next(c)
26 }26 }
M internal/httpserve/router.go +25 -25
@@ -1,7 +1,7 @@
11 package httpserve
22
33 import (
4- "github.com/bnema/gordon/internal/httpserve/handler"
4+ "github.com/bnema/gordon/internal/httpserve/handlers"
55 "github.com/bnema/gordon/internal/httpserve/middleware"
66 "github.com/bnema/gordon/internal/server"
77 _ "github.com/joho/godotenv/autoload"
@@ -53,45 +53,45 @@ func bindAPIEndpoints(e *echo.Echo, a *server.App) {
5353
5454 // Device flow endpoints (without RequireToken middleware)
5555 apiGroup.POST("/device/code", func(c echo.Context) error {
56- return handler.DeviceCodeRequest(c, a)
56+ return handlers.DeviceCodeRequest(c, a)
5757 })
5858 apiGroup.POST("/device/token", func(c echo.Context) error {
59- return handler.DeviceTokenRequest(c, a)
59+ return handlers.DeviceTokenRequest(c, a)
6060 })
6161
6262 // Other API endpoints that require a token
6363 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))
6464 protectedApiGroup.GET("/ping", func(c echo.Context) error {
65- return handler.GetInfos(c, a)
65+ return handlers.GetInfos(c, a)
6666 })
6767 protectedApiGroup.POST("/deploy", func(c echo.Context) error {
68- return handler.PostDeploy(c, a)
68+ return handlers.PostDeploy(c, a)
6969 })
7070 protectedApiGroup.POST("/push", func(c echo.Context) error {
71- return handler.PostPush(c, a)
71+ return handlers.PostPush(c, a)
7272 })
7373 }
7474
7575 // bindStaticRoute bind static path
7676 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
7777 e.GET(path, func(c echo.Context) error {
78- return handler.StaticRoute(c, a)
78+ return handlers.StaticRoute(c, a)
7979 }, echomid.Gzip())
8080 }
8181
8282 // bindLoginRoute binds all login routes
8383 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
8484 e.GET(adminPath+"/login", func(c echo.Context) error {
85- return handler.RenderLoginPage(c, a)
85+ return handlers.RenderLoginPage(c, a)
8686 })
8787 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
88- return handler.StartOAuthGithub(c, a)
88+ return handlers.StartOAuthGithub(c, a)
8989 })
9090 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
91- return handler.OAuthCallback(c, a)
91+ return handlers.OAuthCallback(c, a)
9292 })
9393 e.GET(adminPath+"/logout", func(c echo.Context) error {
94- return handler.Logout(c, a)
94+ return handlers.Logout(c, a)
9595 })
9696 }
9797
@@ -104,10 +104,10 @@ func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
104104 }, middleware.RequireLogin(a))
105105
106106 adminGroup.GET("/manager", func(c echo.Context) error {
107- return handler.AdminManagerRoute(c, a)
107+ return handlers.AdminManagerRoute(c, a)
108108 }, middleware.RequireLogin(a))
109109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {
110- return handler.CreateContainerFullGET(c, a)
110+ return handlers.CreateContainerFullGET(c, a)
111111 }, middleware.RequireLogin(a))
112112 }
113113
@@ -121,52 +121,52 @@ func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
121121
122122 // List all images component
123123 htmxGroup.GET("/image-manager", func(c echo.Context) error {
124- return handler.ImageManagerComponent(c, a)
124+ return handlers.ImageManagerComponent(c, a)
125125 })
126126 // Delete an image
127127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
128- return handler.ImageManagerDelete(c, a)
128+ return handlers.ImageManagerDelete(c, a)
129129 })
130130
131131 // List all containers
132132 htmxGroup.GET("/container-manager", func(c echo.Context) error {
133- return handler.ContainerManagerComponent(c, a)
133+ return handlers.ContainerManagerComponent(c, a)
134134 })
135135 // Stop a container
136136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
137- return handler.ContainerManagerStop(c, a)
137+ return handlers.ContainerManagerStop(c, a)
138138 })
139139 // Delete a container
140140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
141- return handler.ContainerManagerDelete(c, a)
141+ return handlers.ContainerManagerDelete(c, a)
142142 })
143143 // Start a container
144144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
145- return handler.ContainerManagerStart(c, a)
145+ return handlers.ContainerManagerStart(c, a)
146146 })
147147 // Edit a container view
148148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
149- return handler.ContainerManagerEditGET(c, a)
149+ return handlers.ContainerManagerEditGET(c, a)
150150 })
151151 // Edit a container action
152152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
153- return handler.ContainerManagerEditPOST(c, a)
153+ return handlers.ContainerManagerEditPOST(c, a)
154154 })
155155
156156 // Display upload-image component
157157 htmxGroup.GET("/upload-image", func(c echo.Context) error {
158- return handler.UploadImageGETHandler(c, a)
158+ return handlers.UploadImageGETHandler(c, a)
159159 })
160160 // Upload image
161161 htmxGroup.POST("/upload-image", func(c echo.Context) error {
162- return handler.UploadImagePOSTHandler(c, a)
162+ return handlers.UploadImagePOSTHandler(c, a)
163163 })
164164 // Display create-container component
165165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
166- return handler.CreateContainerGET(c, a)
166+ return handlers.CreateContainerGET(c, a)
167167 })
168168 // Create container
169169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
170- return handler.CreateContainerPOST(c, a)
170+ return handlers.CreateContainerPOST(c, a)
171171 })
172172 }
@@ -1,7 +1,7 @@
1 package httpserve1 package httpserve
2 2
3 import (3 import (
4- "github.com/bnema/gordon/internal/httpserve/handler"4+ "github.com/bnema/gordon/internal/httpserve/handlers"
5 "github.com/bnema/gordon/internal/httpserve/middleware"5 "github.com/bnema/gordon/internal/httpserve/middleware"
6 "github.com/bnema/gordon/internal/server"6 "github.com/bnema/gordon/internal/server"
7 _ "github.com/joho/godotenv/autoload"7 _ "github.com/joho/godotenv/autoload"
@@ -53,45 +53,45 @@ func bindAPIEndpoints(e *echo.Echo, a *server.App) {
53 53
54 // Device flow endpoints (without RequireToken middleware)54 // Device flow endpoints (without RequireToken middleware)
55 apiGroup.POST("/device/code", func(c echo.Context) error {55 apiGroup.POST("/device/code", func(c echo.Context) error {
56- return handler.DeviceCodeRequest(c, a)56+ return handlers.DeviceCodeRequest(c, a)
57 })57 })
58 apiGroup.POST("/device/token", func(c echo.Context) error {58 apiGroup.POST("/device/token", func(c echo.Context) error {
59- return handler.DeviceTokenRequest(c, a)59+ return handlers.DeviceTokenRequest(c, a)
60 })60 })
61 61
62 // Other API endpoints that require a token62 // Other API endpoints that require a token
63 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))63 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))
64 protectedApiGroup.GET("/ping", func(c echo.Context) error {64 protectedApiGroup.GET("/ping", func(c echo.Context) error {
65- return handler.GetInfos(c, a)65+ return handlers.GetInfos(c, a)
66 })66 })
67 protectedApiGroup.POST("/deploy", func(c echo.Context) error {67 protectedApiGroup.POST("/deploy", func(c echo.Context) error {
68- return handler.PostDeploy(c, a)68+ return handlers.PostDeploy(c, a)
69 })69 })
70 protectedApiGroup.POST("/push", func(c echo.Context) error {70 protectedApiGroup.POST("/push", func(c echo.Context) error {
71- return handler.PostPush(c, a)71+ return handlers.PostPush(c, a)
72 })72 })
73 }73 }
74 74
75 // bindStaticRoute bind static path75 // bindStaticRoute bind static path
76 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {76 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
77 e.GET(path, func(c echo.Context) error {77 e.GET(path, func(c echo.Context) error {
78- return handler.StaticRoute(c, a)78+ return handlers.StaticRoute(c, a)
79 }, echomid.Gzip())79 }, echomid.Gzip())
80 }80 }
81 81
82 // bindLoginRoute binds all login routes82 // bindLoginRoute binds all login routes
83 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {83 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
84 e.GET(adminPath+"/login", func(c echo.Context) error {84 e.GET(adminPath+"/login", func(c echo.Context) error {
85- return handler.RenderLoginPage(c, a)85+ return handlers.RenderLoginPage(c, a)
86 })86 })
87 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {87 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
88- return handler.StartOAuthGithub(c, a)88+ return handlers.StartOAuthGithub(c, a)
89 })89 })
90 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {90 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
91- return handler.OAuthCallback(c, a)91+ return handlers.OAuthCallback(c, a)
92 })92 })
93 e.GET(adminPath+"/logout", func(c echo.Context) error {93 e.GET(adminPath+"/logout", func(c echo.Context) error {
94- return handler.Logout(c, a)94+ return handlers.Logout(c, a)
95 })95 })
96 }96 }
97 97
@@ -104,10 +104,10 @@ func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
104 }, middleware.RequireLogin(a))104 }, middleware.RequireLogin(a))
105 105
106 adminGroup.GET("/manager", func(c echo.Context) error {106 adminGroup.GET("/manager", func(c echo.Context) error {
107- return handler.AdminManagerRoute(c, a)107+ return handlers.AdminManagerRoute(c, a)
108 }, middleware.RequireLogin(a))108 }, middleware.RequireLogin(a))
109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {
110- return handler.CreateContainerFullGET(c, a)110+ return handlers.CreateContainerFullGET(c, a)
111 }, middleware.RequireLogin(a))111 }, middleware.RequireLogin(a))
112 }112 }
113 113
@@ -121,52 +121,52 @@ func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
121 121
122 // List all images component122 // List all images component
123 htmxGroup.GET("/image-manager", func(c echo.Context) error {123 htmxGroup.GET("/image-manager", func(c echo.Context) error {
124- return handler.ImageManagerComponent(c, a)124+ return handlers.ImageManagerComponent(c, a)
125 })125 })
126 // Delete an image126 // Delete an image
127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
128- return handler.ImageManagerDelete(c, a)128+ return handlers.ImageManagerDelete(c, a)
129 })129 })
130 130
131 // List all containers131 // List all containers
132 htmxGroup.GET("/container-manager", func(c echo.Context) error {132 htmxGroup.GET("/container-manager", func(c echo.Context) error {
133- return handler.ContainerManagerComponent(c, a)133+ return handlers.ContainerManagerComponent(c, a)
134 })134 })
135 // Stop a container135 // Stop a container
136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
137- return handler.ContainerManagerStop(c, a)137+ return handlers.ContainerManagerStop(c, a)
138 })138 })
139 // Delete a container139 // Delete a container
140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
141- return handler.ContainerManagerDelete(c, a)141+ return handlers.ContainerManagerDelete(c, a)
142 })142 })
143 // Start a container143 // Start a container
144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
145- return handler.ContainerManagerStart(c, a)145+ return handlers.ContainerManagerStart(c, a)
146 })146 })
147 // Edit a container view147 // Edit a container view
148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
149- return handler.ContainerManagerEditGET(c, a)149+ return handlers.ContainerManagerEditGET(c, a)
150 })150 })
151 // Edit a container action151 // Edit a container action
152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
153- return handler.ContainerManagerEditPOST(c, a)153+ return handlers.ContainerManagerEditPOST(c, a)
154 })154 })
155 155
156 // Display upload-image component156 // Display upload-image component
157 htmxGroup.GET("/upload-image", func(c echo.Context) error {157 htmxGroup.GET("/upload-image", func(c echo.Context) error {
158- return handler.UploadImageGETHandler(c, a)158+ return handlers.UploadImageGETHandler(c, a)
159 })159 })
160 // Upload image160 // Upload image
161 htmxGroup.POST("/upload-image", func(c echo.Context) error {161 htmxGroup.POST("/upload-image", func(c echo.Context) error {
162- return handler.UploadImagePOSTHandler(c, a)162+ return handlers.UploadImagePOSTHandler(c, a)
163 })163 })
164 // Display create-container component164 // Display create-container component
165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
166- return handler.CreateContainerGET(c, a)166+ return handlers.CreateContainerGET(c, a)
167 })167 })
168 // Create container168 // Create container
169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
170- return handler.CreateContainerPOST(c, a)170+ return handlers.CreateContainerPOST(c, a)
171 })171 })
172 }172 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close