Add CLI flags for setup and server configuration
- Add --setup flag to create admin user - Add --admin-user and --admin-password for setup - Generate cryptographically random passwords for --setup - Add --bind and --port flags for server binding - Add BIND env var support - Add SMTP email service for password reset - Add password reset token storage - Add auth header to queue/logs frontend pages - Fix journalctl timestamp format - Fix logs to return empty array instead of error when no entries - Fix queue handler to return proper error message - Hide Users/Aliases nav links when no domain selected
This commit is contained in:
parent
2c3a4c3daa
commit
53ce3b06ae
14 changed files with 435 additions and 69 deletions
|
|
@ -1,6 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
|
@ -13,8 +16,22 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
setup := flag.Bool("setup", false, "Create admin user and exit")
|
||||
adminUser := flag.String("admin-user", "admin", "Admin username for setup")
|
||||
adminPassword := flag.String("admin-password", "", "Admin password for setup (required with --setup)")
|
||||
bind := flag.String("bind", "", "IP address to bind to (default: 0.0.0.0)")
|
||||
port := flag.String("port", "", "Port to listen on (default: 8080)")
|
||||
flag.Parse()
|
||||
|
||||
cfg := config.Load()
|
||||
|
||||
if *bind != "" {
|
||||
cfg.Bind = *bind
|
||||
}
|
||||
if *port != "" {
|
||||
cfg.Port = *port
|
||||
}
|
||||
|
||||
database, err := db.Connect(cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to database: %v", err)
|
||||
|
|
@ -24,6 +41,28 @@ func main() {
|
|||
log.Printf("Warning: Could not initialize schema: %v", err)
|
||||
}
|
||||
|
||||
if *setup {
|
||||
password := *adminPassword
|
||||
if password == "" {
|
||||
password = generateRandomPassword(16)
|
||||
fmt.Printf("Generated random password: %s\n", password)
|
||||
}
|
||||
|
||||
hash, err := auth.HashPassword(password)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to hash password: %v", err)
|
||||
}
|
||||
|
||||
if err := database.EnsureAdminUser(*adminUser, hash); err != nil {
|
||||
log.Fatalf("Failed to create admin user: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Admin user '%s' created successfully.\n", *adminUser)
|
||||
fmt.Printf("You can now login with username: %s\n", *adminUser)
|
||||
fmt.Printf("Password: %s\n", password)
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.AdminUser != "" && cfg.AdminPassword != "" {
|
||||
hash, err := auth.HashPassword(cfg.AdminPassword)
|
||||
if err != nil {
|
||||
|
|
@ -38,7 +77,6 @@ func main() {
|
|||
}
|
||||
|
||||
useEmbedded := os.Getenv("USE_EMBEDDED") != "false"
|
||||
port := cfg.Port
|
||||
|
||||
frontendFS := FrontendFileSystem()
|
||||
|
||||
|
|
@ -62,18 +100,32 @@ func main() {
|
|||
log.Println("Using filesystem frontend")
|
||||
}
|
||||
|
||||
log.Printf("Server starting on http://localhost:%s", port)
|
||||
log.Fatal(http.ListenAndServe(":"+port, router))
|
||||
addr := fmt.Sprintf("%s:%s", cfg.Bind, cfg.Port)
|
||||
log.Printf("Server starting on http://%s", addr)
|
||||
log.Fatal(http.ListenAndServe(addr, router))
|
||||
}
|
||||
|
||||
func generateRandomPassword(length int) string {
|
||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
|
||||
result := make([]byte, length)
|
||||
if _, err := rand.Read(result); err != nil {
|
||||
for i := range result {
|
||||
result[i] = charset[i%len(charset)]
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
for i := range result {
|
||||
result[i] = charset[int(result[i])%len(charset)]
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
func serveStaticPrefixed(fsys http.FileSystem, prefix string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
path := prefix + r.URL.Path
|
||||
log.Printf("Static file requested: /_app/%s -> %s", r.URL.Path, path)
|
||||
|
||||
file, err := fsys.Open(path)
|
||||
if err != nil {
|
||||
log.Printf("Error opening file %s: %v", path, err)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
|
@ -98,11 +150,8 @@ func serveStaticPrefixed(fsys http.FileSystem, prefix string) http.HandlerFunc {
|
|||
|
||||
func serveStaticFile(fsys http.FileSystem, filename string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Static file requested: /%s", filename)
|
||||
|
||||
file, err := fsys.Open(filename)
|
||||
if err != nil {
|
||||
log.Printf("Error opening file %s: %v", filename, err)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
|
@ -129,11 +178,7 @@ func serveSPA(fsys http.FileSystem) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
if path == "/" || path == "" {
|
||||
path = "embed/index.html"
|
||||
} else {
|
||||
path = "embed/index.html"
|
||||
}
|
||||
path = "embed/index.html"
|
||||
|
||||
file, err := fsys.Open(path)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue