gosora/common/forum_perms_store.go
Azareal 60964868d4 Moved the counters to their own package.
De-duped some of the logging code.
Added per-route state to the not found errors.
Exported debugDetail, debugDetailf, debugLog, and debugLogf.
Tweaked the padding on Tempra Simple.
Added panel submenus to Tempra Conflux.
Added Chart CSS to Tempra Conflux.
Fixed the padding and margins for the Control Panel in Cosora.
Made Cosora's Control Panel a little more tablet friendly.
Added the rowmsg CSS class to better style message rows.
Removed the repetitive guard code for the pre-render hooks.
Removed the repetitive guard code for the string-string hooks.
We now capture views for routes.StaticFile
Added the move action to the moderation logs.

Added the viewchunks_forums table.
Began work on Per-forum Views.
I probably missed a few things in this changelog.
2018-02-19 04:26:01 +00:00

218 lines
5.4 KiB
Go

package common
import (
"database/sql"
"encoding/json"
"sync"
"../query_gen/lib"
)
var FPStore ForumPermsStore
type ForumPermsStore interface {
Init() error
Get(fid int, gid int) (fperms *ForumPerms, err error)
GetCopy(fid int, gid int) (fperms ForumPerms, err error)
Reload(id int) error
ReloadGroup(fid int, gid int) error
}
type ForumPermsCache interface {
}
type MemoryForumPermsStore struct {
get *sql.Stmt
getByForum *sql.Stmt
getByForumGroup *sql.Stmt
updateMutex sync.Mutex
}
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
acc := qgen.Builder.Accumulator()
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 := Forums.GetAllIDs()
if err != nil {
return err
}
DebugDetail("fids: ", fids)
rows, err := fps.get.Query()
if err != nil {
return err
}
defer rows.Close()
DebugLog("Adding the forum permissions")
DebugDetail("forumPerms[gid][fid]")
forumPerms = make(map[int]map[int]*ForumPerms)
for rows.Next() {
var gid, fid int
var perms []byte
err = rows.Scan(&gid, &fid, &perms)
if err != nil {
return err
}
pperms, err := fps.parseForumPerm(perms)
if err != nil {
return err
}
_, ok := forumPerms[gid]
if !ok {
forumPerms[gid] = make(map[int]*ForumPerms)
}
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 {
fps.updateMutex.Lock()
defer fps.updateMutex.Unlock()
DebugLogf("Reloading the forum permissions for forum #%d", fid)
fids, err := Forums.GetAllIDs()
if err != nil {
return err
}
rows, err := fps.getByForum.Query(fid)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var gid int
var perms []byte
err := rows.Scan(&gid, &perms)
if err != nil {
return err
}
pperms, err := fps.parseForumPerm(perms)
if err != nil {
return err
}
_, ok := forumPerms[gid]
if !ok {
forumPerms[gid] = make(map[int]*ForumPerms)
}
forumPerms[gid][fid] = pperms
}
return fps.cascadePermSetToGroups(forumPerms, fids)
}
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 := Groups.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 := Groups.GetAll()
if err != nil {
return err
}
for _, group := range groups {
DebugLogf("Updating the forum permissions for Group #%d", group.ID)
group.Forums = []*ForumPerms{BlankForumPerms()}
group.CanSee = []int{}
fps.cascadePermSetToGroup(forumPerms, group, fids)
DebugDetailf("group.CanSee (length %d): %+v \n", len(group.CanSee), group.CanSee)
DebugDetailf("group.Forums (length %d): %+v\n", len(group.Forums), group.Forums)
}
return nil
}
func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]*ForumPerms, group *Group, fids []int) {
for _, fid := range fids {
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()
group.Forums = append(group.Forums, forumPerm)
}
if forumPerm.Overrides {
if forumPerm.ViewTopic {
group.CanSee = append(group.CanSee, fid)
}
} else if group.Perms.ViewTopic {
group.CanSee = append(group.CanSee, fid)
}
DebugDetail("group.ID: ", group.ID)
DebugDetailf("forumPerm: %+v\n", forumPerm)
DebugDetail("group.CanSee: ", group.CanSee)
}
}
// TODO: Add a hook here and have plugin_guilds use it
// TODO: Check if the forum exists?
// TODO: Fix the races
func (fps *MemoryForumPermsStore) Get(fid int, gid int) (fperms *ForumPerms, err error) {
group, err := Groups.Get(gid)
if err != nil {
return fperms, ErrNoRows
}
return group.Forums[fid], nil
}
// TODO: Check if the forum exists?
// TODO: Fix the races
func (fps *MemoryForumPermsStore) GetCopy(fid int, gid int) (fperms ForumPerms, err error) {
group, err := Groups.Get(gid)
if err != nil {
return fperms, ErrNoRows
}
return *group.Forums[fid], nil
}