gosora/routes/panel/logs.go
Azareal 0c1d6f0516 Add CreateProfileReply and AutoEmbed group permissions.
Log profile reply deletions in the moderator log.
Split the global permissions in the UI to make them easier to manage.
Experiment with showing group ID in group edit header.
Avoid loading groups multiple times for the same profile reply.

Initialise disabled IP log points to empty string rather than 0.

Add CreateProfileReply perm phrase.
Add AutoEmbed perm phrase.
Add panel_group_mod_permissions phrase.
Add panel_logs_mod_action_profile_reply_delete phrase.
2020-02-04 21:47:03 +10:00

222 lines
8.4 KiB
Go

package panel
import (
"fmt"
"html/template"
"net/http"
"strconv"
"strings"
c "github.com/Azareal/Gosora/common"
p "github.com/Azareal/Gosora/common/phrases"
)
// TODO: Link the usernames for successful registrations to the profiles
func LogsRegs(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
basePage, ferr := buildBasePage(w, r, &user, "registration_logs", "logs")
if ferr != nil {
return ferr
}
logCount := c.RegLogs.Count()
page, _ := strconv.Atoi(r.FormValue("page"))
perPage := 12
offset, page, lastPage := c.PageOffset(logCount, page, perPage)
logs, err := c.RegLogs.GetOffset(offset, perPage)
if err != nil {
return c.InternalError(err, w, r)
}
llist := make([]c.PageRegLogItem, len(logs))
for index, log := range logs {
llist[index] = c.PageRegLogItem{log, strings.Replace(strings.TrimSuffix(log.FailureReason, "|"), "|", " | ", -1)}
}
pageList := c.Paginate(page, lastPage, 5)
pi := c.PanelRegLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}}
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_reglogs", pi})
}
// TODO: Log errors when something really screwy is going on?
// TODO: Base the slugs on the localised usernames?
func handleUnknownUser(u *c.User, err error) *c.User {
if err != nil {
return &c.User{Name: p.GetTmplPhrase("user_unknown"), Link: c.BuildProfileURL("unknown", 0)}
}
return u
}
func handleUnknownTopic(t *c.Topic, err error) *c.Topic {
if err != nil {
return &c.Topic{Title: p.GetTmplPhrase("topic_unknown"), Link: c.BuildTopicURL("unknown", 0)}
}
return t
}
// TODO: Move the log building logic into /common/ and it's own abstraction
func topicElementTypeAction(action, elementType string, elementID int, actor *c.User, topic *c.Topic) (out string) {
if action == "delete" {
return p.GetTmplPhrasef("panel_logs_mod_action_topic_delete", elementID, actor.Link, actor.Name)
}
var tbit string
aarr := strings.Split(action, "-")
switch aarr[0] {
case "lock", "unlock", "stick", "unstick":
tbit = aarr[0]
case "move":
if len(aarr) == 2 {
fid, _ := strconv.Atoi(aarr[1])
forum, err := c.Forums.Get(fid)
if err == nil {
return p.GetTmplPhrasef("panel_logs_mod_action_topic_move_dest", topic.Link, topic.Title, forum.Link, forum.Name, actor.Link, actor.Name)
}
}
tbit = "move"
default:
return p.GetTmplPhrasef("panel_logs_mod_action_topic_unknown", action, elementType, actor.Link, actor.Name)
}
if tbit != "" {
return p.GetTmplPhrasef("panel_logs_mod_action_topic_"+tbit, topic.Link, topic.Title, actor.Link, actor.Name)
}
return fmt.Sprintf(out, topic.Link, topic.Title, actor.Link, actor.Name)
}
func modlogsElementType(action, elementType string, elementID int, actor *c.User) (out string) {
switch elementType {
case "topic":
topic := handleUnknownTopic(c.Topics.Get(elementID))
out = topicElementTypeAction(action, elementType, elementID, actor, topic)
case "user":
targetUser := handleUnknownUser(c.Users.Get(elementID))
out = p.GetTmplPhrasef("panel_logs_mod_action_user_"+action, targetUser.Link, targetUser.Name, actor.Link, actor.Name)
case "reply":
if action == "delete" {
topic := handleUnknownTopic(c.TopicByReplyID(elementID))
out = p.GetTmplPhrasef("panel_logs_mod_action_reply_delete", topic.Link, topic.Title, actor.Link, actor.Name)
}
case "profile-reply":
if action == "delete" {
// TODO: Optimise this
var profile *c.User
profileReply, err := c.Prstore.Get(elementID)
if err != nil {
profile = &c.User{Name: p.GetTmplPhrase("user_unknown"), Link: c.BuildProfileURL("unknown", 0)}
} else {
profile = handleUnknownUser(c.Users.Get(profileReply.ParentID))
}
out = p.GetTmplPhrasef("panel_logs_mod_action_profile_reply_delete", profile.Link, profile.Name, actor.Link, actor.Name)
}
}
if out == "" {
out = p.GetTmplPhrasef("panel_logs_mod_action_unknown", action, elementType, actor.Link, actor.Name)
}
return out
}
func adminlogsElementType(action, elementType string, elementID int, actor *c.User, extra string) (out string) {
switch elementType {
// TODO: Record more detail for this, e.g. which field/s was changed
case "user":
targetUser := handleUnknownUser(c.Users.Get(elementID))
out = p.GetTmplPhrasef("panel_logs_admin_action_user_"+action, targetUser.Link, targetUser.Name, actor.Link, actor.Name)
case "group":
g, err := c.Groups.Get(elementID)
if err != nil {
g = &c.Group{Name: p.GetTmplPhrase("group_unknown")}
}
out = p.GetTmplPhrasef("panel_logs_admin_action_group_"+action, "/panel/groups/edit/"+strconv.Itoa(g.ID), g.Name, actor.Link, actor.Name)
case "group_promotion":
out = p.GetTmplPhrasef("panel_logs_admin_action_group_promotion_"+action, actor.Link, actor.Name)
case "forum":
f, err := c.Forums.Get(elementID)
if err != nil {
f = &c.Forum{Name: p.GetTmplPhrase("forum_unknown")}
}
if action == "reorder" {
out = p.GetTmplPhrasef("panel_logs_admin_action_forum_reorder", actor.Link, actor.Name)
} else {
out = p.GetTmplPhrasef("panel_logs_admin_action_forum_"+action, "/panel/forums/edit/"+strconv.Itoa(f.ID), f.Name, actor.Link, actor.Name)
}
case "page":
pp, err := c.Pages.Get(elementID)
if err != nil {
pp = &c.CustomPage{Name: p.GetTmplPhrase("page_unknown")}
}
out = p.GetTmplPhrasef("panel_logs_admin_action_page_"+action, "/panel/pages/edit/"+strconv.Itoa(pp.ID), pp.Name, actor.Link, actor.Name)
case "setting":
s, err := c.SettingBox.Load().(c.SettingMap).BypassGet(action)
if err != nil {
s = &c.Setting{Name: p.GetTmplPhrase("setting_unknown")}
}
out = p.GetTmplPhrasef("panel_logs_admin_action_setting_edit", "/panel/settings/edit/"+s.Name, s.Name, actor.Link, actor.Name)
case "word_filter":
out = p.GetTmplPhrasef("panel_logs_admin_action_word_filter_"+action, actor.Link, actor.Name)
case "menu":
if action == "suborder" {
out = p.GetTmplPhrasef("panel_logs_admin_action_menu_suborder", elementID, actor.Link, actor.Name)
}
case "menu_item":
out = p.GetTmplPhrasef("panel_logs_admin_action_menu_item_"+action, "/panel/themes/menus/item/edit/"+strconv.Itoa(elementID), elementID, actor.Link, actor.Name)
case "widget":
out = p.GetTmplPhrasef("panel_logs_admin_action_widget_"+action, "/panel/themes/widgets/", elementID, actor.Link, actor.Name)
case "plugin":
out = p.GetTmplPhrasef("panel_logs_admin_action_plugin_"+action, extra, actor.Link, actor.Name)
case "backup":
out = p.GetTmplPhrasef("panel_logs_admin_action_backup_"+action, actor.Link, actor.Name)
}
if out == "" {
out = p.GetTmplPhrasef("panel_logs_admin_action_unknown", action, elementType, actor.Link, actor.Name)
}
return out
}
func LogsMod(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
basePage, ferr := buildBasePage(w, r, &user, "mod_logs", "logs")
if ferr != nil {
return ferr
}
page, _ := strconv.Atoi(r.FormValue("page"))
perPage := 12
offset, page, lastPage := c.PageOffset(c.ModLogs.Count(), page, perPage)
logs, err := c.ModLogs.GetOffset(offset, perPage)
if err != nil {
return c.InternalError(err, w, r)
}
llist := make([]c.PageLogItem, len(logs))
for index, log := range logs {
actor := handleUnknownUser(c.Users.Get(log.ActorID))
action := modlogsElementType(log.Action, log.ElementType, log.ElementID, actor)
llist[index] = c.PageLogItem{Action: template.HTML(action), IP: log.IP, DoneAt: log.DoneAt}
}
pageList := c.Paginate(page, lastPage, 5)
pi := c.PanelLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}}
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_modlogs", pi})
}
func LogsAdmin(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
basePage, ferr := buildBasePage(w, r, &user, "admin_logs", "logs")
if ferr != nil {
return ferr
}
page, _ := strconv.Atoi(r.FormValue("page"))
perPage := 12
offset, page, lastPage := c.PageOffset(c.AdminLogs.Count(), page, perPage)
logs, err := c.AdminLogs.GetOffset(offset, perPage)
if err != nil {
return c.InternalError(err, w, r)
}
llist := make([]c.PageLogItem, len(logs))
for index, log := range logs {
actor := handleUnknownUser(c.Users.Get(log.ActorID))
action := adminlogsElementType(log.Action, log.ElementType, log.ElementID, actor, log.Extra)
llist[index] = c.PageLogItem{Action: template.HTML(action), IP: log.IP, DoneAt: log.DoneAt}
}
pageList := c.Paginate(page, lastPage, 5)
pi := c.PanelLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}}
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_adminlogs", pi})
}