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 }