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

Turn staff action map into an array for more control over ordering

This commit is contained in:
Eggbertx 2022-01-01 16:03:39 -08:00
parent c4e4b775ba
commit 9fb5ebbd0b
7 changed files with 116 additions and 77 deletions

View file

@ -11,10 +11,7 @@ const notAStaff = {
Rank: 0
};
/**
* @type {StaffActionMap}
*/
export let staffActions = {};
export let staffActions = [];
export let staffInfo = notAStaff;
/**
@ -95,18 +92,26 @@ export function banSelectedPost() {
* A helper function for creating a menu item
* @param {StaffAction} action
*/
function menuItem(action, id = "") {
if(id == "") {
function menuItem(action, isCategory = false) {
if(isCategory) {
return $("<div/>").append($("<b/>").text(action));
} else {
return $("<div/>").append(
$("<a/>").prop({
href: `${webroot}manage?action=${id}`
href: `${webroot}manage?action=${action.id}`
}).text(action.title)
);
}
}
function getAction(id) {
for (const action of staffActions) {
if(action.id == id) {
return action;
}
}
}
/**
* @param {StaffAction} action
* @param {number} perms
@ -130,27 +135,29 @@ export function createStaffMenu(rank = staffInfo.Rank) {
id: "staffmenu",
class: "dropdown-menu"
});
let actions = Object.keys(staffActions);
let adminActions = actions.filter(val => filterAction(staffActions[val], 3));
let modActions = actions.filter(val => filterAction(staffActions[val], 2));
let janitorActions = actions.filter(val => filterAction(staffActions[val], 1));
let adminActions = staffActions.filter(val => filterAction(val, 3));
let modActions = staffActions.filter(val => filterAction(val, 2));
let janitorActions = staffActions.filter(val => filterAction(val, 1));
$staffMenu.append(
menuItem(getAction("logout")),
menuItem(getAction("dashboard")));
$staffMenu.append(menuItem(staffActions["logout"], "logout"), menuItem(staffActions["dashboard"], "dashboard"))
$staffMenu.append(menuItem("Janitorial"));
for(const actionID of janitorActions) {
$staffMenu.append(menuItem(staffActions[actionID], actionID));
$staffMenu.append(menuItem("Janitorial", true));
for(const action of janitorActions) {
$staffMenu.append(menuItem(action));
}
if(rank < 2) return $staffMenu;
$staffMenu.append(menuItem("Moderation"));
for(const actionID of modActions) {
$staffMenu.append(menuItem(staffActions[actionID], actionID));
$staffMenu.append(menuItem("Moderation", true));
for(const action of modActions) {
$staffMenu.append(menuItem(action));
}
if(rank < 3) return $staffMenu;
$staffMenu.append(menuItem("Administration"));
for(const actionID of adminActions) {
$staffMenu.append(menuItem(staffActions[actionID], actionID));
$staffMenu.append(menuItem("Administration", true));
for(const action of adminActions) {
$staffMenu.append(menuItem(action));
}
$staffBtn = new TopBarButton("Staff", () => {
let exists = $(document).find($staffMenu).length > 0;

View file

@ -132,14 +132,9 @@ interface StaffAction {
}
/**
* The result of requestiong /manage?action=actions
* The result of requesting /manage?action=actions
*/
interface StaffActionMap {
/**
* The "id" of the action. Retreived by requesting /manage?action=<id>
*/
[id:string]: StaffAction;
}
declare var staffActions: StaffAction[];
/**
* The menu shown when the Staff button on the top bar is clicked

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -49,22 +49,31 @@ var (
// Action represents the functions accessed by staff members at /manage?action=<functionname>.
type Action struct {
// the string used when the user requests /manage?action=<id>
ID string `json:"id"`
// The text shown in the staff menu and the window title
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:"-"`
}
var actions = map[string]Action{
"cleanup": {
// var actions = map[string]Action{
var actions = []Action{
{
ID: "cleanup",
Title: "Cleanup",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -95,7 +104,8 @@ var actions = map[string]Action{
}
return outputStr, nil
}},
"config": {
{
ID: "config",
Title: "Configuration",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -307,7 +317,8 @@ var actions = map[string]Action{
errStr := "web-based configuration tool has been temporarily disabled"
return errStr, errors.New(errStr)
}},
"dashboard": {
{
ID: "dashboard",
Title: "Dashboard",
Permissions: JanitorPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -321,7 +332,8 @@ var actions = map[string]Action{
}
return dashBuffer.String(), nil
}},
"login": {
{
ID: "login",
Title: "Login",
Permissions: NoPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -350,7 +362,8 @@ var actions = map[string]Action{
}
return
}},
"logout": {
{
ID: "logout",
Title: "Logout",
Permissions: JanitorPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -360,7 +373,8 @@ var actions = map[string]Action{
http.SetCookie(writer, cookie)
return "Logged out successfully", nil
}},
"announcements": {
{
ID: "announcements",
Title: "Announcements",
Permissions: JanitorPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -384,7 +398,8 @@ var actions = map[string]Action{
}
return outputStr, nil
}},
"bans": {
{
ID: "bans",
Title: "Bans",
Permissions: ModPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) { //TODO whatever this does idk man
@ -473,14 +488,16 @@ var actions = map[string]Action{
outputStr += manageBansBuffer.String()
return outputStr, nil
}},
"staffinfo": {
{
ID: "staffinfo",
Permissions: NoPerms,
JSONoutput: AlwaysJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
staff, err := getCurrentFullStaff(request)
return staff, err
}},
"boards": {
{
ID: "boards",
Title: "Boards",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -661,7 +678,8 @@ var actions = map[string]Action{
gcsql.ResetBoardSectionArrays()
return
}},
"rebuildfront": {
{
ID: "rebuildfront",
Title: "Rebuild front page",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -670,7 +688,8 @@ var actions = map[string]Action{
}
return "Built front page successfully", building.BuildFrontPage()
}},
"rebuildall": {
{
ID: "rebuildall",
Title: "Rebuild everything",
Permissions: AdminPerms,
JSONoutput: OptionalJSON,
@ -729,7 +748,8 @@ var actions = map[string]Action{
}
return buildStr, nil
}},
"rebuildboard": {
{
ID: "rebuildboard",
Title: "Rebuild board",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -749,7 +769,8 @@ var actions = map[string]Action{
// Message: fmt.Sprintf("/%s/ is not a board"),
// }
}},
"rebuildboards": {
{
ID: "rebuildboards",
Title: "Rebuild boards",
Permissions: AdminPerms,
JSONoutput: OptionalJSON,
@ -765,7 +786,8 @@ var actions = map[string]Action{
}
return "Boards built successfully", building.BuildBoards(false)
}},
"reparsehtml": {
{
ID: "reparsehtml",
Title: "Reparse HTML",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -800,7 +822,8 @@ var actions = map[string]Action{
outputStr += "Done building boards<hr />"
return outputStr, nil
}},
"recentposts": {
{
ID: "recentposts",
Title: "Recent posts",
Permissions: JanitorPerms,
JSONoutput: OptionalJSON,
@ -846,7 +869,8 @@ var actions = map[string]Action{
outputStr += "</table>"
return
}},
"postinfo": {
{
ID: "postinfo",
Title: "Post info",
Permissions: ModPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
@ -859,7 +883,8 @@ var actions = map[string]Action{
jsonStr, _ := gcutil.MarshalJSON(post, false)
return jsonStr, nil
}},
"staff": {
{
ID: "staff",
Title: "Staff",
Permissions: AdminPerms,
JSONoutput: OptionalJSON,
@ -916,7 +941,8 @@ var actions = map[string]Action{
outputStr += staffBuffer.String()
return outputStr, nil
}},
"tempposts": {
{
ID: "tempposts",
Title: "Temporary posts lists",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {

View file

@ -54,66 +54,63 @@ func CallManageFunction(writer http.ResponseWriter, request *http.Request) {
return
}
wantsJSON := isRequestingJSON(request)
action := request.FormValue("action")
actionID := request.FormValue("action")
staffRank := GetStaffRank(request)
var managePageBuffer bytes.Buffer
if action == "" {
if actionID == "" {
if staffRank == NoPerms {
action = "login"
actionID = "login"
} else {
action = "dashboard"
actionID = "dashboard"
}
}
handler, ok := actions[action]
if !ok {
var managePageBuffer bytes.Buffer
action := getAction(actionID, staffRank)
if action == nil {
if wantsJSON {
serveError(writer, "notfound", action, "action not found", wantsJSON)
serveError(writer, "notfound", actionID, "action not found", wantsJSON)
} else {
serverutil.ServeNotFound(writer, request)
}
return
}
if staffRank == NoPerms && handler.Permissions > NoPerms {
handler = actions["login"]
} else if staffRank < handler.Permissions {
if staffRank < action.Permissions {
writer.WriteHeader(403)
staffName, _ := getCurrentStaff(request)
gclog.Printf(gclog.LStaffLog,
"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", wantsJSON || (handler.JSONoutput > NoJSON))
actionID, staffName)
serveError(writer, "permission", actionID, "You do not have permission to access this page", wantsJSON || (action.JSONoutput > NoJSON))
return
}
var output interface{}
if wantsJSON && handler.JSONoutput == NoJSON {
if wantsJSON && action.JSONoutput == NoJSON {
output = nil
err = &ErrStaffAction{
ErrorField: "nojson",
Action: action,
Action: actionID,
Message: "Requested mod page does not have a JSON output option",
}
} else {
output, err = handler.Callback(writer, request, wantsJSON)
output, err = action.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.JSONoutput > NoJSON))
"Error accessing manage page %s by %s: %s", actionID, staffName, err.Error())
serveError(writer, "actionerror", actionID, err.Error(), wantsJSON || (action.JSONoutput > NoJSON))
return
}
if handler.JSONoutput == AlwaysJSON || wantsJSON {
if action.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)
if err != nil {
serveError(writer, "error", action, err.Error(), true)
serveError(writer, "error", actionID, err.Error(), true)
return
}
serverutil.MinifyWriter(writer, []byte(outputJSON), "application/json")

View file

@ -93,24 +93,38 @@ func GetStaffRank(request *http.Request) int {
return staff.Rank
}
// returns the action by its ID, or nil if it doesn't exist
func getAction(id string, rank int) *Action {
for a, _ := range actions {
if rank == NoPerms && actions[a].Permissions > NoPerms {
id = "login"
}
if actions[a].ID == id {
return &actions[a]
}
}
return nil
}
func init() {
actions["actions"] = Action{
actions = append(actions, Action{
ID: "actions",
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{}
actionArr := []Action{}
for id, action := range actions {
for _, action := range actions {
if rank < action.Permissions || action.Permissions == NoPerms {
continue
}
actionMap[id] = action
actionArr = append(actionArr, action)
}
return actionMap, nil
return actionArr, nil
}