rewrite using net/http
tronnet/workflows: Static Analysis -- Golang / static-go (push) Failing after 5s

This commit is contained in:
alu committed 2026-10-22 19:03:37 +00:00
1 parent db8ed2e830
commit 98790dbe3b
9 files changed
+270 -189

No files matched your search

+25 -28
View File
@@ -4,12 +4,11 @@ import (
"flag" "flag"
"fmt" "fmt"
"log" "log"
"net/http"
"proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/common"
"proxmoxaas-dashboard/app/routes" "proxmoxaas-dashboard/app/routes"
"strings"
"web" // go will complain here until the first build "web" // go will complain here until the first build
"github.com/gin-gonic/gin"
"github.com/tdewolff/minify/v2" "github.com/tdewolff/minify/v2"
) )
@@ -19,44 +18,42 @@ func Run() {
common.Global = common.GetConfig(*configPath) common.Global = common.GetConfig(*configPath)
// setup gin // setup http router
gin.SetMode(gin.ReleaseMode) router := http.NewServeMux()
router := gin.Default()
// setup static resources // setup static resources
m := common.InitMinify() m := common.InitMinify()
ServeStatic(router, m) ServeStatic(router, m)
html := common.MinifyStatic(m, web.Templates) html := common.MinifyStatic(m, web.Templates)
common.TMPL = common.LoadHTMLToGin(router, html) common.TMPL = common.LoadHTML(html)
// dynamic routes for pages and page fragments // dynamic routes for pages and page fragments
router.GET("/", routes.HandleGETIndex) router.HandleFunc("GET /", routes.HandleGETIndex)
router.GET("/index", routes.HandleGETIndex) router.HandleFunc("GET /index", routes.HandleGETIndex)
router.GET("/index/instances", routes.HandleGETInstancesFragment) router.HandleFunc("GET /index/instances", routes.HandleGETInstancesFragment)
router.GET("/account", routes.HandleGETAccount) router.HandleFunc("GET /account", routes.HandleGETAccount)
router.GET("/config", routes.HandleGETConfig) router.HandleFunc("GET /config", routes.HandleGETConfig)
router.GET("/config/volumes", routes.HandleGETConfigVolumesFragment) router.HandleFunc("GET /config/volumes", routes.HandleGETConfigVolumesFragment)
router.GET("/config/nets", routes.HandleGETConfigNetsFragment) router.HandleFunc("GET /config/nets", routes.HandleGETConfigNetsFragment)
router.GET("/config/devices", routes.HandleGETConfigDevicesFragment) router.HandleFunc("GET /config/devices", routes.HandleGETConfigDevicesFragment)
router.GET("/config/boot", routes.HandleGETConfigBootFragment) router.HandleFunc("GET /config/boot", routes.HandleGETConfigBootFragment)
router.GET("/backups", routes.HandleGETBackups) router.HandleFunc("GET /backups", routes.HandleGETBackups)
router.GET("/backups/backups", routes.HandleGETBackupsFragment) router.HandleFunc("GET /backups/backups", routes.HandleGETBackupsFragment)
router.GET("/login", routes.HandleGETLogin) router.HandleFunc("GET /login", routes.HandleGETLogin)
router.GET("/settings", routes.HandleGETSettings) router.HandleFunc("GET /settings", routes.HandleGETSettings)
// run on all interfaces with port // run on all interfaces with port
log.Fatal("[ERR ] starting gin router: ", router.Run(fmt.Sprintf("0.0.0.0:%d", common.Global.Port))) log.Fatal("[ERR ] starting gin router: ", http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", common.Global.Port), router))
} }
// setup static resources under web (css, images, modules, scripts) // setup static resources under web (css, images, modules, scripts)
func ServeStatic(router *gin.Engine, m *minify.M) { func ServeStatic(router *http.ServeMux, m *minify.M) {
static := common.MinifyStatic(m, web.Static) static := common.MinifyStatic(m, web.Static)
router.GET("/websrc/*path", func(c *gin.Context) { router.HandleFunc("GET /websrc/{path...}", func(w http.ResponseWriter, r *http.Request) {
path, _ := c.Params.Get("path") path := r.PathValue("path")
trimed_path := strings.Replace(path, "/", "", 1) // replace leading "/" captured by *path data := static[path]
data := static[trimed_path] w.Header().Set("Content-Encoding", data.MimeType.Encoding)
fmt.Println(path) w.Header().Set("Content-Type", data.MimeType.Type)
c.Header("Content-Encoding", data.MimeType.Encoding) w.Write([]byte(data.Data))
c.Data(200, data.MimeType.Type, []byte(data.Data))
}) })
} }
+41 -24
View File
@@ -16,7 +16,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/gin-gonic/gin"
"github.com/tdewolff/minify/v2" "github.com/tdewolff/minify/v2"
paas "proxmoxaas-common-lib" paas "proxmoxaas-common-lib"
@@ -103,9 +102,8 @@ func MinifyStatic(m *minify.M, files embed.FS) map[string]StaticFile {
} }
} }
func LoadHTMLToGin(engine *gin.Engine, html map[string]StaticFile) *template.Template { func LoadHTML(html map[string]StaticFile) *template.Template {
root := template.New("") funcMap := template.FuncMap{
engine.FuncMap = template.FuncMap{
"MapKeys": func(x any, sep string) string { "MapKeys": func(x any, sep string) string {
v := reflect.ValueOf(x) v := reflect.ValueOf(x)
keys := v.MapKeys() keys := v.MapKeys()
@@ -133,9 +131,11 @@ func LoadHTMLToGin(engine *gin.Engine, html map[string]StaticFile) *template.Tem
return dict, nil return dict, nil
}, },
} }
tmpl := template.Must(root, LoadAndAddToRoot(engine.FuncMap, root, html)) root := template.New("").Funcs(funcMap)
engine.SetHTMLTemplate(root) if err := LoadAndAddToRoot(funcMap, root, html); err != nil {
return tmpl log.Fatal(err)
}
return root
} }
func LoadAndAddToRoot(FuncMap template.FuncMap, root *template.Template, html map[string]StaticFile) error { func LoadAndAddToRoot(FuncMap template.FuncMap, root *template.Template, html map[string]StaticFile) error {
@@ -170,9 +170,9 @@ func TemplateMinifier(m *minify.M, w io.Writer, r io.Reader, _ map[string]string
return nil return nil
} }
func HandleNonFatalError(c *gin.Context, err error) { func HandleNonFatalError(w http.ResponseWriter, err error) {
log.Printf("[WARN] encountered a non-fatal error: %s", err.Error()) log.Printf("[WARN] encountered a non-fatal error: %s", err.Error())
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
} }
func RequestGetAPI(path string, auth *paas.Auth, body any) (*http.Response, int, error) { func RequestGetAPI(path string, auth *paas.Auth, body any) (*http.Response, int, error) {
@@ -221,25 +221,41 @@ func RequestGetAPI(path string, auth *paas.Auth, body any) (*http.Response, int,
return response, response.StatusCode, nil return response, response.StatusCode, nil
} }
func GetAuthFromRequest(c *gin.Context) (paas.Auth, error) { func GetAuthFromRequest(r *http.Request) (paas.Auth, error) {
_, errAuth := c.Cookie("auth") _, errAuth := r.Cookie("auth")
username, errUsername := c.Cookie("username") username, errUsername := r.Cookie("username")
token, errToken := c.Cookie("PVEAuthCookie") token, errToken := r.Cookie("PVEAuthCookie")
csrf, errCSRF := c.Cookie("CSRFPreventionToken") csrf, errCSRF := r.Cookie("CSRFPreventionToken")
access, errAccess := c.Cookie("PAASAccessManagerTicket") access, errAccess := r.Cookie("PAASAccessManagerTicket")
if errUsername != nil || errAuth != nil || errToken != nil || errCSRF != nil || errAccess != nil {
return paas.Auth{}, fmt.Errorf("error occured getting user cookies: (auth: %s, token: %s, csrf: %s)", errAuth, errToken, errCSRF) if errUsername != nil || errAuth != nil || errToken != nil ||
} else { errCSRF != nil || errAccess != nil {
return paas.Auth{Username: username, Token: token, CSRF: csrf, AccessManagerTicket: access}, nil return paas.Auth{}, fmt.Errorf(
"error occurred getting user cookies: (auth: %v, token: %v, csrf: %v)",
errAuth, errToken, errCSRF,
)
} }
return paas.Auth{
Username: username.Value,
Token: token.Value,
CSRF: csrf.Value,
AccessManagerTicket: access.Value,
}, nil
} }
func GetInstancePathFromRequest(c *gin.Context) (paas.InstancePath, error) { func GetInstancePathFromRequest(r *http.Request) (paas.InstancePath, error) {
req_node := c.Query("node") query := r.URL.Query()
req_type := c.Query("type")
req_vmid := c.Query("vmid") req_node := query.Get("node")
req_type := query.Get("type")
req_vmid := query.Get("vmid")
if req_node == "" || req_type == "" || req_vmid == "" { if req_node == "" || req_type == "" || req_vmid == "" {
return paas.InstancePath{}, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid) return paas.InstancePath{}, fmt.Errorf(
"request missing required values: (node: %s, type: %s, vmid: %s)",
req_node, req_type, req_vmid,
)
} }
vmid_int, err := strconv.ParseUint(req_vmid, 10, 64) vmid_int, err := strconv.ParseUint(req_vmid, 10, 64)
@@ -252,6 +268,7 @@ func GetInstancePathFromRequest(c *gin.Context) (paas.InstancePath, error) {
InstanceType: paas.InstanceType(req_type), InstanceType: paas.InstanceType(req_type),
InstanceID: paas.InstanceID(vmid_int), InstanceID: paas.InstanceID(vmid_int),
} }
return vm_path, nil return vm_path, nil
} }
+17 -7
View File
@@ -1,13 +1,13 @@
package routes package routes
import ( import (
"bytes"
"fmt" "fmt"
"net/http" "net/http"
paas "proxmoxaas-common-lib" paas "proxmoxaas-common-lib"
"proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/common"
"github.com/gerow/go-color" "github.com/gerow/go-color"
"github.com/gin-gonic/gin"
"github.com/go-viper/mapstructure/v2" "github.com/go-viper/mapstructure/v2"
) )
@@ -40,29 +40,39 @@ var Green = color.RGB{
B: 0, B: 0,
} }
func HandleGETAccount(c *gin.Context) { func HandleGETAccount(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
user, err := GetUserBasic(auth) user, err := GetUserBasic(auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
pools, err := GetUserPools(auth) pools, err := GetUserPools(auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
c.HTML(http.StatusOK, "html/account.html", gin.H{ w.Header().Set("Content-Type", "text/html")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/account.html", map[string]any{
"global": common.Global, "global": common.Global,
"page": "account", "page": "account",
"user": user, "user": user,
"pools": pools, "pools": pools,
}) })
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page w.Write(body.Bytes())
return
}
} else {
http.Redirect(w, r, "/login", http.StatusFound) // if user is not authed, redirect user to login page
return
} }
} }
+36 -19
View File
@@ -1,13 +1,13 @@
package routes package routes
import ( import (
"bytes"
"fmt" "fmt"
"net/http" "net/http"
paas "proxmoxaas-common-lib" paas "proxmoxaas-common-lib"
"proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/common"
"time" "time"
"github.com/gin-gonic/gin"
"github.com/go-viper/mapstructure/v2" "github.com/go-viper/mapstructure/v2"
) )
@@ -20,61 +20,78 @@ type InstanceBackup struct {
TimeFormatted string TimeFormatted string
} }
func HandleGETBackups(c *gin.Context) { func HandleGETBackups(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
backups, err := GetInstanceBackups(vm_path, auth) backups, err := GetInstanceBackups(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance backups: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance backups: %s", err.Error()))
return
} }
config, err := GetInstanceConfig(vm_path, auth) // only used for the VM's name config, err := GetInstanceConfig(vm_path, auth) // only used for the VM's name
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
return
} }
c.HTML(http.StatusOK, "html/backups.html", gin.H{ w.Header().Set("Content-Type", "text/html")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/index.html", map[string]any{
"global": common.Global, "global": common.Global,
"page": "backups", "page": "backups",
"backups": backups, "backups": backups,
"config": config, "config": config,
}) })
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Redirect(http.StatusFound, "/login") w.Write(body.Bytes())
return
}
} else {
http.Redirect(w, r, "/login", http.StatusFound)
return
} }
} }
func HandleGETBackupsFragment(c *gin.Context) { func HandleGETBackupsFragment(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { // user should be authed, try to return index with population if err == nil { // user should be authed, try to return index with population
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
backups, err := GetInstanceBackups(vm_path, auth) backups, err := GetInstanceBackups(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance backups: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance backups: %s", err.Error()))
return
} }
c.Header("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
err = common.TMPL.ExecuteTemplate(c.Writer, "html/backups-backups.go.tmpl", gin.H{ body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/backups-backups.go.tmpl", map[string]any{
"backups": backups, "backups": backups,
}) })
if err != nil { if err != nil {
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Status(http.StatusOK) w.Write(body.Bytes())
return
} }
} else { // return 401 } else { // return 401
c.Status(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return
} }
} }
+84 -52
View File
@@ -1,6 +1,7 @@
package routes package routes
import ( import (
"bytes"
"fmt" "fmt"
"net/http" "net/http"
paas "proxmoxaas-common-lib" paas "proxmoxaas-common-lib"
@@ -8,7 +9,6 @@ import (
"slices" "slices"
"sort" "sort"
"github.com/gin-gonic/gin"
"github.com/go-viper/mapstructure/v2" "github.com/go-viper/mapstructure/v2"
) )
@@ -31,24 +31,26 @@ type PoolConfig struct {
} }
} }
func HandleGETConfig(c *gin.Context) { func HandleGETConfig(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
config, err := GetInstanceConfig(vm_path, auth) config, err := GetInstanceConfig(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
return
} }
if config.Type == "VM" { // if VM, fetch CPU types from node if config.Type == "VM" { // if VM, fetch CPU types from node
config.ProctypeSelect, err = GetCPUTypes(vm_path, config.Pool, auth) config.ProctypeSelect, err = GetCPUTypes(vm_path, config.Pool, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting proctypes: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting proctypes: %s", err.Error()))
return
} }
} }
for i, cpu := range config.ProctypeSelect.Options { for i, cpu := range config.ProctypeSelect.Options {
@@ -57,125 +59,155 @@ func HandleGETConfig(c *gin.Context) {
} }
} }
c.HTML(http.StatusOK, "html/config.html", gin.H{ w.Header().Set("Content-Type", "text/html")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/config.html", map[string]any{
"global": common.Global, "global": common.Global,
"page": "config", "page": "config",
"config": config, "config": config,
}) })
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Redirect(http.StatusFound, "/login") w.Write(body.Bytes())
return
}
} else {
http.Redirect(w, r, "/login", http.StatusFound)
return
} }
} }
func HandleGETConfigVolumesFragment(c *gin.Context) { func HandleGETConfigVolumesFragment(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
config, err := GetInstanceConfig(vm_path, auth) config, err := GetInstanceConfig(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
return
} }
c.Header("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-volumes.go.tmpl", gin.H{ body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/config-volumes.go.tmpl", map[string]any{
"config": config, "config": config,
}) })
if err != nil { if err != nil {
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Status(http.StatusOK) w.Write(body.Bytes())
return
} }
} else { } else {
c.Status(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return
} }
} }
func HandleGETConfigNetsFragment(c *gin.Context) { func HandleGETConfigNetsFragment(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
config, err := GetInstanceConfig(vm_path, auth) config, err := GetInstanceConfig(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
return
} }
c.Header("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-nets.go.tmpl", gin.H{ body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/config-nets.go.tmpl", map[string]any{
"config": config, "config": config,
}) })
if err != nil { if err != nil {
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Status(http.StatusOK) w.Write(body.Bytes())
return
} }
} else { } else { // return 401
c.Status(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return
} }
} }
func HandleGETConfigDevicesFragment(c *gin.Context) { func HandleGETConfigDevicesFragment(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
config, err := GetInstanceConfig(vm_path, auth) config, err := GetInstanceConfig(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
return
} }
c.Header("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-devices.go.tmpl", gin.H{ body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/config-devices.go.tmpl", map[string]any{
"config": config, "config": config,
}) })
if err != nil { if err != nil {
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Status(http.StatusOK) w.Write(body.Bytes())
return
} }
} else { } else { // return 401
c.Status(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return
} }
} }
func HandleGETConfigBootFragment(c *gin.Context) { func HandleGETConfigBootFragment(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
vm_path, err := common.GetInstancePathFromRequest(c) vm_path, err := common.GetInstancePathFromRequest(r)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
config, err := GetInstanceConfig(vm_path, auth) config, err := GetInstanceConfig(vm_path, auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error())) common.HandleNonFatalError(w, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
return
} }
c.Header("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
err = common.TMPL.ExecuteTemplate(c.Writer, "html/config-boot.go.tmpl", gin.H{ body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/config-boot.go.tmpl", map[string]any{
"config": config, "config": config,
}) })
if err != nil { if err != nil {
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Status(http.StatusOK) w.Write(body.Bytes())
return
} }
} else { } else { // return 401
c.Status(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return
} }
} }
+31 -16
View File
@@ -1,13 +1,13 @@
package routes package routes
import ( import (
"bytes"
"fmt" "fmt"
"net/http" "net/http"
paas "proxmoxaas-common-lib" paas "proxmoxaas-common-lib"
"proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/common"
"strconv" "strconv"
"github.com/gin-gonic/gin"
"github.com/go-viper/mapstructure/v2" "github.com/go-viper/mapstructure/v2"
) )
@@ -45,46 +45,61 @@ type InstanceStatus struct {
Status string Status string
} }
func HandleGETIndex(c *gin.Context) { func HandleGETIndex(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { // user should be authed, try to return index with population if err == nil { // user should be authed, try to return index with population
instances, _, err := GetClusterResources(auth) instances, _, err := GetClusterResources(auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
page := gin.H{ page := map[string]any{
"global": common.Global, "global": common.Global,
"page": "index", "page": "index",
"instances": instances, "instances": instances,
} }
c.HTML(http.StatusOK, "html/index.html", page)
w.Header().Set("Content-Type", "text/html")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/index.html", page)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} else {
w.Write(body.Bytes())
return
}
} else { // return index without populating } else { // return index without populating
c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page http.Redirect(w, r, "/login", http.StatusFound)
return
} }
} }
func HandleGETInstancesFragment(c *gin.Context) { func HandleGETInstancesFragment(w http.ResponseWriter, r *http.Request) {
auth, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { // user should be authed, try to return index with population if err == nil { // user should be authed, try to return index with population
instances, _, err := GetClusterResources(auth) instances, _, err := GetClusterResources(auth)
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return return
} }
c.Header("Content-Type", "text/plain")
err = common.TMPL.ExecuteTemplate(c.Writer, "html/index-instances.go.tmpl", gin.H{ w.Header().Set("Content-Type", "text/plain")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/index-instances.go.tmpl", map[string]any{
"instances": instances, "instances": instances,
}) })
if err != nil { if err != nil {
c.Status(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Status(http.StatusOK) w.Write(body.Bytes())
return
} }
} else { // return 401 } else { // return 401
c.Status(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return
} }
} }
func GetClusterResources(auth paas.Auth) (map[uint]InstanceCard, map[string]Node, error) { func GetClusterResources(auth paas.Auth) (map[uint]InstanceCard, map[string]Node, error) {
+14 -4
View File
@@ -1,11 +1,11 @@
package routes package routes
import ( import (
"bytes"
"fmt" "fmt"
"net/http" "net/http"
"proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/common"
"github.com/gin-gonic/gin"
"github.com/go-viper/mapstructure/v2" "github.com/go-viper/mapstructure/v2"
) )
@@ -41,10 +41,11 @@ func GetLoginRealms() ([]Realm, error) {
return realms, nil return realms, nil
} }
func HandleGETLogin(c *gin.Context) { func HandleGETLogin(w http.ResponseWriter, r *http.Request) {
realms, err := GetLoginRealms() realms, err := GetLoginRealms()
if err != nil { if err != nil {
common.HandleNonFatalError(c, err) common.HandleNonFatalError(w, err)
return
} }
sel := common.Select{ sel := common.Select{
@@ -60,9 +61,18 @@ func HandleGETLogin(c *gin.Context) {
}) })
} }
c.HTML(http.StatusOK, "html/login.html", gin.H{ w.Header().Set("Content-Type", "text/html")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/login.html", map[string]any{
"global": common.Global, "global": common.Global,
"page": "login", "page": "login",
"realms": sel, "realms": sel,
}) })
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} else {
w.Write(body.Bytes())
return
}
} }
+21 -6
View File
@@ -1,20 +1,35 @@
package routes package routes
import ( import (
"bytes"
"net/http" "net/http"
"proxmoxaas-dashboard/app/common" "proxmoxaas-dashboard/app/common"
"github.com/gin-gonic/gin"
) )
func HandleGETSettings(c *gin.Context) { func HandleGETSettings(w http.ResponseWriter, r *http.Request) {
_, err := common.GetAuthFromRequest(c) auth, err := common.GetAuthFromRequest(r)
if err == nil { if err == nil {
c.HTML(http.StatusOK, "html/settings.html", gin.H{ _, err := GetUserBasic(auth)
if err != nil {
common.HandleNonFatalError(w, err)
return
}
w.Header().Set("Content-Type", "text/html")
body := bytes.Buffer{}
err = common.TMPL.ExecuteTemplate(&body, "html/settings.html", map[string]any{
"global": common.Global, "global": common.Global,
"page": "settings", "page": "settings",
}) })
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} else { } else {
c.Redirect(http.StatusFound, "/login") w.Write(body.Bytes())
return
}
} else {
http.Redirect(w, r, "/login", http.StatusFound)
return
} }
} }
+1 -33
View File
@@ -4,7 +4,6 @@ go 1.27.0
require ( require (
github.com/gerow/go-color v0.0.0-20140219113758-125d37f527f1 github.com/gerow/go-color v0.0.0-20140219113758-125d37f527f1
github.com/gin-gonic/gin v1.12.0
github.com/go-viper/mapstructure/v2 v2.5.0 github.com/go-viper/mapstructure/v2 v2.5.0
github.com/tdewolff/minify/v2 v2.24.17 github.com/tdewolff/minify/v2 v2.24.17
proxmoxaas-common-lib v0.0.0 proxmoxaas-common-lib v0.0.0
@@ -15,35 +14,4 @@ replace proxmoxaas-common-lib => ./proxmoxaas-common-lib
replace web => ./dist/web replace web => ./dist/web
require ( require github.com/tdewolff/parse/v2 v2.8.16 // indirect
github.com/bytedance/gopkg v0.1.4 // indirect
github.com/bytedance/sonic v1.15.2 // indirect
github.com/bytedance/sonic/loader v0.5.2 // indirect
github.com/cloudwego/base64x v0.1.7 // indirect
github.com/gabriel-vasile/mimetype v1.4.15 // indirect
github.com/gin-contrib/sse v1.1.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.30.3 // indirect
github.com/goccy/go-json v0.10.6 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.4.0 // indirect
github.com/leodido/go-urn v1.5.0 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.4.3 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.61.0 // indirect
github.com/tdewolff/parse/v2 v2.8.16 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.2 // indirect
go.mongodb.org/mongo-driver/v2 v2.8.1 // indirect
golang.org/x/arch v0.30.0 // indirect
golang.org/x/crypto v0.55.0 // indirect
golang.org/x/net v0.58.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/text v0.41.0 // indirect
google.golang.org/protobuf v1.36.12 // indirect
)