Finish up the adminlogs.
Throw an error instead of updating a word filter that doesn't exist. Track a bit of extra data for word filter updates. Shorten the prefixes of the adminlog phrases from panel_logs_administration_ to panel_logs_admin_ Add a bunch of new adminlog phrases. Tweak the word filter phrases. Add the extra column to the moderation_logs and administration_logs tables. You need to run the updater / patcher for this commit.
This commit is contained in:
parent
d03c0faf42
commit
1044518e74
|
@ -167,6 +167,7 @@ func createTables(adapter qgen.Adapter) (err error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Should we add a users prefix to this table to fit the "unofficial convention"?
|
// TODO: Should we add a users prefix to this table to fit the "unofficial convention"?
|
||||||
|
// TODO: Add an autoincrement key?
|
||||||
createTable("emails", "", "",
|
createTable("emails", "", "",
|
||||||
[]tC{
|
[]tC{
|
||||||
tC{"email", "varchar", 200, false, false, ""},
|
tC{"email", "varchar", 200, false, false, ""},
|
||||||
|
@ -620,6 +621,7 @@ func createTables(adapter qgen.Adapter) (err error) {
|
||||||
tC{"ipaddress", "varchar", 200, false, false, ""},
|
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
tC{"actorID", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
tC{"actorID", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
tC{"doneAt", "datetime", 0, false, false, ""},
|
tC{"doneAt", "datetime", 0, false, false, ""},
|
||||||
|
tC{"extra", "text", 0, false, false, ""},
|
||||||
}, nil,
|
}, nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -631,6 +633,7 @@ func createTables(adapter qgen.Adapter) (err error) {
|
||||||
tC{"ipaddress", "varchar", 200, false, false, ""},
|
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
tC{"actorID", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
tC{"actorID", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
tC{"doneAt", "datetime", 0, false, false, ""},
|
tC{"doneAt", "datetime", 0, false, false, ""},
|
||||||
|
tC{"extra", "text", 0, false, false, ""},
|
||||||
}, nil,
|
}, nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Azareal/Gosora/query_gen"
|
qgen "github.com/Azareal/Gosora/query_gen"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ModLogs LogStore
|
var ModLogs LogStore
|
||||||
|
@ -17,12 +17,14 @@ type LogItem struct {
|
||||||
IP string
|
IP string
|
||||||
ActorID int
|
ActorID int
|
||||||
DoneAt string
|
DoneAt string
|
||||||
|
Extra string
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogStore interface {
|
type LogStore interface {
|
||||||
Create(action string, elementID int, elementType string, ip string, actorID int) (err error)
|
Create(action string, elementID int, elementType string, ip string, actorID int) (err error)
|
||||||
|
CreateExtra(action string, elementID int, elementType string, ip string, actorID int, extra string) (err error)
|
||||||
Count() int
|
Count() int
|
||||||
GetOffset(offset int, perPage int) (logs []LogItem, err error)
|
GetOffset(offset, perPage int) (logs []LogItem, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SQLModLogStore struct {
|
type SQLModLogStore struct {
|
||||||
|
@ -34,15 +36,19 @@ type SQLModLogStore struct {
|
||||||
func NewModLogStore(acc *qgen.Accumulator) (*SQLModLogStore, error) {
|
func NewModLogStore(acc *qgen.Accumulator) (*SQLModLogStore, error) {
|
||||||
ml := "moderation_logs"
|
ml := "moderation_logs"
|
||||||
return &SQLModLogStore{
|
return &SQLModLogStore{
|
||||||
create: acc.Insert(ml).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(),
|
create: acc.Insert(ml).Columns("action, elementID, elementType, ipaddress, actorID, doneAt, extra").Fields("?,?,?,?,?,UTC_TIMESTAMP(),?").Prepare(),
|
||||||
count: acc.Count(ml).Prepare(),
|
count: acc.Count(ml).Prepare(),
|
||||||
getOffset: acc.Select(ml).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(),
|
getOffset: acc.Select(ml).Columns("action, elementID, elementType, ipaddress, actorID, doneAt, extra").Orderby("doneAt DESC").Limit("?,?").Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make a store for this?
|
// TODO: Make a store for this?
|
||||||
func (s *SQLModLogStore) Create(action string, elementID int, elementType string, ip string, actorID int) (err error) {
|
func (s *SQLModLogStore) Create(action string, elementID int, elementType string, ip string, actorID int) (err error) {
|
||||||
_, err = s.create.Exec(action, elementID, elementType, ip, actorID)
|
return s.CreateExtra(action, elementID, elementType, ip, actorID, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SQLModLogStore) CreateExtra(action string, elementID int, elementType string, ip string, actorID int, extra string) (err error) {
|
||||||
|
_, err = s.create.Exec(action, elementID, elementType, ip, actorID, extra)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +64,7 @@ func buildLogList(rows *sql.Rows) (logs []LogItem, err error) {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var l LogItem
|
var l LogItem
|
||||||
var doneAt time.Time
|
var doneAt time.Time
|
||||||
err := rows.Scan(&l.Action, &l.ElementID, &l.ElementType, &l.IP, &l.ActorID, &doneAt)
|
err := rows.Scan(&l.Action, &l.ElementID, &l.ElementType, &l.IP, &l.ActorID, &doneAt, &l.Extra)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logs, err
|
return logs, err
|
||||||
}
|
}
|
||||||
|
@ -68,7 +74,7 @@ func buildLogList(rows *sql.Rows) (logs []LogItem, err error) {
|
||||||
return logs, rows.Err()
|
return logs, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLModLogStore) GetOffset(offset int, perPage int) (logs []LogItem, err error) {
|
func (s *SQLModLogStore) GetOffset(offset, perPage int) (logs []LogItem, err error) {
|
||||||
rows, err := s.getOffset.Query(offset, perPage)
|
rows, err := s.getOffset.Query(offset, perPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logs, err
|
return logs, err
|
||||||
|
@ -86,15 +92,19 @@ type SQLAdminLogStore struct {
|
||||||
func NewAdminLogStore(acc *qgen.Accumulator) (*SQLAdminLogStore, error) {
|
func NewAdminLogStore(acc *qgen.Accumulator) (*SQLAdminLogStore, error) {
|
||||||
al := "administration_logs"
|
al := "administration_logs"
|
||||||
return &SQLAdminLogStore{
|
return &SQLAdminLogStore{
|
||||||
create: acc.Insert(al).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(),
|
create: acc.Insert(al).Columns("action, elementID, elementType, ipaddress, actorID, doneAt, extra").Fields("?,?,?,?,?,UTC_TIMESTAMP(),?").Prepare(),
|
||||||
count: acc.Count(al).Prepare(),
|
count: acc.Count(al).Prepare(),
|
||||||
getOffset: acc.Select(al).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(),
|
getOffset: acc.Select(al).Columns("action, elementID, elementType, ipaddress, actorID, doneAt, extra").Orderby("doneAt DESC").Limit("?,?").Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make a store for this?
|
// TODO: Make a store for this?
|
||||||
func (s *SQLAdminLogStore) Create(action string, elementID int, elementType string, ip string, actorID int) (err error) {
|
func (s *SQLAdminLogStore) Create(action string, elementID int, elementType string, ip string, actorID int) (err error) {
|
||||||
_, err = s.create.Exec(action, elementID, elementType, ip, actorID)
|
return s.CreateExtra(action, elementID, elementType, ip, actorID, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SQLAdminLogStore) CreateExtra(action string, elementID int, elementType string, ip string, actorID int, extra string) (err error) {
|
||||||
|
_, err = s.create.Exec(action, elementID, elementType, ip, actorID, extra)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +116,7 @@ func (s *SQLAdminLogStore) Count() (count int) {
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLAdminLogStore) GetOffset(offset int, perPage int) (logs []LogItem, err error) {
|
func (s *SQLAdminLogStore) GetOffset(offset, perPage int) (logs []LogItem, err error) {
|
||||||
rows, err := s.getOffset.Query(offset, perPage)
|
rows, err := s.getOffset.Query(offset, perPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logs, err
|
return logs, err
|
||||||
|
|
|
@ -321,11 +321,11 @@ type Plugin struct {
|
||||||
Installable bool
|
Installable bool
|
||||||
Installed bool
|
Installed bool
|
||||||
|
|
||||||
Init func(plugin *Plugin) error
|
Init func(pl *Plugin) error
|
||||||
Activate func(plugin *Plugin) error
|
Activate func(pl *Plugin) error
|
||||||
Deactivate func(plugin *Plugin) // TODO: We might want to let this return an error?
|
Deactivate func(pl *Plugin) // TODO: We might want to let this return an error?
|
||||||
Install func(plugin *Plugin) error
|
Install func(pl *Plugin) error
|
||||||
Uninstall func(plugin *Plugin) error // TODO: I'm not sure uninstall is implemented
|
Uninstall func(pl *Plugin) error // TODO: I'm not sure uninstall is implemented
|
||||||
|
|
||||||
Hooks map[string]int
|
Hooks map[string]int
|
||||||
Data interface{} // Usually used for hosting the VMs / reusable elements of non-native plugins
|
Data interface{} // Usually used for hosting the VMs / reusable elements of non-native plugins
|
||||||
|
|
|
@ -470,7 +470,7 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
for _, filter := range wordFilters {
|
for _, filter := range wordFilters {
|
||||||
msg = strings.Replace(msg, filter.Find, filter.Replacement, -1)
|
msg = strings.Replace(msg, filter.Find, filter.Replace, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for URLs, mentions and hashlinks in the messages...
|
// Search for URLs, mentions and hashlinks in the messages...
|
||||||
|
|
|
@ -50,40 +50,40 @@ type Widget struct {
|
||||||
|
|
||||||
Literal bool
|
Literal bool
|
||||||
TickMask atomic.Value
|
TickMask atomic.Value
|
||||||
InitFunc func(widget *Widget, schedule *WidgetScheduler) error
|
InitFunc func(w *Widget, schedule *WidgetScheduler) error
|
||||||
ShutdownFunc func(widget *Widget) error
|
ShutdownFunc func(w *Widget) error
|
||||||
BuildFunc func(widget *Widget, hvars interface{}) (string, error)
|
BuildFunc func(w *Widget, hvars interface{}) (string, error)
|
||||||
TickFunc func(widget *Widget) error
|
TickFunc func(w *Widget) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *Widget) Delete() error {
|
func (w *Widget) Delete() error {
|
||||||
_, err := widgetStmts.delete.Exec(widget.ID)
|
_, err := widgetStmts.delete.Exec(w.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload the dock
|
// Reload the dock
|
||||||
// TODO: Better synchronisation
|
// TODO: Better synchronisation
|
||||||
Widgets.delete(widget.ID)
|
Widgets.delete(w.ID)
|
||||||
widgets, err := getDockWidgets(widget.Side)
|
widgets, err := getDockWidgets(w.Side)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
setDock(widget.Side, widgets)
|
setDock(w.Side, widgets)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *Widget) Copy() (owidget *Widget) {
|
func (w *Widget) Copy() (owidget *Widget) {
|
||||||
owidget = &Widget{}
|
owidget = &Widget{}
|
||||||
*owidget = *widget
|
*owidget = *w
|
||||||
return owidget
|
return owidget
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Test this
|
// TODO: Test this
|
||||||
// TODO: Add support for zone:id. Perhaps, carry a ZoneID property around in *Header? It might allow some weirdness like frontend[5] which matches any zone with an ID of 5 but it would be a tad faster than verifying each zone, although it might be problematic if users end up relying on this behaviour for areas which don't pass IDs to the widgets system but *probably* should
|
// TODO: Add support for zone:id. Perhaps, carry a ZoneID property around in *Header? It might allow some weirdness like frontend[5] which matches any zone with an ID of 5 but it would be a tad faster than verifying each zone, although it might be problematic if users end up relying on this behaviour for areas which don't pass IDs to the widgets system but *probably* should
|
||||||
// TODO: Add a selector which also matches topics inside a specific forum?
|
// TODO: Add a selector which also matches topics inside a specific forum?
|
||||||
func (widget *Widget) Allowed(zone string, zoneid int) bool {
|
func (w *Widget) Allowed(zone string, zoneid int) bool {
|
||||||
for _, loc := range strings.Split(widget.Location, "|") {
|
for _, loc := range strings.Split(w.Location, "|") {
|
||||||
if len(loc) == 0 {
|
if len(loc) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -107,16 +107,15 @@ func (widget *Widget) Allowed(zone string, zoneid int) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Refactor
|
// TODO: Refactor
|
||||||
func (widget *Widget) Build(hvars interface{}) (string, error) {
|
func (w *Widget) Build(hvars interface{}) (string, error) {
|
||||||
if widget.Literal {
|
if w.Literal {
|
||||||
return widget.Body, nil
|
return w.Body, nil
|
||||||
}
|
}
|
||||||
if widget.BuildFunc != nil {
|
if w.BuildFunc != nil {
|
||||||
return widget.BuildFunc(widget, hvars)
|
return w.BuildFunc(w, hvars)
|
||||||
}
|
}
|
||||||
|
|
||||||
header := hvars.(*Header)
|
header := hvars.(*Header)
|
||||||
err := header.Theme.RunTmpl(widget.Body, hvars, header.Writer)
|
err := header.Theme.RunTmpl(w.Body, hvars, header.Writer)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,40 +124,42 @@ type WidgetEdit struct {
|
||||||
Data map[string]string
|
Data map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *WidgetEdit) Create() error {
|
func (w *WidgetEdit) Create() (int, error) {
|
||||||
data, err := json.Marshal(widget.Data)
|
data, err := json.Marshal(w.Data)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
res, err := widgetStmts.create.Exec(w.Position, w.Side, w.Type, w.Enabled, w.Location, data)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload the dock
|
||||||
|
widgets, err := getDockWidgets(w.Side)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
setDock(w.Side, widgets)
|
||||||
|
|
||||||
|
wid64, err := res.LastInsertId()
|
||||||
|
return int(wid64), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WidgetEdit) Commit() error {
|
||||||
|
data, err := json.Marshal(w.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = widgetStmts.create.Exec(widget.Position, widget.Side, widget.Type, widget.Enabled, widget.Location, data)
|
_, err = widgetStmts.update.Exec(w.Position, w.Side, w.Type, w.Enabled, w.Location, data, w.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload the dock
|
// Reload the dock
|
||||||
widgets, err := getDockWidgets(widget.Side)
|
widgets, err := getDockWidgets(w.Side)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
setDock(widget.Side, widgets)
|
setDock(w.Side, widgets)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (widget *WidgetEdit) Commit() error {
|
|
||||||
data, err := json.Marshal(widget.Data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = widgetStmts.update.Exec(widget.Position, widget.Side, widget.Type, widget.Enabled, widget.Location, data, widget.ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload the dock
|
|
||||||
widgets, err := getDockWidgets(widget.Side)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
setDock(widget.Side, widgets)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,13 @@ import (
|
||||||
type WordFilter struct {
|
type WordFilter struct {
|
||||||
ID int
|
ID int
|
||||||
Find string
|
Find string
|
||||||
Replacement string
|
Replace string
|
||||||
|
}
|
||||||
|
type WordFilterDiff struct {
|
||||||
|
BeforeFind string
|
||||||
|
BeforeReplace string
|
||||||
|
AfterFind string
|
||||||
|
AfterReplace string
|
||||||
}
|
}
|
||||||
|
|
||||||
var WordFilters WordFilterStore
|
var WordFilters WordFilterStore
|
||||||
|
@ -82,7 +88,7 @@ func (s *DefaultWordFilterStore) bypassGetAll() (filters []*WordFilter, err erro
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
f := &WordFilter{ID: 0}
|
f := &WordFilter{ID: 0}
|
||||||
err := rows.Scan(&f.ID, &f.Find, &f.Replacement)
|
err := rows.Scan(&f.ID, &f.Find, &f.Replace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return filters, err
|
return filters, err
|
||||||
}
|
}
|
||||||
|
@ -98,7 +104,7 @@ func (s *DefaultWordFilterStore) GetAll() (filters map[int]*WordFilter, err erro
|
||||||
|
|
||||||
func (s *DefaultWordFilterStore) Get(id int) (*WordFilter, error) {
|
func (s *DefaultWordFilterStore) Get(id int) (*WordFilter, error) {
|
||||||
wf := &WordFilter{ID: id}
|
wf := &WordFilter{ID: id}
|
||||||
err := s.get.QueryRow(id).Scan(&wf.Find, &wf.Replacement)
|
err := s.get.QueryRow(id).Scan(&wf.Find, &wf.Replace)
|
||||||
return wf, err
|
return wf, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,14 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func initAdventure(plugin *c.Plugin) error {
|
func initAdventure(pl *c.Plugin) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Change the signature to return an error?
|
// TODO: Change the signature to return an error?
|
||||||
func deactivateAdventure(plugin *c.Plugin) {
|
func deactivateAdventure(pl *c.Plugin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func installAdventure(plugin *c.Plugin) error {
|
func installAdventure(pl *c.Plugin) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1024,26 +1024,36 @@
|
||||||
"page_unknown":"Unknown",
|
"page_unknown":"Unknown",
|
||||||
"setting_unknown":"unknown",
|
"setting_unknown":"unknown",
|
||||||
|
|
||||||
"panel_logs_administration_head":"Admin Action Logs",
|
"panel_logs_admin_head":"Admin Action Logs",
|
||||||
"panel_logs_administration_action_user_edit":"User <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_user_edit":"User <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_group_create":"Group <a href='%s'>%s</a> was created by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_group_create":"Group <a href='%s'>%s</a> was created by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_group_edit":"Group <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_group_edit":"Group <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_group_promotion_create":"A group promotion was created by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_group_promotion_create":"A group promotion was created by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_group_promotion_delete":"A group promotion was deleted by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_group_promotion_delete":"A group promotion was deleted by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_forum_reorder":"Forums were reordered by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_forum_reorder":"Forums were reordered by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_forum_create":"Forum <a href='%s'>%s</a> was created by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_forum_create":"Forum <a href='%s'>%s</a> was created by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_forum_delete":"Forum <a href='%s'>%s</a> was deleted by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_forum_delete":"Forum <a href='%s'>%s</a> was deleted by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_forum_edit":"Forum <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_forum_edit":"Forum <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_page_create":"Page <a href='%s'>%s</a> was created by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_page_create":"Page <a href='%s'>%s</a> was created by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_page_delete":"Page <a href='%s'>%s</a> was deleted by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_page_delete":"Page <a href='%s'>%s</a> was deleted by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_page_edit":"Page <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_page_edit":"Page <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_setting_edit":"Setting <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_setting_edit":"Setting <a href='%s'>%s</a> was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_word_filter_create":"Word Filter <a href='%s'>%d</a> was created by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_word_filter_create":"A word filter was created by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_word_filter_delete":"Word Filter <a href='%s'>%d</a> was deleted by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_word_filter_delete":"A word filter was deleted by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_word_filter_edit":"Word Filter <a href='%s'>%d</a> was modified by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_word_filter_edit":"A word filter was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_backup_download":"A backup was downloaded by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_menu_suborder":"Menu #%d was reordered by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_action_unknown":"Unknown action '%s' on elementType '%s' by <a href='%s'>%s</a>",
|
"panel_logs_admin_action_menu_item_edit":"Menu item <a href='%s'>#%d</a> was modified by <a href='%s'>%s</a>",
|
||||||
"panel_logs_administration_no_logs":"There aren't any events logged.",
|
"panel_logs_admin_action_menu_item_create":"Menu item <a href='%s'>#%d</a> was created by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_menu_item_delete":"Menu item <a href='%s'>#%d</a> was deleted by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_widget_edit":"Widget <a href='%s'>#%d</a> was modified by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_widget_create":"Widget <a href='%s'>#%d</a> was created by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_widget_delete":"Widget <a href='%s'>#%d</a> was deleted by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_plugin_activate":"The plugin '%s' was activated by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_plugin_deactivate":"The plugin '%s' was deactivated by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_plugin_install":"The plugin '%s' was installed by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_backup_download":"A backup was downloaded by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_action_unknown":"Unknown action '%s' on elementType '%s' by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_admin_no_logs":"There aren't any events logged.",
|
||||||
|
|
||||||
"panel_plugins_head":"Plugins",
|
"panel_plugins_head":"Plugins",
|
||||||
"panel_plugins_author_prefix":"Author: ",
|
"panel_plugins_author_prefix":"Author: ",
|
||||||
|
|
11
misc_test.go
11
misc_test.go
|
@ -1355,13 +1355,13 @@ func TestWordFilters(t *testing.T) {
|
||||||
filter := filters[1]
|
filter := filters[1]
|
||||||
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
||||||
expect(t, filter.Find == "imbecile", "Word filter needle should be imbecile")
|
expect(t, filter.Find == "imbecile", "Word filter needle should be imbecile")
|
||||||
expect(t, filter.Replacement == "lovely", "Word filter replacement should be lovely")
|
expect(t, filter.Replace == "lovely", "Word filter replacement should be lovely")
|
||||||
|
|
||||||
filter, err = c.WordFilters.Get(1)
|
filter, err = c.WordFilters.Get(1)
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
||||||
expect(t, filter.Find == "imbecile", "Word filter needle should be imbecile")
|
expect(t, filter.Find == "imbecile", "Word filter needle should be imbecile")
|
||||||
expect(t, filter.Replacement == "lovely", "Word filter replacement should be lovely")
|
expect(t, filter.Replace == "lovely", "Word filter replacement should be lovely")
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
expectNilErr(t, c.WordFilters.Update(1, "b", "a"))
|
expectNilErr(t, c.WordFilters.Update(1, "b", "a"))
|
||||||
|
@ -1376,13 +1376,13 @@ func TestWordFilters(t *testing.T) {
|
||||||
filter = filters[1]
|
filter = filters[1]
|
||||||
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
||||||
expect(t, filter.Find == "b", "Word filter needle should be b")
|
expect(t, filter.Find == "b", "Word filter needle should be b")
|
||||||
expect(t, filter.Replacement == "a", "Word filter replacement should be a")
|
expect(t, filter.Replace == "a", "Word filter replacement should be a")
|
||||||
|
|
||||||
filter, err = c.WordFilters.Get(1)
|
filter, err = c.WordFilters.Get(1)
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
expect(t, filter.ID == 1, "Word filter ID should be 1")
|
||||||
expect(t, filter.Find == "b", "Word filter needle should be imbecile")
|
expect(t, filter.Find == "b", "Word filter needle should be imbecile")
|
||||||
expect(t, filter.Replacement == "a", "Word filter replacement should be a")
|
expect(t, filter.Replace == "a", "Word filter replacement should be a")
|
||||||
|
|
||||||
// TODO: Add a test for ParseMessage relating to word filters
|
// TODO: Add a test for ParseMessage relating to word filters
|
||||||
|
|
||||||
|
@ -1445,8 +1445,9 @@ func TestWidgets(t *testing.T) {
|
||||||
|
|
||||||
widget := &c.Widget{Position: 0, Side: "rightSidebar", Type: "simple", Enabled: true, Location: "global"}
|
widget := &c.Widget{Position: 0, Side: "rightSidebar", Type: "simple", Enabled: true, Location: "global"}
|
||||||
ewidget := &c.WidgetEdit{widget, map[string]string{"Name": "Test", "Text": "Testing"}}
|
ewidget := &c.WidgetEdit{widget, map[string]string{"Name": "Test", "Text": "Testing"}}
|
||||||
err = ewidget.Create()
|
wid, err := ewidget.Create()
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
|
expect(t,wid==1,"wid should be 1")
|
||||||
|
|
||||||
// TODO: Do a test for the widget body
|
// TODO: Do a test for the widget body
|
||||||
widget2, err := c.Widgets.Get(1)
|
widget2, err := c.Widgets.Get(1)
|
||||||
|
|
|
@ -130,8 +130,10 @@ func patcher(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
err := patch(scanner)
|
err := patch(scanner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Failed to apply patch "+strconv.Itoa(index+1))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
fmt.Println("Applied patch "+strconv.Itoa(index+1))
|
||||||
patched++
|
patched++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +142,8 @@ func patcher(scanner *bufio.Scanner) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("No new patches found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
type tblColumn = qgen.DBTableColumn
|
type tblColumn = qgen.DBTableColumn
|
||||||
type tC = tblColumn
|
type tC = tblColumn
|
||||||
type tblKey = qgen.DBTableKey
|
type tblKey = qgen.DBTableKey
|
||||||
|
type tK = tblKey
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
addPatch(0, patch0)
|
addPatch(0, patch0)
|
||||||
|
@ -40,6 +41,7 @@ func init() {
|
||||||
addPatch(24, patch24)
|
addPatch(24, patch24)
|
||||||
addPatch(25, patch25)
|
addPatch(25, patch25)
|
||||||
addPatch(26, patch26)
|
addPatch(26, patch26)
|
||||||
|
addPatch(27, patch27)
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch0(scanner *bufio.Scanner) (err error) {
|
func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
|
@ -56,8 +58,8 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
[]tC{
|
[]tC{
|
||||||
tC{"mid", "int", 0, false, true, ""},
|
tC{"mid", "int", 0, false, true, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"mid", "primary", "", false},
|
tK{"mid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -83,8 +85,8 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
tC{"staffOnly", "boolean", 0, false, false, "0"},
|
tC{"staffOnly", "boolean", 0, false, false, "0"},
|
||||||
tC{"adminOnly", "boolean", 0, false, false, "0"},
|
tC{"adminOnly", "boolean", 0, false, false, "0"},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"miid", "primary", "", false},
|
tK{"miid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -190,8 +192,8 @@ func patch3(scanner *bufio.Scanner) error {
|
||||||
tC{"ipaddress", "varchar", 200, false, false, ""},
|
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
tC{"doneAt", "createdAt", 0, false, false, ""},
|
tC{"doneAt", "createdAt", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"rlid", "primary", "", false},
|
tK{"rlid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -253,8 +255,8 @@ func patch4(scanner *bufio.Scanner) error {
|
||||||
tC{"allowedGroups", "text", 0, false, false, ""},
|
tC{"allowedGroups", "text", 0, false, false, ""},
|
||||||
tC{"menuID", "int", 0, false, false, "-1"},
|
tC{"menuID", "int", 0, false, false, "-1"},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"pid", "primary", "", false},
|
tK{"pid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -277,7 +279,7 @@ func patch5(scanner *bufio.Scanner) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.SimpleUpdate("menu_items", "path = '/user/edit/'", "path = '/user/edit/critical/'"))
|
err = execStmt(qgen.Builder.SimpleUpdate("menu_items", "path='/user/edit/'", "path='/user/edit/critical/'"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -296,8 +298,8 @@ func patch5(scanner *bufio.Scanner) error {
|
||||||
tC{"scratch8", "varchar", 50, false, false, ""},
|
tC{"scratch8", "varchar", 50, false, false, ""},
|
||||||
tC{"createdAt", "createdAt", 0, false, false, ""},
|
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"uid", "primary", "", false},
|
tK{"uid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -316,8 +318,8 @@ func patch7(scanner *bufio.Scanner) error {
|
||||||
[]tC{
|
[]tC{
|
||||||
tC{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
tC{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"uid", "primary", "", false},
|
tK{"uid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -378,8 +380,7 @@ func patch8(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.CreateTable("updates", "", "",
|
return execStmt(qgen.Builder.CreateTable("updates", "", "",
|
||||||
[]tC{
|
[]tC{
|
||||||
tC{"dbVersion", "int", 0, false, false, "0"},
|
tC{"dbVersion", "int", 0, false, false, "0"},
|
||||||
},
|
}, nil,
|
||||||
[]tblKey{},
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,8 +399,8 @@ func patch9(scanner *bufio.Scanner) error {
|
||||||
tC{"ipaddress", "varchar", 200, false, false, ""},
|
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
tC{"doneAt", "createdAt", 0, false, false, ""},
|
tC{"doneAt", "createdAt", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"lid", "primary", "", false},
|
tK{"lid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -461,23 +462,21 @@ func patch11(scanner *bufio.Scanner) error {
|
||||||
// We could probably do something more efficient, but as there shouldn't be too many sites right now, we can probably cheat a little, otherwise it'll take forever to get things done
|
// We could probably do something more efficient, but as there shouldn't be too many sites right now, we can probably cheat a little, otherwise it'll take forever to get things done
|
||||||
return acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
|
return acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
|
||||||
stid := itoa(tid)
|
stid := itoa(tid)
|
||||||
count, err := acc().Count("attachments").Where("originTable = 'topics' and originID = " + stid).Total()
|
count, err := acc().Count("attachments").Where("originTable='topics' and originID=" + stid).Total()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = acc().Update("topics").Set("attachCount = ?").Where("tid = " + stid).Exec(count)
|
_, err = acc().Update("topics").Set("attachCount = ?").Where("tid = " + stid).Exec(count)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
/*return acc().Select("replies").Cols("rid").EachInt(func(rid int) error {
|
/*return acc().Select("replies").Cols("rid").EachInt(func(rid int) error {
|
||||||
srid := itoa(rid)
|
srid := itoa(rid)
|
||||||
count, err := acc().Count("attachments").Where("originTable = 'replies' and originID = " + srid).Total()
|
count, err := acc().Count("attachments").Where("originTable='replies' and originID=" + srid).Total()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_, err = acc().Update("replies").Set("attachCount = ?").Where("rid=" + srid).Exec(count)
|
||||||
_, err = acc().Update("replies").Set("attachCount = ?").Where("rid = " + srid).Exec(count)
|
|
||||||
return err
|
return err
|
||||||
})*/
|
})*/
|
||||||
}
|
}
|
||||||
|
@ -519,24 +518,19 @@ func patch12(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch13(scanner *bufio.Scanner) error {
|
func patch13(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddColumn("widgets", tC{"wid", "int", 0, false, true, ""}, &tblKey{"wid", "primary", "", false}))
|
return execStmt(qgen.Builder.AddColumn("widgets", tC{"wid", "int", 0, false, true, ""}, &tK{"wid", "primary", "", false}))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch14(scanner *bufio.Scanner) error {
|
func patch14(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddKey("topics", "title", tblKey{"title", "fulltext", "", false}))
|
err := execStmt(qgen.Builder.AddKey("topics", "title", tK{"title", "fulltext", "", false}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = execStmt(qgen.Builder.AddKey("topics", "content", tblKey{"content", "fulltext", "", false}))
|
err = execStmt(qgen.Builder.AddKey("topics", "content", tK{"content", "fulltext", "", false}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = execStmt(qgen.Builder.AddKey("replies", "content", tblKey{"content", "fulltext", "", false}))
|
err = execStmt(qgen.Builder.AddKey("replies", "content", tK{"content", "fulltext", "", false}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -585,12 +579,10 @@ func patch17(scanner *bufio.Scanner) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = acc().Select("topics").Cols("parentID").Where("tid = ?").QueryRow(tid).Scan(§ionID)
|
err = acc().Select("topics").Cols("parentID").Where("tid = ?").QueryRow(tid).Scan(§ionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = acc().Update("attachments").Set("sectionID = ?, extra = ?").Where("originTable = 'replies' AND originID = ?").Exec(sectionID, tid, rid)
|
_, err = acc().Update("attachments").Set("sectionID = ?, extra = ?").Where("originTable = 'replies' AND originID = ?").Exec(sectionID, tid, rid)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -616,12 +608,10 @@ func patch20(scanner *bufio.Scanner) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = acc().Select("activity_stream").Cols("asid").Where("asid = ?").QueryRow(asid).Scan(&asid)
|
err = acc().Select("activity_stream").Cols("asid").Where("asid = ?").QueryRow(asid).Scan(&asid)
|
||||||
if err != sql.ErrNoRows {
|
if err != sql.ErrNoRows {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = acc().Delete("activity_stream_matches").Where("asid = ?").Run(asid)
|
_, err = acc().Delete("activity_stream_matches").Where("asid = ?").Run(asid)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -673,8 +663,8 @@ func patch23(scanner *bufio.Scanner) error {
|
||||||
tC{"lastReplyAt", "datetime", 0, false, false, ""},
|
tC{"lastReplyAt", "datetime", 0, false, false, ""},
|
||||||
tC{"lastReplyBy", "int", 0, false, false, ""},
|
tC{"lastReplyBy", "int", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"cid", "primary", "", false},
|
tK{"cid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -693,8 +683,8 @@ func patch23(scanner *bufio.Scanner) error {
|
||||||
tC{"body", "varchar", 50, false, false, ""},
|
tC{"body", "varchar", 50, false, false, ""},
|
||||||
tC{"post", "varchar", 50, false, false, "''"},
|
tC{"post", "varchar", 50, false, false, "''"},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"pid", "primary", "", false},
|
tK{"pid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -729,8 +719,8 @@ func patch24(scanner *bufio.Scanner) error {
|
||||||
tC{"level", "int", 0, false, false, ""},
|
tC{"level", "int", 0, false, false, ""},
|
||||||
tC{"minTime", "int", 0, false, false, ""}, // How long someone needs to have been in their current group before being promoted
|
tC{"minTime", "int", 0, false, false, ""}, // How long someone needs to have been in their current group before being promoted
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tK{
|
||||||
tblKey{"pid", "primary", "", false},
|
tK{"pid", "primary", "", false},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -747,3 +737,11 @@ func patch26(scanner *bufio.Scanner) error {
|
||||||
}, nil,
|
}, nil,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func patch27(scanner *bufio.Scanner) error {
|
||||||
|
err := execStmt(qgen.Builder.AddColumn("moderation_logs", tC{"extra", "text", 0, false, false, ""}, nil))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return execStmt(qgen.Builder.AddColumn("administration_logs", tC{"extra", "text", 0, false, false, ""}, nil))
|
||||||
|
}
|
||||||
|
|
|
@ -100,53 +100,59 @@ func modlogsElementType(action string, elementType string, elementID int, actor
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminlogsElementType(action string, elementType string, elementID int, actor *c.User) (out string) {
|
func adminlogsElementType(action string, elementType string, elementID int, actor *c.User, extra string) (out string) {
|
||||||
switch elementType {
|
switch elementType {
|
||||||
// TODO: Record more detail for this, e.g. which field/s was changed
|
// TODO: Record more detail for this, e.g. which field/s was changed
|
||||||
case "user":
|
case "user":
|
||||||
targetUser := handleUnknownUser(c.Users.Get(elementID))
|
targetUser := handleUnknownUser(c.Users.Get(elementID))
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_user_"+action, targetUser.Link, targetUser.Name, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_user_"+action, targetUser.Link, targetUser.Name, actor.Link, actor.Name)
|
||||||
case "group":
|
case "group":
|
||||||
g, err := c.Groups.Get(elementID)
|
g, err := c.Groups.Get(elementID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g = &c.Group{Name: p.GetTmplPhrase("group_unknown")}
|
g = &c.Group{Name: p.GetTmplPhrase("group_unknown")}
|
||||||
}
|
}
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_group_"+action, "/panel/groups/edit/"+strconv.Itoa(g.ID), g.Name, actor.Link, actor.Name)
|
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":
|
case "group_promotion":
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_group_promotion_"+action, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_group_promotion_"+action, actor.Link, actor.Name)
|
||||||
case "forum":
|
case "forum":
|
||||||
f, err := c.Forums.Get(elementID)
|
f, err := c.Forums.Get(elementID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f = &c.Forum{Name: p.GetTmplPhrase("forum_unknown")}
|
f = &c.Forum{Name: p.GetTmplPhrase("forum_unknown")}
|
||||||
}
|
}
|
||||||
if action == "reorder" {
|
if action == "reorder" {
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_forum_reorder", actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_forum_reorder", actor.Link, actor.Name)
|
||||||
} else {
|
} else {
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_forum_"+action, "/panel/forums/edit/"+strconv.Itoa(f.ID), f.Name, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_forum_"+action, "/panel/forums/edit/"+strconv.Itoa(f.ID), f.Name, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
case "page":
|
case "page":
|
||||||
pp, err := c.Pages.Get(elementID)
|
pp, err := c.Pages.Get(elementID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pp = &c.CustomPage{Name: p.GetTmplPhrase("page_unknown")}
|
pp = &c.CustomPage{Name: p.GetTmplPhrase("page_unknown")}
|
||||||
}
|
}
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_page_"+action, "/panel/pages/edit/"+strconv.Itoa(pp.ID), pp.Name, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_page_"+action, "/panel/pages/edit/"+strconv.Itoa(pp.ID), pp.Name, actor.Link, actor.Name)
|
||||||
case "setting":
|
case "setting":
|
||||||
s, err := c.SettingBox.Load().(c.SettingMap).BypassGet(action)
|
s, err := c.SettingBox.Load().(c.SettingMap).BypassGet(action)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s = &c.Setting{Name: p.GetTmplPhrase("setting_unknown")}
|
s = &c.Setting{Name: p.GetTmplPhrase("setting_unknown")}
|
||||||
}
|
}
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_setting_edit", "/panel/settings/edit/"+s.Name, s.Name, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_setting_edit", "/panel/settings/edit/"+s.Name, s.Name, actor.Link, actor.Name)
|
||||||
case "word_filter":
|
case "word_filter":
|
||||||
wf, err := c.WordFilters.Get(elementID)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_word_filter_"+action, actor.Link, actor.Name)
|
||||||
if err != nil {
|
case "menu":
|
||||||
wf = &c.WordFilter{}
|
if action == "suborder" {
|
||||||
|
out = p.GetTmplPhrasef("panel_logs_admin_action_menu_suborder", elementID, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_word_filter_"+action, "/panel/settings/word-filters/", wf.ID, 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":
|
case "backup":
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_backup_"+action, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_backup_"+action, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
if out == "" {
|
if out == "" {
|
||||||
out = p.GetTmplPhrasef("panel_logs_administration_action_unknown", action, elementType, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_admin_action_unknown", action, elementType, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
@ -182,8 +188,6 @@ func LogsAdmin(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
basePage.AddNotice("Currently under development")
|
|
||||||
|
|
||||||
page, _ := strconv.Atoi(r.FormValue("page"))
|
page, _ := strconv.Atoi(r.FormValue("page"))
|
||||||
perPage := 12
|
perPage := 12
|
||||||
offset, page, lastPage := c.PageOffset(c.AdminLogs.Count(), page, perPage)
|
offset, page, lastPage := c.PageOffset(c.AdminLogs.Count(), page, perPage)
|
||||||
|
@ -195,7 +199,7 @@ func LogsAdmin(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
|
||||||
llist := make([]c.PageLogItem, len(logs))
|
llist := make([]c.PageLogItem, len(logs))
|
||||||
for index, log := range logs {
|
for index, log := range logs {
|
||||||
actor := handleUnknownUser(c.Users.Get(log.ActorID))
|
actor := handleUnknownUser(c.Users.Get(log.ActorID))
|
||||||
action := adminlogsElementType(log.Action, log.ElementType, log.ElementID, actor)
|
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}
|
llist[index] = c.PageLogItem{Action: template.HTML(action), IP: log.IP, DoneAt: log.DoneAt}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ func Plugins(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
|
||||||
pluginList = append(pluginList, plugin)
|
pluginList = append(pluginList, plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_plugins", c.PanelPage{basePage, pluginList, nil}})
|
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_plugins", c.PanelPage{basePage, pluginList, nil}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Abstract more of the plugin activation / installation / deactivation logic, so we can test all that more reliably and easily
|
// TODO: Abstract more of the plugin activation / installation / deactivation logic, so we can test all that more reliably and easily
|
||||||
|
@ -73,6 +73,10 @@ func PluginsActivate(w http.ResponseWriter, r *http.Request, user c.User, uname
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalError(err.Error(), w, r, user)
|
return c.LocalError(err.Error(), w, r, user)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.CreateExtra("activate", 0, "plugin", user.LastIP, user.ID, c.SanitiseSingleLine(plugin.Name))
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther)
|
http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
|
@ -107,6 +111,10 @@ func PluginsDeactivate(w http.ResponseWriter, r *http.Request, user c.User, unam
|
||||||
if plugin.Deactivate != nil {
|
if plugin.Deactivate != nil {
|
||||||
plugin.Deactivate(plugin)
|
plugin.Deactivate(plugin)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.CreateExtra("deactivate", 0, "plugin", user.LastIP, user.ID, c.SanitiseSingleLine(plugin.Name))
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther)
|
http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
|
@ -173,6 +181,10 @@ func PluginsInstall(w http.ResponseWriter, r *http.Request, user c.User, uname s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalError(err.Error(), w, r, user)
|
return c.LocalError(err.Error(), w, r, user)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.CreateExtra("install", 0, "plugin", user.LastIP, user.ID, c.SanitiseSingleLine(plugin.Name))
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther)
|
http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -58,6 +58,10 @@ func ThemesSetDefault(w http.ResponseWriter, r *http.Request, user c.User, uname
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.CreateExtra("set_default", 0, "theme", user.LastIP, user.ID, c.SanitiseSingleLine(theme.Name))
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/panel/themes/", http.StatusSeeOther)
|
http.Redirect(w, r, "/panel/themes/", http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
|
@ -173,10 +177,10 @@ func themesMenuItemSetters(r *http.Request, i c.MenuItem) c.MenuItem {
|
||||||
i.Aria = getItem("aria")
|
i.Aria = getItem("aria")
|
||||||
i.Tooltip = getItem("tooltip")
|
i.Tooltip = getItem("tooltip")
|
||||||
i.TmplName = getItem("tmplname")
|
i.TmplName = getItem("tmplname")
|
||||||
|
i.GuestOnly = false
|
||||||
|
|
||||||
switch getItem("permissions") {
|
switch getItem("permissions") {
|
||||||
case "everyone":
|
case "everyone":
|
||||||
i.GuestOnly = false
|
|
||||||
i.MemberOnly = false
|
i.MemberOnly = false
|
||||||
i.SuperModOnly = false
|
i.SuperModOnly = false
|
||||||
i.AdminOnly = false
|
i.AdminOnly = false
|
||||||
|
@ -186,17 +190,14 @@ func themesMenuItemSetters(r *http.Request, i c.MenuItem) c.MenuItem {
|
||||||
i.SuperModOnly = false
|
i.SuperModOnly = false
|
||||||
i.AdminOnly = false
|
i.AdminOnly = false
|
||||||
case "member-only":
|
case "member-only":
|
||||||
i.GuestOnly = false
|
|
||||||
i.MemberOnly = true
|
i.MemberOnly = true
|
||||||
i.SuperModOnly = false
|
i.SuperModOnly = false
|
||||||
i.AdminOnly = false
|
i.AdminOnly = false
|
||||||
case "supermod-only":
|
case "supermod-only":
|
||||||
i.GuestOnly = false
|
|
||||||
i.MemberOnly = true
|
i.MemberOnly = true
|
||||||
i.SuperModOnly = true
|
i.SuperModOnly = true
|
||||||
i.AdminOnly = false
|
i.AdminOnly = false
|
||||||
case "admin-only":
|
case "admin-only":
|
||||||
i.GuestOnly = false
|
|
||||||
i.MemberOnly = true
|
i.MemberOnly = true
|
||||||
i.SuperModOnly = true
|
i.SuperModOnly = true
|
||||||
i.AdminOnly = true
|
i.AdminOnly = true
|
||||||
|
@ -232,6 +233,11 @@ func ThemesMenuItemEditSubmit(w http.ResponseWriter, r *http.Request, user c.Use
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.Create("edit", menuItem.ID, "menu_item", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/menus/item/edit/"+strconv.Itoa(itemID), w, r, js)
|
return successRedirect("/panel/themes/menus/item/edit/"+strconv.Itoa(itemID), w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,11 +246,11 @@ func ThemesMenuItemCreateSubmit(w http.ResponseWriter, r *http.Request, user c.U
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
|
|
||||||
js := r.PostFormValue("js") == "1"
|
js := r.PostFormValue("js") == "1"
|
||||||
if !user.Perms.ManageThemes {
|
if !user.Perms.ManageThemes {
|
||||||
return c.NoPermissionsJSQ(w, r, user, js)
|
return c.NoPermissionsJSQ(w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
smenuID := r.PostFormValue("mid")
|
smenuID := r.PostFormValue("mid")
|
||||||
if smenuID == "" {
|
if smenuID == "" {
|
||||||
return c.LocalErrorJSQ("No menuID provided", w, r, user, js)
|
return c.LocalErrorJSQ("No menuID provided", w, r, user, js)
|
||||||
|
@ -260,6 +266,11 @@ func ThemesMenuItemCreateSubmit(w http.ResponseWriter, r *http.Request, user c.U
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.Create("create", itemID, "menu_item", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/menus/item/edit/"+strconv.Itoa(itemID), w, r, js)
|
return successRedirect("/panel/themes/menus/item/edit/"+strconv.Itoa(itemID), w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,6 +300,11 @@ func ThemesMenuItemDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.U
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.Create("delete", menuItem.ID, "menu_item", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/menus/", w, r, js)
|
return successRedirect("/panel/themes/menus/", w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +342,11 @@ func ThemesMenuItemOrderSubmit(w http.ResponseWriter, r *http.Request, user c.Us
|
||||||
}
|
}
|
||||||
menuHold.UpdateOrder(updateMap)
|
menuHold.UpdateOrder(updateMap)
|
||||||
|
|
||||||
|
err = c.AdminLogs.Create("suborder", menuHold.MenuID, "menu", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/menus/edit/"+strconv.Itoa(mid), w, r, js)
|
return successRedirect("/panel/themes/menus/edit/"+strconv.Itoa(mid), w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,7 +430,6 @@ func ThemesWidgetsEditSubmit(w http.ResponseWriter, r *http.Request, user c.User
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalErrorJSQ(p.GetErrorPhrase("id_must_be_integer"), w, r, user, js)
|
return c.LocalErrorJSQ(p.GetErrorPhrase("id_must_be_integer"), w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
widget, err := c.Widgets.Get(wid)
|
widget, err := c.Widgets.Get(wid)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.NotFoundJSQ(w, r, nil, js)
|
return c.NotFoundJSQ(w, r, nil, js)
|
||||||
|
@ -426,6 +446,10 @@ func ThemesWidgetsEditSubmit(w http.ResponseWriter, r *http.Request, user c.User
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.Create("edit", widget.ID, "widget", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/widgets/", w, r, js)
|
return successRedirect("/panel/themes/widgets/", w, r, js)
|
||||||
}
|
}
|
||||||
|
@ -446,10 +470,14 @@ func ThemesWidgetsCreateSubmit(w http.ResponseWriter, r *http.Request, user c.Us
|
||||||
return c.LocalErrorJSQ(err.Error(), w, r, user, js)
|
return c.LocalErrorJSQ(err.Error(), w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ewidget.Create()
|
wid, err := ewidget.Create()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.Create("create", wid, "widget", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/widgets/", w, r, js)
|
return successRedirect("/panel/themes/widgets/", w, r, js)
|
||||||
}
|
}
|
||||||
|
@ -479,6 +507,10 @@ func ThemesWidgetsDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.Us
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
err = c.AdminLogs.Create("delete", widget.ID, "widget", user.LastIP, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
return successRedirect("/panel/themes/widgets/", w, r, js)
|
return successRedirect("/panel/themes/widgets/", w, r, js)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package panel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -95,13 +96,24 @@ func WordFiltersEditSubmit(w http.ResponseWriter, r *http.Request, user c.User,
|
||||||
// Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement
|
// Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement
|
||||||
replace := strings.TrimSpace(r.PostFormValue("replace"))
|
replace := strings.TrimSpace(r.PostFormValue("replace"))
|
||||||
|
|
||||||
|
wf, err := c.WordFilters.Get(wfid)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return c.LocalErrorJSQ("This word filter doesn't exist.", w, r, user, js)
|
||||||
|
} else if err != nil {
|
||||||
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
err = c.WordFilters.Update(wfid, find, replace)
|
err = c.WordFilters.Update(wfid, find, replace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
err = c.AdminLogs.Create("edit", wfid, "word_filter", user.LastIP, user.ID)
|
|
||||||
|
lBytes, err := json.Marshal(c.WordFilterDiff{wf.Find, wf.Replace, find, replace})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
err = c.AdminLogs.CreateExtra("edit", wfid, "word_filter", user.LastIP, user.ID, string(lBytes))
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/panel/settings/word-filters/", http.StatusSeeOther)
|
http.Redirect(w, r, "/panel/settings/word-filters/", http.StatusSeeOther)
|
||||||
|
|
|
@ -4,5 +4,6 @@ CREATE TABLE [administration_logs] (
|
||||||
[elementType] nvarchar (100) not null,
|
[elementType] nvarchar (100) not null,
|
||||||
[ipaddress] nvarchar (200) not null,
|
[ipaddress] nvarchar (200) not null,
|
||||||
[actorID] int not null,
|
[actorID] int not null,
|
||||||
[doneAt] datetime not null
|
[doneAt] datetime not null,
|
||||||
|
[extra] nvarchar (MAX) not null
|
||||||
);
|
);
|
|
@ -4,5 +4,6 @@ CREATE TABLE [moderation_logs] (
|
||||||
[elementType] nvarchar (100) not null,
|
[elementType] nvarchar (100) not null,
|
||||||
[ipaddress] nvarchar (200) not null,
|
[ipaddress] nvarchar (200) not null,
|
||||||
[actorID] int not null,
|
[actorID] int not null,
|
||||||
[doneAt] datetime not null
|
[doneAt] datetime not null,
|
||||||
|
[extra] nvarchar (MAX) not null
|
||||||
);
|
);
|
|
@ -4,5 +4,6 @@ CREATE TABLE `administration_logs` (
|
||||||
`elementType` varchar(100) not null,
|
`elementType` varchar(100) not null,
|
||||||
`ipaddress` varchar(200) not null,
|
`ipaddress` varchar(200) not null,
|
||||||
`actorID` int not null,
|
`actorID` int not null,
|
||||||
`doneAt` datetime not null
|
`doneAt` datetime not null,
|
||||||
|
`extra` text not null
|
||||||
);
|
);
|
|
@ -4,5 +4,6 @@ CREATE TABLE `moderation_logs` (
|
||||||
`elementType` varchar(100) not null,
|
`elementType` varchar(100) not null,
|
||||||
`ipaddress` varchar(200) not null,
|
`ipaddress` varchar(200) not null,
|
||||||
`actorID` int not null,
|
`actorID` int not null,
|
||||||
`doneAt` datetime not null
|
`doneAt` datetime not null,
|
||||||
|
`extra` text not null
|
||||||
);
|
);
|
|
@ -4,5 +4,6 @@ CREATE TABLE "administration_logs" (
|
||||||
`elementType` varchar (100) not null,
|
`elementType` varchar (100) not null,
|
||||||
`ipaddress` varchar (200) not null,
|
`ipaddress` varchar (200) not null,
|
||||||
`actorID` int not null,
|
`actorID` int not null,
|
||||||
`doneAt` timestamp not null
|
`doneAt` timestamp not null,
|
||||||
|
`extra` text not null
|
||||||
);
|
);
|
|
@ -4,5 +4,6 @@ CREATE TABLE "moderation_logs" (
|
||||||
`elementType` varchar (100) not null,
|
`elementType` varchar (100) not null,
|
||||||
`ipaddress` varchar (200) not null,
|
`ipaddress` varchar (200) not null,
|
||||||
`actorID` int not null,
|
`actorID` int not null,
|
||||||
`doneAt` timestamp not null
|
`doneAt` timestamp not null,
|
||||||
|
`extra` text not null
|
||||||
);
|
);
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><h1>{{lang "panel_logs_administration_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "panel_logs_admin_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_modlogs" class="colstack_item rowlist loglist">
|
<div id="panel_modlogs" class="colstack_item rowlist loglist">
|
||||||
{{range .Logs}}
|
{{range .Logs}}
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="rowitem rowmsg">
|
<div class="rowitem rowmsg">
|
||||||
<a>{{lang "panel_logs_administration_no_logs"}}</a>
|
<a>{{lang "panel_logs_admin_no_logs"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="rowitem panel_compactrow editable_parent">
|
<div class="rowitem panel_compactrow editable_parent">
|
||||||
<a data-field="find" data-type="text" href="/panel/settings/word-filters/edit/{{.ID}}" class="editable_block panel_upshift edit_fields filter_find">{{.Find}}</a>
|
<a data-field="find" data-type="text" href="/panel/settings/word-filters/edit/{{.ID}}" class="editable_block panel_upshift edit_fields filter_find">{{.Find}}</a>
|
||||||
<span class="itemSeparator"></span>
|
<span class="itemSeparator"></span>
|
||||||
<a data-field="replace" data-type="text" class="editable_block panel_compacttext filter_replace">{{.Replacement}}</a>
|
<a data-field="replace" data-type="text" class="editable_block panel_compacttext filter_replace">{{.Replace}}</a>
|
||||||
<span class="panel_buttons">
|
<span class="panel_buttons">
|
||||||
<a class="panel_tag edit_fields hide_on_edit panel_right_button edit_button" aria-label="{{lang "panel_word_filters_edit_button_aria"}}"></a>
|
<a class="panel_tag edit_fields hide_on_edit panel_right_button edit_button" aria-label="{{lang "panel_word_filters_edit_button_aria"}}"></a>
|
||||||
<a class="panel_right_button show_on_edit" href="/panel/settings/word-filters/edit/submit/{{.ID}}"><button class='panel_tag submit_edit' type='submit'>{{lang "panel_word_filters_update_button"}}</button></a>
|
<a class="panel_right_button show_on_edit" href="/panel/settings/word-filters/edit/submit/{{.ID}}"><button class='panel_tag submit_edit' type='submit'>{{lang "panel_word_filters_update_button"}}</button></a>
|
||||||
|
|
Loading…
Reference in New Issue