Moved the modlog and admin log logic to their own file.
Refactored the code to use the new builder syntax. Fixed the DbInit logic. Made sure the prepared statements are cleaned up. Added the AdminOnly middleware and added it to the routes. Added the Query method to the selectBuilder.
This commit is contained in:
parent
7ac3de8299
commit
6bae378db0
|
@ -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
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import "database/sql"
|
import (
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
// nolint I don't want to write comments for each of these o.o
|
// nolint I don't want to write comments for each of these o.o
|
||||||
const Hour int = 60 * 60
|
const Hour int = 60 * 60
|
||||||
|
@ -60,11 +62,11 @@ func (slice StringList) Contains(needle string) bool {
|
||||||
return false
|
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 {
|
for _, init := range inits {
|
||||||
err := init()
|
err := init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -74,6 +76,6 @@ func (inits DBInits) Run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inits DBInits) Add(init ...func() error) {
|
func (inits dbInits) Add(init ...func() error) {
|
||||||
inits = append(inits, init...)
|
DbInits = dbInits(append(DbInits, init...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -137,6 +138,22 @@ type Plugin struct {
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
func InitExtend() (err error) {
|
||||||
err = InitPluginLangs()
|
err = InitPluginLangs()
|
||||||
if err != nil {
|
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
|
// Load polls the database to see which plugins have been activated and which have been installed
|
||||||
func (plugins PluginList) Load() error {
|
func (plugins PluginList) Load() error {
|
||||||
getPlugins, err := qgen.Builder.SimpleSelect("plugins", "uname, active, installed", "", "", "")
|
rows, err := extendStmts.getPlugins.Query()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rows, err := getPlugins.Query()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -283,24 +296,24 @@ func (plugin *Plugin) RemoveHook(name string, handler interface{}) {
|
||||||
delete(plugin.Hooks, name)
|
delete(plugin.Hooks, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var pluginsInited = false
|
var PluginsInited = false
|
||||||
|
|
||||||
func InitPlugins() {
|
func InitPlugins() {
|
||||||
for name, body := range Plugins {
|
for name, body := range Plugins {
|
||||||
log.Printf("Added plugin %s", name)
|
log.Printf("Added plugin '%s'", name)
|
||||||
if body.Active {
|
if body.Active {
|
||||||
log.Printf("Initialised plugin %s", name)
|
log.Printf("Initialised plugin '%s'", name)
|
||||||
if Plugins[name].Init != nil {
|
if Plugins[name].Init != nil {
|
||||||
err := Plugins[name].Init()
|
err := Plugins[name].Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
} else {
|
} 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?
|
// ? - Are the following functions racey?
|
||||||
|
|
|
@ -25,18 +25,11 @@ type MemoryForumPermsStore struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
||||||
getPermsStmt, err := qgen.Builder.SimpleSelect("forums_permissions", "gid, fid, permissions", "", "gid ASC, fid ASC", "")
|
acc := qgen.Builder.Accumulator()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
getPermsByForumStmt, err := qgen.Builder.SimpleSelect("forums_permissions", "gid, permissions", "fid = ?", "gid ASC", "")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &MemoryForumPermsStore{
|
return &MemoryForumPermsStore{
|
||||||
get: getPermsStmt,
|
get: acc.Select("forums_permissions").Columns("gid, fid, permissions").Orderby("gid ASC, fid ASC").Prepare(),
|
||||||
getByForum: getPermsByForumStmt,
|
getByForum: acc.Select("forums_permissions").Columns("gid, permissions").Where("fid = ?").Orderby("gid ASC").Prepare(),
|
||||||
}, nil
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fps *MemoryForumPermsStore) Init() error {
|
func (fps *MemoryForumPermsStore) Init() error {
|
||||||
|
|
|
@ -483,6 +483,7 @@ func RebuildGroupPermissions(gid int) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer getGroupPerms.Close()
|
||||||
|
|
||||||
err = getGroupPerms.QueryRow(gid).Scan(&permstr)
|
err = getGroupPerms.QueryRow(gid).Scan(&permstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -294,6 +294,14 @@ func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
|
||||||
return *usercpy, true
|
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
|
// 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 {
|
func SuperModOnly(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||||
if !user.IsSuperMod {
|
if !user.IsSuperMod {
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
import "strings"
|
"database/sql"
|
||||||
import "sync/atomic"
|
"strconv"
|
||||||
import "../query_gen/lib"
|
"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
|
// 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{}
|
type SettingMap map[string]interface{}
|
||||||
|
@ -23,17 +27,25 @@ type Setting struct {
|
||||||
Constraint string
|
Constraint string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SettingStmts struct {
|
||||||
|
getFull *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingStmts SettingStmts
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
SettingBox.Store(SettingMap(make(map[string]interface{})))
|
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 {
|
func LoadSettings() error {
|
||||||
// TODO: Stop doing this inline
|
rows, err := settingStmts.getFull.Query()
|
||||||
getFullSettings, err := qgen.Builder.SimpleSelect("settings", "name, content, type, constraints", "", "", "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rows, err := getFullSettings.Query()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,24 +7,35 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"../query_gen/lib"
|
"../query_gen/lib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TaskStmts struct {
|
||||||
|
getExpiredScheduledGroups *sql.Stmt
|
||||||
|
getSync *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
var taskStmts TaskStmts
|
||||||
var lastSync time.Time
|
var lastSync time.Time
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lastSync = time.Now()
|
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 {
|
func HandleExpiredScheduledGroups() error {
|
||||||
getExpiredScheduledGroups, err := qgen.Builder.SimpleSelect("users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", "")
|
rows, err := taskStmts.getExpiredScheduledGroups.Query()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rows, err := getExpiredScheduledGroups.Query()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -50,11 +61,7 @@ func HandleExpiredScheduledGroups() error {
|
||||||
|
|
||||||
func HandleServerSync() error {
|
func HandleServerSync() error {
|
||||||
var lastUpdate time.Time
|
var lastUpdate time.Time
|
||||||
getSync, err := qgen.Builder.SimpleSelect("sync", "last_update", "", "", "")
|
err := taskStmts.getSync.QueryRow().Scan(&lastUpdate)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = getSync.QueryRow().Scan(&lastUpdate)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package common
|
||||||
import (
|
import (
|
||||||
//"fmt"
|
//"fmt"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -74,20 +75,28 @@ type ThemeResource struct {
|
||||||
Location string
|
Location string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ThemeStmts struct {
|
||||||
|
getThemes *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
var themeStmts ThemeStmts
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
DefaultThemeBox.Store(fallbackTheme)
|
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
|
// TODO: Make the initThemes and LoadThemes functions less confusing
|
||||||
// ? - Delete themes which no longer exist in the themes folder from the database?
|
// ? - Delete themes which no longer exist in the themes folder from the database?
|
||||||
func (themes ThemeList) LoadActiveStatus() error {
|
func (themes ThemeList) LoadActiveStatus() error {
|
||||||
getThemes, err := qgen.Builder.SimpleSelect("themes", "uname, default", "", "", "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ChangeDefaultThemeMutex.Lock()
|
ChangeDefaultThemeMutex.Lock()
|
||||||
rows, err := getThemes.Query()
|
rows, err := themeStmts.getThemes.Query()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,12 +170,8 @@ func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
|
||||||
}
|
}
|
||||||
qlist = qlist[0 : len(qlist)-1]
|
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+")", "", "")
|
acc := qgen.Builder.Accumulator()
|
||||||
if err != nil {
|
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...)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rows, err := stmt.Query(uidList...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -187,13 +183,8 @@ func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the user
|
|
||||||
user.Init()
|
user.Init()
|
||||||
|
mus.CacheSet(user)
|
||||||
// Add it to the cache...
|
|
||||||
_ = mus.CacheSet(user)
|
|
||||||
|
|
||||||
// Add it to the list to be returned
|
|
||||||
list[user.ID] = 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]
|
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) {
|
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]
|
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+")", "", "")
|
acc := qgen.Builder.Accumulator()
|
||||||
if err != nil {
|
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...)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rows, err := stmt.Query(uidList...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -438,10 +425,7 @@ func (mus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the user
|
|
||||||
user.Init()
|
user.Init()
|
||||||
|
|
||||||
// Add it to the list to be returned
|
|
||||||
list[user.ID] = user
|
list[user.ID] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"../query_gen/lib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version stores a Gosora version
|
// Version stores a Gosora version
|
||||||
|
@ -374,23 +372,3 @@ func BuildSlug(slug string, id int) string {
|
||||||
}
|
}
|
||||||
return slug + "." + strconv.Itoa(id)
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
/* Copyright Azareal 2017 - 2018 */
|
/* Copyright Azareal 2017 - 2018 */
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import "log"
|
import (
|
||||||
import "bytes"
|
"bytes"
|
||||||
import "sync"
|
"database/sql"
|
||||||
import "encoding/json"
|
"encoding/json"
|
||||||
import "../query_gen/lib"
|
"log"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"../query_gen/lib"
|
||||||
|
)
|
||||||
|
|
||||||
var Docks WidgetDocks
|
var Docks WidgetDocks
|
||||||
var widgetUpdateMutex sync.RWMutex
|
var widgetUpdateMutex sync.RWMutex
|
||||||
|
@ -39,13 +43,25 @@ type NameTextPair struct {
|
||||||
Text string
|
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?
|
// TODO: Make a store for this?
|
||||||
func InitWidgets() error {
|
func InitWidgets() error {
|
||||||
getWidgets, err := qgen.Builder.SimpleSelect("widgets", "position, side, type, active, location, data", "", "position ASC", "")
|
rows, err := widgetStmts.getWidgets.Query()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rows, err := getWidgets.Query()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import "sync/atomic"
|
import (
|
||||||
import "../query_gen/lib"
|
"database/sql"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"../query_gen/lib"
|
||||||
|
)
|
||||||
|
|
||||||
type WordFilter struct {
|
type WordFilter struct {
|
||||||
ID int
|
ID int
|
||||||
|
@ -12,16 +16,25 @@ type WordFilterMap map[int]WordFilter
|
||||||
|
|
||||||
var WordFilterBox atomic.Value // An atomic value holding a WordFilterBox
|
var WordFilterBox atomic.Value // An atomic value holding a WordFilterBox
|
||||||
|
|
||||||
|
type FilterStmts struct {
|
||||||
|
getWordFilters *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterStmts FilterStmts
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
WordFilterBox.Store(WordFilterMap(make(map[int]WordFilter)))
|
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 {
|
func LoadWordFilters() error {
|
||||||
getWordFilters, err := qgen.Builder.SimpleSelect("word_filters", "wfid, find, replacement", "", "", "")
|
rows, err := filterStmts.getWordFilters.Query()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rows, err := getWordFilters.Query()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ func InitDatabase() (err error) {
|
||||||
}
|
}
|
||||||
globs = &Globs{stmts}
|
globs = &Globs{stmts}
|
||||||
|
|
||||||
|
log.Print("Running the db handlers.")
|
||||||
err = common.DbInits.Run()
|
err = common.DbInits.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
108
gen_router.go
108
gen_router.go
|
@ -192,50 +192,134 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
case "/panel/forums/":
|
case "/panel/forums/":
|
||||||
err = routePanelForums(w,req,user)
|
err = routePanelForums(w,req,user)
|
||||||
case "/panel/forums/create/":
|
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)
|
err = routePanelForumsCreateSubmit(w,req,user)
|
||||||
case "/panel/forums/delete/":
|
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)
|
err = routePanelForumsDelete(w,req,user,extra_data)
|
||||||
case "/panel/forums/delete/submit/":
|
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)
|
err = routePanelForumsDeleteSubmit(w,req,user,extra_data)
|
||||||
case "/panel/forums/edit/":
|
case "/panel/forums/edit/":
|
||||||
err = routePanelForumsEdit(w,req,user,extra_data)
|
err = routePanelForumsEdit(w,req,user,extra_data)
|
||||||
case "/panel/forums/edit/submit/":
|
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)
|
err = routePanelForumsEditSubmit(w,req,user,extra_data)
|
||||||
case "/panel/forums/edit/perms/submit/":
|
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)
|
err = routePanelForumsEditPermsSubmit(w,req,user,extra_data)
|
||||||
case "/panel/settings/":
|
case "/panel/settings/":
|
||||||
err = routePanelSettings(w,req,user)
|
err = routePanelSettings(w,req,user)
|
||||||
case "/panel/settings/edit/":
|
case "/panel/settings/edit/":
|
||||||
err = routePanelSetting(w,req,user,extra_data)
|
err = routePanelSetting(w,req,user,extra_data)
|
||||||
case "/panel/settings/edit/submit/":
|
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)
|
err = routePanelSettingEdit(w,req,user,extra_data)
|
||||||
case "/panel/settings/word-filters/":
|
case "/panel/settings/word-filters/":
|
||||||
err = routePanelWordFilters(w,req,user)
|
err = routePanelWordFilters(w,req,user)
|
||||||
case "/panel/settings/word-filters/create/":
|
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)
|
err = routePanelWordFiltersCreate(w,req,user)
|
||||||
case "/panel/settings/word-filters/edit/":
|
case "/panel/settings/word-filters/edit/":
|
||||||
err = routePanelWordFiltersEdit(w,req,user,extra_data)
|
err = routePanelWordFiltersEdit(w,req,user,extra_data)
|
||||||
case "/panel/settings/word-filters/edit/submit/":
|
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)
|
err = routePanelWordFiltersEditSubmit(w,req,user,extra_data)
|
||||||
case "/panel/settings/word-filters/delete/submit/":
|
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)
|
err = routePanelWordFiltersDeleteSubmit(w,req,user,extra_data)
|
||||||
case "/panel/themes/":
|
case "/panel/themes/":
|
||||||
err = routePanelThemes(w,req,user)
|
err = routePanelThemes(w,req,user)
|
||||||
case "/panel/themes/default/":
|
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)
|
err = routePanelThemesSetDefault(w,req,user,extra_data)
|
||||||
case "/panel/plugins/":
|
case "/panel/plugins/":
|
||||||
err = routePanelPlugins(w,req,user)
|
err = routePanelPlugins(w,req,user)
|
||||||
case "/panel/plugins/activate/":
|
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)
|
err = routePanelPluginsActivate(w,req,user,extra_data)
|
||||||
case "/panel/plugins/deactivate/":
|
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)
|
err = routePanelPluginsDeactivate(w,req,user,extra_data)
|
||||||
case "/panel/plugins/install/":
|
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)
|
err = routePanelPluginsInstall(w,req,user,extra_data)
|
||||||
case "/panel/users/":
|
case "/panel/users/":
|
||||||
err = routePanelUsers(w,req,user)
|
err = routePanelUsers(w,req,user)
|
||||||
case "/panel/users/edit/":
|
case "/panel/users/edit/":
|
||||||
err = routePanelUsersEdit(w,req,user,extra_data)
|
err = routePanelUsersEdit(w,req,user,extra_data)
|
||||||
case "/panel/users/edit/submit/":
|
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)
|
err = routePanelUsersEditSubmit(w,req,user,extra_data)
|
||||||
case "/panel/groups/":
|
case "/panel/groups/":
|
||||||
err = routePanelGroups(w,req,user)
|
err = routePanelGroups(w,req,user)
|
||||||
|
@ -244,16 +328,40 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
case "/panel/groups/edit/perms/":
|
case "/panel/groups/edit/perms/":
|
||||||
err = routePanelGroupsEditPerms(w,req,user,extra_data)
|
err = routePanelGroupsEditPerms(w,req,user,extra_data)
|
||||||
case "/panel/groups/edit/submit/":
|
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)
|
err = routePanelGroupsEditSubmit(w,req,user,extra_data)
|
||||||
case "/panel/groups/edit/perms/submit/":
|
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)
|
err = routePanelGroupsEditPermsSubmit(w,req,user,extra_data)
|
||||||
case "/panel/groups/create/":
|
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)
|
err = routePanelGroupsCreateSubmit(w,req,user)
|
||||||
case "/panel/backups/":
|
case "/panel/backups/":
|
||||||
err = routePanelBackups(w,req,user,extra_data)
|
err = routePanelBackups(w,req,user,extra_data)
|
||||||
case "/panel/logs/mod/":
|
case "/panel/logs/mod/":
|
||||||
err = routePanelLogsMod(w,req,user)
|
err = routePanelLogsMod(w,req,user)
|
||||||
case "/panel/debug/":
|
case "/panel/debug/":
|
||||||
|
err = common.AdminOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
router.handleError(err,w,req,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = routePanelDebug(w,req,user)
|
err = routePanelDebug(w,req,user)
|
||||||
default:
|
default:
|
||||||
err = routePanel(w,req,user)
|
err = routePanel(w,req,user)
|
||||||
|
|
|
@ -553,6 +553,7 @@ func BenchmarkQueryPreparedTopicParallel(b *testing.B) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer getTopicUser.Close()
|
||||||
|
|
||||||
for pb.Next() {
|
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)
|
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)
|
||||||
|
|
120
panel_routes.go
120
panel_routes.go
|
@ -229,21 +229,13 @@ func routePanelForumsCreateSubmit(w http.ResponseWriter, r *http.Request, user c
|
||||||
return common.NoPermissions(w, r, user)
|
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")
|
fname := r.PostFormValue("forum-name")
|
||||||
fdesc := r.PostFormValue("forum-desc")
|
fdesc := r.PostFormValue("forum-desc")
|
||||||
fpreset := common.StripInvalidPreset(r.PostFormValue("forum-preset"))
|
fpreset := common.StripInvalidPreset(r.PostFormValue("forum-preset"))
|
||||||
factive := r.PostFormValue("forum-name")
|
factive := r.PostFormValue("forum-name")
|
||||||
active := (factive == "on" || factive == "1")
|
active := (factive == "on" || factive == "1")
|
||||||
|
|
||||||
_, err = common.Fstore.Create(fname, fdesc, active, fpreset)
|
_, err := common.Fstore.Create(fname, fdesc, active, fpreset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
@ -261,9 +253,6 @@ func routePanelForumsDelete(w http.ResponseWriter, r *http.Request, user common.
|
||||||
if !user.Perms.ManageForums {
|
if !user.Perms.ManageForums {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -301,9 +290,6 @@ func routePanelForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, user c
|
||||||
if !user.Perms.ManageForums {
|
if !user.Perms.ManageForums {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -380,14 +366,6 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user com
|
||||||
if !user.Perms.ManageForums {
|
if !user.Perms.ManageForums {
|
||||||
return common.NoPermissions(w, r, user)
|
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")
|
isJs := (r.PostFormValue("js") == "1")
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
|
@ -435,14 +413,6 @@ func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
|
||||||
if !user.Perms.ManageForums {
|
if !user.Perms.ManageForums {
|
||||||
return common.NoPermissions(w, r, user)
|
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")
|
isJs := (r.PostFormValue("js") == "1")
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
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)
|
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
|
var stype, sconstraints string
|
||||||
scontent := r.PostFormValue("setting-value")
|
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 {
|
if err == ErrNoRows {
|
||||||
return common.LocalError("The setting you want to edit doesn't exist.", w, r, user)
|
return common.LocalError("The setting you want to edit doesn't exist.", w, r, user)
|
||||||
} else if err != nil {
|
} 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 {
|
func routePanelWordFilters(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return nil
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.EditSettings {
|
if !user.Perms.EditSettings {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
|
@ -693,11 +655,6 @@ func routePanelWordFiltersCreate(w http.ResponseWriter, r *http.Request, user co
|
||||||
if !user.Perms.EditSettings {
|
if !user.Perms.EditSettings {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.ParseForm()
|
|
||||||
if err != nil {
|
|
||||||
return common.PreError("Bad Form", w, r)
|
|
||||||
}
|
|
||||||
isJs := (r.PostFormValue("js") == "1")
|
isJs := (r.PostFormValue("js") == "1")
|
||||||
|
|
||||||
find := strings.TrimSpace(r.PostFormValue("find"))
|
find := strings.TrimSpace(r.PostFormValue("find"))
|
||||||
|
@ -755,11 +712,6 @@ func routePanelWordFiltersEditSubmit(w http.ResponseWriter, r *http.Request, use
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
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
|
// TODO: Either call it isJs or js rather than flip-flopping back and forth across the routes x.x
|
||||||
isJs := (r.PostFormValue("isJs") == "1")
|
isJs := (r.PostFormValue("isJs") == "1")
|
||||||
if !user.Perms.EditSettings {
|
if !user.Perms.EditSettings {
|
||||||
|
@ -798,10 +750,6 @@ func routePanelWordFiltersDeleteSubmit(w http.ResponseWriter, r *http.Request, u
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.ParseForm()
|
|
||||||
if err != nil {
|
|
||||||
return common.PreError("Bad Form", w, r)
|
|
||||||
}
|
|
||||||
isJs := (r.PostFormValue("isJs") == "1")
|
isJs := (r.PostFormValue("isJs") == "1")
|
||||||
if !user.Perms.EditSettings {
|
if !user.Perms.EditSettings {
|
||||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
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 {
|
if !user.Perms.ManagePlugins {
|
||||||
return common.NoPermissions(w, r, user)
|
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]
|
plugin, ok := common.Plugins[uname]
|
||||||
if !ok {
|
if !ok {
|
||||||
return common.LocalError("The plugin isn't registered in the system", w, r, user)
|
return common.LocalError("The plugin isn't registered in the system", w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
if plugin.Installable && !plugin.Installed {
|
if plugin.Installable && !plugin.Installed {
|
||||||
return common.LocalError("You can't activate this plugin without installing it first", w, r, user)
|
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 hasPlugin {
|
||||||
if active {
|
if active {
|
||||||
return common.LocalError("The plugin is already active", w, r, user)
|
return common.LocalError("The plugin is already active", w, r, user)
|
||||||
}
|
}
|
||||||
//log.Print("updatePlugin")
|
|
||||||
_, err = stmts.updatePlugin.Exec(1, uname)
|
_, err = stmts.updatePlugin.Exec(1, uname)
|
||||||
if err != nil {
|
|
||||||
return common.InternalError(err, w, r)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//log.Print("addPlugin")
|
_, err = stmts.addPlugin.Exec(uname, 1, 0)
|
||||||
_, err := stmts.addPlugin.Exec(uname, 1, 0)
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Print("Activating plugin '" + plugin.Name + "'")
|
log.Printf("Activating plugin '%s'", plugin.Name)
|
||||||
plugin.Active = true
|
plugin.Active = true
|
||||||
common.Plugins[uname] = plugin
|
common.Plugins[uname] = plugin
|
||||||
err = common.Plugins[uname].Init()
|
err = common.Plugins[uname].Init()
|
||||||
|
@ -927,9 +863,6 @@ func routePanelPluginsDeactivate(w http.ResponseWriter, r *http.Request, user co
|
||||||
if !user.Perms.ManagePlugins {
|
if !user.Perms.ManagePlugins {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin, ok := common.Plugins[uname]
|
plugin, ok := common.Plugins[uname]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -968,9 +901,6 @@ func routePanelPluginsInstall(w http.ResponseWriter, r *http.Request, user commo
|
||||||
if !user.Perms.ManagePlugins {
|
if !user.Perms.ManagePlugins {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin, ok := common.Plugins[uname]
|
plugin, ok := common.Plugins[uname]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -1096,7 +1026,6 @@ func routePanelUsersEdit(w http.ResponseWriter, r *http.Request, user common.Use
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.Perms.EditUser {
|
if !user.Perms.EditUser {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
|
@ -1155,9 +1084,6 @@ func routePanelUsersEditSubmit(w http.ResponseWriter, r *http.Request, user comm
|
||||||
if !user.Perms.EditUser {
|
if !user.Perms.EditUser {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
uid, err := strconv.Atoi(suid)
|
uid, err := strconv.Atoi(suid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1434,9 +1360,6 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user com
|
||||||
if !user.Perms.EditGroup {
|
if !user.Perms.EditGroup {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
gid, err := strconv.Atoi(sgid)
|
gid, err := strconv.Atoi(sgid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1527,9 +1450,6 @@ func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
|
||||||
if !user.Perms.EditGroup {
|
if !user.Perms.EditGroup {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
gid, err := strconv.Atoi(sgid)
|
gid, err := strconv.Atoi(sgid)
|
||||||
if err != nil {
|
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)
|
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)
|
var pmap = make(map[string]bool)
|
||||||
if user.Perms.EditGroupLocalPerms {
|
if user.Perms.EditGroupLocalPerms {
|
||||||
for _, perm := range common.LocalPermList {
|
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 {
|
if user.Perms.EditGroupGlobalPerms {
|
||||||
for _, perm := range common.GlobalPermList {
|
for _, perm := range common.GlobalPermList {
|
||||||
pvalue := r.PostFormValue("group-perm-" + perm)
|
pvalue := r.PostFormValue("group-perm-" + perm)
|
||||||
|
@ -1593,9 +1511,6 @@ func routePanelGroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user c
|
||||||
if !user.Perms.EditGroup {
|
if !user.Perms.EditGroup {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
groupName := r.PostFormValue("group-name")
|
groupName := r.PostFormValue("group-name")
|
||||||
if groupName == "" {
|
if groupName == "" {
|
||||||
|
@ -1673,9 +1588,6 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com
|
||||||
if !user.Perms.ManageThemes {
|
if !user.Perms.ManageThemes {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
if r.FormValue("session") != user.Session {
|
|
||||||
return common.SecurityError(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
theme, ok := common.Themes[uname]
|
theme, ok := common.Themes[uname]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -1686,7 +1598,6 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com
|
||||||
}
|
}
|
||||||
|
|
||||||
var isDefault bool
|
var isDefault bool
|
||||||
log.Print("uname", uname) // TODO: Do we need to log this?
|
|
||||||
err := stmts.isThemeDefault.QueryRow(uname).Scan(&isDefault)
|
err := stmts.isThemeDefault.QueryRow(uname).Scan(&isDefault)
|
||||||
if err != nil && err != ErrNoRows {
|
if err != nil && err != ErrNoRows {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
|
@ -1694,19 +1605,15 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com
|
||||||
|
|
||||||
hasTheme := err != ErrNoRows
|
hasTheme := err != ErrNoRows
|
||||||
if hasTheme {
|
if hasTheme {
|
||||||
log.Print("isDefault", isDefault) // TODO: Do we need to log this?
|
|
||||||
if isDefault {
|
if isDefault {
|
||||||
return common.LocalError("The theme is already active", w, r, user)
|
return common.LocalError("The theme is already active", w, r, user)
|
||||||
}
|
}
|
||||||
_, err = stmts.updateTheme.Exec(1, uname)
|
_, err = stmts.updateTheme.Exec(1, uname)
|
||||||
if err != nil {
|
|
||||||
return common.InternalError(err, w, r)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
_, err := stmts.addTheme.Exec(uname, 1)
|
_, err = stmts.addTheme.Exec(uname, 1)
|
||||||
if err != nil {
|
}
|
||||||
return common.InternalError(err, w, r)
|
if err != nil {
|
||||||
}
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make this less racey
|
// TODO: Make this less racey
|
||||||
|
@ -1908,9 +1815,6 @@ func routePanelDebug(w http.ResponseWriter, r *http.Request, user common.User) c
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.IsAdmin {
|
|
||||||
return common.NoPermissions(w, r, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
uptime := "..."
|
uptime := "..."
|
||||||
dbStats := db.Stats()
|
dbStats := db.Stats()
|
||||||
|
|
|
@ -271,6 +271,14 @@ func (selectItem *selectBuilder) Prepare() *sql.Stmt {
|
||||||
return selectItem.build.SimpleSelect(selectItem.table, selectItem.columns, selectItem.where, selectItem.orderby, selectItem.limit)
|
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 {
|
func (build *accBuilder) Insert(table string) *insertBuilder {
|
||||||
return &insertBuilder{table, "", "", build}
|
return &insertBuilder{table, "", "", build}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,45 +62,45 @@ func buildPanelRoutes() {
|
||||||
panelGroup.Routes(
|
panelGroup.Routes(
|
||||||
Route("routePanel", "/panel/"),
|
Route("routePanel", "/panel/"),
|
||||||
Route("routePanelForums", "/panel/forums/"),
|
Route("routePanelForums", "/panel/forums/"),
|
||||||
Route("routePanelForumsCreateSubmit", "/panel/forums/create/"),
|
Route("routePanelForumsCreateSubmit", "/panel/forums/create/").Before("NoSessionMismatch"),
|
||||||
Route("routePanelForumsDelete", "/panel/forums/delete/", "extra_data"),
|
Route("routePanelForumsDelete", "/panel/forums/delete/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelForumsDeleteSubmit", "/panel/forums/delete/submit/", "extra_data"),
|
Route("routePanelForumsDeleteSubmit", "/panel/forums/delete/submit/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelForumsEdit", "/panel/forums/edit/", "extra_data"),
|
Route("routePanelForumsEdit", "/panel/forums/edit/", "extra_data"),
|
||||||
Route("routePanelForumsEditSubmit", "/panel/forums/edit/submit/", "extra_data"),
|
Route("routePanelForumsEditSubmit", "/panel/forums/edit/submit/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelForumsEditPermsSubmit", "/panel/forums/edit/perms/submit/", "extra_data"),
|
Route("routePanelForumsEditPermsSubmit", "/panel/forums/edit/perms/submit/", "extra_data").Before("NoSessionMismatch"),
|
||||||
|
|
||||||
Route("routePanelSettings", "/panel/settings/"),
|
Route("routePanelSettings", "/panel/settings/"),
|
||||||
Route("routePanelSetting", "/panel/settings/edit/", "extra_data"),
|
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("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("routePanelWordFiltersEdit", "/panel/settings/word-filters/edit/", "extra_data"),
|
||||||
Route("routePanelWordFiltersEditSubmit", "/panel/settings/word-filters/edit/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"),
|
Route("routePanelWordFiltersDeleteSubmit", "/panel/settings/word-filters/delete/submit/", "extra_data").Before("ParseForm"),
|
||||||
|
|
||||||
Route("routePanelThemes", "/panel/themes/"),
|
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("routePanelPlugins", "/panel/plugins/"),
|
||||||
Route("routePanelPluginsActivate", "/panel/plugins/activate/", "extra_data"),
|
Route("routePanelPluginsActivate", "/panel/plugins/activate/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelPluginsDeactivate", "/panel/plugins/deactivate/", "extra_data"),
|
Route("routePanelPluginsDeactivate", "/panel/plugins/deactivate/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelPluginsInstall", "/panel/plugins/install/", "extra_data"),
|
Route("routePanelPluginsInstall", "/panel/plugins/install/", "extra_data").Before("NoSessionMismatch"),
|
||||||
|
|
||||||
Route("routePanelUsers", "/panel/users/"),
|
Route("routePanelUsers", "/panel/users/"),
|
||||||
Route("routePanelUsersEdit", "/panel/users/edit/", "extra_data"),
|
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("routePanelGroups", "/panel/groups/"),
|
||||||
Route("routePanelGroupsEdit", "/panel/groups/edit/", "extra_data"),
|
Route("routePanelGroupsEdit", "/panel/groups/edit/", "extra_data"),
|
||||||
Route("routePanelGroupsEditPerms", "/panel/groups/edit/perms/", "extra_data"),
|
Route("routePanelGroupsEditPerms", "/panel/groups/edit/perms/", "extra_data"),
|
||||||
Route("routePanelGroupsEditSubmit", "/panel/groups/edit/submit/", "extra_data"),
|
Route("routePanelGroupsEditSubmit", "/panel/groups/edit/submit/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelGroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extra_data"),
|
Route("routePanelGroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extra_data").Before("NoSessionMismatch"),
|
||||||
Route("routePanelGroupsCreateSubmit", "/panel/groups/create/"),
|
Route("routePanelGroupsCreateSubmit", "/panel/groups/create/").Before("NoSessionMismatch"),
|
||||||
|
|
||||||
Route("routePanelBackups", "/panel/backups/", "extra_data"),
|
Route("routePanelBackups", "/panel/backups/", "extra_data"),
|
||||||
Route("routePanelLogsMod", "/panel/logs/mod/"),
|
Route("routePanelLogsMod", "/panel/logs/mod/"),
|
||||||
Route("routePanelDebug", "/panel/debug/"),
|
Route("routePanelDebug", "/panel/debug/").Before("AdminOnly"),
|
||||||
)
|
)
|
||||||
addRouteGroup(panelGroup)
|
addRouteGroup(panelGroup)
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,7 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
defer topicCountStmt.Close()
|
||||||
|
|
||||||
var topicCount int
|
var topicCount int
|
||||||
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
|
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 {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
argList = append(argList, offset)
|
argList = append(argList, offset)
|
||||||
argList = append(argList, common.Config.ItemsPerPage)
|
argList = append(argList, common.Config.ItemsPerPage)
|
||||||
|
|
Loading…
Reference in New Issue