85 lines
2.6 KiB
Go
85 lines
2.6 KiB
Go
package accountHandler
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/justinas/nosurf"
|
|
|
|
securityHelpers "synlotto-website/internal/helpers/security"
|
|
templateHelpers "synlotto-website/internal/helpers/template"
|
|
"synlotto-website/internal/logging"
|
|
"synlotto-website/internal/models"
|
|
"synlotto-website/internal/platform/bootstrap"
|
|
"synlotto-website/internal/platform/sessionkeys"
|
|
auditlogStorage "synlotto-website/internal/storage/auditlog"
|
|
usersStorage "synlotto-website/internal/storage/users"
|
|
)
|
|
|
|
func LoginGet(c *gin.Context) {
|
|
app := c.MustGet("app").(*bootstrap.App)
|
|
sm := app.SessionManager
|
|
|
|
ctx := templateHelpers.TemplateContext(c.Writer, c.Request, models.TemplateData{})
|
|
|
|
if f := sm.PopString(c.Request.Context(), "flash"); f != "" {
|
|
ctx["Flash"] = f
|
|
}
|
|
|
|
ctx["CSRFToken"] = nosurf.Token(c.Request)
|
|
|
|
tmpl := templateHelpers.LoadTemplateFiles("layout.html", "web/templates/account/login.html")
|
|
|
|
c.Status(http.StatusOK)
|
|
if err := tmpl.ExecuteTemplate(c.Writer, "layout", ctx); err != nil {
|
|
logging.Info("❌ Template render error: %v", err)
|
|
c.String(http.StatusInternalServerError, "Error rendering login page")
|
|
}
|
|
}
|
|
|
|
func LoginPost(c *gin.Context) {
|
|
app := c.MustGet("app").(*bootstrap.App)
|
|
sm := app.SessionManager
|
|
db := app.DB
|
|
|
|
r := c.Request
|
|
w := c.Writer
|
|
|
|
username := r.FormValue("username")
|
|
password := r.FormValue("password")
|
|
|
|
logging.Info("🔐 Login attempt - Username: %s", username)
|
|
|
|
user := usersStorage.GetUserByUsername(db, username)
|
|
if user == nil {
|
|
logging.Info("❌ User not found: %s", username)
|
|
auditlogStorage.LogLoginAttempt(db, r.RemoteAddr, r.UserAgent(), username, false)
|
|
sm.Put(r.Context(), "flash", "Invalid username or password.")
|
|
c.Redirect(http.StatusSeeOther, "/account/login")
|
|
return
|
|
}
|
|
|
|
if !securityHelpers.CheckPasswordHash(user.PasswordHash, password) {
|
|
logging.Info("❌ Password mismatch for user: %s", username)
|
|
auditlogStorage.LogLoginAttempt(db, r.RemoteAddr, r.UserAgent(), username, false)
|
|
sm.Put(r.Context(), "flash", "Invalid username or password.")
|
|
c.Redirect(http.StatusSeeOther, "/account/login")
|
|
return
|
|
}
|
|
|
|
logging.Info("✅ Login successful for user: %s", username)
|
|
auditlogStorage.LogLoginAttempt(db, r.RemoteAddr, r.UserAgent(), username, true)
|
|
|
|
_ = sm.Destroy(r.Context())
|
|
_ = sm.RenewToken(r.Context())
|
|
|
|
sm.Put(r.Context(), "user_id", user.Id)
|
|
sm.Put(r.Context(), sessionkeys.Username, user.Username)
|
|
sm.Put(r.Context(), sessionkeys.IsAdmin, user.IsAdmin)
|
|
sm.Put(r.Context(), "last_activity", time.Now().UTC())
|
|
sm.Put(r.Context(), "flash", "Welcome back, "+user.Username+"!")
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|