gosora/user_store.go
Azareal 1ccd4479ae Added support for offsets and max counts to the query generator.
Early draft of the ForumStore. Not much to see here yet!

Fixed a race condition in forum creation.
Fixed a race condition in group creation.
Fixed a race condition in forum deletion.
Moved four queries to the query generator.
Renamed StaticTopicStore to MemoryTopicStore.
Renamed StaticUserStore to MemoryUserStore.
SimpleSessionCheck is now pluggable.

We no longer have any raw queries outside mysql.go or the query generator, yay.
2017-06-15 12:40:35 +01:00

299 lines
8.0 KiB
Go

package main
import "log"
import "sync"
import "strings"
import "strconv"
import "database/sql"
import "./query_gen/lib"
var users UserStore
type UserStore interface {
Load(id int) error
Get(id int) (*User, error)
GetUnsafe(id int) (*User, error)
CascadeGet(id int) (*User, error)
BypassGet(id int) (*User, error)
Set(item *User) error
Add(item *User) error
AddUnsafe(item *User) error
//SetConn(conn interface{}) error
//GetConn() interface{}
Remove(id int) error
RemoveUnsafe(id int) error
GetLength() int
GetCapacity() int
}
type MemoryUserStore struct {
items map[int]*User
length int
capacity int
get *sql.Stmt
sync.RWMutex
}
func NewMemoryUserStore(capacity int) *MemoryUserStore {
stmt, err := qgen.Builder.SimpleSelect("users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid = ?","","")
if err != nil {
log.Fatal(err)
}
return &MemoryUserStore{
items:make(map[int]*User),
capacity:capacity,
get:stmt,
}
}
func (sus *MemoryUserStore) Get(id int) (*User, error) {
sus.RLock()
item, ok := sus.items[id]
sus.RUnlock()
if ok {
return item, nil
}
return item, sql.ErrNoRows
}
func (sus *MemoryUserStore) GetUnsafe(id int) (*User, error) {
item, ok := sus.items[id]
if ok {
return item, nil
}
return item, sql.ErrNoRows
}
func (sus *MemoryUserStore) CascadeGet(id int) (*User, error) {
sus.RLock()
user, ok := sus.items[id]
sus.RUnlock()
if ok {
return user, nil
}
user = &User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(user)
if err == nil {
sus.Set(user)
}
return user, err
}
func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
user := &User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(user)
return user, err
}
func (sus *MemoryUserStore) Load(id int) error {
user := &User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if err != nil {
sus.Remove(id)
return err
}
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(user)
sus.Set(user)
return nil
}
func (sus *MemoryUserStore) Set(item *User) error {
sus.Lock()
user, ok := sus.items[item.ID]
if ok {
sus.Unlock()
*user = *item
} else if sus.length >= sus.capacity {
sus.Unlock()
return ErrStoreCapacityOverflow
} else {
sus.items[item.ID] = item
sus.Unlock()
sus.length++
}
return nil
}
func (sus *MemoryUserStore) Add(item *User) error {
if sus.length >= sus.capacity {
return ErrStoreCapacityOverflow
}
sus.Lock()
sus.items[item.ID] = item
sus.Unlock()
sus.length++
return nil
}
func (sus *MemoryUserStore) AddUnsafe(item *User) error {
if sus.length >= sus.capacity {
return ErrStoreCapacityOverflow
}
sus.items[item.ID] = item
sus.length++
return nil
}
func (sus *MemoryUserStore) Remove(id int) error {
sus.Lock()
delete(sus.items,id)
sus.Unlock()
sus.length--
return nil
}
func (sus *MemoryUserStore) RemoveUnsafe(id int) error {
delete(sus.items,id)
sus.length--
return nil
}
func (sus *MemoryUserStore) GetLength() int {
return sus.length
}
func (sus *MemoryUserStore) SetCapacity(capacity int) {
sus.capacity = capacity
}
func (sus *MemoryUserStore) GetCapacity() int {
return sus.capacity
}
type SqlUserStore struct {
get *sql.Stmt
}
func NewSqlUserStore() *SqlUserStore {
stmt, err := qgen.Builder.SimpleSelect("users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid = ?","","")
if err != nil {
log.Fatal(err)
}
return &SqlUserStore{stmt}
}
func (sus *SqlUserStore) Get(id int) (*User, error) {
user := User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(&user)
return &user, err
}
func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) {
user := User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(&user)
return &user, err
}
func (sus *SqlUserStore) CascadeGet(id int) (*User, error) {
user := User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(&user)
return &user, err
}
func (sus *SqlUserStore) BypassGet(id int) (*User, error) {
user := User{ID:id,Loggedin:true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(&user)
return &user, err
}
func (sus *SqlUserStore) Load(id int) error {
user := &User{ID:id}
// Simplify this into a quick check whether the user exists
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
return err
}
// Placeholder methods, the actual queries are done elsewhere
func (sus *SqlUserStore) Set(item *User) error {
return nil
}
func (sus *SqlUserStore) Add(item *User) error {
return nil
}
func (sus *SqlUserStore) AddUnsafe(item *User) error {
return nil
}
func (sus *SqlUserStore) Remove(id int) error {
return nil
}
func (sus *SqlUserStore) RemoveUnsafe(id int) error {
return nil
}
func (sus *SqlUserStore) GetCapacity() int {
return 0
}
func (sus *SqlUserStore) GetLength() int {
return 0 // Return the total number of users registered on the forums?
}