mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-21 21:33:18 +01:00
163 lines
4.1 KiB
Go
163 lines
4.1 KiB
Go
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
"html/template"
|
|
"io"
|
|
"sort"
|
|
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
|
|
"github.com/amir20/dozzle/internal/analytics"
|
|
"github.com/amir20/dozzle/internal/auth"
|
|
"github.com/amir20/dozzle/internal/docker"
|
|
"github.com/amir20/dozzle/internal/profile"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (h *handler) index(w http.ResponseWriter, req *http.Request) {
|
|
_, err := h.content.Open(req.URL.Path)
|
|
if err == nil && req.URL.Path != "" && req.URL.Path != "/" {
|
|
fileServer.ServeHTTP(w, req)
|
|
} else {
|
|
if !isAuthorized(req) && req.URL.Path != "login" {
|
|
http.Redirect(w, req, path.Clean(h.config.Base+"/login"), http.StatusTemporaryRedirect)
|
|
return
|
|
}
|
|
go h.sendRequestEvent()
|
|
h.executeTemplate(w, req)
|
|
}
|
|
}
|
|
|
|
func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
|
|
file, err := h.content.Open("index.html")
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
bytes, err := io.ReadAll(file)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
tmpl, err := template.New("index.html").Funcs(template.FuncMap{
|
|
"marshal": func(v interface{}) template.JS {
|
|
a, _ := json.Marshal(v)
|
|
return template.JS(a)
|
|
},
|
|
}).Parse(string(bytes))
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
base := ""
|
|
if h.config.Base != "/" {
|
|
base = h.config.Base
|
|
}
|
|
|
|
hosts := make([]*docker.Host, 0, len(h.clients))
|
|
for _, v := range h.clients {
|
|
hosts = append(hosts, v.Host())
|
|
}
|
|
sort.Slice(hosts, func(i, j int) bool {
|
|
return hosts[i].Name < hosts[j].Name
|
|
})
|
|
|
|
config := map[string]interface{}{
|
|
"base": base,
|
|
"version": h.config.Version,
|
|
"authorizationNeeded": h.isAuthorizationNeeded(req),
|
|
"secured": secured,
|
|
"hostname": h.config.Hostname,
|
|
"hosts": hosts,
|
|
"authProvider": h.config.AuthProvider,
|
|
}
|
|
|
|
user := auth.UserFromContext(req.Context())
|
|
if user != nil {
|
|
if settings, err := profile.LoadUserSettings(user); err == nil {
|
|
config["serverSettings"] = settings
|
|
} else {
|
|
config["serverSettings"] = struct{}{}
|
|
}
|
|
config["user"] = user
|
|
} else if h.config.AuthProvider == FORWARD_PROXY {
|
|
log.Error("Unable to find remote user. Please check your proxy configuration. Expecting headers Remote-Email, Remote-User, Remote-Name.")
|
|
log.Debugf("Dumping all headers for url /%s", req.URL.String())
|
|
for k, v := range req.Header {
|
|
log.Debugf("%s: %s", k, v)
|
|
}
|
|
http.Error(w, "Unauthorized user", http.StatusUnauthorized)
|
|
return
|
|
} else if h.config.AuthProvider == SIMPLE && req.URL.Path != "login" {
|
|
log.Debugf("Redirecting to login page for url /%s", req.URL.String())
|
|
http.Redirect(w, req, path.Clean(h.config.Base+"/login"), http.StatusTemporaryRedirect)
|
|
return
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"Config": config,
|
|
"Dev": h.config.Dev,
|
|
"Manifest": h.readManifest(),
|
|
"Base": base,
|
|
}
|
|
|
|
err = tmpl.Execute(w, data)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
func (h *handler) readManifest() map[string]interface{} {
|
|
if h.config.Dev {
|
|
return map[string]interface{}{}
|
|
} else {
|
|
file, err := h.content.Open("manifest.json")
|
|
if err != nil {
|
|
// this should only happen during test. In production, the file is embedded in the binary and checked in main.go
|
|
return map[string]interface{}{}
|
|
}
|
|
bytes, err := io.ReadAll(file)
|
|
if err != nil {
|
|
log.Fatalf("Could not read manifest.json: %v", err)
|
|
}
|
|
var manifest map[string]interface{}
|
|
err = json.Unmarshal(bytes, &manifest)
|
|
if err != nil {
|
|
log.Fatalf("Could not parse manifest.json: %v", err)
|
|
}
|
|
return manifest
|
|
}
|
|
}
|
|
|
|
func (h *handler) sendRequestEvent() {
|
|
if !h.config.NoAnalytics {
|
|
host, _ := os.Hostname()
|
|
|
|
var client DockerClient
|
|
for _, v := range h.clients {
|
|
client = v
|
|
break
|
|
}
|
|
|
|
if containers, err := client.ListContainers(); err == nil {
|
|
totalContainers := len(containers)
|
|
runningContainers := 0
|
|
for _, container := range containers {
|
|
if container.State == "running" {
|
|
runningContainers++
|
|
}
|
|
}
|
|
|
|
re := analytics.RequestEvent{
|
|
ClientId: host,
|
|
TotalContainers: totalContainers,
|
|
RunningContainers: runningContainers,
|
|
}
|
|
analytics.SendRequestEvent(re)
|
|
}
|
|
}
|
|
}
|