Goit

Simple and lightweight Git web server
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2023-12-25 10:04:58
Commit83800a4f8dddc219023ac9b3d658ddfe00fc9591
Parent43a7c2cb71f267e0ea76a78bb81696c5b3c06953

Replace admin index page with status

Diffstat

M res/admin/header.html | 7 +++----
D res/admin/index.html | 17 -----------------
M res/admin/repos.html | 16 +---------------
A res/admin/status.html | 33 +++++++++++++++++++++++++++++++++
M res/admin/user_create.html | 16 +---------------
M res/admin/user_edit.html | 16 +---------------
M res/admin/users.html | 16 +---------------
M res/res.go | 4 ++--
D src/admin/admin.go | 28 ----------------------------
A src/admin/status.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M src/goit/goit.go | 2 ++
M src/goit/http.go | 2 +-
M src/main.go | 3 ++-

13 files changed, 138 insertions, 113 deletions

diff --git a/res/admin/header.html b/res/admin/header.html
index ed6a382..dcf3bf2 100644
--- a/res/admin/header.html
+++ b/res/admin/header.html
@@ -1,12 +1,11 @@
 <table>
 	<tr>
-		<td rowspan="2">
-			<a href="/"><img style="max-height: 24px;" src="/static/favicon.png"></a>
-		</td>
+		<td rowspan="2"><a href="/"><img style="max-height: 24px;" src="/static/favicon.png"></a></td>
 		<td><h1>{{.Title}}</h1></td>
 	</tr>
 	<tr><td>
-		<a href="/admin/users">Users</a>
+		<a href="/admin/status">Status</a>
+		| <a href="/admin/users">Users</a>
 		| <a href="/admin/repos">Repositories</a>
 		| <a href="/admin/user/create">Create User</a>
 	</td></tr>
diff --git a/res/admin/index.html b/res/admin/index.html
deleted file mode 100644
index 31ec05c..0000000
--- a/res/admin/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<head lang="en-GB">{{template "base/head" .}}</head>
-<body>
-	<table>
-		<tr>
-			<td rowspan="2">
-				<a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a>
-			</td>
-			<td><h1>{{.Title}}</h1></td>
-		</tr>
-		<tr><td>
-			<a href="/admin/users">Users</a>
-			| <a href="/admin/repos">Repositories</a>
-			| <a href="/admin/user/create">Create User</a>
-		</td></tr>
-	</table>
-</body>
diff --git a/res/admin/repos.html b/res/admin/repos.html
index ec30841..9f7b42a 100644
--- a/res/admin/repos.html
+++ b/res/admin/repos.html
@@ -1,21 +1,7 @@
 <!DOCTYPE html>
 <head lang="en-GB">{{template "base/head" .}}</head>
 <body>
-	<header>
-		<table>
-			<tr>
-				<td rowspan="2">
-					<a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a>
-				</td>
-				<td><h1>{{.Title}}</h1></td>
-			</tr>
-			<tr><td>
-				<a href="/admin/users">Users</a>
-				| <a href="/admin/repos">Repositories</a>
-				| <a href="/admin/user/create">Create User</a>
-			</td></tr>
-		</table>
-	</header><hr>
+	<header>{{template "admin/header" .}}</header><hr>
 	<main>
 		<table class="highlight-row">
 			<thead>
diff --git a/res/admin/status.html b/res/admin/status.html
new file mode 100644
index 0000000..5917200
--- /dev/null
+++ b/res/admin/status.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<head lang="en-GB">{{template "base/head" .}}</head>
+<body>
+	<header>{{template "admin/header" .}}</header><hr>
+	<main>
+		<table>
+			<tr>
+				<td style="text-align: right;"><b>Version</b></td>
+				<td>{{.Version}}</td>
+			</tr>
+			<tr>
+				<td style="text-align: right;"><b>Uptime</b></td>
+				<td>{{.Uptime}}</td>
+			</tr>
+			<tr>
+				<td style="text-align: right;"><b>Goroutines</b></td>
+				<td>{{.Goroutines}}</td>
+			</tr>
+			<tr>
+				<td style="text-align: right;"><b>Memory</b></td>
+				<td>{{.Memory}}</td>
+			</tr>
+			<tr>
+				<td style="text-align: right;"><b>Stack Usage</b></td>
+				<td>{{.Stack}}</td>
+			</tr>
+			<tr>
+				<td style="text-align: right;"><b>Heap Usage</b></td>
+				<td>{{.Heap}}</td>
+			</tr>
+		</table>
+	</main>
+</body>
diff --git a/res/admin/user_create.html b/res/admin/user_create.html
index 0352901..10274eb 100644
--- a/res/admin/user_create.html
+++ b/res/admin/user_create.html
@@ -1,21 +1,7 @@
 <!DOCTYPE html>
 <head lang="en-GB">{{template "base/head" .}}</head>
 <body>
-	<header>
-		<table>
-			<tr>
-				<td rowspan="2">
-					<a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a>
-				</td>
-				<td><h1>{{.Title}}</h1></td>
-			</tr>
-			<tr><td>
-				<a href="/admin/users">Users</a>
-				| <a href="/admin/repos">Repositories</a>
-				| <a href="/admin/user/create">Create User</a>
-			</td></tr>
-		</table>
-	</header><hr>
+	<header>{{template "admin/header" .}}</header><hr>
 	<main>
 		<h1>{{.Title}}</h1><hr>
 		<form action="/admin/user/create" method="post">
diff --git a/res/admin/user_edit.html b/res/admin/user_edit.html
index 2696ddb..5ea5aa3 100644
--- a/res/admin/user_edit.html
+++ b/res/admin/user_edit.html
@@ -1,21 +1,7 @@
 <!DOCTYPE html>
 <head lang="en-GB">{{template "base/head" .}}</head>
 <body>
-	<header>
-		<table>
-			<tr>
-				<td rowspan="2">
-					<a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a>
-				</td>
-				<td><h1>{{.Title}}</h1></td>
-			</tr>
-			<tr><td>
-				<a href="/admin/users">Users</a>
-				| <a href="/admin/repos">Repositories</a>
-				| <a href="/admin/user/create">Create User</a>
-			</td></tr>
-		</table>
-	</header><hr>
+	<header>{{template "admin/header" .}}</header><hr>
 	<main>
 		<h1>{{.Title}}</h1><hr>
 		<form action="/admin/user/edit?user={{.Form.Id}}" method="post">
diff --git a/res/admin/users.html b/res/admin/users.html
index ec963ac..5e5ff62 100644
--- a/res/admin/users.html
+++ b/res/admin/users.html
@@ -1,21 +1,7 @@
 <!DOCTYPE html>
 <head lang="en-GB">{{template "base/head" .}}</head>
 <body>
-	<header>
-		<table>
-			<tr>
-				<td rowspan="2">
-					<a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a>
-				</td>
-				<td><h1>{{.Title}}</h1></td>
-			</tr>
-			<tr><td>
-				<a href="/admin/users">Users</a>
-				| <a href="/admin/repos">Repositories</a>
-				| <a href="/admin/user/create">Create User</a>
-			</td></tr>
-		</table>
-	</header><hr>
+	<header>{{template "admin/header" .}}</header><hr>
 	<main>
 		<table class="highlight-row">
 			<thead>
diff --git a/res/res.go b/res/res.go
index d257f88..f087216 100644
--- a/res/res.go
+++ b/res/res.go
@@ -16,8 +16,8 @@ var BaseHead string
 //go:embed admin/header.html
 var AdminHeader string
 
-//go:embed admin/index.html
-var AdminIndex string
+//go:embed admin/status.html
+var AdminStatus string
 
 //go:embed admin/users.html
 var AdminUsers string
diff --git a/src/admin/admin.go b/src/admin/admin.go
deleted file mode 100644
index a445b33..0000000
--- a/src/admin/admin.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2023, Jakob Wakeling
-// All rights reserved.
-
-package admin
-
-import (
-	"log"
-	"net/http"
-
-	"github.com/Jamozed/Goit/src/goit"
-)
-
-func HandleIndex(w http.ResponseWriter, r *http.Request) {
-	auth, user, err := goit.Auth(w, r, true)
-	if err != nil {
-		log.Println("[admin]", err.Error())
-		goit.HttpError(w, http.StatusInternalServerError)
-	}
-
-	if !auth || !user.IsAdmin {
-		goit.HttpError(w, http.StatusNotFound)
-		return
-	}
-
-	if err := goit.Tmpl.ExecuteTemplate(w, "admin/index", struct{ Title string }{"Admin"}); err != nil {
-		log.Println("[/admin/index]", err.Error())
-	}
-}
diff --git a/src/admin/status.go b/src/admin/status.go
new file mode 100644
index 0000000..6db3d4b
--- /dev/null
+++ b/src/admin/status.go
@@ -0,0 +1,91 @@
+// Copyright (C) 2023, Jakob Wakeling
+// All rights reserved.
+
+package admin
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"runtime"
+	"strings"
+	"time"
+
+	"github.com/Jamozed/Goit/res"
+	"github.com/Jamozed/Goit/src/goit"
+	"github.com/dustin/go-humanize"
+)
+
+func HandleStatus(w http.ResponseWriter, r *http.Request) {
+	auth, user, err := goit.Auth(w, r, true)
+	if err != nil {
+		log.Println("[admin]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+	}
+
+	if !auth || !user.IsAdmin {
+		goit.HttpError(w, http.StatusNotFound)
+		return
+	}
+
+	mem := runtime.MemStats{}
+	runtime.ReadMemStats(&mem)
+
+	data := struct {
+		Title, Version, Uptime string
+		Goroutines             int
+		Memory, Stack, Heap    string
+	}{
+		Title:      "Admin - Status",
+		Version:    res.Version,
+		Uptime:     formatUptime(time.Since(goit.StartTime)),
+		Goroutines: runtime.NumGoroutine(),
+		Memory:     humanize.Bytes(mem.Sys),
+		Stack:      humanize.Bytes(mem.StackInuse),
+		Heap:       humanize.Bytes(mem.HeapInuse),
+	}
+
+	if err := goit.Tmpl.ExecuteTemplate(w, "admin/status", data); err != nil {
+		log.Println("[/admin/status]", err.Error())
+	}
+}
+
+func formatUptime(uptime time.Duration) string {
+	const (
+		day  = time.Hour * 24
+		week = day * 7
+	)
+
+	weeks := int64(uptime / week)
+	uptime -= time.Duration(weeks) * week
+	days := int64(uptime / day)
+	uptime -= time.Duration(days) * day
+	hours := int64(uptime / time.Hour)
+	uptime -= time.Duration(hours) * time.Hour
+	minutes := int64(uptime / time.Minute)
+	uptime -= time.Duration(minutes) * time.Minute
+	seconds := int64(uptime / time.Second)
+
+	var parts []string
+	if weeks > 0 {
+		parts = append(parts, fmt.Sprintf("%d weeks", weeks))
+	}
+	if days > 0 {
+		parts = append(parts, fmt.Sprintf("%d days", days))
+	}
+	if hours > 0 {
+		parts = append(parts, fmt.Sprintf("%d hours", hours))
+	}
+	if minutes > 0 {
+		parts = append(parts, fmt.Sprintf("%d minutes", minutes))
+	}
+	if seconds > 0 {
+		parts = append(parts, fmt.Sprintf("%d seconds", seconds))
+	}
+
+	if len(parts) == 0 {
+		return "0 seconds"
+	}
+
+	return strings.Join(parts, ", ")
+}
diff --git a/src/goit/goit.go b/src/goit/goit.go
index 9067d28..c96acb0 100644
--- a/src/goit/goit.go
+++ b/src/goit/goit.go
@@ -55,6 +55,8 @@ var Cron *cron.Cron
 
 var Reserved []string = []string{"admin", "repo", "static", "user"}
 
+var StartTime = time.Now()
+
 func Goit(conf string) (err error) {
 	if dat, err := os.ReadFile(conf); err != nil {
 		if !errors.Is(err, os.ErrNotExist) {
diff --git a/src/goit/http.go b/src/goit/http.go
index 80f1b9e..3fc333b 100644
--- a/src/goit/http.go
+++ b/src/goit/http.go
@@ -19,7 +19,7 @@ func init() {
 	template.Must(Tmpl.New("base/head").Parse(res.BaseHead))
 
 	template.Must(Tmpl.New("admin/header").Parse(res.AdminHeader))
-	template.Must(Tmpl.New("admin/index").Parse(res.AdminIndex))
+	template.Must(Tmpl.New("admin/status").Parse(res.AdminStatus))
 	template.Must(Tmpl.New("admin/users").Parse(res.AdminUsers))
 	template.Must(Tmpl.New("admin/user/create").Parse(res.AdminUserCreate))
 	template.Must(Tmpl.New("admin/user/edit").Parse(res.AdminUserEdit))
diff --git a/src/main.go b/src/main.go
index 1933a86..4a88489 100644
--- a/src/main.go
+++ b/src/main.go
@@ -115,7 +115,8 @@ func main() {
 		r.Post("/user/edit", user.HandleEdit)
 		r.Get("/repo/create", repo.HandleCreate)
 		r.Post("/repo/create", repo.HandleCreate)
-		r.Get("/admin", admin.HandleIndex)
+		r.Get("/admin", admin.HandleStatus)
+		r.Get("/admin/status", admin.HandleStatus)
 		r.Get("/admin/users", admin.HandleUsers)
 		r.Get("/admin/user/create", admin.HandleUserCreate)
 		r.Post("/admin/user/create", admin.HandleUserCreate)