package repository import ( "encoding/json" "fmt" normalizer "github.com/dimuska139/go-email-normalizer/v2" "gitrepo.ru/neonxp/gorum/models" "go.etcd.io/bbolt" "golang.org/x/crypto/bcrypt" ) type User struct { db *bbolt.DB } func NewUser(db *bbolt.DB) *User { return &User{ db: db, } } func (t *User) Init() error { return t.db.Update(func(tx *bbolt.Tx) error { _, err := tx.CreateBucketIfNotExists([]byte("users")) return err }) } func (u *User) Create(email, password, username string, role models.UserRole) error { if len(password) < 8 { return models.ErrInvalidPassword } hpassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return models.ErrInvalidPassword } email = normalizer.NewNormalizer().Normalize(email) user := &models.User{ Email: email, Password: string(hpassword), Username: username, Role: role, } u.db.Update(func(tx *bbolt.Tx) error { bucket, err := tx.CreateBucketIfNotExists([]byte("users")) if err != nil { return err } ub := bucket.Get([]byte(email)) if ub != nil { return models.ErrUserAlreadyExists } ub, err = json.Marshal(user) if err != nil { return err } return bucket.Put([]byte(email), ub) }) return nil } func (u *User) Login(email, password string) (*models.User, error) { user := new(models.User) email = normalizer.NewNormalizer().Normalize(email) return user, u.db.View(func(tx *bbolt.Tx) error { ub := tx.Bucket([]byte("users")).Get([]byte(email)) if ub == nil { return models.ErrInvalidUserOrPassword } if err := json.Unmarshal(ub, user); err != nil { return err } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { return fmt.Errorf("invalid password: %w", models.ErrInvalidUserOrPassword) } return nil }) } func (u *User) Get(email string) (*models.User, error) { user := new(models.User) email = normalizer.NewNormalizer().Normalize(email) return user, u.db.View(func(tx *bbolt.Tx) error { ub := tx.Bucket([]byte("users")).Get([]byte(email)) if ub == nil { return models.ErrInvalidUserOrPassword } return json.Unmarshal(ub, user) }) } func (u *User) List() ([]*models.User, error) { ret := make([]*models.User, 0) return ret, u.db.View(func(tx *bbolt.Tx) error { bucket := tx.Bucket([]byte("users")) return bucket.ForEach(func(k, v []byte) error { u := new(models.User) if err := json.Unmarshal(v, u); err != nil { return err } ret = append(ret, u) return nil }) }) }