create admin account on first start
This commit is contained in:
parent
708722865d
commit
0e080dd391
5 changed files with 113 additions and 8 deletions
5
go.mod
5
go.mod
|
|
@ -2,4 +2,7 @@ module tms
|
|||
|
||||
go 1.22.0
|
||||
|
||||
require github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
require (
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
golang.org/x/crypto v0.33.0
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -1,2 +1,4 @@
|
|||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
|
|
|
|||
87
main.go
87
main.go
|
|
@ -8,6 +8,8 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
|
|
@ -300,16 +302,87 @@ func addTrainerHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
}
|
||||
|
||||
func hashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func setupAdminHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if an admin exists
|
||||
var count int
|
||||
err := db.QueryRow("SELECT COUNT(*) FROM admins").Scan(&count)
|
||||
if err != nil {
|
||||
http.Error(w, "Database error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// If an admin exists, redirect to login
|
||||
if count > 0 {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// If it's a POST request, create the admin
|
||||
if r.Method == http.MethodPost {
|
||||
name := r.FormValue("name")
|
||||
email := r.FormValue("email")
|
||||
password := r.FormValue("password")
|
||||
|
||||
if email == "" || password == "" || name == "" {
|
||||
http.Error(w, "Name, email and password are required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Hash the password
|
||||
hashedPassword, err := hashPassword(password)
|
||||
if err != nil {
|
||||
http.Error(w, "Error hashing password", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Insert the admin into the database
|
||||
_, err = db.Exec("INSERT INTO admins (name, email, password) VALUES (?, ?, ?)", name, email, hashedPassword)
|
||||
if err != nil {
|
||||
http.Error(w, "Error saving admin", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect to login after setup
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Show the admin setup page
|
||||
err = tmpl.ExecuteTemplate(w, "setup_admin.html", nil)
|
||||
if err != nil {
|
||||
http.Error(w, "Template rendering error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func redirectIfNoAdmin(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var count int
|
||||
err := db.QueryRow("SELECT COUNT(*) FROM admins").Scan(&count)
|
||||
if err != nil || count == 0 {
|
||||
http.Redirect(w, r, "/setup-admin", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
initDB()
|
||||
initTemplates()
|
||||
http.HandleFunc("/", homeHandler)
|
||||
http.HandleFunc("/trainings", trainingListHandler)
|
||||
http.HandleFunc("/trainers", trainerListHandler)
|
||||
http.HandleFunc("/trainers/add", addTrainerHandler)
|
||||
http.HandleFunc("/training-areas", trainingAreaListHandler)
|
||||
http.HandleFunc("/training-areas/add", addTrainingAreaHandler)
|
||||
http.HandleFunc("/training-areas/assign-trainer", assignTrainerToAreaHandler)
|
||||
http.Handle("/", redirectIfNoAdmin(http.HandlerFunc(homeHandler)))
|
||||
http.Handle("/trainings", redirectIfNoAdmin(http.HandlerFunc(trainingListHandler)))
|
||||
http.Handle("/trainers", redirectIfNoAdmin(http.HandlerFunc(trainerListHandler)))
|
||||
http.Handle("/trainers/add", redirectIfNoAdmin(http.HandlerFunc(addTrainerHandler)))
|
||||
http.Handle("/training-areas", redirectIfNoAdmin(http.HandlerFunc(trainingAreaListHandler)))
|
||||
http.Handle("/training-areas/add", redirectIfNoAdmin(http.HandlerFunc(addTrainingAreaHandler)))
|
||||
http.Handle("/training-areas/assign-trainer", redirectIfNoAdmin(http.HandlerFunc(assignTrainerToAreaHandler)))
|
||||
|
||||
http.HandleFunc("/setup-admin", setupAdminHandler)
|
||||
|
||||
fmt.Println("Server running on http://localhost:8080")
|
||||
http.ListenAndServe(":8080", nil)
|
||||
|
|
|
|||
|
|
@ -42,3 +42,10 @@ CREATE TABLE IF NOT EXISTS training_training_areas (
|
|||
FOREIGN KEY (training_id) REFERENCES trainings(id),
|
||||
FOREIGN KEY (training_area_id) REFERENCES training_areas(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admins (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL
|
||||
);
|
||||
20
templates/setup_admin.html
Normal file
20
templates/setup_admin.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
{{template "head.html" .}} <!-- Include header template -->
|
||||
|
||||
<body>
|
||||
{{template "header.html" .}}
|
||||
<h2>Setup Admin Account</h2>
|
||||
<form method="post">
|
||||
<label>Name:</label>
|
||||
<input type="text", name="name" required><br>
|
||||
<label>Email:</label>
|
||||
<input type="email" name="email" required><br>
|
||||
|
||||
<label>Password:</label>
|
||||
<input type="password" name="password" required><br>
|
||||
|
||||
<button type="submit">Create Admin</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue