diff --git a/common/audit_logs.go b/common/audit_logs.go new file mode 100644 index 00000000..d74d6739 --- /dev/null +++ b/common/audit_logs.go @@ -0,0 +1,37 @@ +package common + +import ( + "database/sql" + + "../query_gen/lib" +) + +type LogStmts struct { + addModLogEntry *sql.Stmt + addAdminLogEntry *sql.Stmt +} + +var logStmts LogStmts + +func init() { + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + logStmts = LogStmts{ + addModLogEntry: acc.Insert("moderation_logs").Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), + addAdminLogEntry: acc.Insert("administration_logs").Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), + } + return acc.FirstError() + }) +} + +// TODO: Make a store for this? +func AddModLog(action string, elementID int, elementType string, ipaddress string, actorID int) (err error) { + _, err = logStmts.addModLogEntry.Exec(action, elementID, elementType, ipaddress, actorID) + return err +} + +// TODO: Make a store for this? +func AddAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) (err error) { + _, err = logStmts.addAdminLogEntry.Exec(action, elementID, elementType, ipaddress, actorID) + return err +} diff --git a/common/common.go b/common/common.go index 288796b1..1e98d43f 100644 --- a/common/common.go +++ b/common/common.go @@ -1,6 +1,8 @@ package common -import "database/sql" +import ( + "database/sql" +) // nolint I don't want to write comments for each of these o.o const Hour int = 60 * 60 @@ -60,11 +62,11 @@ func (slice StringList) Contains(needle string) bool { return false } -type DBInits []func() error +type dbInits []func() error -var DbInits DBInits +var DbInits dbInits -func (inits DBInits) Run() error { +func (inits dbInits) Run() error { for _, init := range inits { err := init() if err != nil { @@ -74,6 +76,6 @@ func (inits DBInits) Run() error { return nil } -func (inits DBInits) Add(init ...func() error) { - inits = append(inits, init...) +func (inits dbInits) Add(init ...func() error) { + DbInits = dbInits(append(DbInits, init...)) } diff --git a/common/extend.go b/common/extend.go index c6a06f94..288f2982 100644 --- a/common/extend.go +++ b/common/extend.go @@ -7,6 +7,7 @@ package common import ( + "database/sql" "log" "net/http" @@ -137,6 +138,22 @@ type Plugin struct { Data interface{} // Usually used for hosting the VMs / reusable elements of non-native plugins } +type ExtendStmts struct { + getPlugins *sql.Stmt +} + +var extendStmts ExtendStmts + +func init() { + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + extendStmts = ExtendStmts{ + getPlugins: acc.Select("plugins").Columns("uname, active, installed").Prepare(), + } + return acc.FirstError() + }) +} + func InitExtend() (err error) { err = InitPluginLangs() if err != nil { @@ -147,11 +164,7 @@ func InitExtend() (err error) { // Load polls the database to see which plugins have been activated and which have been installed func (plugins PluginList) Load() error { - getPlugins, err := qgen.Builder.SimpleSelect("plugins", "uname, active, installed", "", "", "") - if err != nil { - return err - } - rows, err := getPlugins.Query() + rows, err := extendStmts.getPlugins.Query() if err != nil { return err } @@ -283,24 +296,24 @@ func (plugin *Plugin) RemoveHook(name string, handler interface{}) { delete(plugin.Hooks, name) } -var pluginsInited = false +var PluginsInited = false func InitPlugins() { for name, body := range Plugins { - log.Printf("Added plugin %s", name) + log.Printf("Added plugin '%s'", name) if body.Active { - log.Printf("Initialised plugin %s", name) + log.Printf("Initialised plugin '%s'", name) if Plugins[name].Init != nil { err := Plugins[name].Init() if err != nil { log.Print(err) } } else { - log.Printf("Plugin %s doesn't have an initialiser.", name) + log.Printf("Plugin '%s' doesn't have an initialiser.", name) } } } - pluginsInited = true + PluginsInited = true } // ? - Are the following functions racey? diff --git a/common/forum_perms_store.go b/common/forum_perms_store.go index fa954fad..262e2764 100644 --- a/common/forum_perms_store.go +++ b/common/forum_perms_store.go @@ -25,18 +25,11 @@ type MemoryForumPermsStore struct { } func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) { - getPermsStmt, err := qgen.Builder.SimpleSelect("forums_permissions", "gid, fid, permissions", "", "gid ASC, fid ASC", "") - if err != nil { - return nil, err - } - getPermsByForumStmt, err := qgen.Builder.SimpleSelect("forums_permissions", "gid, permissions", "fid = ?", "gid ASC", "") - if err != nil { - return nil, err - } + acc := qgen.Builder.Accumulator() return &MemoryForumPermsStore{ - get: getPermsStmt, - getByForum: getPermsByForumStmt, - }, nil + get: acc.Select("forums_permissions").Columns("gid, fid, permissions").Orderby("gid ASC, fid ASC").Prepare(), + getByForum: acc.Select("forums_permissions").Columns("gid, permissions").Where("fid = ?").Orderby("gid ASC").Prepare(), + }, acc.FirstError() } func (fps *MemoryForumPermsStore) Init() error { diff --git a/common/permissions.go b/common/permissions.go index d2ca6d59..6b954577 100644 --- a/common/permissions.go +++ b/common/permissions.go @@ -483,6 +483,7 @@ func RebuildGroupPermissions(gid int) error { if err != nil { return err } + defer getGroupPerms.Close() err = getGroupPerms.QueryRow(gid).Scan(&permstr) if err != nil { diff --git a/common/routes_common.go b/common/routes_common.go index 3656fa30..470d2912 100644 --- a/common/routes_common.go +++ b/common/routes_common.go @@ -294,6 +294,14 @@ func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) { return *usercpy, true } +// AdminOnly makes sure that only admins can access certain panel routes +func AdminOnly(w http.ResponseWriter, r *http.Request, user User) RouteError { + if !user.IsAdmin { + return NoPermissions(w, r, user) + } + return nil +} + // SuperModeOnly makes sure that only super mods or higher can access the panel routes func SuperModOnly(w http.ResponseWriter, r *http.Request, user User) RouteError { if !user.IsSuperMod { diff --git a/common/setting.go b/common/setting.go index 4dcce5f9..a784de97 100644 --- a/common/setting.go +++ b/common/setting.go @@ -1,9 +1,13 @@ package common -import "strconv" -import "strings" -import "sync/atomic" -import "../query_gen/lib" +import ( + "database/sql" + "strconv" + "strings" + "sync/atomic" + + "../query_gen/lib" +) // SettingMap is a map type specifically for holding the various settings admins set to toggle features on and off or to otherwise alter Gosora's behaviour from the Control Panel type SettingMap map[string]interface{} @@ -23,17 +27,25 @@ type Setting struct { Constraint string } +type SettingStmts struct { + getFull *sql.Stmt +} + +var settingStmts SettingStmts + func init() { SettingBox.Store(SettingMap(make(map[string]interface{}))) + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + settingStmts = SettingStmts{ + getFull: acc.Select("settings").Columns("name, content, type, constraints").Prepare(), + } + return acc.FirstError() + }) } func LoadSettings() error { - // TODO: Stop doing this inline - getFullSettings, err := qgen.Builder.SimpleSelect("settings", "name, content, type, constraints", "", "", "") - if err != nil { - return err - } - rows, err := getFullSettings.Query() + rows, err := settingStmts.getFull.Query() if err != nil { return err } diff --git a/common/tasks.go b/common/tasks.go index c5fb7d42..b1024cef 100644 --- a/common/tasks.go +++ b/common/tasks.go @@ -7,24 +7,35 @@ package common import ( + "database/sql" "log" "time" "../query_gen/lib" ) +type TaskStmts struct { + getExpiredScheduledGroups *sql.Stmt + getSync *sql.Stmt +} + +var taskStmts TaskStmts var lastSync time.Time func init() { lastSync = time.Now() + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + taskStmts = TaskStmts{ + getExpiredScheduledGroups: acc.SimpleSelect("users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", ""), + getSync: acc.SimpleSelect("sync", "last_update", "", "", ""), + } + return acc.FirstError() + }) } func HandleExpiredScheduledGroups() error { - getExpiredScheduledGroups, err := qgen.Builder.SimpleSelect("users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", "") - if err != nil { - return err - } - rows, err := getExpiredScheduledGroups.Query() + rows, err := taskStmts.getExpiredScheduledGroups.Query() if err != nil { return err } @@ -50,11 +61,7 @@ func HandleExpiredScheduledGroups() error { func HandleServerSync() error { var lastUpdate time.Time - getSync, err := qgen.Builder.SimpleSelect("sync", "last_update", "", "", "") - if err != nil { - return err - } - err = getSync.QueryRow().Scan(&lastUpdate) + err := taskStmts.getSync.QueryRow().Scan(&lastUpdate) if err != nil { return err } diff --git a/common/themes.go b/common/themes.go index 41cfd0f1..87a01b99 100644 --- a/common/themes.go +++ b/common/themes.go @@ -4,6 +4,7 @@ package common import ( //"fmt" "bytes" + "database/sql" "encoding/json" "errors" "io/ioutil" @@ -74,20 +75,28 @@ type ThemeResource struct { Location string } +type ThemeStmts struct { + getThemes *sql.Stmt +} + +var themeStmts ThemeStmts + func init() { DefaultThemeBox.Store(fallbackTheme) + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + themeStmts = ThemeStmts{ + getThemes: acc.Select("themes").Columns("uname, default").Prepare(), + } + return acc.FirstError() + }) } // TODO: Make the initThemes and LoadThemes functions less confusing // ? - Delete themes which no longer exist in the themes folder from the database? func (themes ThemeList) LoadActiveStatus() error { - getThemes, err := qgen.Builder.SimpleSelect("themes", "uname, default", "", "", "") - if err != nil { - return err - } - ChangeDefaultThemeMutex.Lock() - rows, err := getThemes.Query() + rows, err := themeStmts.getThemes.Query() if err != nil { return err } diff --git a/common/user_store.go b/common/user_store.go index 41f16472..a67c084d 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -170,12 +170,8 @@ func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error } qlist = qlist[0 : len(qlist)-1] - stmt, err := qgen.Builder.SimpleSelect("users", "uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group", "uid IN("+qlist+")", "", "") - if err != nil { - return nil, err - } - - rows, err := stmt.Query(uidList...) + acc := qgen.Builder.Accumulator() + rows, err := acc.Select("users").Columns("uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group").Where("uid IN(" + qlist + ")").Query(uidList...) if err != nil { return nil, err } @@ -187,13 +183,8 @@ func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error return nil, err } - // Initialise the user user.Init() - - // Add it to the cache... - _ = mus.CacheSet(user) - - // Add it to the list to be returned + mus.CacheSet(user) list[user.ID] = user } @@ -219,10 +210,10 @@ func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error } sidList = sidList[0 : len(sidList)-1] - return list, errors.New("Unable to find the users with the following IDs: " + sidList) + err = errors.New("Unable to find the users with the following IDs: " + sidList) } - return list, nil + return list, err } func (mus *MemoryUserStore) BypassGet(id int) (*User, error) { @@ -420,12 +411,8 @@ func (mus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) { } qlist = qlist[0 : len(qlist)-1] - stmt, err := qgen.Builder.SimpleSelect("users", "uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group", "uid IN("+qlist+")", "", "") - if err != nil { - return nil, err - } - - rows, err := stmt.Query(uidList...) + acc := qgen.Builder.Accumulator() + rows, err := acc.Select("users").Columns("uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group").Where("uid IN(" + qlist + ")").Query(uidList...) if err != nil { return nil, err } @@ -438,10 +425,7 @@ func (mus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) { return nil, err } - // Initialise the user user.Init() - - // Add it to the list to be returned list[user.ID] = user } diff --git a/common/utils.go b/common/utils.go index 71a3bc6c..d375b0be 100644 --- a/common/utils.go +++ b/common/utils.go @@ -17,8 +17,6 @@ import ( "strings" "time" "unicode" - - "../query_gen/lib" ) // Version stores a Gosora version @@ -374,23 +372,3 @@ func BuildSlug(slug string, id int) string { } return slug + "." + strconv.Itoa(id) } - -// TODO: Make a store for this? -func AddModLog(action string, elementID int, elementType string, ipaddress string, actorID int) (err error) { - addModLogEntry, err := qgen.Builder.SimpleInsert("moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()") - if err != nil { - return err - } - _, err = addModLogEntry.Exec(action, elementID, elementType, ipaddress, actorID) - return err -} - -// TODO: Make a store for this? -func AddAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) (err error) { - addAdminLogEntry, err := qgen.Builder.SimpleInsert("administration_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()") - if err != nil { - return err - } - _, err = addAdminLogEntry.Exec(action, elementID, elementType, ipaddress, actorID) - return err -} diff --git a/common/widgets.go b/common/widgets.go index 8c6be918..a4711e72 100644 --- a/common/widgets.go +++ b/common/widgets.go @@ -1,11 +1,15 @@ /* Copyright Azareal 2017 - 2018 */ package common -import "log" -import "bytes" -import "sync" -import "encoding/json" -import "../query_gen/lib" +import ( + "bytes" + "database/sql" + "encoding/json" + "log" + "sync" + + "../query_gen/lib" +) var Docks WidgetDocks var widgetUpdateMutex sync.RWMutex @@ -39,13 +43,25 @@ type NameTextPair struct { Text string } +type WidgetStmts struct { + getWidgets *sql.Stmt +} + +var widgetStmts WidgetStmts + +func init() { + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + widgetStmts = WidgetStmts{ + getWidgets: acc.Select("widgets").Columns("position, side, type, active, location, data").Orderby("position ASC").Prepare(), + } + return acc.FirstError() + }) +} + // TODO: Make a store for this? func InitWidgets() error { - getWidgets, err := qgen.Builder.SimpleSelect("widgets", "position, side, type, active, location, data", "", "position ASC", "") - if err != nil { - return err - } - rows, err := getWidgets.Query() + rows, err := widgetStmts.getWidgets.Query() if err != nil { return err } diff --git a/common/word_filters.go b/common/word_filters.go index d5512c03..9915809e 100644 --- a/common/word_filters.go +++ b/common/word_filters.go @@ -1,7 +1,11 @@ package common -import "sync/atomic" -import "../query_gen/lib" +import ( + "database/sql" + "sync/atomic" + + "../query_gen/lib" +) type WordFilter struct { ID int @@ -12,16 +16,25 @@ type WordFilterMap map[int]WordFilter var WordFilterBox atomic.Value // An atomic value holding a WordFilterBox +type FilterStmts struct { + getWordFilters *sql.Stmt +} + +var filterStmts FilterStmts + func init() { WordFilterBox.Store(WordFilterMap(make(map[int]WordFilter))) + DbInits.Add(func() error { + acc := qgen.Builder.Accumulator() + filterStmts = FilterStmts{ + getWordFilters: acc.Select("word_filters").Columns("wfid, find, replacement").Prepare(), + } + return acc.FirstError() + }) } func LoadWordFilters() error { - getWordFilters, err := qgen.Builder.SimpleSelect("word_filters", "wfid, find, replacement", "", "", "") - if err != nil { - return err - } - rows, err := getWordFilters.Query() + rows, err := filterStmts.getWordFilters.Query() if err != nil { return err } diff --git a/database.go b/database.go index e4bcd97e..0f37fc30 100644 --- a/database.go +++ b/database.go @@ -28,6 +28,7 @@ func InitDatabase() (err error) { } globs = &Globs{stmts} + log.Print("Running the db handlers.") err = common.DbInits.Run() if err != nil { return err diff --git a/gen_router.go b/gen_router.go index 72f62d29..6d82ccca 100644 --- a/gen_router.go +++ b/gen_router.go @@ -192,50 +192,134 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { case "/panel/forums/": err = routePanelForums(w,req,user) case "/panel/forums/create/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelForumsCreateSubmit(w,req,user) case "/panel/forums/delete/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelForumsDelete(w,req,user,extra_data) case "/panel/forums/delete/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelForumsDeleteSubmit(w,req,user,extra_data) case "/panel/forums/edit/": err = routePanelForumsEdit(w,req,user,extra_data) case "/panel/forums/edit/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelForumsEditSubmit(w,req,user,extra_data) case "/panel/forums/edit/perms/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelForumsEditPermsSubmit(w,req,user,extra_data) case "/panel/settings/": err = routePanelSettings(w,req,user) case "/panel/settings/edit/": err = routePanelSetting(w,req,user,extra_data) case "/panel/settings/edit/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelSettingEdit(w,req,user,extra_data) case "/panel/settings/word-filters/": err = routePanelWordFilters(w,req,user) case "/panel/settings/word-filters/create/": + err = common.ParseForm(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelWordFiltersCreate(w,req,user) case "/panel/settings/word-filters/edit/": err = routePanelWordFiltersEdit(w,req,user,extra_data) case "/panel/settings/word-filters/edit/submit/": + err = common.ParseForm(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelWordFiltersEditSubmit(w,req,user,extra_data) case "/panel/settings/word-filters/delete/submit/": + err = common.ParseForm(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelWordFiltersDeleteSubmit(w,req,user,extra_data) case "/panel/themes/": err = routePanelThemes(w,req,user) case "/panel/themes/default/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelThemesSetDefault(w,req,user,extra_data) case "/panel/plugins/": err = routePanelPlugins(w,req,user) case "/panel/plugins/activate/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelPluginsActivate(w,req,user,extra_data) case "/panel/plugins/deactivate/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelPluginsDeactivate(w,req,user,extra_data) case "/panel/plugins/install/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelPluginsInstall(w,req,user,extra_data) case "/panel/users/": err = routePanelUsers(w,req,user) case "/panel/users/edit/": err = routePanelUsersEdit(w,req,user,extra_data) case "/panel/users/edit/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelUsersEditSubmit(w,req,user,extra_data) case "/panel/groups/": err = routePanelGroups(w,req,user) @@ -244,16 +328,40 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { case "/panel/groups/edit/perms/": err = routePanelGroupsEditPerms(w,req,user,extra_data) case "/panel/groups/edit/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelGroupsEditSubmit(w,req,user,extra_data) case "/panel/groups/edit/perms/submit/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelGroupsEditPermsSubmit(w,req,user,extra_data) case "/panel/groups/create/": + err = common.NoSessionMismatch(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelGroupsCreateSubmit(w,req,user) case "/panel/backups/": err = routePanelBackups(w,req,user,extra_data) case "/panel/logs/mod/": err = routePanelLogsMod(w,req,user) case "/panel/debug/": + err = common.AdminOnly(w,req,user) + if err != nil { + router.handleError(err,w,req,user) + return + } + err = routePanelDebug(w,req,user) default: err = routePanel(w,req,user) diff --git a/general_test.go b/general_test.go index e30ab5bb..4824d21d 100644 --- a/general_test.go +++ b/general_test.go @@ -553,6 +553,7 @@ func BenchmarkQueryPreparedTopicParallel(b *testing.B) { if err != nil { b.Fatal(err) } + defer getTopicUser.Close() for pb.Next() { err := getTopicUser.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) diff --git a/panel_routes.go b/panel_routes.go index d3910280..7d910ca0 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -229,21 +229,13 @@ func routePanelForumsCreateSubmit(w http.ResponseWriter, r *http.Request, user c return common.NoPermissions(w, r, user) } - err := r.ParseForm() - if err != nil { - return common.LocalError("Bad Form", w, r, user) - } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } - fname := r.PostFormValue("forum-name") fdesc := r.PostFormValue("forum-desc") fpreset := common.StripInvalidPreset(r.PostFormValue("forum-preset")) factive := r.PostFormValue("forum-name") active := (factive == "on" || factive == "1") - _, err = common.Fstore.Create(fname, fdesc, active, fpreset) + _, err := common.Fstore.Create(fname, fdesc, active, fpreset) if err != nil { return common.InternalError(err, w, r) } @@ -261,9 +253,6 @@ func routePanelForumsDelete(w http.ResponseWriter, r *http.Request, user common. if !user.Perms.ManageForums { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } fid, err := strconv.Atoi(sfid) if err != nil { @@ -301,9 +290,6 @@ func routePanelForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, user c if !user.Perms.ManageForums { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } fid, err := strconv.Atoi(sfid) if err != nil { @@ -380,14 +366,6 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user com if !user.Perms.ManageForums { return common.NoPermissions(w, r, user) } - - err := r.ParseForm() - if err != nil { - return common.LocalError("Bad Form", w, r, user) - } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } isJs := (r.PostFormValue("js") == "1") fid, err := strconv.Atoi(sfid) @@ -435,14 +413,6 @@ func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use if !user.Perms.ManageForums { return common.NoPermissions(w, r, user) } - - err := r.ParseForm() - if err != nil { - return common.LocalError("Bad Form", w, r, user) - } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } isJs := (r.PostFormValue("js") == "1") fid, err := strconv.Atoi(sfid) @@ -620,18 +590,10 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user common.U return common.NoPermissions(w, r, user) } - err := r.ParseForm() - if err != nil { - return common.LocalError("Bad Form", w, r, user) - } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } - var stype, sconstraints string scontent := r.PostFormValue("setting-value") - err = stmts.getFullSetting.QueryRow(sname).Scan(&sname, &stype, &sconstraints) + err := stmts.getFullSetting.QueryRow(sname).Scan(&sname, &stype, &sconstraints) if err == ErrNoRows { return common.LocalError("The setting you want to edit doesn't exist.", w, r, user) } else if err != nil { @@ -665,7 +627,7 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user common.U func routePanelWordFilters(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { headerVars, stats, ferr := common.PanelUserCheck(w, r, &user) if ferr != nil { - return nil + return ferr } if !user.Perms.EditSettings { return common.NoPermissions(w, r, user) @@ -693,11 +655,6 @@ func routePanelWordFiltersCreate(w http.ResponseWriter, r *http.Request, user co if !user.Perms.EditSettings { return common.NoPermissions(w, r, user) } - - err := r.ParseForm() - if err != nil { - return common.PreError("Bad Form", w, r) - } isJs := (r.PostFormValue("js") == "1") find := strings.TrimSpace(r.PostFormValue("find")) @@ -755,11 +712,6 @@ func routePanelWordFiltersEditSubmit(w http.ResponseWriter, r *http.Request, use if ferr != nil { return ferr } - - err := r.ParseForm() - if err != nil { - return common.PreError("Bad Form", w, r) - } // TODO: Either call it isJs or js rather than flip-flopping back and forth across the routes x.x isJs := (r.PostFormValue("isJs") == "1") if !user.Perms.EditSettings { @@ -798,10 +750,6 @@ func routePanelWordFiltersDeleteSubmit(w http.ResponseWriter, r *http.Request, u return ferr } - err := r.ParseForm() - if err != nil { - return common.PreError("Bad Form", w, r) - } isJs := (r.PostFormValue("isJs") == "1") if !user.Perms.EditSettings { return common.NoPermissionsJSQ(w, r, user, isJs) @@ -860,16 +808,11 @@ func routePanelPluginsActivate(w http.ResponseWriter, r *http.Request, user comm if !user.Perms.ManagePlugins { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } - //log.Print("uname","'"+uname+"'") plugin, ok := common.Plugins[uname] if !ok { return common.LocalError("The plugin isn't registered in the system", w, r, user) } - if plugin.Installable && !plugin.Installed { return common.LocalError("You can't activate this plugin without installing it first", w, r, user) } @@ -888,26 +831,19 @@ func routePanelPluginsActivate(w http.ResponseWriter, r *http.Request, user comm } } - //log.Print("err", err) - //log.Print("active", active) if hasPlugin { if active { return common.LocalError("The plugin is already active", w, r, user) } - //log.Print("updatePlugin") _, err = stmts.updatePlugin.Exec(1, uname) - if err != nil { - return common.InternalError(err, w, r) - } } else { - //log.Print("addPlugin") - _, err := stmts.addPlugin.Exec(uname, 1, 0) - if err != nil { - return common.InternalError(err, w, r) - } + _, err = stmts.addPlugin.Exec(uname, 1, 0) + } + if err != nil { + return common.InternalError(err, w, r) } - log.Print("Activating plugin '" + plugin.Name + "'") + log.Printf("Activating plugin '%s'", plugin.Name) plugin.Active = true common.Plugins[uname] = plugin err = common.Plugins[uname].Init() @@ -927,9 +863,6 @@ func routePanelPluginsDeactivate(w http.ResponseWriter, r *http.Request, user co if !user.Perms.ManagePlugins { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } plugin, ok := common.Plugins[uname] if !ok { @@ -968,9 +901,6 @@ func routePanelPluginsInstall(w http.ResponseWriter, r *http.Request, user commo if !user.Perms.ManagePlugins { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } plugin, ok := common.Plugins[uname] if !ok { @@ -1096,7 +1026,6 @@ func routePanelUsersEdit(w http.ResponseWriter, r *http.Request, user common.Use if ferr != nil { return ferr } - if !user.Perms.EditUser { return common.NoPermissions(w, r, user) } @@ -1155,9 +1084,6 @@ func routePanelUsersEditSubmit(w http.ResponseWriter, r *http.Request, user comm if !user.Perms.EditUser { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } uid, err := strconv.Atoi(suid) if err != nil { @@ -1434,9 +1360,6 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user com if !user.Perms.EditGroup { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } gid, err := strconv.Atoi(sgid) if err != nil { @@ -1527,9 +1450,6 @@ func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use if !user.Perms.EditGroup { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } gid, err := strconv.Atoi(sgid) if err != nil { @@ -1551,7 +1471,6 @@ func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) } - ////var lpmap map[string]bool = make(map[string]bool) var pmap = make(map[string]bool) if user.Perms.EditGroupLocalPerms { for _, perm := range common.LocalPermList { @@ -1560,7 +1479,6 @@ func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use } } - ////var gpmap map[string]bool = make(map[string]bool) if user.Perms.EditGroupGlobalPerms { for _, perm := range common.GlobalPermList { pvalue := r.PostFormValue("group-perm-" + perm) @@ -1593,9 +1511,6 @@ func routePanelGroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user c if !user.Perms.EditGroup { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } groupName := r.PostFormValue("group-name") if groupName == "" { @@ -1673,9 +1588,6 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com if !user.Perms.ManageThemes { return common.NoPermissions(w, r, user) } - if r.FormValue("session") != user.Session { - return common.SecurityError(w, r, user) - } theme, ok := common.Themes[uname] if !ok { @@ -1686,7 +1598,6 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com } var isDefault bool - log.Print("uname", uname) // TODO: Do we need to log this? err := stmts.isThemeDefault.QueryRow(uname).Scan(&isDefault) if err != nil && err != ErrNoRows { return common.InternalError(err, w, r) @@ -1694,19 +1605,15 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com hasTheme := err != ErrNoRows if hasTheme { - log.Print("isDefault", isDefault) // TODO: Do we need to log this? if isDefault { return common.LocalError("The theme is already active", w, r, user) } _, err = stmts.updateTheme.Exec(1, uname) - if err != nil { - return common.InternalError(err, w, r) - } } else { - _, err := stmts.addTheme.Exec(uname, 1) - if err != nil { - return common.InternalError(err, w, r) - } + _, err = stmts.addTheme.Exec(uname, 1) + } + if err != nil { + return common.InternalError(err, w, r) } // TODO: Make this less racey @@ -1908,9 +1815,6 @@ func routePanelDebug(w http.ResponseWriter, r *http.Request, user common.User) c if ferr != nil { return ferr } - if !user.IsAdmin { - return common.NoPermissions(w, r, user) - } uptime := "..." dbStats := db.Stats() diff --git a/query_gen/lib/accumulator.go b/query_gen/lib/accumulator.go index e0c5363e..59a85792 100644 --- a/query_gen/lib/accumulator.go +++ b/query_gen/lib/accumulator.go @@ -271,6 +271,14 @@ func (selectItem *selectBuilder) Prepare() *sql.Stmt { return selectItem.build.SimpleSelect(selectItem.table, selectItem.columns, selectItem.where, selectItem.orderby, selectItem.limit) } +func (selectItem *selectBuilder) Query(args ...interface{}) (*sql.Rows, error) { + stmt := selectItem.Prepare() + if stmt != nil { + return stmt.Query(args...) + } + return nil, selectItem.FirstError() +} + func (build *accBuilder) Insert(table string) *insertBuilder { return &insertBuilder{table, "", "", build} } diff --git a/router_gen/routes.go b/router_gen/routes.go index aa731b21..4484886e 100644 --- a/router_gen/routes.go +++ b/router_gen/routes.go @@ -62,45 +62,45 @@ func buildPanelRoutes() { panelGroup.Routes( Route("routePanel", "/panel/"), Route("routePanelForums", "/panel/forums/"), - Route("routePanelForumsCreateSubmit", "/panel/forums/create/"), - Route("routePanelForumsDelete", "/panel/forums/delete/", "extra_data"), - Route("routePanelForumsDeleteSubmit", "/panel/forums/delete/submit/", "extra_data"), + Route("routePanelForumsCreateSubmit", "/panel/forums/create/").Before("NoSessionMismatch"), + Route("routePanelForumsDelete", "/panel/forums/delete/", "extra_data").Before("NoSessionMismatch"), + Route("routePanelForumsDeleteSubmit", "/panel/forums/delete/submit/", "extra_data").Before("NoSessionMismatch"), Route("routePanelForumsEdit", "/panel/forums/edit/", "extra_data"), - Route("routePanelForumsEditSubmit", "/panel/forums/edit/submit/", "extra_data"), - Route("routePanelForumsEditPermsSubmit", "/panel/forums/edit/perms/submit/", "extra_data"), + Route("routePanelForumsEditSubmit", "/panel/forums/edit/submit/", "extra_data").Before("NoSessionMismatch"), + Route("routePanelForumsEditPermsSubmit", "/panel/forums/edit/perms/submit/", "extra_data").Before("NoSessionMismatch"), Route("routePanelSettings", "/panel/settings/"), Route("routePanelSetting", "/panel/settings/edit/", "extra_data"), - Route("routePanelSettingEdit", "/panel/settings/edit/submit/", "extra_data"), + Route("routePanelSettingEdit", "/panel/settings/edit/submit/", "extra_data").Before("NoSessionMismatch"), Route("routePanelWordFilters", "/panel/settings/word-filters/"), - Route("routePanelWordFiltersCreate", "/panel/settings/word-filters/create/"), + Route("routePanelWordFiltersCreate", "/panel/settings/word-filters/create/").Before("ParseForm"), Route("routePanelWordFiltersEdit", "/panel/settings/word-filters/edit/", "extra_data"), - Route("routePanelWordFiltersEditSubmit", "/panel/settings/word-filters/edit/submit/", "extra_data"), - Route("routePanelWordFiltersDeleteSubmit", "/panel/settings/word-filters/delete/submit/", "extra_data"), + Route("routePanelWordFiltersEditSubmit", "/panel/settings/word-filters/edit/submit/", "extra_data").Before("ParseForm"), + Route("routePanelWordFiltersDeleteSubmit", "/panel/settings/word-filters/delete/submit/", "extra_data").Before("ParseForm"), Route("routePanelThemes", "/panel/themes/"), - Route("routePanelThemesSetDefault", "/panel/themes/default/", "extra_data"), + Route("routePanelThemesSetDefault", "/panel/themes/default/", "extra_data").Before("NoSessionMismatch"), Route("routePanelPlugins", "/panel/plugins/"), - Route("routePanelPluginsActivate", "/panel/plugins/activate/", "extra_data"), - Route("routePanelPluginsDeactivate", "/panel/plugins/deactivate/", "extra_data"), - Route("routePanelPluginsInstall", "/panel/plugins/install/", "extra_data"), + Route("routePanelPluginsActivate", "/panel/plugins/activate/", "extra_data").Before("NoSessionMismatch"), + Route("routePanelPluginsDeactivate", "/panel/plugins/deactivate/", "extra_data").Before("NoSessionMismatch"), + Route("routePanelPluginsInstall", "/panel/plugins/install/", "extra_data").Before("NoSessionMismatch"), Route("routePanelUsers", "/panel/users/"), Route("routePanelUsersEdit", "/panel/users/edit/", "extra_data"), - Route("routePanelUsersEditSubmit", "/panel/users/edit/submit/", "extra_data"), + Route("routePanelUsersEditSubmit", "/panel/users/edit/submit/", "extra_data").Before("NoSessionMismatch"), Route("routePanelGroups", "/panel/groups/"), Route("routePanelGroupsEdit", "/panel/groups/edit/", "extra_data"), Route("routePanelGroupsEditPerms", "/panel/groups/edit/perms/", "extra_data"), - Route("routePanelGroupsEditSubmit", "/panel/groups/edit/submit/", "extra_data"), - Route("routePanelGroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extra_data"), - Route("routePanelGroupsCreateSubmit", "/panel/groups/create/"), + Route("routePanelGroupsEditSubmit", "/panel/groups/edit/submit/", "extra_data").Before("NoSessionMismatch"), + Route("routePanelGroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extra_data").Before("NoSessionMismatch"), + Route("routePanelGroupsCreateSubmit", "/panel/groups/create/").Before("NoSessionMismatch"), Route("routePanelBackups", "/panel/backups/", "extra_data"), Route("routePanelLogsMod", "/panel/logs/mod/"), - Route("routePanelDebug", "/panel/debug/"), + Route("routePanelDebug", "/panel/debug/").Before("AdminOnly"), ) addRouteGroup(panelGroup) } diff --git a/routes.go b/routes.go index 10a8a684..1f217a3e 100644 --- a/routes.go +++ b/routes.go @@ -202,6 +202,7 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo if err != nil { return common.InternalError(err, w, r) } + defer topicCountStmt.Close() var topicCount int err = topicCountStmt.QueryRow(argList...).Scan(&topicCount) @@ -229,6 +230,7 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo if err != nil { return common.InternalError(err, w, r) } + defer stmt.Close() argList = append(argList, offset) argList = append(argList, common.Config.ItemsPerPage)