Personal Git forge.
package middlewareimport ( "context" "farga/db/types" "farga/lib" "fmt" "net/http" "time" "github.com/google/uuid" "github.com/gorilla/mux")// Use to force users to authenticate if they're not. Pass user to context.func RequireAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { loggedIn, ok := r.Context().Value(lib.LoggedInKey).(bool) if !loggedIn || !ok { http.Redirect(w, r, "/auth/login?err=RequireAuth", http.StatusFound) return } next.ServeHTTP(w, r) })}// Use when you don't want anyone with a session cookie accessing a page.func ExcludeAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { loggedIn, ok := r.Context().Value(lib.LoggedInKey).(bool) if loggedIn && ok { http.Redirect(w, r, "/?err=AlreadyAuthenticated", http.StatusFound) return } next.ServeHTTP(w, r) })}func RequireAdmin(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { loggedIn, loggedInOk := r.Context().Value(lib.LoggedInKey).(bool) user, userOk := r.Context().Value(lib.UserKey).(*types.User) if !loggedInOk || !userOk || !loggedIn || user.Role != types.RoleAdmin { http.Redirect(w, r, "/?err=Forbidden", http.StatusFound) return } next.ServeHTTP(w, r) })}// paves the road for later use of ExcludeAuth and RequireAuth middlewares.func GeneralAuth(store Store) mux.MiddlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sessionCookie, err := r.Cookie(lib.SessionKey) ctx := context.WithValue(r.Context(), lib.LoggedInKey, false) if err == nil && sessionCookie != nil { sessionToken, err := uuid.Parse(sessionCookie.Value) if err != nil { lib.DeleteCookie(w, lib.SessionKey) http.Redirect(w, r, "/auth/login?err=InvalidSession", http.StatusSeeOther) fmt.Println(err) return } session, err := store.Session(sessionToken) // if it doesn't exist or expired if err != nil || time.Time(session.CreatedAt).Before(time.Now().AddDate(0, 0, -lib.SessionDurationDays)) { lib.DeleteCookie(w, lib.SessionKey) store.DeleteSession(sessionToken.String()) http.Redirect(w, r, "/auth/login?err=InvalidSession", http.StatusSeeOther) return } user, err := store.User(*session.UserID) if err != nil { lib.DeleteCookie(w, lib.SessionKey) http.Redirect(w, r, "/auth/login?err=UserNotFound", http.StatusSeeOther) return } ctx = context.WithValue(r.Context(), lib.SessionKey, sessionCookie.Value) ctx = context.WithValue(ctx, lib.UserKey, user) ctx = context.WithValue(ctx, lib.LoggedInKey, true) } next.ServeHTTP(w, r.WithContext(ctx)) }) }}