127 lines
3.4 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|
|
|
|
}
|