ribbit/model_user.go

238 lines
4.8 KiB
Go

package main
import (
"errors"
"fmt"
"strings"
"github.com/pborman/uuid"
"golang.org/x/crypto/bcrypt"
)
type User struct {
Username string `json:username`
Uuid string `json:uuid`
SubSlugs []string `json:subs`
IsAdmin bool `json:admin`
}
func NewUser(un string) *User {
u := new(User)
u.Username = un
u.Uuid = uuid.New()
return u
}
/*
func (u *User) UpdateFeed() error {
for _, slug := range u.SubSlugs {
pts := strings.Split(slug, ";")
if len(pts) != 2 {
continue
}
if comic, err := m.GetComic(pts[0], pts[1]); err == nil {
comic.Update()
}
}
return nil
}
*/
func (m *model) SaveUser(u *User) error {
var err error
if err = m.openDB(); err != nil {
return err
}
defer m.closeDB()
bkt := []string{"users", u.Uuid}
if err = m.bolt.MkBucketPath(bkt); err != nil {
return err
}
if err = m.bolt.SetValue(bkt, "username", u.Username); err != nil {
return err
}
var adminVal = "false"
if u.IsAdmin {
adminVal = "true"
}
if err = m.bolt.SetValue(bkt, "admin", adminVal); err != nil {
return err
}
var newSubs []string
for _, v := range u.SubSlugs {
if strings.TrimSpace(v) != "" {
newSubs = append(newSubs, v)
}
}
slugs := strings.Join(newSubs, ",")
if err = m.bolt.SetValue(bkt, "subs", slugs); err != nil {
return err
}
return nil
}
func (m *model) isValidUser(uid string) bool {
var err error
if err = m.openDB(); err != nil {
return false
}
defer m.closeDB()
ret := new(User)
bkt := []string{"users", uid}
ret.Uuid = uid
if ret.Username, err = m.bolt.GetValue(bkt, "username"); err != nil {
fmt.Println("Error getting username value:", err.Error())
return false
}
return true
}
func (m *model) GetUserByEmail(email string) (*User, error) {
if email == "" {
return nil, errors.New("No email given")
}
u := m.GetAllUsers()
for i := range u {
if u[i].Username == email {
return &u[i], nil
}
}
return nil, errors.New("No user found")
}
func (m *model) GetUser(uid string) (*User, error) {
if uid == "" {
return nil, errors.New("No user id given")
}
var err error
if err = m.openDB(); err != nil {
return nil, err
}
defer m.closeDB()
ret := new(User)
bkt := []string{"users", uid}
ret.Uuid = uid
if ret.Username, err = m.bolt.GetValue(bkt, "username"); err != nil {
fmt.Println("Error getting username value:", err.Error())
return nil, err
}
admin, _ := m.bolt.GetValue(bkt, "admin")
ret.IsAdmin = (admin == "true")
var subs string
if subs, err = m.bolt.GetValue(bkt, "subs"); err != nil {
return nil, err
}
ret.SubSlugs = strings.Split(subs, ",")
return ret, nil
}
func (m *model) SaveAllUsers(users []User) {
var err error
if err = m.openDB(); err != nil {
return
}
defer m.closeDB()
for i := range users {
m.SaveUser(&users[i])
}
}
func (m *model) LoadUsers() error {
m.Users = m.GetAllUsers()
return nil
}
func (m *model) GetAllUsers() []User {
var err error
var ret []User
if err = m.openDB(); err != nil {
return ret
}
defer m.closeDB()
uids := m.GetUserIdList()
for _, uid := range uids {
if u, e := m.GetUser(uid); e == nil {
ret = append(ret, *u)
}
}
return ret
}
func (m *model) GetUserByName(nm string) (*User, error) {
var err error
if err = m.openDB(); err != nil {
return nil, err
}
defer m.closeDB()
usrids := m.GetUserIdList()
for i := range usrids {
bkt := []string{"users", usrids[i]}
var tstuname string
if tstuname, _ = m.bolt.GetValue(bkt, "username"); tstuname == nm {
// Found it
return m.GetUser(usrids[i])
}
}
return nil, errors.New("No user with username " + nm + " found")
}
func (m *model) GetUserIdList() []string {
var ret []string
var err error
if err = m.openDB(); err != nil {
return ret
}
defer m.closeDB()
bkt := []string{"users"}
ret, _ = m.bolt.GetBucketList(bkt)
return ret
}
// updateUserPassword
// Takes a user id and a password
// Fails if the user doesn't exist
func (m *model) updateUserPassword(uid, password string) error {
cryptPw, cryptError := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if cryptError != nil {
return cryptError
}
if _, err := m.GetUser(uid); err != nil {
return err
}
if err := m.openDB(); err != nil {
return err
}
defer m.closeDB()
usrPath := []string{"users", uid}
return m.bolt.SetValue(usrPath, "password", string(cryptPw))
}
// Is the uid and pw given valid?
func (m *model) checkCredentials(uid, pw string) error {
var err error
if err = m.openDB(); err != nil {
return err
}
defer m.closeDB()
var uPw string
usrPath := []string{"users", uid}
if uPw, err = m.bolt.GetValue(usrPath, "password"); err != nil {
return err
}
return bcrypt.CompareHashAndPassword([]byte(uPw), []byte(pw))
}
func (m *model) hasAdminUser() bool {
users := m.GetAllUsers()
for i := range users {
if users[i].IsAdmin {
return true
}
}
return false
}