From 9179eb9711cde38dfb40963e2e4a8804feeb2261 Mon Sep 17 00:00:00 2001 From: Azareal Date: Thu, 18 Apr 2019 11:00:39 +1000 Subject: [PATCH] The moderation logs can now be localised. Error pages which call CustomError should now stick on the theme the user chose rather than the global fallback theme. Move the theme fetching logic out of userCheck and panelUserCheck and into it's own function. Split prepResources out of userCheck, so that errors can make use of it. Fixed a bug where no scripts or stylesheets would run on error pages. Fixed a bug where unknown topics would point to /user/ rather than /topic/ Added the panel_logs_moderation_action_topic_stick phrase. Added the panel_logs_moderation_action_topic_unstick phrase. Added the panel_logs_moderation_action_topic_lock phrase. Added the panel_logs_moderation_action_topic_unlock phrase. Added the panel_logs_moderation_action_topic_delete phrase. Added the panel_logs_moderation_action_topic_move phrase. Added the panel_logs_moderation_action_topic_move_dest phrase. Added the panel_logs_moderation_action_topic_unknown phrase. Added the panel_logs_moderation_action_reply_delete phrase. Added the panel_logs_moderation_action_user_ban phrase. Added the panel_logs_moderation_action_user_unban phrase. Added the panel_logs_moderation_action_user_activate phrase. Added the panel_logs_moderation_action_unknown phrase. Added the user_unknown phrase. --- common/errors.go | 10 ++++++++-- common/routes_common.go | 32 +++++++++++++++--------------- langs/english.json | 17 ++++++++++++++++ routes/panel/logs.go | 43 ++++++++++++++++------------------------- routes/topic.go | 2 +- 5 files changed, 59 insertions(+), 45 deletions(-) diff --git a/common/errors.go b/common/errors.go index 6d095eac..f0485dff 100644 --- a/common/errors.go +++ b/common/errors.go @@ -129,12 +129,14 @@ func errorHeader(w http.ResponseWriter, user User, title string) *Header { header := DefaultHeader(w, user) header.Title = title header.Zone = "error" + prepResources(&user, header, header.Theme) return header } // TODO: Dump the request? // InternalError is the main function for handling internal errors, while simultaneously printing out a page for the end-user to let them know that *something* has gone wrong // ? - Add a user parameter? +// ! Do not call CustomError here or we might get an error loop func InternalError(err error, w http.ResponseWriter, r *http.Request) RouteError { w.WriteHeader(500) pi := ErrorPage{errorHeader(w, GuestUser, phrases.GetErrorPhrase("internal_error_title")), phrases.GetErrorPhrase("internal_error_body")} @@ -188,6 +190,7 @@ func SilentInternalErrorXML(err error, w http.ResponseWriter, r *http.Request) R return HandledRouteError() } +// ! Do not call CustomError here otherwise we might get an error loop func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError { w.WriteHeader(500) pi := ErrorPage{errorHeader(w, GuestUser, phrases.GetErrorPhrase("error_title")), errmsg} @@ -342,9 +345,12 @@ func NotFoundJSQ(w http.ResponseWriter, r *http.Request, header *Header, js bool } // CustomError lets us make custom error types which aren't covered by the generic functions above -func CustomError(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, header *Header, user User) RouteError { +func CustomError(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, header *Header, user User) (rerr RouteError) { if header == nil { - header = DefaultHeader(w, user) + header, rerr = UserCheck(w, r, &user) + if rerr != nil { + header = errorHeader(w, user, errtitle) + } } header.Title = errtitle header.Zone = "error" diff --git a/common/routes_common.go b/common/routes_common.go index 8c7ee2c8..c235d903 100644 --- a/common/routes_common.go +++ b/common/routes_common.go @@ -95,18 +95,7 @@ func cascadeForumPerms(fperms *ForumPerms, user *User) { // Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with // TODO: Do a panel specific theme? func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Header, stats PanelStats, rerr RouteError) { - var theme = &Theme{Name: ""} - cookie, err := r.Cookie("current_theme") - if err == nil { - inTheme, ok := Themes[html.EscapeString(cookie.Value)] - if ok && !theme.HideFromThemes { - theme = inTheme - } - } - if theme.Name == "" { - theme = Themes[DefaultThemeBox.Load().(string)] - } - + theme := getTheme(r) header = &Header{ Site: Site, Settings: SettingBox.Load().(SettingMap), @@ -186,8 +175,7 @@ func simpleUserCheck(w http.ResponseWriter, r *http.Request, user *User) (header }, nil } -// TODO: Add the ability for admins to restrict certain themes to certain groups? -func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Header, rerr RouteError) { +func getTheme(r *http.Request) *Theme { var theme = &Theme{Name: ""} cookie, err := r.Cookie("current_theme") @@ -201,6 +189,13 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Head theme = Themes[DefaultThemeBox.Load().(string)] } + return theme +} + +// TODO: Add the ability for admins to restrict certain themes to certain groups? +// ! Be careful about firing errors off here as CustomError uses this +func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Header, rerr RouteError) { + theme := getTheme(r) header = &Header{ Site: Site, Settings: SettingBox.Load().(SettingMap), @@ -220,13 +215,20 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Head if user.Loggedin && !user.Active { header.AddNotice("account_inactive") } + // An optimisation so we don't populate StartedAt for users who shouldn't see the stat anyway // ? - Should we only show this in debug mode? It might be useful for detecting issues in production, if we show it there as-well if user.IsAdmin { header.StartedAt = time.Now() } + prepResources(user,header,theme) + return header, nil +} + +func prepResources(user *User, header *Header, theme *Theme) { header.AddSheet(theme.Name + "/main.css") + if len(theme.Resources) > 0 { rlist := theme.Resources for _, resource := range rlist { @@ -269,8 +271,6 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Head addPreScript("topic_c_edit_post") addPreScript("topic_c_attach_item") } - - return header, nil } func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) { diff --git a/langs/english.json b/langs/english.json index 572857b9..252ced77 100644 --- a/langs/english.json +++ b/langs/english.json @@ -903,7 +903,24 @@ "panel_logs_registration_attempt":"Attempt", "panel_logs_registration_email":"email", "panel_logs_registration_reason":"reason", + "panel_logs_moderation_head":"Mod Action Logs", + "panel_logs_moderation_action_topic_stick":"%s was pinned by %s", + "panel_logs_moderation_action_topic_unstick":"%s was unpinned by %s", + "panel_logs_moderation_action_topic_lock":"%s was locked by %s", + "panel_logs_moderation_action_topic_unlock":"%s was reopened by %s", + "panel_logs_moderation_action_topic_delete":"Topic #%d was deleted by %s", + "panel_logs_moderation_action_topic_move":"%s was moved by %s", + "panel_logs_moderation_action_topic_move_dest":"%s was moved to %s by %s", + "panel_logs_moderation_action_topic_unknown":"Unknown action '%s' on elementType '%s' by %s", + "panel_logs_moderation_action_reply_delete":"A reply in %s was deleted by %s", + "panel_logs_moderation_action_user_ban":"%s was banned by %s", + "panel_logs_moderation_action_user_unban":"%s was unbanned by %s", + "panel_logs_moderation_action_user_activate":"%s was activated by %s", + "panel_logs_moderation_action_unknown":"Unknown action '%s' on elementType '%s' by %s", + + "user_unknown":"Unknown", + "panel_logs_administration_head":"Admin Action Logs", "panel_plugins_head":"Plugins", diff --git a/routes/panel/logs.go b/routes/panel/logs.go index 6e6c6e55..699d0c58 100644 --- a/routes/panel/logs.go +++ b/routes/panel/logs.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/Azareal/Gosora/common" + "github.com/Azareal/Gosora/common/phrases" ) // TODO: Link the usernames for successful registrations to the profiles @@ -37,46 +38,44 @@ func LogsRegs(w http.ResponseWriter, r *http.Request, user common.User) common.R } // TODO: Log errors when something really screwy is going on? +// TODO: Base the slugs on the localised usernames? func handleUnknownUser(user *common.User, err error) *common.User { if err != nil { - return &common.User{Name: "Unknown", Link: common.BuildProfileURL("unknown", 0)} + return &common.User{Name: phrases.GetTmplPhrase("user_unknown"), Link: common.BuildProfileURL("unknown", 0)} } return user } func handleUnknownTopic(topic *common.Topic, err error) *common.Topic { if err != nil { - return &common.Topic{Title: "Unknown", Link: common.BuildProfileURL("unknown", 0)} + return &common.Topic{Title: phrases.GetTmplPhrase("user_unknown"), Link: common.BuildTopicURL("unknown", 0)} } return topic } // TODO: Move the log building logic into /common/ and it's own abstraction -// TODO: Localise this func topicElementTypeAction(action string, elementType string, elementID int, actor *common.User, topic *common.Topic) (out string) { if action == "delete" { - return fmt.Sprintf("Topic #%d was deleted by %s", elementID, actor.Link, actor.Name) + return phrases.GetTmplPhrasef("panel_logs_moderation_action_topic_delete", elementID, actor.Link, actor.Name) } + var tbit string aarr := strings.Split(action, "-") switch aarr[0] { - case "lock": - out = "%s was locked by %s" - case "unlock": - out = "%s was reopened by %s" - case "stick": - out = "%s was pinned by %s" - case "unstick": - out = "%s was unpinned by %s" + case "lock","unlock","stick","unstick": + tbit = aarr[0] case "move": if len(aarr) == 2 { fid, _ := strconv.Atoi(aarr[1]) forum, err := common.Forums.Get(fid) if err == nil { - return fmt.Sprintf("%s was moved to %s by %s", topic.Link, topic.Title, forum.Link, forum.Name, actor.Link, actor.Name) + return phrases.GetTmplPhrasef("panel_logs_moderation_action_topic_move_dest", topic.Link, topic.Title, forum.Link, forum.Name, actor.Link, actor.Name) } } - out = "%s was moved by %s" // TODO: Add where it was moved to, we'll have to change the source data for that, most likely? Investigate that and try to work this in + tbit = "move" default: - return fmt.Sprintf("Unknown action '%s' on elementType '%s' by %s", action, elementType, actor.Link, actor.Name) + return phrases.GetTmplPhrasef("panel_logs_moderation_action_topic_unknown", action, elementType, actor.Link, actor.Name) + } + if tbit != "" { + return phrases.GetTmplPhrasef("panel_logs_moderation_action_topic_"+tbit, topic.Link, topic.Title, actor.Link, actor.Name) } return fmt.Sprintf(out, topic.Link, topic.Title, actor.Link, actor.Name) } @@ -88,24 +87,16 @@ func modlogsElementType(action string, elementType string, elementID int, actor out = topicElementTypeAction(action, elementType, elementID, actor, topic) case "user": targetUser := handleUnknownUser(common.Users.Get(elementID)) - switch action { - case "ban": - out = "%s was banned by %s" - case "unban": - out = "%s was unbanned by %s" - case "activate": - out = "%s was activated by %s" - } - out = fmt.Sprintf(out, targetUser.Link, targetUser.Name, actor.Link, actor.Name) + out = phrases.GetTmplPhrasef("panel_logs_moderation_action_user_"+action, targetUser.Link, targetUser.Name, actor.Link, actor.Name) case "reply": if action == "delete" { topic := handleUnknownTopic(common.TopicByReplyID(elementID)) - out = fmt.Sprintf("A reply in %s was deleted by %s", topic.Link, topic.Title, actor.Link, actor.Name) + out = phrases.GetTmplPhrasef("panel_logs_moderation_action_reply_delete", topic.Link, topic.Title, actor.Link, actor.Name) } } if out == "" { - out = fmt.Sprintf("Unknown action '%s' on elementType '%s' by %s", action, elementType, actor.Link, actor.Name) + out = phrases.GetTmplPhrasef("panel_logs_moderation_action_unknown", action, elementType, actor.Link, actor.Name) } return out } diff --git a/routes/topic.go b/routes/topic.go index d42dbdba..234e0910 100644 --- a/routes/topic.go +++ b/routes/topic.go @@ -51,7 +51,7 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, header // Get the topic... topic, err := common.GetTopicUser(&user, tid) if err == sql.ErrNoRows { - return common.NotFound(w, r, nil) // TODO: Can we add a simplified invocation of headerVars here? This is likely to be an extremely common NotFound + return common.NotFound(w, r, nil) // TODO: Can we add a simplified invocation of header here? This is likely to be an extremely common NotFound } else if err != nil { return common.InternalError(err, w, r) }