1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-09-04 10:06:24 -07:00

Simplify controling the JSON-compatible output for manage pages

Rather than having to check whether the user is requesting JSON output in each action, it is done automatically
This commit is contained in:
Eggbertx 2021-12-23 14:41:49 -08:00
parent 16b9b4a92f
commit 352cb0227f
3 changed files with 48 additions and 35 deletions

View file

@ -34,15 +34,30 @@ const (
AdminPerms
)
const (
// NoJSON actions will return an error if JSON is requested by the user
NoJSON = iota
// OptionalJSON actions have an optional JSON output if requested
OptionalJSON
// AlwaysJSON actions always return JSON whether or not it is requested
AlwaysJSON
)
var (
chopPortNumRegex = regexp.MustCompile(`(.+|\w+):(\d+)$`)
)
// Action represents the functions accessed by staff members at /manage?action=<functionname>.
type Action struct {
Title string `json:"title"`
Permissions int `json:"perms"` // 0 = non-staff, 1 => janitor, 2 => moderator, 3 => administrator
isJSON bool // if it can sometimes return JSON, this should still be false
Title string `json:"title"`
// Permissions represent who can access the page. 0 for anyone,
// 1 requires the user to have a janitor, mod, or admin account. 2 requires mod or admin,
// and 3 is only accessible by admins
Permissions int `json:"perms"`
// JSONoutput sets what the action can output. If it is 0, it will throw an error
// if JSON is requested. If it is 1, it can output JSON if requested, and if 2, it always
// outputs JSON whether it is requested or not
JSONoutput int `json:"jsonOutput"` // if it can sometimes return JSON, this should still be false
// Callback executes the staff page. if wantsJSON is true, it returns an object to be marshalled
// into JSON. Otherwise, a string assumed to be valid HTML is returned.
Callback func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) `json:"-"`
@ -53,6 +68,7 @@ var actions = map[string]Action{
Title: "Cleanup",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
// TODO: make a proper JSON output for this, possibly /manage?action=cleanup&json=1&confirmed=1
outputStr := `<h2 class="manage-header">Cleanup</h2><br />`
if request.FormValue("run") == "Run Cleanup" {
outputStr += "Removing deleted posts from the database.<hr />"
@ -294,11 +310,7 @@ var actions = map[string]Action{
"dashboard": {
Title: "Dashboard",
Permissions: JanitorPerms,
isJSON: false,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
if wantsJSON {
return "", createNoJSONError("dashboard")
}
dashBuffer := bytes.NewBufferString("")
if err = serverutil.MinifyTemplate(gctemplates.ManageDashboard,
@ -313,10 +325,6 @@ var actions = map[string]Action{
Title: "Login",
Permissions: NoPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
if wantsJSON {
return "", createNoJSONError("dashboard")
}
systemCritical := config.GetSystemCriticalConfig()
if GetStaffRank(request) > 0 {
http.Redirect(writer, request, path.Join(systemCritical.WebRoot, "manage"), http.StatusFound)
@ -467,7 +475,7 @@ var actions = map[string]Action{
}},
"staffinfo": {
Permissions: NoPerms,
isJSON: true,
JSONoutput: AlwaysJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
staff, err := getCurrentFullStaff(request)
return staff, err
@ -653,11 +661,6 @@ var actions = map[string]Action{
gcsql.ResetBoardSectionArrays()
return
}},
"actions": {
Title: "Staff actions",
Permissions: JanitorPerms,
isJSON: true,
},
"rebuildfront": {
Title: "Rebuild front page",
Permissions: AdminPerms,
@ -670,6 +673,7 @@ var actions = map[string]Action{
"rebuildall": {
Title: "Rebuild everything",
Permissions: AdminPerms,
JSONoutput: OptionalJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
gctemplates.InitTemplates()
gcsql.ResetBoardSectionArrays()
@ -728,7 +732,6 @@ var actions = map[string]Action{
"rebuildboard": {
Title: "Rebuild board",
Permissions: AdminPerms,
isJSON: true,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
return "Not implemented (yet)", gcutil.ErrNotImplemented
// if err = gctemplates.InitTemplates(); err != nil {
@ -749,6 +752,7 @@ var actions = map[string]Action{
"rebuildboards": {
Title: "Rebuild boards",
Permissions: AdminPerms,
JSONoutput: OptionalJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
if err = gctemplates.InitTemplates(); err != nil {
return "", err
@ -799,6 +803,7 @@ var actions = map[string]Action{
"recentposts": {
Title: "Recent posts",
Permissions: JanitorPerms,
JSONoutput: OptionalJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
var outputStr string
systemCritical := config.GetSystemCriticalConfig()
@ -844,7 +849,6 @@ var actions = map[string]Action{
"postinfo": {
Title: "Post info",
Permissions: ModPerms,
isJSON: true,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
var post gcsql.Post
post, err = gcsql.GetSpecificPost(gcutil.HackyStringToInt(request.FormValue("postid")), false)
@ -858,6 +862,7 @@ var actions = map[string]Action{
"staff": {
Title: "Staff",
Permissions: AdminPerms,
JSONoutput: OptionalJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
var outputStr string
do := request.FormValue("do")

View file

@ -12,14 +12,6 @@ import (
"github.com/gochan-org/gochan/pkg/serverutil"
)
func createNoJSONError(action string) *ErrStaffAction {
return &ErrStaffAction{
ErrorField: "nojson",
Action: action,
Message: "Requested mod page does not have a JSON output option",
}
}
type ErrStaffAction struct {
// ErrorField can be used in the frontend for giving more specific info about the error
ErrorField string `json:"error"`
@ -83,10 +75,6 @@ func CallManageFunction(writer http.ResponseWriter, request *http.Request) {
}
return
}
if action == "actions" {
handler.Callback = getStaffActions
wantsJSON = true
}
if staffRank == NoPerms && handler.Permissions > NoPerms {
handler = actions["login"]
} else if staffRank < handler.Permissions {
@ -97,20 +85,30 @@ func CallManageFunction(writer http.ResponseWriter, request *http.Request) {
"Rejected request to manage page %s from %s (insufficient permissions)",
action, staffName)
serveError(writer, "permission", action, "You do not have permission to access this page", handler.isJSON || wantsJSON)
serveError(writer, "permission", action, "You do not have permission to access this page", wantsJSON || (handler.JSONoutput > NoJSON))
return
}
output, err := handler.Callback(writer, request, isRequestingJSON(request))
var output interface{}
if wantsJSON && handler.JSONoutput == NoJSON {
output = nil
err = &ErrStaffAction{
ErrorField: "nojson",
Action: action,
Message: "Requested mod page does not have a JSON output option",
}
} else {
output, err = handler.Callback(writer, request, wantsJSON)
}
if err != nil {
staffName, _ := getCurrentStaff(request)
// writer.WriteHeader(500)
gclog.Printf(gclog.LStaffLog|gclog.LErrorLog,
"Error accessing manage page %s by %s: %s", action, staffName, err.Error())
serveError(writer, "actionerror", action, err.Error(), wantsJSON || handler.isJSON)
serveError(writer, "actionerror", action, err.Error(), wantsJSON || (handler.JSONoutput > NoJSON))
return
}
if handler.isJSON || wantsJSON {
if handler.JSONoutput == AlwaysJSON || wantsJSON {
writer.Header().Add("Content-Type", "application/json")
writer.Header().Add("Cache-Control", "max-age=5, must-revalidate")
outputJSON, err := gcutil.MarshalJSON(output, true)

View file

@ -93,9 +93,19 @@ func GetStaffRank(request *http.Request) int {
return staff.Rank
}
func init() {
actions["actions"] = Action{
Title: "Staff actions",
Permissions: JanitorPerms,
JSONoutput: AlwaysJSON,
Callback: getStaffActions,
}
}
func getStaffActions(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (interface{}, error) {
rank := GetStaffRank(request)
actionMap := map[string]Action{}
for id, action := range actions {
if rank < action.Permissions || action.Permissions == NoPerms {
continue