gosora/chi_router.go

379 lines
15 KiB
Go

package main
import (
"context"
"log"
"net/http"
"git.tuxpa.in/a/gosora/common"
"git.tuxpa.in/a/gosora/routes"
"git.tuxpa.in/a/gosora/routes/panel"
"git.tuxpa.in/a/gosora/uutils"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
type ContextKey string
var ContextKey_USER ContextKey = "gosora_user"
var ContextKey_EXTRADATA ContextKey = "gosora_extradata"
func AuthContextMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user_copy, ok := common.PreRoute(w, r)
if !ok {
return
}
user := &user_copy
ctx := context.WithValue(r.Context(), ContextKey_USER, user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func ParseFormMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := common.ParseForm(w, r, u)
if err != nil {
log.Println("error parsing form middleware")
return
}
next.ServeHTTP(w, r)
})
}
func NoBannedMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := common.NoBanned(w, r, user)
if err != nil {
log.Println(err)
return
}
next.ServeHTTP(w, r)
})
}
func NoSessionMismatchMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := common.NoSessionMismatch(w, r, user)
if err != nil {
log.Println(err)
return
}
next.ServeHTTP(w, r)
})
}
func MemberOnlyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := common.MemberOnly(w, r, user)
if err != nil {
log.Println(err)
return
}
next.ServeHTTP(w, r)
})
}
func SuperModOnlyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := common.SuperModOnly(w, r, user)
if err != nil {
log.Println(err)
return
}
next.ServeHTTP(w, r)
})
}
func SuperAdminOnlyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := common.SuperAdminOnly(w, r, user)
if err != nil {
log.Println(err)
return
}
next.ServeHTTP(w, r)
})
}
type UserRoute = func(w http.ResponseWriter, r *http.Request, u *common.User) common.RouteError
type ExtraRoute = func(w http.ResponseWriter, r *http.Request, u *common.User, s string) common.RouteError
type HeaderRoute = func(w http.ResponseWriter, r *http.Request, u *common.User, h *common.Header) common.RouteError
type HeaderExtraRoute = func(w http.ResponseWriter, r *http.Request, u *common.User, h *common.Header, s string) common.RouteError
func ConvertUserRoute(fn UserRoute) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, ok := r.Context().Value(ContextKey_USER).(*common.User)
if !ok {
log.Println("error grabbing user from context")
return
}
err := fn(w, r, u)
if err != nil {
log.Println("error handling %s %s", fn, err)
}
})
}
func ConvertHeaderRoute(fn HeaderRoute) http.HandlerFunc {
return ConvertUserRoute(func(w http.ResponseWriter, r *http.Request, u *common.User) common.RouteError {
h, err := common.UserCheckNano(w, r, u, uutils.Nanotime())
if err != nil {
return err
}
return fn(w, r, u, h)
})
}
func ConvertExtraRoute(fn ExtraRoute) http.HandlerFunc {
return ConvertUserRoute(func(w http.ResponseWriter, r *http.Request, u *common.User) common.RouteError {
s := chi.URLParam(r, "extra")
return fn(w, r, u, s)
})
}
func ConvertHeaderExtraRoute(fn HeaderExtraRoute) http.HandlerFunc {
return ConvertHeaderRoute(func(w http.ResponseWriter, r *http.Request, u *common.User, h *common.Header) common.RouteError {
s := chi.URLParam(r, "extra")
return fn(w, r, u, h, s)
})
}
func NewChiRouter() {
r := chi.NewRouter()
// A good base middleware stack
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(AuthContextMiddleware)
r.Route("/overview", func(r chi.Router) {
r.Get("/", ConvertHeaderRoute(routes.Overview))
})
r.Route("/pages", func(r chi.Router) {
r.Get("/{extra}", ConvertHeaderExtraRoute(routes.CustomPage))
})
r.Route("/forums", func(r chi.Router) {
r.Get("/", ConvertHeaderRoute(routes.ForumList))
})
r.Route("/forum", func(r chi.Router) {
r.Get("/{extra}", ConvertHeaderExtraRoute(routes.ViewForum))
})
r.Route("/theme", func(r chi.Router) {
r.Use(ParseFormMiddleware)
r.Get("/", ConvertUserRoute(routes.ChangeTheme))
})
r.Route("/attachs", func(r chi.Router) {
r.Use(ParseFormMiddleware)
r.Get("/{extra}", ConvertExtraRoute(routes.ShowAttachment))
})
r.Route("/ws", func(r chi.Router) {
r.Get("/{extra}", ConvertUserRoute(common.RouteWebsockets))
})
r.Route("/api", func(r chi.Router) {
r.Get("/phrases*", ConvertUserRoute(routeAPIPhrases))
r.Get("/me*", ConvertUserRoute(routes.APIMe))
r.Get("/watches*", ConvertUserRoute(routeJSAntispam))
r.Get("/*", ConvertUserRoute(routeAPI))
})
r.Route("/report", func(r chi.Router) {
r.Use(NoBannedMiddleware)
r.Use(NoSessionMismatchMiddleware)
r.Use(MemberOnlyMiddleware)
r.Get("/submit/{extra}", ConvertExtraRoute(routes.ReportSubmit))
})
r.Route("/topics", func(r chi.Router) {
r.Get("/most-viewed", ConvertHeaderRoute(routes.TopicListMostViewed))
r.Get("/week-views", ConvertHeaderRoute(routes.TopicListWeekViews))
r.Get("/create", ConvertHeaderExtraRoute(routes.CreateTopic))
r.Get("/", ConvertHeaderRoute(routes.TopicList))
})
r.Route("/panel", func(r chi.Router) {
r.Use(SuperModOnlyMiddleware)
r.Use(NoSessionMismatchMiddleware)
r.Route("/forums", func(r chi.Router) {
r.Get("/", ConvertUserRoute(panel.Forums))
r.Get("/create", ConvertUserRoute(panel.ForumsCreateSubmit))
r.Get("/delete/{extra}", ConvertExtraRoute(panel.ForumsDelete))
r.Get("/delete/submit/{extra}", ConvertExtraRoute(panel.ForumsDeleteSubmit))
r.Get("/order/edit/submit", ConvertUserRoute(panel.ForumsOrderSubmit))
r.Get("/edit/{extra}", ConvertExtraRoute(panel.ForumsEdit))
r.Get("/edit/submit/{extra}", ConvertExtraRoute(panel.ForumsEditSubmit))
r.Get("/edit/perms/submit/{extra}", ConvertExtraRoute(panel.ForumsEditPermsSubmit))
r.Get("/edit/perms/{extra}", ConvertExtraRoute(panel.ForumsEditPermsAdvance))
r.Get("/edit/perms/adv/submit/{extra}", ConvertExtraRoute(panel.ForumsEditPermsAdvanceSubmit))
r.Get("/action/create/submit/{extra}", ConvertExtraRoute(panel.ForumsEditActionCreateSubmit))
r.Get("/action/delete/submit/{extra}", ConvertExtraRoute(panel.ForumsEditActionDeleteSubmit))
})
r.Route("/settings", func(r chi.Router) {
r.Get("/", ConvertUserRoute(panel.Settings))
r.Get("/edit/{extra}", ConvertExtraRoute(panel.SettingEdit))
r.Get("/edit/submit/{extra}", ConvertExtraRoute(panel.SettingEditSubmit))
r.Get("/word-filters", ConvertUserRoute(panel.WordFilters))
r.Get("/word-filters/create", ConvertUserRoute(panel.WordFiltersCreateSubmit))
r.Get("/word-filters/edit/{extra}", ConvertExtraRoute(panel.WordFiltersEdit))
r.Get("/word-filters/edit/submit/{extra}", ConvertExtraRoute(panel.WordFiltersEdit))
r.Get("/word-filters/delete/submit/{extra}", ConvertExtraRoute(panel.WordFiltersDeleteSubmit))
})
r.Route("/pages", func(r chi.Router) {
r.Get("/create/submit", ConvertUserRoute(panel.PagesCreateSubmit))
r.Get("/edit/{extra}", ConvertExtraRoute(panel.PagesEdit))
r.Get("/edit/submit/{extra}", ConvertExtraRoute(panel.PagesEditSubmit))
r.Get("/delete/submit/{extra}", ConvertExtraRoute(panel.PagesDeleteSubmit))
})
r.Route("/themes", func(r chi.Router) {
r.Get("/", ConvertUserRoute(panel.Themes))
r.Get("/default/{extra}", ConvertExtraRoute(panel.ThemesSetDefault))
r.Get("/menus", ConvertUserRoute(panel.ThemesMenus))
r.Get("/menus/edit/{extra}", ConvertExtraRoute(panel.ThemesMenusEdit))
r.Get("/menus/item/edit/{extra}", ConvertExtraRoute(panel.ThemesMenuItemEdit))
r.Get("/menus/item/edit/submit/{extra}", ConvertExtraRoute(panel.ThemesMenuItemEditSubmit))
r.Get("/menus/item/create/submit", ConvertUserRoute(panel.ThemesMenuItemCreateSubmit))
r.Get("/menus/item/delete/submit/{extra}", ConvertExtraRoute(panel.ThemesMenuItemDeleteSubmit))
r.Get("/menus/item/order/edit/submit/{extra}", ConvertExtraRoute(panel.ThemesMenuItemOrderSubmit))
r.Get("/widgets/edit/submit/{extra}", ConvertExtraRoute(panel.ThemesWidgetsEditSubmit))
r.Get("/widgets/create/submit", ConvertUserRoute(panel.ThemesWidgetsCreateSubmit))
r.Get("/widgets/delete/submit/{extra}", ConvertExtraRoute(panel.ThemesWidgetsDeleteSubmit))
})
r.Route("/plugins", func(r chi.Router) {
r.Get("/{extra}", ConvertExtraRoute(panel.PluginsInstall))
r.Get("/activate/{extra}", ConvertExtraRoute(panel.PluginsActivate))
r.Get("/deactivate/{extra}", ConvertExtraRoute(panel.PluginsDeactivate))
r.Get("/install/{extra}", ConvertExtraRoute(panel.PluginsInstall))
})
})
r.Route("/user", func(r chi.Router) {
r.Use(MemberOnlyMiddleware)
r.Route("/edit", func(r chi.Router) {
r.Get("/", ConvertHeaderRoute(routes.AccountEdit))
r.Get("/password", ConvertHeaderRoute(routes.AccountEditPassword))
r.Get("/password/submit", ConvertUserRoute(routes.AccountEditPasswordSubmit))
r.Get("/avatar/submit", ConvertUserRoute(routes.AccountEditAvatarSubmit))
r.Get("/avatar/revoke/submit", ConvertUserRoute(routes.AccountEditRevokeAvatarSubmit))
r.Get("/username/submit", ConvertUserRoute(routes.AccountEditUsernameSubmit))
r.Get("/privacy", ConvertHeaderRoute(routes.AccountEditPrivacy))
r.Get("/privacy/submit", ConvertUserRoute(routes.AccountEditPrivacySubmit))
r.Get("/mfa", ConvertHeaderRoute(routes.AccountEditMFA))
r.Get("/mfa/setup", ConvertHeaderRoute(routes.AccountEditMFASetup))
r.Get("/mfa/setup/submit", ConvertUserRoute(routes.AccountEditMFASetupSubmit))
r.Get("/mfa/disable/submit", ConvertUserRoute(routes.AccountEditMFADisableSubmit))
r.Get("/email", ConvertHeaderRoute(routes.AccountEditEmail))
r.Get("/token", ConvertExtraRoute(routes.AccountEditEmailTokenSubmit))
r.Get("/logins", ConvertHeaderRoute(routes.AccountLogins))
r.Get("/blocked", ConvertHeaderRoute(routes.AccountBlocked))
})
r.Get("/levels", ConvertHeaderRoute(routes.LevelList))
r.Get("/convos", ConvertHeaderRoute(routes.Convos))
r.Get("/convos/create", ConvertHeaderRoute(routes.ConvosCreate))
r.Get("/convo", ConvertHeaderExtraRoute(routes.Convo))
r.Get("/convos/create/submit", ConvertUserRoute(routes.ConvosCreateSubmit))
r.Get("/convo/create/submit", ConvertUserRoute(routes.ConvosCreateSubmit))
r.Get("/convo/delete/submit", ConvertExtraRoute(routes.ConvosDeleteReplySubmit))
r.Get("/convo/edit/submit", ConvertExtraRoute(routes.ConvosEditReplySubmit))
r.Get("/block/create", ConvertHeaderExtraRoute(routes.RelationsBlockCreate))
r.Get("/block/create/submit", ConvertExtraRoute(routes.RelationsBlockCreateSubmit))
r.Get("/block/remove", ConvertHeaderExtraRoute(routes.RelationsBlockRemove))
r.Get("/block/remove/submit", ConvertExtraRoute(routes.RelationsBlockRemoveSubmit))
r.Get("/{user}", ConvertHeaderRoute(routes.ViewProfile))
})
r.Route("/users", func(r chi.Router) {
r.Use(NoSessionMismatchMiddleware)
r.Get("/ban/submit", ConvertExtraRoute(routes.BanUserSubmit))
r.Get("/unban", ConvertExtraRoute(routes.UnbanUser))
r.Get("/activate", ConvertExtraRoute(routes.ActivateUser))
r.Get("/ips", ConvertHeaderRoute(routes.IPSearch))
r.Get("/delete-posts/submit", ConvertExtraRoute(routes.DeletePostsSubmit))
})
r.Route("/topic", func(r chi.Router) {
r.Use(MemberOnlyMiddleware)
r.Use(NoSessionMismatchMiddleware)
r.Get("/create/submit", ConvertUserRoute(routes.CreateTopicSubmit))
r.Get("/edit/submit", ConvertExtraRoute(routes.EditTopicSubmit))
r.Get("/delete/submit", ConvertUserRoute(routes.DeleteTopicSubmit))
r.Get("/stick/submit", ConvertExtraRoute(routes.StickTopicSubmit))
r.Get("/unstick/submit", ConvertExtraRoute(routes.UnstickTopicSubmit))
r.Get("/lock/submit", ConvertUserRoute(routes.LockTopicSubmit))
r.Get("/unlock/submit", ConvertExtraRoute(routes.UnlockTopicSubmit))
r.Get("/move/submit", ConvertExtraRoute(routes.MoveTopicSubmit))
r.Get("/like/submit", ConvertExtraRoute(routes.LikeTopicSubmit))
r.Get("/unlike/submit", ConvertExtraRoute(routes.UnlikeTopicSubmit))
r.Get("/attach/add/submit", ConvertExtraRoute(routes.AddAttachToTopicSubmit))
r.Get("/attach/remove/submit", ConvertExtraRoute(routes.RemoveAttachFromTopicSubmit))
})
r.Route("/reply", func(r chi.Router) {
r.Use(MemberOnlyMiddleware)
r.Get("/create", ConvertUserRoute(routes.ProfileReplyCreateSubmit))
r.Get("/edit/submit", ConvertExtraRoute(routes.ReplyEditSubmit))
r.Get("/delete/submit", ConvertExtraRoute(routes.ReplyDeleteSubmit))
r.Get("/like/submit", ConvertExtraRoute(routes.ReplyLikeSubmit))
r.Get("/unlike/submit", ConvertExtraRoute(routes.ReplyUnlikeSubmit))
r.Get("/attach/add/submit", ConvertExtraRoute(routes.AddAttachToReplySubmit))
r.Get("/attach/remove/submit", ConvertExtraRoute(routes.RemoveAttachFromReplySubmit))
})
r.Route("/profile", func(r chi.Router) {
r.Use(MemberOnlyMiddleware)
r.Use(NoSessionMismatchMiddleware)
r.Get("/reply/create", ConvertUserRoute(routes.ProfileReplyCreateSubmit))
r.Get("/reply/edit/submit", ConvertExtraRoute(routes.ProfileReplyEditSubmit))
r.Get("/reply/edit/delete/submit", ConvertExtraRoute(routes.ProfileReplyDeleteSubmit))
})
r.Route("/poll", func(r chi.Router) {
r.Use(MemberOnlyMiddleware)
r.Use(NoSessionMismatchMiddleware)
r.Get("/poll/vote", ConvertExtraRoute(routes.PollVote))
r.Get("/poll/results", ConvertExtraRoute(routes.PollResults))
})
r.Route("/accounts", func(r chi.Router) {
r.Get("/login", ConvertHeaderRoute(routes.AccountLogin))
r.Get("/create", ConvertHeaderRoute(routes.AccountRegister))
r.Get("/logout", ConvertUserRoute(routes.AccountLogout))
r.Get("/login/submit", ConvertUserRoute(routes.AccountLoginSubmit))
r.Get("/mfa_verify", ConvertHeaderRoute(routes.AccountLoginMFAVerify))
r.Get("/mfa_verify/submit", ConvertUserRoute(routes.AccountLoginMFAVerifySubmit))
r.Get("/create/submit", ConvertUserRoute(routes.AccountRegisterSubmit))
r.Get("/password-reset", ConvertHeaderRoute(routes.AccountPasswordReset))
r.Get("/password-reset/submit", ConvertUserRoute(routes.AccountPasswordResetSubmit))
r.Get("/password-reset/token", ConvertHeaderRoute(routes.AccountPasswordResetToken))
r.Get("/password-reset/token/submit", ConvertUserRoute(routes.AccountPasswordResetTokenSubmit))
})
r.Route("/static", func(r chi.Router) {})
r.Route("/uploads", func(r chi.Router) {})
http.ListenAndServe(":3333", r)
}