88 lines
2.3 KiB
Go
88 lines
2.3 KiB
Go
|
package authentication
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
|
||
|
"git.kirsle.net/apps/gophertype/pkg/models"
|
||
|
"git.kirsle.net/apps/gophertype/pkg/session"
|
||
|
)
|
||
|
|
||
|
// CurrentUser returns the currently logged-in user in the browser session.
|
||
|
func CurrentUser(r *http.Request) (models.User, error) {
|
||
|
sess := session.Get(r)
|
||
|
if loggedIn, ok := sess.Values["logged-in"].(bool); ok && loggedIn {
|
||
|
id := sess.Values["user-id"].(int)
|
||
|
user, err := models.GetUserByID(id)
|
||
|
return user, err
|
||
|
}
|
||
|
return models.User{}, errors.New("not logged in")
|
||
|
}
|
||
|
|
||
|
// Login logs the browser session in as the user.
|
||
|
func Login(w http.ResponseWriter, r *http.Request, user models.User) {
|
||
|
sess := session.Get(r)
|
||
|
|
||
|
sess.Values["logged-in"] = true
|
||
|
sess.Values["user-id"] = int(user.ID)
|
||
|
if err := sess.Save(r, w); err != nil {
|
||
|
log.Printf("ERROR: Login() Session error: " + err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Logout logs the current user out.
|
||
|
func Logout(w http.ResponseWriter, r *http.Request) {
|
||
|
sess := session.Get(r)
|
||
|
sess.Values["logged-in"] = false
|
||
|
sess.Values["user-id"] = 0
|
||
|
sess.Save(r, w)
|
||
|
}
|
||
|
|
||
|
// LoggedIn returns whether the session is logged in as a user.
|
||
|
func LoggedIn(r *http.Request) bool {
|
||
|
sess := session.Get(r)
|
||
|
if v, ok := sess.Values["logged-in"].(bool); ok && v == true {
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// LoginRequired is a middleware for authenticated endpoints.
|
||
|
func LoginRequired(next http.Handler) http.Handler {
|
||
|
middleware := func(w http.ResponseWriter, r *http.Request) {
|
||
|
ctx := r.Context()
|
||
|
if user, ok := ctx.Value(session.UserKey).(models.User); ok {
|
||
|
if user.ID > 0 {
|
||
|
next.ServeHTTP(w, r)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Redirect to the login page.
|
||
|
w.Header().Set("Location", "/login?next="+r.URL.Path)
|
||
|
w.WriteHeader(http.StatusFound)
|
||
|
}
|
||
|
|
||
|
return http.HandlerFunc(middleware)
|
||
|
}
|
||
|
|
||
|
// Middleware checks the authentication and loads the user onto the request context.
|
||
|
func Middleware(next http.Handler) http.Handler {
|
||
|
middleware := func(w http.ResponseWriter, r *http.Request) {
|
||
|
user, err := CurrentUser(r)
|
||
|
if err != nil {
|
||
|
// User not logged in, go to next middleware.
|
||
|
next.ServeHTTP(w, r)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Put the CurrentUser into the request context.
|
||
|
ctx := context.WithValue(r.Context(), session.UserKey, user)
|
||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||
|
}
|
||
|
|
||
|
return http.HandlerFunc(middleware)
|
||
|
}
|