added authentication among other things. considered working at this point.
This commit is contained in:
69
handlers/account.go
Normal file
69
handlers/account.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"synlotto-website/models"
|
||||
|
||||
"github.com/gorilla/csrf"
|
||||
)
|
||||
|
||||
func Login(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/account/login.html",
|
||||
))
|
||||
|
||||
tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"csrfField": csrf.TemplateField(r),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
username := r.FormValue("username")
|
||||
password := r.FormValue("password")
|
||||
|
||||
user := models.GetUserByUsername(username)
|
||||
if user == nil || !CheckPasswordHash(user.PasswordHash, password) {
|
||||
http.Error(w, "Invalid credentials", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
session, _ := GetSession(w, r)
|
||||
session.Values["user_id"] = user.Id
|
||||
session.Save(r, w)
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func Signup(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/account/signup.html",
|
||||
))
|
||||
|
||||
tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"csrfField": csrf.TemplateField(r),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
username := r.FormValue("username")
|
||||
password := r.FormValue("password")
|
||||
|
||||
hashed, err := HashPassword(password)
|
||||
if err != nil {
|
||||
http.Error(w, "Server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = models.CreateUser(username, hashed)
|
||||
if err != nil {
|
||||
http.Error(w, "Could not create user", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
}
|
||||
13
handlers/auth.go
Normal file
13
handlers/auth.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package handlers
|
||||
|
||||
import "golang.org/x/crypto/bcrypt"
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPasswordHash(hash, password string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
@@ -1,17 +1,8 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"synlotto-website/models"
|
||||
)
|
||||
|
||||
var Tmpl = template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/index.html",
|
||||
"templates/new_draw.html",
|
||||
"templates/new_ticket.html",
|
||||
"templates/tickets.html",
|
||||
))
|
||||
|
||||
var Draws []models.ThunderballResult
|
||||
var MyTickets []models.MyTicket
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"synlotto-website/helpers"
|
||||
"synlotto-website/models"
|
||||
|
||||
"github.com/gorilla/csrf"
|
||||
)
|
||||
|
||||
func Home(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("✅ Home hit")
|
||||
|
||||
err := Tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"Page": "index",
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/index.html",
|
||||
))
|
||||
|
||||
err := tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"Data": Draws,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -23,9 +30,15 @@ func Home(w http.ResponseWriter, r *http.Request) {
|
||||
func NewDraw(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("➡️ New draw form opened")
|
||||
|
||||
err := Tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"Page": "new_draw",
|
||||
"Data": nil,
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/new_draw.html",
|
||||
))
|
||||
|
||||
err := tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"csrfField": csrf.TemplateField(r),
|
||||
"Page": "new_draw",
|
||||
"Data": nil,
|
||||
})
|
||||
if err != nil {
|
||||
log.Println("❌ Template error:", err)
|
||||
|
||||
44
handlers/session.go
Normal file
44
handlers/session.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
var store = sessions.NewCookieStore([]byte("super-secret-key")) // ToDo: Make global
|
||||
|
||||
func init() {
|
||||
store.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 86400 * 1,
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
}
|
||||
}
|
||||
|
||||
func GetSession(w http.ResponseWriter, r *http.Request) (*sessions.Session, error) {
|
||||
return store.Get(r, "session-name")
|
||||
}
|
||||
|
||||
func GetCurrentUserID(r *http.Request) (int, bool) {
|
||||
session, err := GetSession(nil, r)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
id, ok := session.Values["user_id"].(int)
|
||||
return id, ok
|
||||
}
|
||||
|
||||
func RequireAuth(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
_, ok := GetCurrentUserID(r)
|
||||
if !ok {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,29 @@ package handlers
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"synlotto-website/helpers"
|
||||
"synlotto-website/models"
|
||||
"synlotto-website/storage"
|
||||
|
||||
"github.com/gorilla/csrf"
|
||||
)
|
||||
|
||||
func NewTicket(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("➡️ New ticket form opened")
|
||||
|
||||
err := Tmpl.ExecuteTemplate(w, "new_ticket", map[string]interface{}{
|
||||
"Page": "new_ticket",
|
||||
"Data": nil,
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/new_ticket.html",
|
||||
))
|
||||
|
||||
err := tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"csrfField": csrf.TemplateField(r),
|
||||
"Page": "new_ticket",
|
||||
"Data": nil,
|
||||
})
|
||||
if err != nil {
|
||||
log.Println("❌ Template error:", err)
|
||||
@@ -27,6 +35,10 @@ func NewTicket(db *sql.DB) http.HandlerFunc {
|
||||
|
||||
func SubmitTicket(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if _, ok := GetCurrentUserID(r); !ok {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
ticket := models.MyTicket{
|
||||
GameType: r.FormValue("game_type"),
|
||||
DrawDate: r.FormValue("draw_date"),
|
||||
@@ -53,6 +65,11 @@ func ListTickets(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("📋 Tickets page hit")
|
||||
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/tickets.html",
|
||||
))
|
||||
|
||||
rows, err := db.Query(`
|
||||
SELECT id, game_type, draw_date, ball1, ball2, ball3, ball4, ball5, bonus1, bonus2, duplicate
|
||||
FROM my_tickets
|
||||
@@ -80,7 +97,7 @@ func ListTickets(db *sql.DB) http.HandlerFunc {
|
||||
tickets = append(tickets, t)
|
||||
}
|
||||
|
||||
err = Tmpl.ExecuteTemplate(w, "tickets", map[string]any{
|
||||
err = tmpl.ExecuteTemplate(w, "layout", map[string]any{
|
||||
"Page": "tickets",
|
||||
"Data": tickets,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user