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 }