AuThEnTiCaTiOn and clean up....
This commit is contained in:
@@ -5,30 +5,28 @@ import (
|
||||
"net/http"
|
||||
"synlotto-website/helpers"
|
||||
"synlotto-website/models"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/csrf"
|
||||
)
|
||||
|
||||
func Login(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
session, _ := helpers.GetSession(w, r)
|
||||
if _, ok := session.Values["user_id"].(int); ok {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl := template.Must(template.ParseFiles(
|
||||
"templates/layout.html",
|
||||
"templates/account/login.html",
|
||||
))
|
||||
|
||||
session, _ := helpers.GetSession(w, r)
|
||||
context := helpers.TemplateContext(w, r)
|
||||
context["csrfField"] = csrf.TemplateField(r)
|
||||
|
||||
var flash string
|
||||
if f, ok := session.Values["flash"].(string); ok {
|
||||
flash = f
|
||||
delete(session.Values, "flash")
|
||||
session.Save(r, w)
|
||||
}
|
||||
|
||||
tmpl.ExecuteTemplate(w, "layout", map[string]interface{}{
|
||||
"csrfField": csrf.TemplateField(r),
|
||||
"Flash": flash,
|
||||
})
|
||||
tmpl.ExecuteTemplate(w, "layout", context)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -36,21 +34,27 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
||||
password := r.FormValue("password")
|
||||
|
||||
user := models.GetUserByUsername(username)
|
||||
if user == nil || !CheckPasswordHash(user.PasswordHash, password) {
|
||||
if user == nil || !helpers.CheckPasswordHash(user.PasswordHash, password) {
|
||||
http.Error(w, "Invalid credentials", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
session, err := helpers.GetSession(w, r)
|
||||
if err != nil {
|
||||
http.Error(w, "Session error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
session, _ := helpers.GetSession(w, r)
|
||||
session.Options.MaxAge = -1
|
||||
session.Save(r, w)
|
||||
|
||||
remember := r.FormValue("remember") == "on"
|
||||
|
||||
newSession, _ := helpers.GetSession(w, r)
|
||||
newSession.Values["user_id"] = user.Id
|
||||
newSession.Values["last_activity"] = time.Now()
|
||||
|
||||
if remember {
|
||||
newSession.Options.MaxAge = 60 * 60 * 24 * 30 // 30 days
|
||||
} else {
|
||||
newSession.Options.MaxAge = 0
|
||||
}
|
||||
|
||||
newSession.Save(r, w)
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
@@ -84,7 +88,7 @@ func Signup(w http.ResponseWriter, r *http.Request) {
|
||||
username := r.FormValue("username")
|
||||
password := r.FormValue("password")
|
||||
|
||||
hashed, err := HashPassword(password)
|
||||
hashed, err := helpers.HashPassword(password)
|
||||
if err != nil {
|
||||
http.Error(w, "Server error", http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"synlotto-website/helpers"
|
||||
)
|
||||
|
||||
func GetCurrentUserID(r *http.Request) (int, bool) {
|
||||
session, err := helpers.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)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ 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 {
|
||||
if _, ok := helpers.GetCurrentUserID(r); !ok {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers
|
||||
package helpers
|
||||
|
||||
import "golang.org/x/crypto/bcrypt"
|
||||
|
||||
@@ -2,11 +2,13 @@ package helpers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
var store = sessions.NewCookieStore([]byte("super-secret-key")) // move this here
|
||||
var store = sessions.NewCookieStore([]byte("super-secret-key")) // //ToDo make key global
|
||||
const SessionTimeout = 30 * time.Minute
|
||||
|
||||
func init() {
|
||||
store.Options = &sessions.Options{
|
||||
@@ -21,3 +23,48 @@ func init() {
|
||||
func GetSession(w http.ResponseWriter, r *http.Request) (*sessions.Session, error) {
|
||||
return store.Get(r, "session-name")
|
||||
}
|
||||
|
||||
func IsSessionExpired(session *sessions.Session) bool {
|
||||
last, ok := session.Values["last_activity"].(time.Time)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return time.Since(last) > SessionTimeout
|
||||
}
|
||||
|
||||
func UpdateSessionActivity(session *sessions.Session, r *http.Request, w http.ResponseWriter) {
|
||||
session.Values["last_activity"] = time.Now()
|
||||
session.Save(r, w)
|
||||
}
|
||||
|
||||
func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
session, _ := GetSession(w, r)
|
||||
|
||||
if IsSessionExpired(session) {
|
||||
session.Options.MaxAge = -1
|
||||
session.Save(r, w)
|
||||
|
||||
newSession, _ := GetSession(w, r)
|
||||
newSession.Values["flash"] = "Your session has timed out."
|
||||
newSession.Save(r, w)
|
||||
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
UpdateSessionActivity(session, r, w)
|
||||
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
14
main.go
14
main.go
@@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
"synlotto-website/handlers"
|
||||
"synlotto-website/helpers"
|
||||
"synlotto-website/middleware"
|
||||
"synlotto-website/models"
|
||||
"synlotto-website/storage"
|
||||
|
||||
@@ -17,20 +18,21 @@ func main() {
|
||||
|
||||
csrfMiddleware := csrf.Protect(
|
||||
[]byte("32-byte-long-auth-key-here"), // TodO: Make Global
|
||||
csrf.Secure(false),
|
||||
csrf.Secure(true),
|
||||
csrf.Path("/"),
|
||||
)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("/", handlers.Home(db))
|
||||
mux.HandleFunc("/new", handlers.NewDraw)
|
||||
mux.HandleFunc("/new", handlers.NewDraw) // ToDo: needs to be wrapped in admin auth
|
||||
mux.HandleFunc("/submit", handlers.Submit)
|
||||
mux.HandleFunc("/ticket", handlers.NewTicket(db))
|
||||
mux.HandleFunc("/tickets", handlers.ListTickets(db))
|
||||
mux.HandleFunc("/submit-ticket", handlers.RequireAuth(handlers.SubmitTicket(db)))
|
||||
mux.HandleFunc("/login", handlers.Login)
|
||||
mux.HandleFunc("/tickets", middleware.Auth(true)(handlers.ListTickets(db)))
|
||||
mux.HandleFunc("/submit-ticket", helpers.AuthMiddleware(handlers.SubmitTicket(db)))
|
||||
mux.HandleFunc("/login", middleware.Auth(false)(handlers.Login))
|
||||
mux.HandleFunc("/logout", handlers.Logout)
|
||||
mux.HandleFunc("/signup", handlers.Signup)
|
||||
mux.HandleFunc("/signup", middleware.Auth(false)(handlers.Signup))
|
||||
|
||||
// Result pages
|
||||
mux.HandleFunc("/results/thunderball", handlers.ResultsThunderball(db))
|
||||
|
||||
45
middleware/auth.go
Normal file
45
middleware/auth.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"synlotto-website/helpers"
|
||||
)
|
||||
|
||||
const SessionTimeout = 30 * time.Minute
|
||||
|
||||
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, _ := helpers.GetSession(w, r)
|
||||
|
||||
_, ok := session.Values["user_id"].(int)
|
||||
|
||||
if required && !ok {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
if ok {
|
||||
last, hasLast := session.Values["last_activity"].(time.Time)
|
||||
if hasLast && time.Since(last) > SessionTimeout {
|
||||
session.Options.MaxAge = -1
|
||||
session.Save(r, w)
|
||||
|
||||
newSession, _ := helpers.GetSession(w, r)
|
||||
newSession.Values["flash"] = "Your session has timed out."
|
||||
newSession.Save(r, w)
|
||||
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
session.Values["last_activity"] = time.Now()
|
||||
session.Save(r, w)
|
||||
}
|
||||
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
{{ .csrfField }}
|
||||
<label>Username: <input type="text" name="username" required></label><br>
|
||||
<label>Password: <input type="password" name="password" required></label><br>
|
||||
<label><input type="checkbox" name="remember"> Remember Me</label>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user