Refactor and remove sqlite and replace with MySQL
This commit is contained in:
49
internal/http/middleware/auth.go
Normal file
49
internal/http/middleware/auth.go
Normal 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))
|
||||
}
|
||||
23
internal/http/middleware/headers.go
Normal file
23
internal/http/middleware/headers.go
Normal 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)
|
||||
})
|
||||
}
|
||||
35
internal/http/middleware/ratelimit.go
Normal file
35
internal/http/middleware/ratelimit.go
Normal 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)
|
||||
})
|
||||
}
|
||||
22
internal/http/middleware/recover.go
Normal file
22
internal/http/middleware/recover.go
Normal 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)
|
||||
})
|
||||
}
|
||||
40
internal/http/middleware/sessiontimeout.go
Normal file
40
internal/http/middleware/sessiontimeout.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user