379 lines
15 KiB
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)
|
|
}
|