diff --git a/main.go b/main.go
index 6e72c78..2826527 100644
--- a/main.go
+++ b/main.go
@@ -1,10 +1,15 @@
package main
import (
+ "os"
+ "strconv"
+ "strings"
+ "sync"
"crypto/rand"
"html/template"
"log"
"net/http"
+ "encoding/json"
)
const (
@@ -12,15 +17,47 @@ const (
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
)
-var templates = make(map[string]*template.Template)
-var AppVersion = "development"
+var (
+ templates = make(map[string]*template.Template)
+ AppVersion = "development"
+ counterFile = "/data/counter.txt"
+ mu sync.Mutex
+)
+
+// Diese Funktion wird nur intern aufgerufen, wenn der Mutex bereits gesperrt ist
+func getCount() int {
+ data, err := os.ReadFile(counterFile)
+ if err != nil {
+ return 0
+ }
+ count, _ := strconv.Atoi(strings.TrimSpace(string(data)))
+ return count
+}
+
+// Öffentliche Funktion für das Template (mit Lock)
+func GetPasswordCount() int {
+ mu.Lock()
+ defer mu.Unlock()
+ return getCount()
+}
+
+// Öffentliche Funktion zum Erhöhen (mit Lock)
+func IncrementPasswordCount() {
+ mu.Lock()
+ defer mu.Unlock()
+
+ // Wir rufen jetzt die interne Funktion auf, die NICHT versucht,
+ // den Mutex erneut zu sperren
+ count := getCount()
+ count++
+ os.WriteFile(counterFile, []byte(strconv.Itoa(count)), 0644)
+}
func loadTemplates() {
// 1. FuncMap definieren
funcMap := template.FuncMap{
- "getAppVersion": func() string {
- return AppVersion
- },
+ "getAppVersion": func() string { return AppVersion },
+ "getPassCount": func() int { return GetPasswordCount() },
}
// 2. Templates mit FuncMap laden
@@ -39,6 +76,7 @@ func loadTemplates() {
}
func generatePassword() string {
+ log.Printf("called generatePassword\n")
password := make([]byte, passwordLength)
_, err := rand.Read(password)
if err != nil {
@@ -47,10 +85,29 @@ func generatePassword() string {
for i := 0; i < passwordLength; i++ {
password[i] = chars[int(password[i])%len(chars)]
}
+ IncrementPasswordCount()
return string(password)
}
func passwordHandler(w http.ResponseWriter, r *http.Request) {
+ log.Printf("called passwordHandler\n")
+ password := generatePassword()
+ currentCount := GetPasswordCount()
+ response := map[string]interface{}{
+ "password": password,
+ "count": currentCount,
+ }
+ w.Header().Set("Content-Type", "application/json")
+ err := json.NewEncoder(w).Encode(response)
+ if err != nil {
+ log.Printf("Fehler beim Senden des JSON: %v", err)
+ http.Error(w, "Interner Fehler", http.StatusInternalServerError)
+ return
+ }
+}
+
+func passwordAPIHandler(w http.ResponseWriter, r *http.Request) {
+ log.Printf("called passwordHandler\n")
password := generatePassword()
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(password))
@@ -59,11 +116,13 @@ func passwordHandler(w http.ResponseWriter, r *http.Request) {
func indexHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("call indexHandler: Request %s %s\n", r.Method, r.URL)
password := generatePassword()
+ //password := "load..."
data := struct {
Password string
}{
Password: password,
}
+ log.Printf("prepare template for index\n")
err := templates["index.html"].ExecuteTemplate(w, "base.html", data)
if err != nil {
log.Printf("Fehler beim Rendern des Templates: %v", err)
@@ -86,7 +145,8 @@ func main() {
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.HandleFunc("/", indexHandler)
- http.HandleFunc("/api/password", passwordHandler)
+ http.HandleFunc("/api/password", passwordAPIHandler)
+ http.HandleFunc("/json/password", passwordHandler)
http.HandleFunc("/help", helpHandler)
log.Println("Server läuft auf http://localhost:8080")
diff --git a/misc/docker-compose.traefik.yml b/misc/docker-compose.traefik.yml
index 8c8f90d..e42b662 100644
--- a/misc/docker-compose.traefik.yml
+++ b/misc/docker-compose.traefik.yml
@@ -3,6 +3,8 @@ services:
image: gitea.scu.si/florian.walther/password-generator:latest
container_name: password-generator
restart: always
+ volumes:
+ - ./app_data:/data
expose:
- "8080:8080"
labels:
diff --git a/misc/docker-compose.yml b/misc/docker-compose.yml
index e964b81..fd025f6 100644
--- a/misc/docker-compose.yml
+++ b/misc/docker-compose.yml
@@ -3,6 +3,8 @@ services:
image: gitea.scu.si/florian.walther/password-generator:latest
container_name: password-generator
restart: always
+ volumes:
+ - ./app_data:/data
ports:
- "8080:8080"
# Falls die Registry privat ist, muss der Host zuvor mit
diff --git a/static/style.css b/static/style.css
index e9d4eb8..8f29071 100644
--- a/static/style.css
+++ b/static/style.css
@@ -34,6 +34,7 @@ body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
+ margin-bottom: 60px;
}
.container {
@@ -48,30 +49,63 @@ body {
}
footer {
- /* Fixierung am unteren Rand */
position: fixed;
bottom: 0;
left: 0;
-
- /* Ausdehnung */
width: 100%;
-
- /* Design & Abstände */
- background: var(--password-bg);
- border-top: 1px solid #e0e0e0;
- padding: 8px 16px;
-
- /* Text-Ausrichtung */
- text-align: left;
+ background-color: var(--bg-color);
+ border-top: 1px solid var(--border-color);
+ padding: 10px 20px;
+ box-sizing: border-box;
+ box-shadow: 0 2px 10px var(--shadow-color);
+ z-index: 1000;
+}
+
+.footer-container {
+ display: flex;
+ justify-content: flex-end; /* Schiebt alles nach rechts */
+ gap: 20px; /* Abstand zwischen Counter und Version */
+ align-items: center;
+}
+
+.footer-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ font-size: 13px;
+ color:x#4b5563;
+}
+
+.label {
+ font-weight: 500;
+}
+
+/* Die Badges (Status-Pillen) */
+.value {
+ padding: 2px 8px;
+ border-radius: 12px;
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
+ font-weight: 600;
+ font-size: 11px;
+}
+
+.badge-blue {
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ border: 1px solid var(--border-color);
+}
+
+.badge-gray {
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ border: 1px solid var(border-color);
+}
+
+.claim {
font-family: monospace; /* Monospace sieht für Versionen oft "technischer" aus */
font-size: 12px;
color: var(--text-color);
-
- /* Sicherstellen, dass nichts drüber liegt */
- z-index: 9999;
-
- /* Padding in die Breite einrechnen */
- box-sizing: border-box;
}
#password {
diff --git a/templates/base.html b/templates/base.html
index a14f214..0dfe32a 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -46,6 +46,21 @@
{{ block "body" . }}{{end}}
-
+
+