// Copyright (C) 2018 Marius Schellenberger package db import ( "errors" "git.giftfish.de/ston1th/gowiki/pkg/core" "golang.org/x/crypto/bcrypt" "sort" ) var ( errUserNotFound = dbErr("user not found") errUserExists = dbErr("user already exist") errUserReserved = dbErr("username is reserved") ) func (db *DB) DumpUsers() (users core.Users, err error) { db.users.ForEach(func(username string, _ []byte) error { u, err := db.GetUser(username) if err == nil { users = append(users, u) } return nil }) return } func (db *DB) GetUsers() (users core.Users, err error) { users, err = db.DumpUsers() for i := range users { users[i].Password = "" } sort.Sort(users) return } func (db *DB) GetUserWithoutPassword(username string) (u core.User, err error) { u, err = db.GetUser(username) u.Password = "" return } func (db *DB) GetUser(username string) (u core.User, err error) { err = db.users.Get(username, &u) return } func (db *DB) UserExists(username string) error { return db.users.Get(username, nil) } // TODO /*func (bs *BoltStore) RestoreUsers(users []User) error { return bs.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(userTable)) err := b.ForEach(func(k, v []byte) error { return b.Delete(k) }) if err != nil { return err } for _, u := range users { v, err := bs.Marshal(u) if err != nil { return err } err = b.Put([]byte(u.Username), v) if err != nil { return err } } return nil }) }*/ func (db *DB) CreateUser(username, password string, admin bool) error { if reservedUser(username) { return errUserReserved } if err := db.UserExists(username); err == nil { return errUserExists } hash, err := bcrypt.GenerateFromPassword(validatePassword(password), bcryptCost) if err != nil { return err } return db.users.Set(username, &core.User{ Username: username, Password: string(hash), Admin: admin, }) } func (db *DB) Login(username, password string) (u core.User, err error) { u, err = db.GetUser(username) if err != nil { return } if u.Locked == 3 { err = errors.New("db: user locked") return } if err = bcrypt.CompareHashAndPassword([]byte(u.Password), validatePassword(password)); err != nil { u.Locked++ err = db.users.Set(username, u) if err != nil { return } err = errors.New("db: wrong login") return } if u.Locked > 0 { u.Locked = 0 err = db.users.Set(username, u) if err != nil { return } } return } func (db *DB) UnlockUser(username string) (err error) { var u core.User u, err = db.GetUser(username) if err != nil { return } if u.Locked > 0 { u.Locked = 0 err = db.users.Set(username, u) if err != nil { return } } return } func (db *DB) UpdateUserPassword(username, password string) error { u, err := db.GetUser(username) if err != nil { return err } hash, err := bcrypt.GenerateFromPassword(validatePassword(password), bcryptCost) if err != nil { return err } u.Password = string(hash) return db.users.Set(username, u) } func (db *DB) AdminUpdateUser(username, password string, admin bool) error { if username == defUser && !admin { return errors.New("user '" + defUser + "' cannot lose admin privileges") } u, err := db.GetUser(username) if err != nil { return err } u.Admin = admin if password != "" { hash, err := bcrypt.GenerateFromPassword(validatePassword(password), bcryptCost) if err != nil { return err } u.Password = string(hash) } return db.users.Set(username, u) } //TODO delete all user owned pages func (db *DB) DeleteUser(username string) error { if username == defUser { return errors.New("user '" + defUser + "' cannot be deleted") } return db.users.Delete(username) }