More refactoring. So much data o.o
Fixed the tests. Added wrapper functions for the various logging levels. Added the SetPreset method to *Forum. Added the ReloadGroup to the ForumPermsStore.
This commit is contained in:
parent
0572c3e048
commit
b42181c0c6
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
@ -82,3 +83,27 @@ func (inits dbInits) Run() error {
|
|||
func (inits dbInits) Add(init ...func(acc *qgen.Accumulator) error) {
|
||||
DbInits = dbInits(append(DbInits, init...))
|
||||
}
|
||||
|
||||
func debugDetail(args ...interface{}) {
|
||||
if Dev.SuperDebug {
|
||||
log.Print(args...)
|
||||
}
|
||||
}
|
||||
|
||||
func debugDetailf(str string, args ...interface{}) {
|
||||
if Dev.SuperDebug {
|
||||
log.Printf(str, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func debugLog(args ...interface{}) {
|
||||
if Dev.DebugMode {
|
||||
log.Print(args...)
|
||||
}
|
||||
}
|
||||
|
||||
func debugLogf(str string, args ...interface{}) {
|
||||
if Dev.DebugMode {
|
||||
log.Printf(str, args...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package common
|
|||
//import "fmt"
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -49,6 +50,7 @@ type ForumSimple struct {
|
|||
|
||||
type ForumStmts struct {
|
||||
update *sql.Stmt
|
||||
setPreset *sql.Stmt
|
||||
}
|
||||
|
||||
var forumStmts ForumStmts
|
||||
|
@ -57,6 +59,7 @@ func init() {
|
|||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||
forumStmts = ForumStmts{
|
||||
update: acc.Update("forums").Set("name = ?, desc = ?, active = ?, preset = ?").Where("fid = ?").Prepare(),
|
||||
setPreset: acc.Update("forums").Set("preset = ?").Where("fid = ?").Prepare(),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
|
@ -88,6 +91,39 @@ func (forum *Forum) Update(name string, desc string, active bool, preset string)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (forum *Forum) SetPreset(preset string, gid int) error {
|
||||
fperms, changed := GroupForumPresetToForumPerms(preset)
|
||||
if changed {
|
||||
return forum.setPreset(fperms, preset, gid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Refactor this
|
||||
func (forum *Forum) setPreset(fperms *ForumPerms, preset string, gid int) (err error) {
|
||||
err = ReplaceForumPermsForGroup(gid, map[int]string{forum.ID: preset}, map[int]*ForumPerms{forum.ID: fperms})
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
return errors.New("Unable to update the permissions")
|
||||
}
|
||||
|
||||
// TODO: Add this and replaceForumPermsForGroup into a transaction?
|
||||
_, err = forumStmts.setPreset.Exec("", forum.ID)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
return errors.New("Unable to update the forum")
|
||||
}
|
||||
err = Fstore.Reload(forum.ID)
|
||||
if err != nil {
|
||||
return errors.New("Unable to reload forum")
|
||||
}
|
||||
err = Fpstore.ReloadGroup(forum.ID, gid)
|
||||
if err != nil {
|
||||
return errors.New("Unable to reload the forum permissions")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Replace this sorting mechanism with something a lot more efficient
|
||||
// ? - Use sort.Slice instead?
|
||||
type SortForum []*Forum
|
||||
|
|
|
@ -0,0 +1,307 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
// ? - Can we avoid duplicating the items in this list in a bunch of places?
|
||||
|
||||
var LocalPermList = []string{
|
||||
"ViewTopic",
|
||||
"LikeItem",
|
||||
"CreateTopic",
|
||||
"EditTopic",
|
||||
"DeleteTopic",
|
||||
"CreateReply",
|
||||
"EditReply",
|
||||
"DeleteReply",
|
||||
"PinTopic",
|
||||
"CloseTopic",
|
||||
}
|
||||
|
||||
/* Inherit from group permissions for ones we don't have */
|
||||
type ForumPerms struct {
|
||||
ViewTopic bool
|
||||
//ViewOwnTopic bool
|
||||
LikeItem bool
|
||||
CreateTopic bool
|
||||
EditTopic bool
|
||||
DeleteTopic bool
|
||||
CreateReply bool
|
||||
//CreateReplyToOwn bool
|
||||
EditReply bool
|
||||
//EditOwnReply bool
|
||||
DeleteReply bool
|
||||
PinTopic bool
|
||||
CloseTopic bool
|
||||
//CloseOwnTopic bool
|
||||
|
||||
Overrides bool
|
||||
ExtData map[string]bool
|
||||
}
|
||||
|
||||
func PresetToPermmap(preset string) (out map[string]*ForumPerms) {
|
||||
out = make(map[string]*ForumPerms)
|
||||
switch preset {
|
||||
case "all":
|
||||
out["guests"] = ReadForumPerms()
|
||||
out["members"] = ReadWriteForumPerms()
|
||||
out["staff"] = AllForumPerms()
|
||||
out["admins"] = AllForumPerms()
|
||||
case "announce":
|
||||
out["guests"] = ReadForumPerms()
|
||||
out["members"] = ReadReplyForumPerms()
|
||||
out["staff"] = AllForumPerms()
|
||||
out["admins"] = AllForumPerms()
|
||||
case "members":
|
||||
out["guests"] = BlankForumPerms()
|
||||
out["members"] = ReadWriteForumPerms()
|
||||
out["staff"] = AllForumPerms()
|
||||
out["admins"] = AllForumPerms()
|
||||
case "staff":
|
||||
out["guests"] = BlankForumPerms()
|
||||
out["members"] = BlankForumPerms()
|
||||
out["staff"] = ReadWriteForumPerms()
|
||||
out["admins"] = AllForumPerms()
|
||||
case "admins":
|
||||
out["guests"] = BlankForumPerms()
|
||||
out["members"] = BlankForumPerms()
|
||||
out["staff"] = BlankForumPerms()
|
||||
out["admins"] = AllForumPerms()
|
||||
case "archive":
|
||||
out["guests"] = ReadForumPerms()
|
||||
out["members"] = ReadForumPerms()
|
||||
out["staff"] = ReadForumPerms()
|
||||
out["admins"] = ReadForumPerms() //CurateForumPerms. Delete / Edit but no create?
|
||||
default:
|
||||
out["guests"] = BlankForumPerms()
|
||||
out["members"] = BlankForumPerms()
|
||||
out["staff"] = BlankForumPerms()
|
||||
out["admins"] = BlankForumPerms()
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func PermmapToQuery(permmap map[string]*ForumPerms, fid int) error {
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
deleteForumPermsByForumTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = deleteForumPermsByForumTx.Exec(fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
perms, err := json.Marshal(permmap["admins"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToForumAdminsTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
|
||||
qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""},
|
||||
qgen.DBSelect{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 1", "", ""},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = addForumPermsToForumAdminsTx.Exec(fid, "", perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
perms, err = json.Marshal(permmap["staff"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToForumStaffTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
|
||||
qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""},
|
||||
qgen.DBSelect{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 1", "", ""},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addForumPermsToForumStaffTx.Exec(fid, "", perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
perms, err = json.Marshal(permmap["members"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToForumMembersTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
|
||||
qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""},
|
||||
qgen.DBSelect{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addForumPermsToForumMembersTx.Exec(fid, "", perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 6 is the ID of the Not Loggedin Group
|
||||
// TODO: Use a shared variable rather than a literal for the group ID
|
||||
err = ReplaceForumPermsForGroupTx(tx, 6, map[int]string{fid: ""}, map[int]*ForumPerms{fid: permmap["guests"]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return Fpstore.Reload(fid)
|
||||
}
|
||||
|
||||
func ReplaceForumPermsForGroup(gid int, presetSet map[int]string, permSets map[int]*ForumPerms) error {
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
err = ReplaceForumPermsForGroupTx(tx, gid, presetSet, permSets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func ReplaceForumPermsForGroupTx(tx *sql.Tx, gid int, presetSets map[int]string, permSets map[int]*ForumPerms) error {
|
||||
deleteForumPermsForGroupTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "gid = ? AND fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToGroupTx, err := qgen.Builder.SimpleInsertTx(tx, "forums_permissions", "gid, fid, preset, permissions", "?,?,?,?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for fid, permSet := range permSets {
|
||||
permstr, err := json.Marshal(permSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = deleteForumPermsForGroupTx.Exec(gid, fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addForumPermsToGroupTx.Exec(gid, fid, presetSets[fid], string(permstr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Refactor this and write tests for it
|
||||
func ForumPermsToGroupForumPreset(fperms *ForumPerms) string {
|
||||
if !fperms.Overrides {
|
||||
return "default"
|
||||
}
|
||||
if !fperms.ViewTopic {
|
||||
return "no_access"
|
||||
}
|
||||
var canPost = (fperms.LikeItem && fperms.CreateTopic && fperms.CreateReply)
|
||||
var canModerate = (canPost && fperms.EditTopic && fperms.DeleteTopic && fperms.EditReply && fperms.DeleteReply && fperms.PinTopic && fperms.CloseTopic)
|
||||
if canModerate {
|
||||
return "can_moderate"
|
||||
}
|
||||
if fperms.EditTopic || fperms.DeleteTopic || fperms.EditReply || fperms.DeleteReply || fperms.PinTopic || fperms.CloseTopic {
|
||||
if !canPost {
|
||||
return "custom"
|
||||
}
|
||||
return "quasi_mod"
|
||||
}
|
||||
|
||||
if canPost {
|
||||
return "can_post"
|
||||
}
|
||||
if fperms.ViewTopic && !fperms.LikeItem && !fperms.CreateTopic && !fperms.CreateReply {
|
||||
return "read_only"
|
||||
}
|
||||
return "custom"
|
||||
}
|
||||
|
||||
func GroupForumPresetToForumPerms(preset string) (fperms *ForumPerms, changed bool) {
|
||||
switch preset {
|
||||
case "read_only":
|
||||
return ReadForumPerms(), true
|
||||
case "can_post":
|
||||
return ReadWriteForumPerms(), true
|
||||
case "can_moderate":
|
||||
return AllForumPerms(), true
|
||||
case "no_access":
|
||||
return &ForumPerms{Overrides: true, ExtData: make(map[string]bool)}, true
|
||||
case "default":
|
||||
return BlankForumPerms(), true
|
||||
}
|
||||
return fperms, false
|
||||
}
|
||||
|
||||
func BlankForumPerms() *ForumPerms {
|
||||
return &ForumPerms{ViewTopic: false}
|
||||
}
|
||||
|
||||
func ReadWriteForumPerms() *ForumPerms {
|
||||
return &ForumPerms{
|
||||
ViewTopic: true,
|
||||
LikeItem: true,
|
||||
CreateTopic: true,
|
||||
CreateReply: true,
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func ReadReplyForumPerms() *ForumPerms {
|
||||
return &ForumPerms{
|
||||
ViewTopic: true,
|
||||
LikeItem: true,
|
||||
CreateReply: true,
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func ReadForumPerms() *ForumPerms {
|
||||
return &ForumPerms{
|
||||
ViewTopic: true,
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// AllForumPerms is a set of forum local permissions with everything set to true
|
||||
func AllForumPerms() *ForumPerms {
|
||||
return &ForumPerms{
|
||||
ViewTopic: true,
|
||||
LikeItem: true,
|
||||
CreateTopic: true,
|
||||
EditTopic: true,
|
||||
DeleteTopic: true,
|
||||
CreateReply: true,
|
||||
EditReply: true,
|
||||
DeleteReply: true,
|
||||
PinTopic: true,
|
||||
CloseTopic: true,
|
||||
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import (
|
|||
"database/sql"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
@ -12,8 +13,9 @@ var Fpstore ForumPermsStore
|
|||
|
||||
type ForumPermsStore interface {
|
||||
Init() error
|
||||
Get(fid int, gid int) (fperms ForumPerms, err error)
|
||||
Get(fid int, gid int) (fperms *ForumPerms, err error)
|
||||
Reload(id int) error
|
||||
ReloadGroup(fid int, gid int) error
|
||||
}
|
||||
|
||||
type ForumPermsCache interface {
|
||||
|
@ -22,6 +24,9 @@ type ForumPermsCache interface {
|
|||
type MemoryForumPermsStore struct {
|
||||
get *sql.Stmt
|
||||
getByForum *sql.Stmt
|
||||
getByForumGroup *sql.Stmt
|
||||
|
||||
updateMutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
||||
|
@ -29,72 +34,69 @@ func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
|||
return &MemoryForumPermsStore{
|
||||
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(),
|
||||
getByForumGroup: acc.Select("forums_permissions").Columns("permissions").Where("fid = ? AND gid = ?").Prepare(),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) Init() error {
|
||||
fps.updateMutex.Lock()
|
||||
defer fps.updateMutex.Unlock()
|
||||
fids, err := Fstore.GetAllIDs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if Dev.SuperDebug {
|
||||
log.Print("fids: ", fids)
|
||||
}
|
||||
debugDetail("fids: ", fids)
|
||||
|
||||
rows, err := fps.get.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if Dev.DebugMode {
|
||||
log.Print("Adding the forum permissions")
|
||||
if Dev.SuperDebug {
|
||||
log.Print("forumPerms[gid][fid]")
|
||||
}
|
||||
}
|
||||
debugLog("Adding the forum permissions")
|
||||
debugDetail("forumPerms[gid][fid]")
|
||||
|
||||
// Temporarily store the forum perms in a map before transferring it to a much faster and thread-safe slice
|
||||
forumPerms = make(map[int]map[int]ForumPerms)
|
||||
forumPerms = make(map[int]map[int]*ForumPerms)
|
||||
for rows.Next() {
|
||||
var gid, fid int
|
||||
var perms []byte
|
||||
var pperms ForumPerms
|
||||
err = rows.Scan(&gid, &fid, &perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if Dev.SuperDebug {
|
||||
log.Print("perms: ", string(perms))
|
||||
}
|
||||
err = json.Unmarshal(perms, &pperms)
|
||||
pperms, err := fps.parseForumPerm(perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pperms.ExtData = make(map[string]bool)
|
||||
pperms.Overrides = true
|
||||
_, ok := forumPerms[gid]
|
||||
if !ok {
|
||||
forumPerms[gid] = make(map[int]ForumPerms)
|
||||
forumPerms[gid] = make(map[int]*ForumPerms)
|
||||
}
|
||||
|
||||
if Dev.SuperDebug {
|
||||
log.Print("gid: ", gid)
|
||||
log.Print("fid: ", fid)
|
||||
log.Printf("perms: %+v\n", pperms)
|
||||
}
|
||||
debugDetail("gid: ", gid)
|
||||
debugDetail("fid: ", fid)
|
||||
debugDetailf("perms: %+v\n", pperms)
|
||||
forumPerms[gid][fid] = pperms
|
||||
}
|
||||
|
||||
return fps.cascadePermSetToGroups(forumPerms, fids)
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) parseForumPerm(perms []byte) (pperms *ForumPerms, err error) {
|
||||
debugDetail("perms: ", string(perms))
|
||||
pperms = BlankForumPerms()
|
||||
err = json.Unmarshal(perms, &pperms)
|
||||
pperms.ExtData = make(map[string]bool)
|
||||
pperms.Overrides = true
|
||||
return pperms, err
|
||||
}
|
||||
|
||||
// TODO: Need a more thread-safe way of doing this. Possibly with sync.Map?
|
||||
func (fps *MemoryForumPermsStore) Reload(fid int) error {
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Reloading the forum permissions for forum #%d", fid)
|
||||
}
|
||||
fps.updateMutex.Lock()
|
||||
defer fps.updateMutex.Unlock()
|
||||
debugLogf("Reloading the forum permissions for forum #%d", fid)
|
||||
fids, err := Fstore.GetAllIDs()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -109,38 +111,56 @@ func (fps *MemoryForumPermsStore) Reload(fid int) error {
|
|||
for rows.Next() {
|
||||
var gid int
|
||||
var perms []byte
|
||||
var pperms ForumPerms
|
||||
err := rows.Scan(&gid, &perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(perms, &pperms)
|
||||
|
||||
pperms, err := fps.parseForumPerm(perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pperms.ExtData = make(map[string]bool)
|
||||
pperms.Overrides = true
|
||||
_, ok := forumPerms[gid]
|
||||
if !ok {
|
||||
forumPerms[gid] = make(map[int]ForumPerms)
|
||||
forumPerms[gid] = make(map[int]*ForumPerms)
|
||||
}
|
||||
|
||||
forumPerms[gid][fid] = pperms
|
||||
}
|
||||
|
||||
return fps.cascadePermSetToGroups(forumPerms, fids)
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[int]ForumPerms, fids []int) error {
|
||||
func (fps *MemoryForumPermsStore) ReloadGroup(fid int, gid int) (err error) {
|
||||
fps.updateMutex.Lock()
|
||||
defer fps.updateMutex.Unlock()
|
||||
var perms []byte
|
||||
err = fps.getByForumGroup.QueryRow(fid, gid).Scan(&perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fperms, err := fps.parseForumPerm(perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
group, err := Gstore.Get(gid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Refactor this
|
||||
group.Forums[fid] = fperms
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[int]*ForumPerms, fids []int) error {
|
||||
groups, err := Gstore.GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Updating the forum permissions for Group #%d", group.ID)
|
||||
}
|
||||
group.Forums = []ForumPerms{BlankForumPerms}
|
||||
debugLogf("Updating the forum permissions for Group #%d", group.ID)
|
||||
group.Forums = []*ForumPerms{BlankForumPerms()}
|
||||
group.CanSee = []int{}
|
||||
fps.cascadePermSetToGroup(forumPerms, group, fids)
|
||||
|
||||
|
@ -152,18 +172,16 @@ func (fps *MemoryForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[
|
|||
return nil
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]ForumPerms, group *Group, fids []int) {
|
||||
func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]*ForumPerms, group *Group, fids []int) {
|
||||
for _, fid := range fids {
|
||||
if Dev.SuperDebug {
|
||||
log.Printf("Forum #%+v\n", fid)
|
||||
}
|
||||
debugDetailf("Forum #%+v\n", fid)
|
||||
forumPerm, ok := forumPerms[group.ID][fid]
|
||||
if ok {
|
||||
//log.Printf("Overriding permissions for forum #%d",fid)
|
||||
group.Forums = append(group.Forums, forumPerm)
|
||||
} else {
|
||||
//log.Printf("Inheriting from group defaults for forum #%d",fid)
|
||||
forumPerm = BlankForumPerms
|
||||
forumPerm = BlankForumPerms()
|
||||
group.Forums = append(group.Forums, forumPerm)
|
||||
}
|
||||
if forumPerm.Overrides {
|
||||
|
@ -174,16 +192,14 @@ func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[i
|
|||
group.CanSee = append(group.CanSee, fid)
|
||||
}
|
||||
|
||||
if Dev.SuperDebug {
|
||||
log.Print("group.ID: ", group.ID)
|
||||
log.Printf("forumPerm: %+v\n", forumPerm)
|
||||
log.Print("group.CanSee: ", group.CanSee)
|
||||
}
|
||||
debugDetail("group.ID: ", group.ID)
|
||||
debugDetailf("forumPerm: %+v\n", forumPerm)
|
||||
debugDetail("group.CanSee: ", group.CanSee)
|
||||
}
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) Get(fid int, gid int) (fperms ForumPerms, err error) {
|
||||
// TODO: Add a hook here and have plugin_guilds use it
|
||||
// TODO: Add a hook here and have plugin_guilds use it
|
||||
func (fps *MemoryForumPermsStore) Get(fid int, gid int) (fperms *ForumPerms, err error) {
|
||||
group, err := Gstore.Get(gid)
|
||||
if err != nil {
|
||||
return fperms, ErrNoRows
|
||||
|
|
|
@ -17,9 +17,8 @@ import (
|
|||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var ForumUpdateMutex sync.Mutex
|
||||
var forumCreateMutex sync.Mutex
|
||||
var forumPerms map[int]map[int]ForumPerms // [gid][fid]Perms // TODO: Add an abstraction around this and make it more thread-safe
|
||||
var forumPerms map[int]map[int]*ForumPerms // [gid][fid]*ForumPerms // TODO: Add an abstraction around this and make it more thread-safe
|
||||
var Fstore ForumStore
|
||||
|
||||
// ForumStore is an interface for accessing the forums and the metadata stored on them
|
||||
|
@ -110,9 +109,7 @@ func (mfs *MemoryForumStore) LoadForums() error {
|
|||
}
|
||||
|
||||
if forum.Name == "" {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Adding a placeholder forum")
|
||||
}
|
||||
debugLog("Adding a placeholder forum")
|
||||
} else {
|
||||
log.Printf("Adding the '%s' forum", forum.Name)
|
||||
}
|
||||
|
@ -272,11 +269,8 @@ func (mfs *MemoryForumStore) Delete(id int) error {
|
|||
return errors.New("You cannot delete the Reports forum")
|
||||
}
|
||||
_, err := mfs.delete.Exec(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mfs.CacheDelete(id)
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
|
||||
|
|
|
@ -26,7 +26,7 @@ type Group struct {
|
|||
PermissionsText []byte
|
||||
PluginPerms map[string]bool // Custom permissions defined by plugins. What if two plugins declare the same permission, but they handle them in incompatible ways? Very unlikely, we probably don't need to worry about this, the plugin authors should be aware of each other to some extent
|
||||
PluginPermsText []byte
|
||||
Forums []ForumPerms
|
||||
Forums []*ForumPerms
|
||||
CanSee []int // The IDs of the forums this group can see
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,7 @@ func (mgs *MemoryGroupStore) LoadGroups() error {
|
|||
}
|
||||
mgs.groupCount = i
|
||||
|
||||
if Dev.DebugMode {
|
||||
log.Print("Binding the Not Loggedin Group")
|
||||
}
|
||||
debugLog("Binding the Not Loggedin Group")
|
||||
GuestPerms = mgs.dirtyGetUnsafe(6).Perms
|
||||
return nil
|
||||
}
|
||||
|
@ -172,9 +170,7 @@ func (mgs *MemoryGroupStore) initGroup(group *Group) error {
|
|||
log.Print("bad group plugin perms: ", group.PluginPermsText)
|
||||
return err
|
||||
}
|
||||
if Dev.DebugMode {
|
||||
log.Printf(group.Name+": %+v\n", group.PluginPerms)
|
||||
}
|
||||
debugLogf(group.Name+": %+v\n", group.PluginPerms)
|
||||
|
||||
//group.Perms.ExtData = make(map[string]bool)
|
||||
// TODO: Can we optimise the bit where this cascades down to the user now?
|
||||
|
@ -200,6 +196,7 @@ func (mgs *MemoryGroupStore) Exists(gid int) bool {
|
|||
}
|
||||
|
||||
// ? Allow two groups with the same name?
|
||||
// TODO: Refactor this
|
||||
func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod bool, isBanned bool) (gid int, err error) {
|
||||
var permstr = "{}"
|
||||
tx, err := qgen.Builder.Begin()
|
||||
|
@ -224,7 +221,7 @@ func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod
|
|||
gid = int(gid64)
|
||||
|
||||
var perms = BlankPerms
|
||||
var blankForums []ForumPerms
|
||||
var blankForums []*ForumPerms
|
||||
var blankIntList []int
|
||||
var pluginPerms = make(map[string]bool)
|
||||
var pluginPermsBytes = []byte("{}")
|
||||
|
@ -239,18 +236,17 @@ func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod
|
|||
}
|
||||
|
||||
var presetSet = make(map[int]string)
|
||||
var permSet = make(map[int]ForumPerms)
|
||||
PermUpdateMutex.Lock()
|
||||
defer PermUpdateMutex.Unlock()
|
||||
var permSet = make(map[int]*ForumPerms)
|
||||
for _, forum := range fdata {
|
||||
var thePreset string
|
||||
if isAdmin {
|
||||
switch {
|
||||
case isAdmin:
|
||||
thePreset = "admins"
|
||||
} else if isMod {
|
||||
case isMod:
|
||||
thePreset = "staff"
|
||||
} else if isBanned {
|
||||
case isBanned:
|
||||
thePreset = "banned"
|
||||
} else {
|
||||
default:
|
||||
thePreset = "members"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,46 +1,20 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
// TODO: Refactor the perms system
|
||||
|
||||
var PermUpdateMutex sync.Mutex
|
||||
var BlankPerms Perms
|
||||
var BlankForumPerms ForumPerms
|
||||
var GuestPerms Perms
|
||||
var ReadForumPerms ForumPerms
|
||||
var ReadReplyForumPerms ForumPerms
|
||||
var ReadWriteForumPerms ForumPerms
|
||||
|
||||
// AllPerms is a set of global permissions with everything set to true
|
||||
var AllPerms Perms
|
||||
|
||||
// AllForumPerms is a set of forum local permissions with everything set to true
|
||||
var AllForumPerms ForumPerms
|
||||
var AllPluginPerms = make(map[string]bool)
|
||||
|
||||
// ? - Can we avoid duplicating the items in this list in a bunch of places?
|
||||
|
||||
var LocalPermList = []string{
|
||||
"ViewTopic",
|
||||
"LikeItem",
|
||||
"CreateTopic",
|
||||
"EditTopic",
|
||||
"DeleteTopic",
|
||||
"CreateReply",
|
||||
"EditReply",
|
||||
"DeleteReply",
|
||||
"PinTopic",
|
||||
"CloseTopic",
|
||||
}
|
||||
|
||||
// ? - Can we avoid duplicating the items in this list in a bunch of places?
|
||||
var GlobalPermList = []string{
|
||||
"BanUsers",
|
||||
|
@ -111,36 +85,11 @@ type Perms struct {
|
|||
//ExtData map[string]bool
|
||||
}
|
||||
|
||||
/* Inherit from group permissions for ones we don't have */
|
||||
type ForumPerms struct {
|
||||
ViewTopic bool
|
||||
//ViewOwnTopic bool
|
||||
LikeItem bool
|
||||
CreateTopic bool
|
||||
EditTopic bool
|
||||
DeleteTopic bool
|
||||
CreateReply bool
|
||||
//CreateReplyToOwn bool
|
||||
EditReply bool
|
||||
//EditOwnReply bool
|
||||
DeleteReply bool
|
||||
PinTopic bool
|
||||
CloseTopic bool
|
||||
//CloseOwnTopic bool
|
||||
|
||||
Overrides bool
|
||||
ExtData map[string]bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
BlankPerms = Perms{
|
||||
//ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
BlankForumPerms = ForumPerms{
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
GuestPerms = Perms{
|
||||
ViewTopic: true,
|
||||
//ExtData: make(map[string]bool),
|
||||
|
@ -183,266 +132,9 @@ func init() {
|
|||
//ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
AllForumPerms = ForumPerms{
|
||||
ViewTopic: true,
|
||||
LikeItem: true,
|
||||
CreateTopic: true,
|
||||
EditTopic: true,
|
||||
DeleteTopic: true,
|
||||
CreateReply: true,
|
||||
EditReply: true,
|
||||
DeleteReply: true,
|
||||
PinTopic: true,
|
||||
CloseTopic: true,
|
||||
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
ReadWriteForumPerms = ForumPerms{
|
||||
ViewTopic: true,
|
||||
LikeItem: true,
|
||||
CreateTopic: true,
|
||||
CreateReply: true,
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
ReadReplyForumPerms = ForumPerms{
|
||||
ViewTopic: true,
|
||||
LikeItem: true,
|
||||
CreateReply: true,
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
ReadForumPerms = ForumPerms{
|
||||
ViewTopic: true,
|
||||
Overrides: true,
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
GuestUser.Perms = GuestPerms
|
||||
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Guest Perms: %+v\n", GuestPerms)
|
||||
log.Printf("All Perms: %+v\n", AllPerms)
|
||||
}
|
||||
}
|
||||
|
||||
func PresetToPermmap(preset string) (out map[string]ForumPerms) {
|
||||
out = make(map[string]ForumPerms)
|
||||
switch preset {
|
||||
case "all":
|
||||
out["guests"] = ReadForumPerms
|
||||
out["members"] = ReadWriteForumPerms
|
||||
out["staff"] = AllForumPerms
|
||||
out["admins"] = AllForumPerms
|
||||
case "announce":
|
||||
out["guests"] = ReadForumPerms
|
||||
out["members"] = ReadReplyForumPerms
|
||||
out["staff"] = AllForumPerms
|
||||
out["admins"] = AllForumPerms
|
||||
case "members":
|
||||
out["guests"] = BlankForumPerms
|
||||
out["members"] = ReadWriteForumPerms
|
||||
out["staff"] = AllForumPerms
|
||||
out["admins"] = AllForumPerms
|
||||
case "staff":
|
||||
out["guests"] = BlankForumPerms
|
||||
out["members"] = BlankForumPerms
|
||||
out["staff"] = ReadWriteForumPerms
|
||||
out["admins"] = AllForumPerms
|
||||
case "admins":
|
||||
out["guests"] = BlankForumPerms
|
||||
out["members"] = BlankForumPerms
|
||||
out["staff"] = BlankForumPerms
|
||||
out["admins"] = AllForumPerms
|
||||
case "archive":
|
||||
out["guests"] = ReadForumPerms
|
||||
out["members"] = ReadForumPerms
|
||||
out["staff"] = ReadForumPerms
|
||||
out["admins"] = ReadForumPerms //CurateForumPerms. Delete / Edit but no create?
|
||||
default:
|
||||
out["guests"] = BlankForumPerms
|
||||
out["members"] = BlankForumPerms
|
||||
out["staff"] = BlankForumPerms
|
||||
out["admins"] = BlankForumPerms
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func PermmapToQuery(permmap map[string]ForumPerms, fid int) error {
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
deleteForumPermsByForumTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = deleteForumPermsByForumTx.Exec(fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
perms, err := json.Marshal(permmap["admins"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToForumAdminsTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
|
||||
qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""},
|
||||
qgen.DBSelect{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 1", "", ""},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = addForumPermsToForumAdminsTx.Exec(fid, "", perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
perms, err = json.Marshal(permmap["staff"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToForumStaffTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
|
||||
qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""},
|
||||
qgen.DBSelect{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 1", "", ""},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addForumPermsToForumStaffTx.Exec(fid, "", perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
perms, err = json.Marshal(permmap["members"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToForumMembersTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
|
||||
qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""},
|
||||
qgen.DBSelect{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addForumPermsToForumMembersTx.Exec(fid, "", perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 6 is the ID of the Not Loggedin Group
|
||||
// TODO: Use a shared variable rather than a literal for the group ID
|
||||
err = ReplaceForumPermsForGroupTx(tx, 6, map[int]string{fid: ""}, map[int]ForumPerms{fid: permmap["guests"]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
PermUpdateMutex.Lock()
|
||||
defer PermUpdateMutex.Unlock()
|
||||
return Fpstore.Reload(fid)
|
||||
}
|
||||
|
||||
func ReplaceForumPermsForGroup(gid int, presetSet map[int]string, permSets map[int]ForumPerms) error {
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
err = ReplaceForumPermsForGroupTx(tx, gid, presetSet, permSets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func ReplaceForumPermsForGroupTx(tx *sql.Tx, gid int, presetSets map[int]string, permSets map[int]ForumPerms) error {
|
||||
deleteForumPermsForGroupTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "gid = ? AND fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addForumPermsToGroupTx, err := qgen.Builder.SimpleInsertTx(tx, "forums_permissions", "gid, fid, preset, permissions", "?,?,?,?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for fid, permSet := range permSets {
|
||||
permstr, err := json.Marshal(permSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = deleteForumPermsForGroupTx.Exec(gid, fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addForumPermsToGroupTx.Exec(gid, fid, presetSets[fid], string(permstr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Refactor this and write tests for it
|
||||
func ForumPermsToGroupForumPreset(fperms ForumPerms) string {
|
||||
if !fperms.Overrides {
|
||||
return "default"
|
||||
}
|
||||
if !fperms.ViewTopic {
|
||||
return "no_access"
|
||||
}
|
||||
var canPost = (fperms.LikeItem && fperms.CreateTopic && fperms.CreateReply)
|
||||
var canModerate = (canPost && fperms.EditTopic && fperms.DeleteTopic && fperms.EditReply && fperms.DeleteReply && fperms.PinTopic && fperms.CloseTopic)
|
||||
if canModerate {
|
||||
return "can_moderate"
|
||||
}
|
||||
if fperms.EditTopic || fperms.DeleteTopic || fperms.EditReply || fperms.DeleteReply || fperms.PinTopic || fperms.CloseTopic {
|
||||
if !canPost {
|
||||
return "custom"
|
||||
}
|
||||
return "quasi_mod"
|
||||
}
|
||||
|
||||
if canPost {
|
||||
return "can_post"
|
||||
}
|
||||
if fperms.ViewTopic && !fperms.LikeItem && !fperms.CreateTopic && !fperms.CreateReply {
|
||||
return "read_only"
|
||||
}
|
||||
return "custom"
|
||||
}
|
||||
|
||||
func GroupForumPresetToForumPerms(preset string) (fperms ForumPerms, changed bool) {
|
||||
switch preset {
|
||||
case "read_only":
|
||||
return ReadForumPerms, true
|
||||
case "can_post":
|
||||
return ReadWriteForumPerms, true
|
||||
case "can_moderate":
|
||||
return AllForumPerms, true
|
||||
case "no_access":
|
||||
return ForumPerms{Overrides: true, ExtData: make(map[string]bool)}, true
|
||||
case "default":
|
||||
return BlankForumPerms, true
|
||||
//case "custom": return fperms, false
|
||||
}
|
||||
return fperms, false
|
||||
debugLogf("Guest Perms: %+v\n", GuestPerms)
|
||||
debugLogf("All Perms: %+v\n", AllPerms)
|
||||
}
|
||||
|
||||
func StripInvalidGroupForumPreset(preset string) string {
|
||||
|
@ -457,9 +149,8 @@ func StripInvalidPreset(preset string) string {
|
|||
switch preset {
|
||||
case "all", "announce", "members", "staff", "admins", "archive", "custom":
|
||||
return preset
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// TODO: Move this into the phrase system?
|
||||
|
|
|
@ -101,7 +101,7 @@ func forumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int)
|
|||
}
|
||||
|
||||
// TODO: Put this on the user instance? Do we really want forum specific logic in there? Maybe, a method which spits a new pointer with the same contents as user?
|
||||
func cascadeForumPerms(fperms ForumPerms, user *User) {
|
||||
func cascadeForumPerms(fperms *ForumPerms, user *User) {
|
||||
if fperms.Overrides && !user.IsSuperAdmin {
|
||||
user.Perms.ViewTopic = fperms.ViewTopic
|
||||
user.Perms.LikeItem = fperms.LikeItem
|
||||
|
|
|
@ -51,7 +51,6 @@ type Stmts struct {
|
|||
updatePlugin *sql.Stmt
|
||||
updatePluginInstall *sql.Stmt
|
||||
updateTheme *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateUser *sql.Stmt
|
||||
updateGroupPerms *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
|
@ -380,13 +379,6 @@ func _gen_mssql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE [forums] SET [name] = ?,[desc] = ?,[active] = ?,[preset] = ? WHERE [fid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [forums] SET [name] = ?,[desc] = ?,[active] = ?,[preset] = ? WHERE [fid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUser statement.")
|
||||
stmts.updateUser, err = db.Prepare("UPDATE [users] SET [name] = ?,[email] = ?,[group] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
|
|
|
@ -53,7 +53,6 @@ type Stmts struct {
|
|||
updatePlugin *sql.Stmt
|
||||
updatePluginInstall *sql.Stmt
|
||||
updateTheme *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateUser *sql.Stmt
|
||||
updateGroupPerms *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
|
@ -340,12 +339,6 @@ func _gen_mysql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUser statement.")
|
||||
stmts.updateUser, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
|
|
|
@ -15,7 +15,6 @@ type Stmts struct {
|
|||
updatePlugin *sql.Stmt
|
||||
updatePluginInstall *sql.Stmt
|
||||
updateTheme *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateUser *sql.Stmt
|
||||
updateGroupPerms *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
|
@ -80,12 +79,6 @@ func _gen_pgsql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUser statement.")
|
||||
stmts.updateUser, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
|
|
|
@ -50,6 +50,17 @@ func (ins *MysqlInstaller) DefaultPort() string {
|
|||
return "3306"
|
||||
}
|
||||
|
||||
func (ins *MysqlInstaller) dbExists(dbName string) (bool, error) {
|
||||
var waste string
|
||||
err := ins.db.QueryRow("SHOW DATABASES LIKE '" + dbName + "'").Scan(&waste)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return false, err
|
||||
} else if err == sql.ErrNoRows {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (ins *MysqlInstaller) InitDatabase() (err error) {
|
||||
_dbPassword := ins.dbPassword
|
||||
if _dbPassword != "" {
|
||||
|
@ -67,13 +78,13 @@ func (ins *MysqlInstaller) InitDatabase() (err error) {
|
|||
}
|
||||
fmt.Println("Successfully connected to the database")
|
||||
|
||||
var waste string
|
||||
err = db.QueryRow("SHOW DATABASES LIKE '" + ins.dbName + "'").Scan(&waste)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
ins.db = db
|
||||
ok, err := ins.dbExists(ins.dbName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
if !ok {
|
||||
fmt.Println("Unable to find the database. Attempting to create it")
|
||||
_, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + ins.dbName)
|
||||
if err != nil {
|
||||
|
@ -82,7 +93,7 @@ func (ins *MysqlInstaller) InitDatabase() (err error) {
|
|||
fmt.Println("The database was successfully created")
|
||||
}
|
||||
|
||||
fmt.Println("Switching to database " + ins.dbName)
|
||||
fmt.Println("Switching to database ", ins.dbName)
|
||||
_, err = db.Exec("USE " + ins.dbName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -90,13 +101,7 @@ func (ins *MysqlInstaller) InitDatabase() (err error) {
|
|||
|
||||
// Ready the query builder
|
||||
qgen.Builder.SetConn(db)
|
||||
err = qgen.Builder.SetAdapter("mysql")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ins.db = db
|
||||
return nil
|
||||
return qgen.Builder.SetAdapter("mysql")
|
||||
}
|
||||
|
||||
func (ins *MysqlInstaller) TableDefs() (err error) {
|
||||
|
@ -122,7 +127,7 @@ func (ins *MysqlInstaller) TableDefs() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Creating table '" + table + "'")
|
||||
fmt.Printf("Creating table '%s'", table)
|
||||
data, err := ioutil.ReadFile("./schema/mysql/" + f.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -135,7 +140,6 @@ func (ins *MysqlInstaller) TableDefs() (err error) {
|
|||
return err
|
||||
}
|
||||
}
|
||||
//fmt.Println("Finished creating the tables")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -163,8 +167,6 @@ func (ins *MysqlInstaller) InitialData() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//fmt.Println("Finished inserting the database data")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -69,14 +69,9 @@ func (ins *PgsqlInstaller) InitDatabase() (err error) {
|
|||
// TODO: Create the database, if it doesn't exist
|
||||
|
||||
// Ready the query builder
|
||||
qgen.Builder.SetConn(db)
|
||||
err = qgen.Builder.SetAdapter("pgsql")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ins.db = db
|
||||
|
||||
return nil
|
||||
qgen.Builder.SetConn(db)
|
||||
return qgen.Builder.SetAdapter("pgsql")
|
||||
}
|
||||
|
||||
func (ins *PgsqlInstaller) TableDefs() (err error) {
|
||||
|
|
43
misc_test.go
43
misc_test.go
|
@ -607,8 +607,8 @@ func TestForumPermsStore(t *testing.T) {
|
|||
if !gloinited {
|
||||
gloinit()
|
||||
}
|
||||
if !pluginsInited {
|
||||
initPlugins()
|
||||
if !common.PluginsInited {
|
||||
common.InitPlugins()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,8 +617,8 @@ func TestGroupStore(t *testing.T) {
|
|||
if !gloinited {
|
||||
gloinit()
|
||||
}
|
||||
if !pluginsInited {
|
||||
initPlugins()
|
||||
if !common.PluginsInited {
|
||||
common.InitPlugins()
|
||||
}
|
||||
|
||||
_, err := common.Gstore.Get(-1)
|
||||
|
@ -728,8 +728,8 @@ func TestReplyStore(t *testing.T) {
|
|||
if !gloinited {
|
||||
gloinit()
|
||||
}
|
||||
if !pluginsInited {
|
||||
initPlugins()
|
||||
if !common.PluginsInited {
|
||||
common.InitPlugins()
|
||||
}
|
||||
|
||||
_, err := common.Rstore.Get(-1)
|
||||
|
@ -770,8 +770,8 @@ func TestProfileReplyStore(t *testing.T) {
|
|||
if !gloinited {
|
||||
gloinit()
|
||||
}
|
||||
if !pluginsInited {
|
||||
initPlugins()
|
||||
if !common.PluginsInited {
|
||||
common.InitPlugins()
|
||||
}
|
||||
|
||||
_, err := common.Prstore.Get(-1)
|
||||
|
@ -845,7 +845,7 @@ func TestAuth(t *testing.T) {
|
|||
|
||||
/* No extra salt tests, we might not need this extra salt, as bcrypt has it's own? */
|
||||
realPassword = "Madame Cassandra's Mystic Orb"
|
||||
t.Log("Set realPassword to '" + realPassword + "'")
|
||||
t.Logf("Set realPassword to '%s'", realPassword)
|
||||
t.Log("Hashing the real password")
|
||||
hashedPassword, err = common.BcryptGeneratePasswordNoSalt(realPassword)
|
||||
if err != nil {
|
||||
|
@ -853,34 +853,31 @@ func TestAuth(t *testing.T) {
|
|||
}
|
||||
|
||||
password = realPassword
|
||||
t.Log("Testing password '" + password + "'")
|
||||
t.Log("Testing salt '" + salt + "'")
|
||||
t.Logf("Testing password '%s'", password)
|
||||
t.Logf("Testing salt '%s'", salt)
|
||||
err = common.CheckPassword(hashedPassword, password, salt)
|
||||
if err == ErrMismatchedHashAndPassword {
|
||||
if err == common.ErrMismatchedHashAndPassword {
|
||||
t.Error("The two don't match")
|
||||
} else if err == ErrPasswordTooLong {
|
||||
} else if err == common.ErrPasswordTooLong {
|
||||
t.Error("CheckPassword thinks the password is too long")
|
||||
} else if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
password = "hahaha"
|
||||
t.Log("Testing password '" + password + "'")
|
||||
t.Log("Testing salt '" + salt + "'")
|
||||
t.Logf("Testing password '%s'", password)
|
||||
t.Logf("Testing salt '%s'", salt)
|
||||
err = common.CheckPassword(hashedPassword, password, salt)
|
||||
if err == ErrPasswordTooLong {
|
||||
if err == common.ErrPasswordTooLong {
|
||||
t.Error("CheckPassword thinks the password is too long")
|
||||
} else if err == nil {
|
||||
t.Error("The two shouldn't match!")
|
||||
}
|
||||
|
||||
password = "Madame Cassandra's Mystic"
|
||||
t.Log("Testing password '" + password + "'")
|
||||
t.Log("Testing salt '" + salt + "'")
|
||||
t.Logf("Testing password '%s'", password)
|
||||
t.Logf("Testing salt '%s'", salt)
|
||||
err = common.CheckPassword(hashedPassword, password, salt)
|
||||
if err == ErrPasswordTooLong {
|
||||
t.Error("CheckPassword thinks the password is too long")
|
||||
} else if err == nil {
|
||||
t.Error("The two shouldn't match!")
|
||||
}
|
||||
expect(t, err != common.ErrPasswordTooLong, "CheckPassword thinks the password is too long")
|
||||
expect(t, err != nil, "The two shouldn't match!")
|
||||
}
|
||||
|
|
|
@ -425,9 +425,6 @@ func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
|
|||
return common.LocalErrorJSQ("Invalid Group ID", w, r, user, isJs)
|
||||
}
|
||||
|
||||
permPreset := common.StripInvalidGroupForumPreset(r.PostFormValue("perm_preset"))
|
||||
fperms, changed := common.GroupForumPresetToForumPerms(permPreset)
|
||||
|
||||
forum, err := common.Fstore.Get(fid)
|
||||
if err == ErrNoRows {
|
||||
return common.LocalErrorJSQ("This forum doesn't exist", w, r, user, isJs)
|
||||
|
@ -435,33 +432,10 @@ func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
|
|||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// ! IMPORTANT
|
||||
// TODO: Refactor this
|
||||
common.ForumUpdateMutex.Lock()
|
||||
defer common.ForumUpdateMutex.Unlock()
|
||||
if changed {
|
||||
common.PermUpdateMutex.Lock()
|
||||
defer common.PermUpdateMutex.Unlock()
|
||||
group, err := common.Gstore.Get(gid)
|
||||
permPreset := common.StripInvalidGroupForumPreset(r.PostFormValue("perm_preset"))
|
||||
err = forum.SetPreset(permPreset, gid)
|
||||
if err != nil {
|
||||
return common.LocalError("The group whose permissions you're updating doesn't exist.", w, r, user)
|
||||
}
|
||||
group.Forums[fid] = fperms
|
||||
|
||||
err = common.ReplaceForumPermsForGroup(gid, map[int]string{fid: permPreset}, map[int]common.ForumPerms{fid: fperms})
|
||||
if err != nil {
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// TODO: Add this and replaceForumPermsForGroup into a transaction?
|
||||
_, err = stmts.updateForum.Exec(forum.Name, forum.Desc, forum.Active, "", fid)
|
||||
if err != nil {
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
err = common.Fstore.Reload(fid)
|
||||
if err != nil {
|
||||
return common.LocalErrorJSQ("Unable to reload forum", w, r, user, isJs)
|
||||
}
|
||||
return common.LocalErrorJSQ(err.Error(), w, r, user, isJs)
|
||||
}
|
||||
|
||||
if !isJs {
|
||||
|
|
|
@ -181,15 +181,16 @@ func processWhere(wherestr string) (where []DBWhere) {
|
|||
segment += ")"
|
||||
for i := 0; i < len(segment); i++ {
|
||||
char := segment[i]
|
||||
if '0' <= char && char <= '9' {
|
||||
switch {
|
||||
case '0' <= char && char <= '9':
|
||||
i = tmpWhere.parseNumber(segment, i)
|
||||
} else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' {
|
||||
case ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_':
|
||||
i = tmpWhere.parseColumn(segment, i)
|
||||
} else if char == '\'' {
|
||||
case char == '\'':
|
||||
i = tmpWhere.parseString(segment, i)
|
||||
} else if isOpByte(char) {
|
||||
case isOpByte(char):
|
||||
i = tmpWhere.parseOperator(segment, i)
|
||||
} else if char == '?' {
|
||||
case char == '?':
|
||||
tmpWhere.Expr = append(tmpWhere.Expr, DBToken{"?", "substitute"})
|
||||
}
|
||||
}
|
||||
|
@ -216,11 +217,12 @@ func (setter *DBSetter) parseColumn(segment string, i int) int {
|
|||
var buffer string
|
||||
for ; i < len(segment); i++ {
|
||||
char := segment[i]
|
||||
if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' {
|
||||
switch {
|
||||
case ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_':
|
||||
buffer += string(char)
|
||||
} else if char == '(' {
|
||||
case char == '(':
|
||||
return setter.parseFunction(segment, buffer, i)
|
||||
} else {
|
||||
default:
|
||||
i--
|
||||
setter.Expr = append(setter.Expr, DBToken{buffer, "column"})
|
||||
return i
|
||||
|
@ -303,15 +305,16 @@ func processSet(setstr string) (setter []DBSetter) {
|
|||
|
||||
for i := 0; i < len(segment); i++ {
|
||||
char := segment[i]
|
||||
if '0' <= char && char <= '9' {
|
||||
switch {
|
||||
case '0' <= char && char <= '9':
|
||||
i = tmpSetter.parseNumber(segment, i)
|
||||
} else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' {
|
||||
case ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_':
|
||||
i = tmpSetter.parseColumn(segment, i)
|
||||
} else if char == '\'' {
|
||||
case char == '\'':
|
||||
i = tmpSetter.parseString(segment, i)
|
||||
} else if isOpByte(char) {
|
||||
case isOpByte(char):
|
||||
i = tmpSetter.parseOperator(segment, i)
|
||||
} else if char == '?' {
|
||||
case char == '?':
|
||||
tmpSetter.Expr = append(tmpSetter.Expr, DBToken{"?", "substitute"})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,8 +352,6 @@ func writeUpdates(adapter qgen.Adapter) error {
|
|||
|
||||
build.Update("updateTheme").Table("themes").Set("default = ?").Where("uname = ?").Parse()
|
||||
|
||||
build.Update("updateForum").Table("forums").Set("name = ?, desc = ?, active = ?, preset = ?").Where("fid = ?").Parse()
|
||||
|
||||
build.Update("updateUser").Table("users").Set("name = ?, email = ?, group = ?").Where("uid = ?").Parse()
|
||||
|
||||
build.Update("updateGroupPerms").Table("users_groups").Set("permissions = ?").Where("gid = ?").Parse()
|
||||
|
|
|
@ -849,13 +849,12 @@ func routeRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.Use
|
|||
}
|
||||
|
||||
password := r.PostFormValue("password")
|
||||
if password == "" {
|
||||
switch password {
|
||||
case "":
|
||||
return common.LocalError("You didn't put in a password.", w, r, user)
|
||||
}
|
||||
if password == username {
|
||||
case username:
|
||||
return common.LocalError("You can't use your username as your password.", w, r, user)
|
||||
}
|
||||
if password == email {
|
||||
case email:
|
||||
return common.LocalError("You can't use your email as your password.", w, r, user)
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ ul {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.rowblock {
|
||||
.rowblock, .colstack_item {
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid var(--header-border-color);
|
||||
border-bottom: 2px solid var(--header-border-color);
|
||||
|
|
Loading…
Reference in New Issue