src.dualinventive.com/go/users-service/internal/users/users.go

129 lines
3.4 KiB
Go

package users
import (
"src.dualinventive.com/go/lib/dilog"
"src.dualinventive.com/go/mtinfo-go"
"src.dualinventive.com/go/users-service/errors"
"src.dualinventive.com/go/users-service/internal/domain"
"src.dualinventive.com/go/users-service/internal/storage"
)
//UserService contains User related operations.
type UserService struct {
Logger dilog.Logger
UserRepository storage.UserRepository
Mtinfo *mtinfo.Client
}
//GetUserByID returns a user by the given userID, or returns an error.
func (s *UserService) GetUserByID(token string, userID uint64) (*domain.User, error) {
err := s.verifyToken(token)
if err != nil {
return nil, err
}
user, err := s.UserRepository.GetUserByID(userID)
if err != nil {
s.Logger.WithError(err).Error("failed to fetch user")
return nil, errors.NewErrUserRepositoryErr("failed to fetch user", err)
}
if user == nil {
s.Logger.WithField("userID", userID).Warning("user not found")
return nil, errors.NewErrUserNotFound()
}
return user, nil
}
//ListUsers returns users based on filter, paginated and sorted or nil if not found.
func (s *UserService) ListUsers(
token string, filter domain.UsersFilter, page uint64, perPage uint64, sort domain.SortCol,
) ([]domain.User, uint64, error) {
err := s.verifyToken(token)
if err != nil {
return nil, 0, err
}
// Check filter params
filter, err = s.checkFilterParam(filter)
if err != nil {
return nil, 0, err
}
// Check pagination params
err = s.checkPaginationParam(page, perPage)
if err != nil {
return nil, 0, err
}
// Check user
me, err := s.Mtinfo.Auth.Me(token)
if err != nil {
s.Logger.WithError(err).Error("failed to fetch me")
return nil, 0, errors.NewErrUserRepositoryErr("failed to fetch me", err)
}
filter[domain.UsersFilterTypeCompanyID] = uint64(me.Company.ID)
users, count, err := s.UserRepository.ListUsers(filter, page, perPage, sort)
if err != nil {
s.Logger.WithFields(dilog.Fields{
"page": page,
"per_page": perPage,
"sort": sort,
}).WithError(err).Error("failed to fetch users")
return nil, 0, errors.NewErrUserRepositoryErr("failed to fetch users", err)
}
return users, count, nil
}
func (s *UserService) verifyToken(token string) error {
ok, err := s.Mtinfo.Auth.VerifyToken(token)
if err != nil {
s.Logger.WithField("token", token).WithError(err).Warning("unauthorized with error")
return errors.NewErrUnauthorized()
}
if !ok {
s.Logger.WithField("token", token).Warning("unauthorized")
return errors.NewErrUnauthorized()
}
return nil
}
func (s *UserService) checkFilterParam(filter domain.UsersFilter) (domain.UsersFilter, error) {
if filter == nil {
filter = make(domain.UsersFilter)
}
reference, found := filter[domain.UsersFilterTypeReference]
if found {
if len(reference.(string)) == 0 {
return nil, errors.NewErrInvalidArgument(
domain.UsersFilterTypeReference.String(), "can not be empty",
)
}
if len(reference.(string)) > 30 {
return nil, errors.NewErrInvalidArgument(
domain.UsersFilterTypeReference.String(), "string length max. 30 characters",
)
}
}
return filter, nil
}
func (s *UserService) checkPaginationParam(page uint64, perPage uint64) error {
if page == 0 {
return errors.NewErrInvalidArgument("page", "can not be 0")
}
if perPage == 0 {
return errors.NewErrInvalidArgument("per_page", "can not be 0")
}
if perPage > 200 {
return errors.NewErrInvalidArgument("per_page", "can not be > 200")
}
return nil
}