215 lines
5.1 KiB
Go
215 lines
5.1 KiB
Go
/* Under Heavy Construction */
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
var groupCreateMutex sync.Mutex
|
|
var groupUpdateMutex sync.Mutex
|
|
var gstore GroupStore
|
|
|
|
// ? - We could fallback onto the database when an item can't be found in the cache?
|
|
type GroupStore interface {
|
|
LoadGroups() error
|
|
DirtyGet(id int) *Group
|
|
Get(id int) (*Group, error)
|
|
GetCopy(id int) (Group, error)
|
|
Exists(id int) bool
|
|
Create(groupName string, tag string, isAdmin bool, isMod bool, isBanned bool) (int, error)
|
|
GetAll() ([]*Group, error)
|
|
GetRange(lower int, higher int) ([]*Group, error)
|
|
}
|
|
|
|
type GroupCache interface {
|
|
Length() int
|
|
}
|
|
|
|
type MemoryGroupStore struct {
|
|
groups []*Group // TODO: Use a sync.Map instead of a slice
|
|
groupCapCount int
|
|
}
|
|
|
|
func NewMemoryGroupStore() *MemoryGroupStore {
|
|
return &MemoryGroupStore{}
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) LoadGroups() error {
|
|
mgs.groups = []*Group{&Group{ID: 0, Name: "Unknown"}}
|
|
|
|
rows, err := getGroupsStmt.Query()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
i := 1
|
|
for ; rows.Next(); i++ {
|
|
group := Group{ID: 0}
|
|
err := rows.Scan(&group.ID, &group.Name, &group.PermissionsText, &group.PluginPermsText, &group.IsMod, &group.IsAdmin, &group.IsBanned, &group.Tag)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = json.Unmarshal(group.PermissionsText, &group.Perms)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dev.DebugMode {
|
|
log.Print(group.Name + ": ")
|
|
log.Printf("%+v\n", group.Perms)
|
|
}
|
|
|
|
err = json.Unmarshal(group.PluginPermsText, &group.PluginPerms)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dev.DebugMode {
|
|
log.Print(group.Name + ": ")
|
|
log.Printf("%+v\n", group.PluginPerms)
|
|
}
|
|
|
|
//group.Perms.ExtData = make(map[string]bool)
|
|
mgs.groups = append(mgs.groups, &group)
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
mgs.groupCapCount = i
|
|
|
|
if dev.DebugMode {
|
|
log.Print("Binding the Not Loggedin Group")
|
|
}
|
|
GuestPerms = mgs.groups[6].Perms
|
|
return nil
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) DirtyGet(gid int) *Group {
|
|
if !mgs.Exists(gid) {
|
|
return &blankGroup
|
|
}
|
|
return mgs.groups[gid]
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) Get(gid int) (*Group, error) {
|
|
if !mgs.Exists(gid) {
|
|
return nil, ErrNoRows
|
|
}
|
|
return mgs.groups[gid], nil
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) GetCopy(gid int) (Group, error) {
|
|
if !mgs.Exists(gid) {
|
|
return blankGroup, ErrNoRows
|
|
}
|
|
return *mgs.groups[gid], nil
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) Exists(gid int) bool {
|
|
return (gid <= mgs.groupCapCount) && (gid > -1) && mgs.groups[gid].Name != ""
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) Create(groupName string, tag string, isAdmin bool, isMod bool, isBanned bool) (int, error) {
|
|
groupCreateMutex.Lock()
|
|
defer groupCreateMutex.Unlock()
|
|
|
|
var permstr = "{}"
|
|
res, err := createGroupStmt.Exec(groupName, tag, isAdmin, isMod, isBanned, permstr)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
gid64, err := res.LastInsertId()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
var gid = int(gid64)
|
|
|
|
var perms = BlankPerms
|
|
var blankForums []ForumPerms
|
|
var blankIntList []int
|
|
var pluginPerms = make(map[string]bool)
|
|
var pluginPermsBytes = []byte("{}")
|
|
if vhooks["create_group_preappend"] != nil {
|
|
runVhook("create_group_preappend", &pluginPerms, &pluginPermsBytes)
|
|
}
|
|
|
|
mgs.groups = append(mgs.groups, &Group{gid, groupName, isMod, isAdmin, isBanned, tag, perms, []byte(permstr), pluginPerms, pluginPermsBytes, blankForums, blankIntList})
|
|
|
|
// Generate the forum permissions based on the presets...
|
|
fdata, err := fstore.GetAll()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
permUpdateMutex.Lock()
|
|
defer permUpdateMutex.Unlock()
|
|
for _, forum := range fdata {
|
|
var thePreset string
|
|
if isAdmin {
|
|
thePreset = "admins"
|
|
} else if isMod {
|
|
thePreset = "staff"
|
|
} else if isBanned {
|
|
thePreset = "banned"
|
|
} else {
|
|
thePreset = "members"
|
|
}
|
|
|
|
permmap := presetToPermmap(forum.Preset)
|
|
permitem := permmap[thePreset]
|
|
permitem.Overrides = true
|
|
permstr, err := json.Marshal(permitem)
|
|
if err != nil {
|
|
return gid, err
|
|
}
|
|
perms := string(permstr)
|
|
_, err = addForumPermsToGroupStmt.Exec(gid, forum.ID, forum.Preset, perms)
|
|
if err != nil {
|
|
return gid, err
|
|
}
|
|
|
|
err = rebuildForumPermissions(forum.ID)
|
|
if err != nil {
|
|
return gid, err
|
|
}
|
|
}
|
|
return gid, nil
|
|
}
|
|
|
|
// ! NOT CONCURRENT
|
|
func (mgs *MemoryGroupStore) GetAll() ([]*Group, error) {
|
|
return mgs.groups, nil
|
|
}
|
|
|
|
// ? - It's currently faster to use GetAll(), but we'll be dropping the guarantee that the slices are ordered soon
|
|
// ? - Set the lower and higher numbers to 0 to remove the bounds
|
|
// ? - Currently uses slicing for efficiency, so it might behave a little weirdly
|
|
func (mgs *MemoryGroupStore) GetRange(lower int, higher int) (groups []*Group, err error) {
|
|
if lower == 0 && higher == 0 {
|
|
return mgs.GetAll()
|
|
} else if lower == 0 {
|
|
if higher < 0 {
|
|
return nil, errors.New("higher may not be lower than 0")
|
|
}
|
|
if higher > len(mgs.groups) {
|
|
higher = len(mgs.groups)
|
|
}
|
|
groups = mgs.groups[:higher]
|
|
} else if higher == 0 {
|
|
if lower < 0 {
|
|
return nil, errors.New("lower may not be lower than 0")
|
|
}
|
|
groups = mgs.groups[lower:]
|
|
}
|
|
return groups, nil
|
|
}
|
|
|
|
func (mgs *MemoryGroupStore) Length() int {
|
|
return len(mgs.groups)
|
|
}
|