Refactor HTTP Handlers and Utility Functions
- Generalize admin page rendering into a single `renderAdminPage` function - Rewrite the mutex-safe on idMap operations into one function - Update status code usages to use `http` package constants - Use more descriptive function names and comments for better readability - Various comments and code style improvements
- commit
- c10a3cb1c6daefbd9e1c3da5e3a06acf35675217
- author
- bnema · · 2023-10-20 17:35 UTC
- parent
- 3d52ec3
- signature
- unsigned
5 files · +91 -75
M internal/httpserve/handler/adminroutes.go +15 -22
| @@ -3,6 +3,8 @@ package handler | |||
| 3 | 3 | import ( | |
| 4 | 4 | "fmt" | |
| 5 | 5 | ||
| 6 | + | "net/http" | |
| 7 | + | ||
| 6 | 8 | "github.com/bnema/gordon/internal/app" | |
| 7 | 9 | "github.com/bnema/gordon/internal/httpserve/middleware" | |
| 8 | 10 | "github.com/bnema/gordon/internal/templating/render" | |
| @@ -14,6 +16,7 @@ var ( | |||
| 14 | 16 | fragmentsPath = "html/fragments" | |
| 15 | 17 | ) | |
| 16 | 18 | ||
| 19 | + | // GetLocalizedData returns the data for the localization | |
| 17 | 20 | func GetLocalizedData(c echo.Context, a *app.App) (map[string]interface{}, error) { | |
| 18 | 21 | lang := c.Get(middleware.LangKey) | |
| 19 | 22 | ||
| @@ -30,14 +33,14 @@ func GetLocalizedData(c echo.Context, a *app.App) (map[string]interface{}, error | |||
| 30 | 33 | }, nil | |
| 31 | 34 | } | |
| 32 | 35 | ||
| 33 | - | // Handle the admin route to display index.gohtml from the templateFS with the data from strings.yml | |
| 34 | - | func AdminRoute(c echo.Context, a *app.App) error { | |
| 36 | + | // renderAdminPage is a generalized function to render admin pages | |
| 37 | + | func renderAdminPage(c echo.Context, a *app.App, templateName string) error { | |
| 35 | 38 | data, err := GetLocalizedData(c, a) | |
| 36 | 39 | if err != nil { | |
| 37 | 40 | return err | |
| 38 | 41 | } | |
| 39 | - | // Navigate inside the fs.FS to get the template | |
| 40 | - | rendererData, err := render.GetHTMLRenderer(mainPath, "index.gohtml", a.TemplateFS, a, fragmentsPath) | |
| 42 | + | ||
| 43 | + | rendererData, err := render.GetHTMLRenderer(mainPath, templateName, a.TemplateFS, a, fragmentsPath) | |
| 41 | 44 | if err != nil { | |
| 42 | 45 | return err | |
| 43 | 46 | } | |
| @@ -47,25 +50,15 @@ func AdminRoute(c echo.Context, a *app.App) error { | |||
| 47 | 50 | return err | |
| 48 | 51 | } | |
| 49 | 52 | ||
| 50 | - | return c.HTML(200, renderedHTML) | |
| 53 | + | return c.HTML(http.StatusOK, renderedHTML) | |
| 51 | 54 | } | |
| 52 | 55 | ||
| 53 | - | func AdminManagerRoute(c echo.Context, a *app.App) error { | |
| 54 | - | data, err := GetLocalizedData(c, a) | |
| 55 | - | if err != nil { | |
| 56 | - | return err | |
| 57 | - | } | |
| 58 | - | ||
| 59 | - | // Navigate inside the fs.FS to get the template | |
| 60 | - | rendererData, err := render.GetHTMLRenderer(mainPath, "manager.gohtml", a.TemplateFS, a, fragmentsPath) | |
| 61 | - | if err != nil { | |
| 62 | - | return err | |
| 63 | - | } | |
| 64 | - | ||
| 65 | - | renderedHTML, err := rendererData.Render(data, a) | |
| 66 | - | if err != nil { | |
| 67 | - | return err | |
| 68 | - | } | |
| 56 | + | // AdminRoute is the route for the admin panel | |
| 57 | + | func AdminRoute(c echo.Context, a *app.App) error { | |
| 58 | + | return renderAdminPage(c, a, "index.gohtml") | |
| 59 | + | } | |
| 69 | 60 | ||
| 70 | - | return c.HTML(200, renderedHTML) | |
| 61 | + | // AdminManagerRoute is the route of the manager page | |
| 62 | + | func AdminManagerRoute(c echo.Context, a *app.App) error { | |
| 63 | + | return renderAdminPage(c, a, "manager.gohtml") | |
| 71 | 64 | } | |
| @@ -3,6 +3,8 @@ package handler | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "fmt" | 4 | "fmt" | ||
| 5 | 5 | ||||
| 6 | + | "net/http" | |||
| 7 | + | ||||
| 6 | "github.com/bnema/gordon/internal/app" | 8 | "github.com/bnema/gordon/internal/app" | ||
| 7 | "github.com/bnema/gordon/internal/httpserve/middleware" | 9 | "github.com/bnema/gordon/internal/httpserve/middleware" | ||
| 8 | "github.com/bnema/gordon/internal/templating/render" | 10 | "github.com/bnema/gordon/internal/templating/render" | ||
| @@ -14,6 +16,7 @@ var ( | |||||
| 14 | fragmentsPath = "html/fragments" | 16 | fragmentsPath = "html/fragments" | ||
| 15 | ) | 17 | ) | ||
| 16 | 18 | ||||
| 19 | + | // GetLocalizedData returns the data for the localization | |||
| 17 | func GetLocalizedData(c echo.Context, a *app.App) (map[string]interface{}, error) { | 20 | func GetLocalizedData(c echo.Context, a *app.App) (map[string]interface{}, error) { | ||
| 18 | lang := c.Get(middleware.LangKey) | 21 | lang := c.Get(middleware.LangKey) | ||
| 19 | 22 | ||||
| @@ -30,14 +33,14 @@ func GetLocalizedData(c echo.Context, a *app.App) (map[string]interface{}, error | |||||
| 30 | }, nil | 33 | }, nil | ||
| 31 | } | 34 | } | ||
| 32 | 35 | ||||
| 33 | - | // Handle the admin route to display index.gohtml from the templateFS with the data from strings.yml | 36 | + | // renderAdminPage is a generalized function to render admin pages |
| 34 | - | func AdminRoute(c echo.Context, a *app.App) error { | 37 | + | func renderAdminPage(c echo.Context, a *app.App, templateName string) error { |
| 35 | data, err := GetLocalizedData(c, a) | 38 | data, err := GetLocalizedData(c, a) | ||
| 36 | if err != nil { | 39 | if err != nil { | ||
| 37 | return err | 40 | return err | ||
| 38 | } | 41 | } | ||
| 39 | - | // Navigate inside the fs.FS to get the template | 42 | + | |
| 40 | - | rendererData, err := render.GetHTMLRenderer(mainPath, "index.gohtml", a.TemplateFS, a, fragmentsPath) | 43 | + | rendererData, err := render.GetHTMLRenderer(mainPath, templateName, a.TemplateFS, a, fragmentsPath) |
| 41 | if err != nil { | 44 | if err != nil { | ||
| 42 | return err | 45 | return err | ||
| 43 | } | 46 | } | ||
| @@ -47,25 +50,15 @@ func AdminRoute(c echo.Context, a *app.App) error { | |||||
| 47 | return err | 50 | return err | ||
| 48 | } | 51 | } | ||
| 49 | 52 | ||||
| 50 | - | return c.HTML(200, renderedHTML) | 53 | + | return c.HTML(http.StatusOK, renderedHTML) |
| 51 | } | 54 | } | ||
| 52 | 55 | ||||
| 53 | - | func AdminManagerRoute(c echo.Context, a *app.App) error { | 56 | + | // AdminRoute is the route for the admin panel |
| 54 | - | data, err := GetLocalizedData(c, a) | 57 | + | func AdminRoute(c echo.Context, a *app.App) error { |
| 55 | - | if err != nil { | 58 | + | return renderAdminPage(c, a, "index.gohtml") |
| 56 | - | return err | 59 | + | } |
| 57 | - | } | |||
| 58 | - | ||||
| 59 | - | // Navigate inside the fs.FS to get the template | |||
| 60 | - | rendererData, err := render.GetHTMLRenderer(mainPath, "manager.gohtml", a.TemplateFS, a, fragmentsPath) | |||
| 61 | - | if err != nil { | |||
| 62 | - | return err | |||
| 63 | - | } | |||
| 64 | - | ||||
| 65 | - | renderedHTML, err := rendererData.Render(data, a) | |||
| 66 | - | if err != nil { | |||
| 67 | - | return err | |||
| 68 | - | } | |||
| 69 | 60 | ||||
| 70 | - | return c.HTML(200, renderedHTML) | 61 | + | // AdminManagerRoute is the route of the manager page |
| 62 | + | func AdminManagerRoute(c echo.Context, a *app.App) error { | |||
| 63 | + | return renderAdminPage(c, a, "manager.gohtml") | |||
| 71 | } | 64 | } | ||
M internal/httpserve/handler/containers.go +55 -37
| @@ -15,11 +15,40 @@ import ( | |||
| 15 | 15 | "github.com/labstack/echo/v4" | |
| 16 | 16 | ) | |
| 17 | 17 | ||
| 18 | + | type MapOperation string | |
| 19 | + | ||
| 18 | 20 | var ( | |
| 19 | 21 | idMap = make(map[string]string) | |
| 20 | 22 | idMapMutex sync.Mutex | |
| 21 | 23 | ) | |
| 22 | 24 | ||
| 25 | + | const ( | |
| 26 | + | Fetch MapOperation = "Fetch" | |
| 27 | + | Update MapOperation = "Update" | |
| 28 | + | Delete MapOperation = "Delete" | |
| 29 | + | ) | |
| 30 | + | ||
| 31 | + | func safelyInteractWithIDMap(op MapOperation, key string, value ...string) (string, bool) { | |
| 32 | + | idMapMutex.Lock() | |
| 33 | + | defer idMapMutex.Unlock() | |
| 34 | + | ||
| 35 | + | switch op { | |
| 36 | + | case Fetch: | |
| 37 | + | val, exists := idMap[key] | |
| 38 | + | return val, exists | |
| 39 | + | case Update: | |
| 40 | + | if len(value) > 0 { | |
| 41 | + | idMap[key] = value[0] | |
| 42 | + | } | |
| 43 | + | return "", true | |
| 44 | + | case Delete: | |
| 45 | + | delete(idMap, key) | |
| 46 | + | return "", true | |
| 47 | + | default: | |
| 48 | + | return "", false | |
| 49 | + | } | |
| 50 | + | } | |
| 51 | + | ||
| 23 | 52 | type HumanReadableContainerImage struct { | |
| 24 | 53 | *types.ImageSummary | |
| 25 | 54 | Name string | |
| @@ -39,6 +68,20 @@ type HumanReadableContainer struct { | |||
| 39 | 68 | StateColor string | |
| 40 | 69 | } | |
| 41 | 70 | ||
| 71 | + | // renderHTML is a generalized function to render HTML | |
| 72 | + | func renderHTML(c echo.Context, a *app.App, path, templateName string, data map[string]interface{}) error { | |
| 73 | + | rendererData, err := render.GetHTMLRenderer(path, templateName, a.TemplateFS, a) | |
| 74 | + | if err != nil { | |
| 75 | + | return err | |
| 76 | + | } | |
| 77 | + | renderedHTML, err := rendererData.Render(data, a) | |
| 78 | + | if err != nil { | |
| 79 | + | return err | |
| 80 | + | } | |
| 81 | + | return c.HTML(http.StatusOK, renderedHTML) | |
| 82 | + | } | |
| 83 | + | ||
| 84 | + | // ActionSuccess returns the success HTML fragment | |
| 42 | 85 | func ActionSuccess(a *app.App) string { | |
| 43 | 86 | successFragment, err := load.Fragment(a, "success") | |
| 44 | 87 | if err != nil { | |
| @@ -58,10 +101,10 @@ func ImageManagerComponent(c echo.Context, a *app.App) error { | |||
| 58 | 101 | var humanReadableImages []HumanReadableContainerImage | |
| 59 | 102 | ||
| 60 | 103 | for _, image := range images { | |
| 104 | + | // We need to shorten the ID because it breaks the HTML | |
| 61 | 105 | ShortID := image.ID[7:19] | |
| 62 | - | idMapMutex.Lock() | |
| 63 | - | idMap[ShortID] = image.ID | |
| 64 | - | idMapMutex.Unlock() | |
| 106 | + | // And we store both the ShortID and the full ID in a map so we can retrieve the full ID later | |
| 107 | + | safelyInteractWithIDMap(Update, ShortID, image.ID) | |
| 65 | 108 | createdTime := time.Unix(image.Created, 0) | |
| 66 | 109 | createdStr := humanize.TimeAgo(createdTime) | |
| 67 | 110 | sizeStr := humanize.BytesToReadableSize(image.Size) | |
| @@ -80,26 +123,15 @@ func ImageManagerComponent(c echo.Context, a *app.App) error { | |||
| 80 | 123 | "Images": humanReadableImages, | |
| 81 | 124 | } | |
| 82 | 125 | ||
| 83 | - | rendererData, err := render.GetHTMLRenderer("html/fragments", "imagelist.gohtml", a.TemplateFS, a) | |
| 84 | - | if err != nil { | |
| 85 | - | return err | |
| 86 | - | } | |
| 87 | - | renderedHTML, err := rendererData.Render(data, a) | |
| 88 | - | if err != nil { | |
| 89 | - | return err | |
| 90 | - | } | |
| 91 | - | return c.HTML(200, renderedHTML) | |
| 126 | + | return renderHTML(c, a, "html/fragments", "imagelist.gohtml", data) | |
| 92 | 127 | } | |
| 93 | 128 | ||
| 94 | 129 | // ImageManagerDelete handles the /image-manager/delete route | |
| 95 | 130 | func ImageManagerDelete(c echo.Context, a *app.App) error { | |
| 96 | - | // Get the ShortImgID from the URL | |
| 131 | + | // | |
| 97 | 132 | ShortID := c.Param("ID") | |
| 98 | 133 | ||
| 99 | - | idMapMutex.Lock() | |
| 100 | - | // Check if the ShortImgID exists in the idMap | |
| 101 | - | imageID, exists := idMap[ShortID] | |
| 102 | - | idMapMutex.Unlock() | |
| 134 | + | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) | |
| 103 | 135 | ||
| 104 | 136 | if !exists { | |
| 105 | 137 | return c.String(http.StatusBadRequest, "Invalid ShortImgID") | |
| @@ -111,10 +143,7 @@ func ImageManagerDelete(c echo.Context, a *app.App) error { | |||
| 111 | 143 | return c.String(http.StatusInternalServerError, err.Error()) | |
| 112 | 144 | } | |
| 113 | 145 | ||
| 114 | - | // Remove the entry from idMap | |
| 115 | - | idMapMutex.Lock() | |
| 116 | - | delete(idMap, ShortID) | |
| 117 | - | idMapMutex.Unlock() | |
| 146 | + | safelyInteractWithIDMap(Delete, ShortID) | |
| 118 | 147 | ||
| 119 | 148 | return c.String(http.StatusOK, ActionSuccess(a)) | |
| 120 | 149 | } | |
| @@ -163,21 +192,12 @@ func ContainerManagerComponent(c echo.Context, a *app.App) error { | |||
| 163 | 192 | "containers": humanReadableContainers, | |
| 164 | 193 | } | |
| 165 | 194 | ||
| 166 | - | rendererData, err := render.GetHTMLRenderer("html/fragments", "containerlist.gohtml", a.TemplateFS, a) | |
| 167 | - | if err != nil { | |
| 168 | - | return err | |
| 169 | - | } | |
| 170 | - | renderedHTML, err := rendererData.Render(data, a) | |
| 171 | - | if err != nil { | |
| 172 | - | return err | |
| 173 | - | } | |
| 174 | - | return c.HTML(200, renderedHTML) | |
| 195 | + | return renderHTML(c, a, "html/fragments", "containerlist.gohtml", data) | |
| 175 | 196 | } | |
| 176 | 197 | ||
| 177 | 198 | // ContainerManagerDelete handles the /container-manager/delete route | |
| 178 | 199 | func ContainerManagerDelete(c echo.Context, a *app.App) error { | |
| 179 | - | ID := c.Param("ID") | |
| 180 | - | err := docker.RemoveContainer(ID) | |
| 200 | + | err := docker.RemoveContainer(c.Param("ID")) | |
| 181 | 201 | if err != nil { | |
| 182 | 202 | return sendError(c, err) | |
| 183 | 203 | } | |
| @@ -186,9 +206,8 @@ func ContainerManagerDelete(c echo.Context, a *app.App) error { | |||
| 186 | 206 | ||
| 187 | 207 | // ContainerManagerStop handles the /container-manager/stop route | |
| 188 | 208 | func ContainerManagerStop(c echo.Context, a *app.App) error { | |
| 189 | - | ID := c.Param("ID") | |
| 190 | 209 | // Stop the container gracefully with a timeout | |
| 191 | - | stopped, err := docker.StopContainerGracefully(ID, 3*time.Second) | |
| 210 | + | stopped, err := docker.StopContainerGracefully(c.Param("ID"), 3*time.Second) | |
| 192 | 211 | if err != nil { | |
| 193 | 212 | return sendError(c, err) | |
| 194 | 213 | } | |
| @@ -197,7 +216,7 @@ func ContainerManagerStop(c echo.Context, a *app.App) error { | |||
| 197 | 216 | return c.HTML(http.StatusOK, ActionSuccess(a)) | |
| 198 | 217 | } | |
| 199 | 218 | // If stopped is false, the container was not stopped gracefully we force stop it | |
| 200 | - | err = docker.StopContainerRagefully(ID) | |
| 219 | + | err = docker.StopContainerRagefully(c.Param("ID")) | |
| 201 | 220 | if err != nil { | |
| 202 | 221 | return sendError(c, err) | |
| 203 | 222 | } | |
| @@ -207,8 +226,7 @@ func ContainerManagerStop(c echo.Context, a *app.App) error { | |||
| 207 | 226 | ||
| 208 | 227 | // ContainerManagerStart handles the /container-manager/start route | |
| 209 | 228 | func ContainerManagerStart(c echo.Context, a *app.App) error { | |
| 210 | - | ID := c.Param("ID") | |
| 211 | - | err := docker.StartContainer(ID) | |
| 229 | + | err := docker.StartContainer(c.Param("ID")) | |
| 212 | 230 | if err != nil { | |
| 213 | 231 | return sendError(c, err) | |
| 214 | 232 | } | |
| @@ -15,11 +15,40 @@ import ( | |||||
| 15 | "github.com/labstack/echo/v4" | 15 | "github.com/labstack/echo/v4" | ||
| 16 | ) | 16 | ) | ||
| 17 | 17 | ||||
| 18 | + | type MapOperation string | |||
| 19 | + | ||||
| 18 | var ( | 20 | var ( | ||
| 19 | idMap = make(map[string]string) | 21 | idMap = make(map[string]string) | ||
| 20 | idMapMutex sync.Mutex | 22 | idMapMutex sync.Mutex | ||
| 21 | ) | 23 | ) | ||
| 22 | 24 | ||||
| 25 | + | const ( | |||
| 26 | + | Fetch MapOperation = "Fetch" | |||
| 27 | + | Update MapOperation = "Update" | |||
| 28 | + | Delete MapOperation = "Delete" | |||
| 29 | + | ) | |||
| 30 | + | ||||
| 31 | + | func safelyInteractWithIDMap(op MapOperation, key string, value ...string) (string, bool) { | |||
| 32 | + | idMapMutex.Lock() | |||
| 33 | + | defer idMapMutex.Unlock() | |||
| 34 | + | ||||
| 35 | + | switch op { | |||
| 36 | + | case Fetch: | |||
| 37 | + | val, exists := idMap[key] | |||
| 38 | + | return val, exists | |||
| 39 | + | case Update: | |||
| 40 | + | if len(value) > 0 { | |||
| 41 | + | idMap[key] = value[0] | |||
| 42 | + | } | |||
| 43 | + | return "", true | |||
| 44 | + | case Delete: | |||
| 45 | + | delete(idMap, key) | |||
| 46 | + | return "", true | |||
| 47 | + | default: | |||
| 48 | + | return "", false | |||
| 49 | + | } | |||
| 50 | + | } | |||
| 51 | + | ||||
| 23 | type HumanReadableContainerImage struct { | 52 | type HumanReadableContainerImage struct { | ||
| 24 | *types.ImageSummary | 53 | *types.ImageSummary | ||
| 25 | Name string | 54 | Name string | ||
| @@ -39,6 +68,20 @@ type HumanReadableContainer struct { | |||||
| 39 | StateColor string | 68 | StateColor string | ||
| 40 | } | 69 | } | ||
| 41 | 70 | ||||
| 71 | + | // renderHTML is a generalized function to render HTML | |||
| 72 | + | func renderHTML(c echo.Context, a *app.App, path, templateName string, data map[string]interface{}) error { | |||
| 73 | + | rendererData, err := render.GetHTMLRenderer(path, templateName, a.TemplateFS, a) | |||
| 74 | + | if err != nil { | |||
| 75 | + | return err | |||
| 76 | + | } | |||
| 77 | + | renderedHTML, err := rendererData.Render(data, a) | |||
| 78 | + | if err != nil { | |||
| 79 | + | return err | |||
| 80 | + | } | |||
| 81 | + | return c.HTML(http.StatusOK, renderedHTML) | |||
| 82 | + | } | |||
| 83 | + | ||||
| 84 | + | // ActionSuccess returns the success HTML fragment | |||
| 42 | func ActionSuccess(a *app.App) string { | 85 | func ActionSuccess(a *app.App) string { | ||
| 43 | successFragment, err := load.Fragment(a, "success") | 86 | successFragment, err := load.Fragment(a, "success") | ||
| 44 | if err != nil { | 87 | if err != nil { | ||
| @@ -58,10 +101,10 @@ func ImageManagerComponent(c echo.Context, a *app.App) error { | |||||
| 58 | var humanReadableImages []HumanReadableContainerImage | 101 | var humanReadableImages []HumanReadableContainerImage | ||
| 59 | 102 | ||||
| 60 | for _, image := range images { | 103 | for _, image := range images { | ||
| 104 | + | // We need to shorten the ID because it breaks the HTML | |||
| 61 | ShortID := image.ID[7:19] | 105 | ShortID := image.ID[7:19] | ||
| 62 | - | idMapMutex.Lock() | 106 | + | // And we store both the ShortID and the full ID in a map so we can retrieve the full ID later |
| 63 | - | idMap[ShortID] = image.ID | 107 | + | safelyInteractWithIDMap(Update, ShortID, image.ID) |
| 64 | - | idMapMutex.Unlock() | |||
| 65 | createdTime := time.Unix(image.Created, 0) | 108 | createdTime := time.Unix(image.Created, 0) | ||
| 66 | createdStr := humanize.TimeAgo(createdTime) | 109 | createdStr := humanize.TimeAgo(createdTime) | ||
| 67 | sizeStr := humanize.BytesToReadableSize(image.Size) | 110 | sizeStr := humanize.BytesToReadableSize(image.Size) | ||
| @@ -80,26 +123,15 @@ func ImageManagerComponent(c echo.Context, a *app.App) error { | |||||
| 80 | "Images": humanReadableImages, | 123 | "Images": humanReadableImages, | ||
| 81 | } | 124 | } | ||
| 82 | 125 | ||||
| 83 | - | rendererData, err := render.GetHTMLRenderer("html/fragments", "imagelist.gohtml", a.TemplateFS, a) | 126 | + | return renderHTML(c, a, "html/fragments", "imagelist.gohtml", data) |
| 84 | - | if err != nil { | |||
| 85 | - | return err | |||
| 86 | - | } | |||
| 87 | - | renderedHTML, err := rendererData.Render(data, a) | |||
| 88 | - | if err != nil { | |||
| 89 | - | return err | |||
| 90 | - | } | |||
| 91 | - | return c.HTML(200, renderedHTML) | |||
| 92 | } | 127 | } | ||
| 93 | 128 | ||||
| 94 | // ImageManagerDelete handles the /image-manager/delete route | 129 | // ImageManagerDelete handles the /image-manager/delete route | ||
| 95 | func ImageManagerDelete(c echo.Context, a *app.App) error { | 130 | func ImageManagerDelete(c echo.Context, a *app.App) error { | ||
| 96 | - | // Get the ShortImgID from the URL | 131 | + | // |
| 97 | ShortID := c.Param("ID") | 132 | ShortID := c.Param("ID") | ||
| 98 | 133 | ||||
| 99 | - | idMapMutex.Lock() | 134 | + | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) |
| 100 | - | // Check if the ShortImgID exists in the idMap | |||
| 101 | - | imageID, exists := idMap[ShortID] | |||
| 102 | - | idMapMutex.Unlock() | |||
| 103 | 135 | ||||
| 104 | if !exists { | 136 | if !exists { | ||
| 105 | return c.String(http.StatusBadRequest, "Invalid ShortImgID") | 137 | return c.String(http.StatusBadRequest, "Invalid ShortImgID") | ||
| @@ -111,10 +143,7 @@ func ImageManagerDelete(c echo.Context, a *app.App) error { | |||||
| 111 | return c.String(http.StatusInternalServerError, err.Error()) | 143 | return c.String(http.StatusInternalServerError, err.Error()) | ||
| 112 | } | 144 | } | ||
| 113 | 145 | ||||
| 114 | - | // Remove the entry from idMap | 146 | + | safelyInteractWithIDMap(Delete, ShortID) |
| 115 | - | idMapMutex.Lock() | |||
| 116 | - | delete(idMap, ShortID) | |||
| 117 | - | idMapMutex.Unlock() | |||
| 118 | 147 | ||||
| 119 | return c.String(http.StatusOK, ActionSuccess(a)) | 148 | return c.String(http.StatusOK, ActionSuccess(a)) | ||
| 120 | } | 149 | } | ||
| @@ -163,21 +192,12 @@ func ContainerManagerComponent(c echo.Context, a *app.App) error { | |||||
| 163 | "containers": humanReadableContainers, | 192 | "containers": humanReadableContainers, | ||
| 164 | } | 193 | } | ||
| 165 | 194 | ||||
| 166 | - | rendererData, err := render.GetHTMLRenderer("html/fragments", "containerlist.gohtml", a.TemplateFS, a) | 195 | + | return renderHTML(c, a, "html/fragments", "containerlist.gohtml", data) |
| 167 | - | if err != nil { | |||
| 168 | - | return err | |||
| 169 | - | } | |||
| 170 | - | renderedHTML, err := rendererData.Render(data, a) | |||
| 171 | - | if err != nil { | |||
| 172 | - | return err | |||
| 173 | - | } | |||
| 174 | - | return c.HTML(200, renderedHTML) | |||
| 175 | } | 196 | } | ||
| 176 | 197 | ||||
| 177 | // ContainerManagerDelete handles the /container-manager/delete route | 198 | // ContainerManagerDelete handles the /container-manager/delete route | ||
| 178 | func ContainerManagerDelete(c echo.Context, a *app.App) error { | 199 | func ContainerManagerDelete(c echo.Context, a *app.App) error { | ||
| 179 | - | ID := c.Param("ID") | 200 | + | err := docker.RemoveContainer(c.Param("ID")) |
| 180 | - | err := docker.RemoveContainer(ID) | |||
| 181 | if err != nil { | 201 | if err != nil { | ||
| 182 | return sendError(c, err) | 202 | return sendError(c, err) | ||
| 183 | } | 203 | } | ||
| @@ -186,9 +206,8 @@ func ContainerManagerDelete(c echo.Context, a *app.App) error { | |||||
| 186 | 206 | ||||
| 187 | // ContainerManagerStop handles the /container-manager/stop route | 207 | // ContainerManagerStop handles the /container-manager/stop route | ||
| 188 | func ContainerManagerStop(c echo.Context, a *app.App) error { | 208 | func ContainerManagerStop(c echo.Context, a *app.App) error { | ||
| 189 | - | ID := c.Param("ID") | |||
| 190 | // Stop the container gracefully with a timeout | 209 | // Stop the container gracefully with a timeout | ||
| 191 | - | stopped, err := docker.StopContainerGracefully(ID, 3*time.Second) | 210 | + | stopped, err := docker.StopContainerGracefully(c.Param("ID"), 3*time.Second) |
| 192 | if err != nil { | 211 | if err != nil { | ||
| 193 | return sendError(c, err) | 212 | return sendError(c, err) | ||
| 194 | } | 213 | } | ||
| @@ -197,7 +216,7 @@ func ContainerManagerStop(c echo.Context, a *app.App) error { | |||||
| 197 | return c.HTML(http.StatusOK, ActionSuccess(a)) | 216 | return c.HTML(http.StatusOK, ActionSuccess(a)) | ||
| 198 | } | 217 | } | ||
| 199 | // If stopped is false, the container was not stopped gracefully we force stop it | 218 | // If stopped is false, the container was not stopped gracefully we force stop it | ||
| 200 | - | err = docker.StopContainerRagefully(ID) | 219 | + | err = docker.StopContainerRagefully(c.Param("ID")) |
| 201 | if err != nil { | 220 | if err != nil { | ||
| 202 | return sendError(c, err) | 221 | return sendError(c, err) | ||
| 203 | } | 222 | } | ||
| @@ -207,8 +226,7 @@ func ContainerManagerStop(c echo.Context, a *app.App) error { | |||||
| 207 | 226 | ||||
| 208 | // ContainerManagerStart handles the /container-manager/start route | 227 | // ContainerManagerStart handles the /container-manager/start route | ||
| 209 | func ContainerManagerStart(c echo.Context, a *app.App) error { | 228 | func ContainerManagerStart(c echo.Context, a *app.App) error { | ||
| 210 | - | ID := c.Param("ID") | 229 | + | err := docker.StartContainer(c.Param("ID")) |
| 211 | - | err := docker.StartContainer(ID) | |||
| 212 | if err != nil { | 230 | if err != nil { | ||
| 213 | return sendError(c, err) | 231 | return sendError(c, err) | ||
| 214 | } | 232 | } | ||
M internal/httpserve/handler/createcontainer.go +8 -13
| @@ -2,6 +2,7 @@ package handler | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "fmt" | |
| 5 | + | "net/http" | |
| 5 | 6 | ||
| 6 | 7 | "github.com/bnema/gordon/internal/app" | |
| 7 | 8 | "github.com/bnema/gordon/internal/templating/render" | |
| @@ -12,16 +13,11 @@ import ( | |||
| 12 | 13 | ||
| 13 | 14 | // FromShortIDToImageID converts a short image ID to a full image ID | |
| 14 | 15 | func FromShortIDToImageID(ShortID string) (string, error) { | |
| 15 | - | idMapMutex.Lock() | |
| 16 | - | // Check if the ShortImgID exists in the idMap | |
| 17 | - | imageID, exists := idMap[ShortID] | |
| 18 | - | idMapMutex.Unlock() | |
| 19 | - | ||
| 20 | - | if !exists { | |
| 21 | - | return "", fmt.Errorf("image ID not found") | |
| 16 | + | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) | |
| 17 | + | if exists { | |
| 18 | + | return imageID, nil | |
| 22 | 19 | } | |
| 23 | - | ||
| 24 | - | return imageID, nil | |
| 20 | + | return "", fmt.Errorf("image ID not found") | |
| 25 | 21 | } | |
| 26 | 22 | ||
| 27 | 23 | // CreateContainerRoute is the route for creating a new container | |
| @@ -44,7 +40,7 @@ func CreateContainerGET(c echo.Context, a *app.App) error { | |||
| 44 | 40 | // Extract image name | |
| 45 | 41 | var imageName string | |
| 46 | 42 | if len(imageInfo.RepoTags) > 0 { | |
| 47 | - | imageName = imageInfo.RepoTags[0] // Using the first tag as the image name | |
| 43 | + | imageName = imageInfo.RepoTags[0] | |
| 48 | 44 | } | |
| 49 | 45 | ||
| 50 | 46 | data := map[string]interface{}{ | |
| @@ -70,6 +66,7 @@ func CreateContainerGET(c echo.Context, a *app.App) error { | |||
| 70 | 66 | ||
| 71 | 67 | } | |
| 72 | 68 | ||
| 69 | + | // CreateContainerPOST handles the create container form submission | |
| 73 | 70 | func CreateContainerPOST(c echo.Context, a *app.App) error { | |
| 74 | 71 | // Retreive the ShortID of the image from the URL | |
| 75 | 72 | ShortID := c.Param("ID") | |
| @@ -111,13 +108,11 @@ func CreateContainerPOST(c echo.Context, a *app.App) error { | |||
| 111 | 108 | return sendError(c, err) | |
| 112 | 109 | } | |
| 113 | 110 | ||
| 114 | - | fmt.Println(cmdParams.PortMappings) | |
| 115 | - | ||
| 116 | 111 | // Create the container | |
| 117 | 112 | _, err = docker.CreateContainer(cmdParams) | |
| 118 | 113 | if err != nil { | |
| 119 | 114 | return sendError(c, err) | |
| 120 | 115 | } | |
| 121 | 116 | ||
| 122 | - | return c.String(200, "Container created") | |
| 117 | + | return c.HTML(http.StatusOK, ActionSuccess(a)) | |
| 123 | 118 | } | |
| @@ -2,6 +2,7 @@ package handler | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "fmt" | 4 | "fmt" | ||
| 5 | + | "net/http" | |||
| 5 | 6 | ||||
| 6 | "github.com/bnema/gordon/internal/app" | 7 | "github.com/bnema/gordon/internal/app" | ||
| 7 | "github.com/bnema/gordon/internal/templating/render" | 8 | "github.com/bnema/gordon/internal/templating/render" | ||
| @@ -12,16 +13,11 @@ import ( | |||||
| 12 | 13 | ||||
| 13 | // FromShortIDToImageID converts a short image ID to a full image ID | 14 | // FromShortIDToImageID converts a short image ID to a full image ID | ||
| 14 | func FromShortIDToImageID(ShortID string) (string, error) { | 15 | func FromShortIDToImageID(ShortID string) (string, error) { | ||
| 15 | - | idMapMutex.Lock() | 16 | + | imageID, exists := safelyInteractWithIDMap(Fetch, ShortID) |
| 16 | - | // Check if the ShortImgID exists in the idMap | 17 | + | if exists { |
| 17 | - | imageID, exists := idMap[ShortID] | 18 | + | return imageID, nil |
| 18 | - | idMapMutex.Unlock() | |||
| 19 | - | ||||
| 20 | - | if !exists { | |||
| 21 | - | return "", fmt.Errorf("image ID not found") | |||
| 22 | } | 19 | } | ||
| 23 | - | 20 | + | return "", fmt.Errorf("image ID not found") | |
| 24 | - | return imageID, nil | |||
| 25 | } | 21 | } | ||
| 26 | 22 | ||||
| 27 | // CreateContainerRoute is the route for creating a new container | 23 | // CreateContainerRoute is the route for creating a new container | ||
| @@ -44,7 +40,7 @@ func CreateContainerGET(c echo.Context, a *app.App) error { | |||||
| 44 | // Extract image name | 40 | // Extract image name | ||
| 45 | var imageName string | 41 | var imageName string | ||
| 46 | if len(imageInfo.RepoTags) > 0 { | 42 | if len(imageInfo.RepoTags) > 0 { | ||
| 47 | - | imageName = imageInfo.RepoTags[0] // Using the first tag as the image name | 43 | + | imageName = imageInfo.RepoTags[0] |
| 48 | } | 44 | } | ||
| 49 | 45 | ||||
| 50 | data := map[string]interface{}{ | 46 | data := map[string]interface{}{ | ||
| @@ -70,6 +66,7 @@ func CreateContainerGET(c echo.Context, a *app.App) error { | |||||
| 70 | 66 | ||||
| 71 | } | 67 | } | ||
| 72 | 68 | ||||
| 69 | + | // CreateContainerPOST handles the create container form submission | |||
| 73 | func CreateContainerPOST(c echo.Context, a *app.App) error { | 70 | func CreateContainerPOST(c echo.Context, a *app.App) error { | ||
| 74 | // Retreive the ShortID of the image from the URL | 71 | // Retreive the ShortID of the image from the URL | ||
| 75 | ShortID := c.Param("ID") | 72 | ShortID := c.Param("ID") | ||
| @@ -111,13 +108,11 @@ func CreateContainerPOST(c echo.Context, a *app.App) error { | |||||
| 111 | return sendError(c, err) | 108 | return sendError(c, err) | ||
| 112 | } | 109 | } | ||
| 113 | 110 | ||||
| 114 | - | fmt.Println(cmdParams.PortMappings) | |||
| 115 | - | ||||
| 116 | // Create the container | 111 | // Create the container | ||
| 117 | _, err = docker.CreateContainer(cmdParams) | 112 | _, err = docker.CreateContainer(cmdParams) | ||
| 118 | if err != nil { | 113 | if err != nil { | ||
| 119 | return sendError(c, err) | 114 | return sendError(c, err) | ||
| 120 | } | 115 | } | ||
| 121 | 116 | ||||
| 122 | - | return c.String(200, "Container created") | 117 | + | return c.HTML(http.StatusOK, ActionSuccess(a)) |
| 123 | } | 118 | } | ||
M internal/httpserve/handler/editcontainer.go +3 -3
| @@ -45,7 +45,7 @@ func ContainerManagerEditGET(c echo.Context, a *app.App) error { | |||
| 45 | 45 | ||
| 46 | 46 | // Trim the slash from the container name | |
| 47 | 47 | containerInfo.Name = strings.TrimPrefix(containerInfo.Name, "/") | |
| 48 | - | // Get just the network names | |
| 48 | + | // Get the network names | |
| 49 | 49 | networkNames := make([]string, 0, len(containerInfo.NetworkSettings.Networks)) | |
| 50 | 50 | for networkName := range containerInfo.NetworkSettings.Networks { | |
| 51 | 51 | networkNames = append(networkNames, networkName) | |
| @@ -65,7 +65,7 @@ func ContainerManagerEditGET(c echo.Context, a *app.App) error { | |||
| 65 | 65 | volumeMappings = append(volumeMappings, fmt.Sprintf("%s:%s", mount.Source, mount.Destination)) | |
| 66 | 66 | } | |
| 67 | 67 | ||
| 68 | - | // Initialize a map to store the information you want to display | |
| 68 | + | // Initialize a map to store the information from the container | |
| 69 | 69 | infoMap := make(map[string]interface{}) | |
| 70 | 70 | ||
| 71 | 71 | // Populate the map with container details | |
| @@ -198,7 +198,7 @@ func ContainerManagerEditPOST(c echo.Context, a *app.App) error { | |||
| 198 | 198 | return sendError(c, fmt.Errorf("transaction failed: %w", err)) | |
| 199 | 199 | } | |
| 200 | 200 | ||
| 201 | - | return c.HTML(200, fmt.Sprintf("Successfully edited container %s", tq.NewContainerName)) | |
| 201 | + | return c.HTML(200, ActionSuccess(a)) | |
| 202 | 202 | } | |
| 203 | 203 | ||
| 204 | 204 | // CreateNewContainerStep creates a new container with the given parameters | |
| @@ -45,7 +45,7 @@ func ContainerManagerEditGET(c echo.Context, a *app.App) error { | |||||
| 45 | 45 | ||||
| 46 | // Trim the slash from the container name | 46 | // Trim the slash from the container name | ||
| 47 | containerInfo.Name = strings.TrimPrefix(containerInfo.Name, "/") | 47 | containerInfo.Name = strings.TrimPrefix(containerInfo.Name, "/") | ||
| 48 | - | // Get just the network names | 48 | + | // Get the network names |
| 49 | networkNames := make([]string, 0, len(containerInfo.NetworkSettings.Networks)) | 49 | networkNames := make([]string, 0, len(containerInfo.NetworkSettings.Networks)) | ||
| 50 | for networkName := range containerInfo.NetworkSettings.Networks { | 50 | for networkName := range containerInfo.NetworkSettings.Networks { | ||
| 51 | networkNames = append(networkNames, networkName) | 51 | networkNames = append(networkNames, networkName) | ||
| @@ -65,7 +65,7 @@ func ContainerManagerEditGET(c echo.Context, a *app.App) error { | |||||
| 65 | volumeMappings = append(volumeMappings, fmt.Sprintf("%s:%s", mount.Source, mount.Destination)) | 65 | volumeMappings = append(volumeMappings, fmt.Sprintf("%s:%s", mount.Source, mount.Destination)) | ||
| 66 | } | 66 | } | ||
| 67 | 67 | ||||
| 68 | - | // Initialize a map to store the information you want to display | 68 | + | // Initialize a map to store the information from the container |
| 69 | infoMap := make(map[string]interface{}) | 69 | infoMap := make(map[string]interface{}) | ||
| 70 | 70 | ||||
| 71 | // Populate the map with container details | 71 | // Populate the map with container details | ||
| @@ -198,7 +198,7 @@ func ContainerManagerEditPOST(c echo.Context, a *app.App) error { | |||||
| 198 | return sendError(c, fmt.Errorf("transaction failed: %w", err)) | 198 | return sendError(c, fmt.Errorf("transaction failed: %w", err)) | ||
| 199 | } | 199 | } | ||
| 200 | 200 | ||||
| 201 | - | return c.HTML(200, fmt.Sprintf("Successfully edited container %s", tq.NewContainerName)) | 201 | + | return c.HTML(200, ActionSuccess(a)) |
| 202 | } | 202 | } | ||
| 203 | 203 | ||||
| 204 | // CreateNewContainerStep creates a new container with the given parameters | 204 | // CreateNewContainerStep creates a new container with the given parameters | ||
M internal/httpserve/handler/oauth.go +10 -0
| @@ -52,6 +52,7 @@ func RenderLoginPage(c echo.Context, a *app.App) error { | |||
| 52 | 52 | return c.HTML(200, renderedHTML) | |
| 53 | 53 | } | |
| 54 | 54 | ||
| 55 | + | // StartOAuthGithub starts the Github OAuth flow | |
| 55 | 56 | func StartOAuthGithub(c echo.Context, a *app.App) error { | |
| 56 | 57 | // Clear the session in case it is already set or corrupted | |
| 57 | 58 | err := ResetSession(c) | |
| @@ -77,6 +78,7 @@ type Sessions struct { | |||
| 77 | 78 | *db.Sessions | |
| 78 | 79 | } | |
| 79 | 80 | ||
| 81 | + | // OAuthCallback handles the callback response from Github OAuth | |
| 80 | 82 | func OAuthCallback(c echo.Context, a *app.App) error { | |
| 81 | 83 | redirectPath := a.Config.Admin.Path | |
| 82 | 84 | ||
| @@ -119,6 +121,7 @@ func OAuthCallback(c echo.Context, a *app.App) error { | |||
| 119 | 121 | return c.Redirect(http.StatusFound, redirectPath) | |
| 120 | 122 | } | |
| 121 | 123 | ||
| 124 | + | // parseQueryParams parses the query parameters from the callback URL | |
| 122 | 125 | func parseQueryParams(c echo.Context) (string, string, error) { | |
| 123 | 126 | accessToken := c.QueryParam("access_token") | |
| 124 | 127 | encodedState := c.QueryParam("state") | |
| @@ -131,6 +134,7 @@ func parseQueryParams(c echo.Context) (string, string, error) { | |||
| 131 | 134 | return accessToken, encodedState, nil | |
| 132 | 135 | } | |
| 133 | 136 | ||
| 137 | + | // getSession gets the session from the context | |
| 134 | 138 | func getSession(c echo.Context) (*sessions.Session, error) { | |
| 135 | 139 | sess, err := session.Get("session", c) | |
| 136 | 140 | if err != nil { | |
| @@ -139,6 +143,7 @@ func getSession(c echo.Context) (*sessions.Session, error) { | |||
| 139 | 143 | return sess, nil | |
| 140 | 144 | } | |
| 141 | 145 | ||
| 146 | + | // handleUser handles the user creation or update | |
| 142 | 147 | func handleUser(c echo.Context, a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | |
| 143 | 148 | userExists, err := queries.CheckDBUserExists(a) | |
| 144 | 149 | if err != nil { | |
| @@ -179,6 +184,7 @@ func handleUser(c echo.Context, a *app.App, accessToken, browserInfo string, use | |||
| 179 | 184 | return nil, fmt.Errorf("could not handle user") | |
| 180 | 185 | } | |
| 181 | 186 | ||
| 187 | + | // createUser creates a new user in the database | |
| 182 | 188 | func createUser(a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | |
| 183 | 189 | err := queries.CreateUser(a, accessToken, browserInfo, userInfo) | |
| 184 | 190 | if err != nil { | |
| @@ -187,6 +193,7 @@ func createUser(a *app.App, accessToken, browserInfo string, userInfo *queries.G | |||
| 187 | 193 | return &a.DBTables.User, nil | |
| 188 | 194 | } | |
| 189 | 195 | ||
| 196 | + | // updateUser updates an existing user in the database | |
| 190 | 197 | func updateUser(a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | |
| 191 | 198 | user, err := queries.UpdateUser(a, accessToken, browserInfo, userInfo) | |
| 192 | 199 | if err != nil { | |
| @@ -195,6 +202,7 @@ func updateUser(a *app.App, accessToken, browserInfo string, userInfo *queries.G | |||
| 195 | 202 | return user, nil | |
| 196 | 203 | } | |
| 197 | 204 | ||
| 205 | + | // setSessionValues sets the session values for the user | |
| 198 | 206 | func setSessionValues(c echo.Context, sess *sessions.Session, user *db.User, accountID string, expires string, sessionID string) error { | |
| 199 | 207 | sess.Values["authenticated"] = true | |
| 200 | 208 | sess.Values["accountID"] = accountID | |
| @@ -207,6 +215,7 @@ func setSessionValues(c echo.Context, sess *sessions.Session, user *db.User, acc | |||
| 207 | 215 | return nil | |
| 208 | 216 | } | |
| 209 | 217 | ||
| 218 | + | // fetchGithubAPI fetches the Github API | |
| 210 | 219 | func fetchGithubAPI(url string, authHeader string, result interface{}) error { | |
| 211 | 220 | req, err := http.NewRequest("GET", url, nil) | |
| 212 | 221 | if err != nil { | |
| @@ -238,6 +247,7 @@ func fetchGithubAPI(url string, authHeader string, result interface{}) error { | |||
| 238 | 247 | return nil | |
| 239 | 248 | } | |
| 240 | 249 | ||
| 250 | + | // githubGetUserDetails gets the user details from the Github API using the access token | |
| 241 | 251 | func githubGetUserDetails(c echo.Context, a *app.App) (userInfo *queries.GithubUserInfo, err error) { | |
| 242 | 252 | accessToken := c.QueryParam("access_token") | |
| 243 | 253 | ||
| @@ -52,6 +52,7 @@ func RenderLoginPage(c echo.Context, a *app.App) error { | |||||
| 52 | return c.HTML(200, renderedHTML) | 52 | return c.HTML(200, renderedHTML) | ||
| 53 | } | 53 | } | ||
| 54 | 54 | ||||
| 55 | + | // StartOAuthGithub starts the Github OAuth flow | |||
| 55 | func StartOAuthGithub(c echo.Context, a *app.App) error { | 56 | func StartOAuthGithub(c echo.Context, a *app.App) error { | ||
| 56 | // Clear the session in case it is already set or corrupted | 57 | // Clear the session in case it is already set or corrupted | ||
| 57 | err := ResetSession(c) | 58 | err := ResetSession(c) | ||
| @@ -77,6 +78,7 @@ type Sessions struct { | |||||
| 77 | *db.Sessions | 78 | *db.Sessions | ||
| 78 | } | 79 | } | ||
| 79 | 80 | ||||
| 81 | + | // OAuthCallback handles the callback response from Github OAuth | |||
| 80 | func OAuthCallback(c echo.Context, a *app.App) error { | 82 | func OAuthCallback(c echo.Context, a *app.App) error { | ||
| 81 | redirectPath := a.Config.Admin.Path | 83 | redirectPath := a.Config.Admin.Path | ||
| 82 | 84 | ||||
| @@ -119,6 +121,7 @@ func OAuthCallback(c echo.Context, a *app.App) error { | |||||
| 119 | return c.Redirect(http.StatusFound, redirectPath) | 121 | return c.Redirect(http.StatusFound, redirectPath) | ||
| 120 | } | 122 | } | ||
| 121 | 123 | ||||
| 124 | + | // parseQueryParams parses the query parameters from the callback URL | |||
| 122 | func parseQueryParams(c echo.Context) (string, string, error) { | 125 | func parseQueryParams(c echo.Context) (string, string, error) { | ||
| 123 | accessToken := c.QueryParam("access_token") | 126 | accessToken := c.QueryParam("access_token") | ||
| 124 | encodedState := c.QueryParam("state") | 127 | encodedState := c.QueryParam("state") | ||
| @@ -131,6 +134,7 @@ func parseQueryParams(c echo.Context) (string, string, error) { | |||||
| 131 | return accessToken, encodedState, nil | 134 | return accessToken, encodedState, nil | ||
| 132 | } | 135 | } | ||
| 133 | 136 | ||||
| 137 | + | // getSession gets the session from the context | |||
| 134 | func getSession(c echo.Context) (*sessions.Session, error) { | 138 | func getSession(c echo.Context) (*sessions.Session, error) { | ||
| 135 | sess, err := session.Get("session", c) | 139 | sess, err := session.Get("session", c) | ||
| 136 | if err != nil { | 140 | if err != nil { | ||
| @@ -139,6 +143,7 @@ func getSession(c echo.Context) (*sessions.Session, error) { | |||||
| 139 | return sess, nil | 143 | return sess, nil | ||
| 140 | } | 144 | } | ||
| 141 | 145 | ||||
| 146 | + | // handleUser handles the user creation or update | |||
| 142 | func handleUser(c echo.Context, a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | 147 | func handleUser(c echo.Context, a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | ||
| 143 | userExists, err := queries.CheckDBUserExists(a) | 148 | userExists, err := queries.CheckDBUserExists(a) | ||
| 144 | if err != nil { | 149 | if err != nil { | ||
| @@ -179,6 +184,7 @@ func handleUser(c echo.Context, a *app.App, accessToken, browserInfo string, use | |||||
| 179 | return nil, fmt.Errorf("could not handle user") | 184 | return nil, fmt.Errorf("could not handle user") | ||
| 180 | } | 185 | } | ||
| 181 | 186 | ||||
| 187 | + | // createUser creates a new user in the database | |||
| 182 | func createUser(a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | 188 | func createUser(a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | ||
| 183 | err := queries.CreateUser(a, accessToken, browserInfo, userInfo) | 189 | err := queries.CreateUser(a, accessToken, browserInfo, userInfo) | ||
| 184 | if err != nil { | 190 | if err != nil { | ||
| @@ -187,6 +193,7 @@ func createUser(a *app.App, accessToken, browserInfo string, userInfo *queries.G | |||||
| 187 | return &a.DBTables.User, nil | 193 | return &a.DBTables.User, nil | ||
| 188 | } | 194 | } | ||
| 189 | 195 | ||||
| 196 | + | // updateUser updates an existing user in the database | |||
| 190 | func updateUser(a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | 197 | func updateUser(a *app.App, accessToken, browserInfo string, userInfo *queries.GithubUserInfo) (*db.User, error) { | ||
| 191 | user, err := queries.UpdateUser(a, accessToken, browserInfo, userInfo) | 198 | user, err := queries.UpdateUser(a, accessToken, browserInfo, userInfo) | ||
| 192 | if err != nil { | 199 | if err != nil { | ||
| @@ -195,6 +202,7 @@ func updateUser(a *app.App, accessToken, browserInfo string, userInfo *queries.G | |||||
| 195 | return user, nil | 202 | return user, nil | ||
| 196 | } | 203 | } | ||
| 197 | 204 | ||||
| 205 | + | // setSessionValues sets the session values for the user | |||
| 198 | func setSessionValues(c echo.Context, sess *sessions.Session, user *db.User, accountID string, expires string, sessionID string) error { | 206 | func setSessionValues(c echo.Context, sess *sessions.Session, user *db.User, accountID string, expires string, sessionID string) error { | ||
| 199 | sess.Values["authenticated"] = true | 207 | sess.Values["authenticated"] = true | ||
| 200 | sess.Values["accountID"] = accountID | 208 | sess.Values["accountID"] = accountID | ||
| @@ -207,6 +215,7 @@ func setSessionValues(c echo.Context, sess *sessions.Session, user *db.User, acc | |||||
| 207 | return nil | 215 | return nil | ||
| 208 | } | 216 | } | ||
| 209 | 217 | ||||
| 218 | + | // fetchGithubAPI fetches the Github API | |||
| 210 | func fetchGithubAPI(url string, authHeader string, result interface{}) error { | 219 | func fetchGithubAPI(url string, authHeader string, result interface{}) error { | ||
| 211 | req, err := http.NewRequest("GET", url, nil) | 220 | req, err := http.NewRequest("GET", url, nil) | ||
| 212 | if err != nil { | 221 | if err != nil { | ||
| @@ -238,6 +247,7 @@ func fetchGithubAPI(url string, authHeader string, result interface{}) error { | |||||
| 238 | return nil | 247 | return nil | ||
| 239 | } | 248 | } | ||
| 240 | 249 | ||||
| 250 | + | // githubGetUserDetails gets the user details from the Github API using the access token | |||
| 241 | func githubGetUserDetails(c echo.Context, a *app.App) (userInfo *queries.GithubUserInfo, err error) { | 251 | func githubGetUserDetails(c echo.Context, a *app.App) (userInfo *queries.GithubUserInfo, err error) { | ||
| 242 | accessToken := c.QueryParam("access_token") | 252 | accessToken := c.QueryParam("access_token") | ||
| 243 | 253 | ||||