github.com/dhax/go-base@v0.0.0-20231004214136-8be7e5c1972b/database/admAccountStore.go (about)

     1  package database
     2  
     3  import (
     4  	"errors"
     5  	"net/url"
     6  
     7  	"github.com/dhax/go-base/auth/jwt"
     8  	"github.com/dhax/go-base/auth/pwdless"
     9  	"github.com/dhax/go-base/models"
    10  	"github.com/go-pg/pg"
    11  	"github.com/go-pg/pg/orm"
    12  	"github.com/go-pg/pg/urlvalues"
    13  )
    14  
    15  var (
    16  	// ErrUniqueEmailConstraint provides error message for already registered email address.
    17  	ErrUniqueEmailConstraint = errors.New("email already registered")
    18  	// ErrBadParams could not parse params to filter
    19  	ErrBadParams = errors.New("bad parameters")
    20  )
    21  
    22  // AdmAccountStore implements database operations for account management by admin.
    23  type AdmAccountStore struct {
    24  	db *pg.DB
    25  }
    26  
    27  // NewAdmAccountStore returns an AccountStore.
    28  func NewAdmAccountStore(db *pg.DB) *AdmAccountStore {
    29  	return &AdmAccountStore{
    30  		db: db,
    31  	}
    32  }
    33  
    34  // AccountFilter provides pagination and filtering options on accounts.
    35  type AccountFilter struct {
    36  	Pager  *urlvalues.Pager
    37  	Filter *urlvalues.Filter
    38  	Order  []string
    39  }
    40  
    41  // NewAccountFilter returns an AccountFilter with options parsed from request url values.
    42  func NewAccountFilter(params interface{}) (*AccountFilter, error) {
    43  	v, ok := params.(url.Values)
    44  	if !ok {
    45  		return nil, ErrBadParams
    46  	}
    47  	p := urlvalues.Values(v)
    48  	f := &AccountFilter{
    49  		Pager:  urlvalues.NewPager(p),
    50  		Filter: urlvalues.NewFilter(p),
    51  		Order:  p["order"],
    52  	}
    53  	return f, nil
    54  }
    55  
    56  // Apply applies an AccountFilter on an orm.Query.
    57  func (f *AccountFilter) Apply(q *orm.Query) (*orm.Query, error) {
    58  	q = q.Apply(f.Pager.Pagination)
    59  	q = q.Apply(f.Filter.Filters)
    60  	q = q.Order(f.Order...)
    61  	return q, nil
    62  }
    63  
    64  // List applies a filter and returns paginated array of matching results and total count.
    65  func (s *AdmAccountStore) List(f *AccountFilter) ([]pwdless.Account, int, error) {
    66  	a := []pwdless.Account{}
    67  	count, err := s.db.Model(&a).
    68  		Apply(f.Apply).
    69  		SelectAndCount()
    70  	if err != nil {
    71  		return nil, 0, err
    72  	}
    73  	return a, count, nil
    74  }
    75  
    76  // Create creates a new account.
    77  func (s *AdmAccountStore) Create(a *pwdless.Account) error {
    78  	count, _ := s.db.Model(a).
    79  		Where("email = ?email").
    80  		Count()
    81  
    82  	if count != 0 {
    83  		return ErrUniqueEmailConstraint
    84  	}
    85  
    86  	err := s.db.RunInTransaction(func(tx *pg.Tx) error {
    87  		err := tx.Insert(a)
    88  		if err != nil {
    89  			return err
    90  		}
    91  		p := &models.Profile{
    92  			AccountID: a.ID,
    93  		}
    94  		return tx.Insert(p)
    95  	})
    96  
    97  	return err
    98  }
    99  
   100  // Get account by ID.
   101  func (s *AdmAccountStore) Get(id int) (*pwdless.Account, error) {
   102  	a := pwdless.Account{ID: id}
   103  	err := s.db.Select(&a)
   104  	return &a, err
   105  }
   106  
   107  // Update account.
   108  func (s *AdmAccountStore) Update(a *pwdless.Account) error {
   109  	err := s.db.Update(a)
   110  	return err
   111  }
   112  
   113  // Delete account.
   114  func (s *AdmAccountStore) Delete(a *pwdless.Account) error {
   115  	err := s.db.RunInTransaction(func(tx *pg.Tx) error {
   116  		if _, err := tx.Model(&jwt.Token{}).
   117  			Where("account_id = ?", a.ID).
   118  			Delete(); err != nil {
   119  			return err
   120  		}
   121  		if _, err := tx.Model(&models.Profile{}).
   122  			Where("account_id = ?", a.ID).
   123  			Delete(); err != nil {
   124  			return err
   125  		}
   126  		return tx.Delete(a)
   127  	})
   128  	return err
   129  }