Refactor and remove sqlite and replace with MySQL

This commit is contained in:
2025-10-23 18:43:31 +01:00
parent d53e27eea8
commit 21ebc9c34b
139 changed files with 1013 additions and 529 deletions

View File

@@ -0,0 +1,49 @@
package middleware
import (
"net/http"
"time"
httpHelpers "synlotto-website/helpers/http"
"synlotto-website/constants"
)
func Auth(required bool) func(http.HandlerFunc) http.HandlerFunc {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, _ := httpHelpers.GetSession(w, r)
_, ok := session.Values["user_id"].(int)
if required && !ok {
http.Redirect(w, r, "/account/login", http.StatusSeeOther)
return
}
if ok {
last, hasLast := session.Values["last_activity"].(time.Time)
if hasLast && time.Since(last) > constants.SessionDuration {
session.Options.MaxAge = -1
session.Save(r, w)
newSession, _ := httpHelpers.GetSession(w, r)
newSession.Values["flash"] = "Your session has timed out."
newSession.Save(r, w)
http.Redirect(w, r, "/account/login", http.StatusSeeOther)
return
}
session.Values["last_activity"] = time.Now()
session.Save(r, w)
}
next(w, r)
}
}
}
func Protected(h http.HandlerFunc) http.HandlerFunc {
return Auth(true)(SessionTimeout(h))
}

View File

@@ -0,0 +1,23 @@
package middleware
import "net/http"
func EnforceHTTPS(next http.Handler, enabled bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if enabled && r.Header.Get("X-Forwarded-Proto") != "https" && r.TLS == nil {
http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusMovedPermanently)
return
}
next.ServeHTTP(w, r)
})
}
func SecureHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Security-Policy", "default-src 'self'; style-src 'self' https://cdn.jsdelivr.net; script-src 'self' https://cdn.jsdelivr.net; font-src 'self' https://cdn.jsdelivr.net")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-XSS-Protection", "1; mode=block")
next.ServeHTTP(w, r)
})
}

View File

@@ -0,0 +1,35 @@
package middleware
import (
"net"
"net/http"
"sync"
"golang.org/x/time/rate"
)
var visitors = make(map[string]*rate.Limiter)
var mu sync.Mutex
func GetVisitorLimiter(ip string) *rate.Limiter {
mu.Lock()
defer mu.Unlock()
limiter, exists := visitors[ip]
if !exists {
limiter = rate.NewLimiter(3, 5)
visitors[ip] = limiter
}
return limiter
}
func RateLimit(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
if !GetVisitorLimiter(ip).Allow() {
http.Error(w, "Too many requests", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}

View File

@@ -0,0 +1,22 @@
package middleware
import (
"log"
"net/http"
"runtime/debug"
templateHelpers "synlotto-website/helpers/template"
)
func Recover(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
log.Printf("🔥 Recovered from panic: %v\n%s", rec, debug.Stack())
templateHelpers.RenderError(w, r, http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}

View File

@@ -0,0 +1,40 @@
package middleware
import (
"log"
"net/http"
"time"
session "synlotto-website/handlers/session"
"synlotto-website/constants"
)
func SessionTimeout(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
sess, err := session.GetSession(w, r)
if err != nil {
http.Redirect(w, r, "/account/login", http.StatusSeeOther)
return
}
last, ok := sess.Values["last_activity"].(time.Time)
if !ok || time.Since(last) > constants.SessionDuration {
sess.Options.MaxAge = -1
_ = sess.Save(r, w)
newSession, _ := session.GetSession(w, r)
newSession.Values["flash"] = "Your session has timed out."
_ = newSession.Save(r, w)
log.Printf("Session timeout triggered")
http.Redirect(w, r, "/account/login", http.StatusSeeOther)
return
}
sess.Values["last_activity"] = time.Now().UTC()
_ = sess.Save(r, w)
next(w, r)
}
}