Files
ersteller/authentication/auth.go
T

127 lines
3.4 KiB
Go

package authentication
import (
. "ersteller-lib"
"net/http"
"strings"
"github.com/gorilla/sessions"
"golang.org/x/net/context"
)
const sessionName = "session"
const EmailKey = "email"
const UserIdKey = "userId"
const AuthContextKey = "authContext"
type AuthContext struct {
Email string
UserId int
}
func SaveEmailAndUserIdToSessionStore(request *http.Request, writer http.ResponseWriter, store *sessions.CookieStore, email string, userId int) error {
session, err := store.New(request, sessionName)
if err != nil {
LogError("Failed to create session: %v", err)
return err
}
session.Values = map[interface{}]interface{}{
EmailKey: email,
UserIdKey: userId,
}
err = session.Save(request, writer)
if err != nil {
LogError("Failed to save session: %v", err)
return err
}
return nil
}
func SetUserIdAndEmailFromSessionStore(request *http.Request, store *sessions.CookieStore) (bool, *http.Request, error) {
session, err := store.Get(request, sessionName)
if err != nil {
LogError("Failed to get session: %v", err)
return false, nil, err
}
email, ok := session.Values[EmailKey].(string)
if !ok {
return false, nil, nil
}
userId, ok := session.Values[UserIdKey].(int)
if !ok {
return false, nil, nil
}
ctx := context.WithValue(request.Context(), AuthContextKey, AuthContext{
Email: email,
UserId: userId,
})
return true, request.WithContext(ctx), nil
}
func LogoutSession(writer http.ResponseWriter, request *http.Request, sessionStore *sessions.CookieStore, redirectUrl string) {
// Clear the session
session, err := sessionStore.Get(request, sessionName) // Using default session name
if err != nil {
LogError("Failed to get session: %v", err)
http.Redirect(writer, request, redirectUrl, http.StatusTemporaryRedirect)
return
}
session.Options.MaxAge = -1
err = session.Save(request, writer)
if err != nil {
LogError("Failed to save session: %v", err)
http.Error(writer, "Failed to clear session", http.StatusInternalServerError)
return
}
http.Redirect(writer, request, redirectUrl, http.StatusTemporaryRedirect)
}
func Middleware(store *sessions.CookieStore, excludedPrefixes []string, redirect LanguagePaths) MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Debug("Authenticating for page", r.URL.Path)
if r.Method == http.MethodOptions {
next.ServeHTTP(w, r)
return
}
for _, prefix := range excludedPrefixes {
if strings.HasPrefix(r.URL.Path, prefix) {
next.ServeHTTP(w, r)
return
}
}
for _, path := range redirect {
if strings.HasPrefix(r.URL.Path, path) {
next.ServeHTTP(w, r)
return
}
}
ok, newR, err := SetUserIdAndEmailFromSessionStore(r, store)
if err != nil {
LogError("Failed to set user id and email from session: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
if ok {
next.ServeHTTP(w, newR)
} else {
redirectUrl := En.GetPath() + redirect[En]
for lang, path := range redirect {
if strings.HasPrefix(r.URL.Path, lang.GetPath()) {
redirectUrl = lang.GetPath() + path
break
}
}
if redirectUrl == "" {
redirectUrl = "/"
}
Debug("Redirecting to ", redirectUrl, "because there is no session")
http.Redirect(w, r, redirectUrl, http.StatusTemporaryRedirect)
}
})
}
}