github.com/k0marov/go-socnet@v0.0.0-20220715154813-90d07867c782/features/profiles/domain/service/service.go (about)

     1  package service
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/k0marov/go-socnet/core/abstract/likeable"
     6  	"github.com/k0marov/go-socnet/core/general/client_errors"
     7  	"github.com/k0marov/go-socnet/core/general/core_entities"
     8  	"github.com/k0marov/go-socnet/core/general/core_err"
     9  	"github.com/k0marov/go-socnet/core/general/core_values"
    10  	"github.com/k0marov/go-socnet/core/general/static_store"
    11  	"github.com/k0marov/go-socnet/core/helpers"
    12  
    13  	"github.com/k0marov/go-socnet/features/profiles/domain/contexters"
    14  	"github.com/k0marov/go-socnet/features/profiles/domain/models"
    15  
    16  	"github.com/k0marov/go-socnet/features/profiles/domain/entities"
    17  	"github.com/k0marov/go-socnet/features/profiles/domain/store"
    18  	"github.com/k0marov/go-socnet/features/profiles/domain/validators"
    19  	"github.com/k0marov/go-socnet/features/profiles/domain/values"
    20  )
    21  
    22  type (
    23  	ProfileGetter  func(id, caller core_values.UserId) (entities.ContextedProfile, error)
    24  	ProfileUpdater func(core_entities.User, values.ProfileUpdateData) (entities.ContextedProfile, error)
    25  	AvatarUpdater  func(core_entities.User, values.AvatarData) (core_values.FileURL, error)
    26  	ProfileCreator func(core_entities.User) (entities.Profile, error)
    27  	FollowToggler  func(target, follower core_values.UserId) error
    28  	FollowsGetter  func(target, caller core_values.UserId) ([]entities.ContextedProfile, error)
    29  )
    30  
    31  func NewProfileGetter(getProfile store.StoreProfileGetter, addContext contexters.ProfileContextAdder) ProfileGetter {
    32  	return func(id core_values.UserId, caller core_values.UserId) (entities.ContextedProfile, error) {
    33  		profile, err := getProfile(id)
    34  		if err != nil {
    35  			if err == core_err.ErrNotFound {
    36  				return entities.ContextedProfile{}, client_errors.NotFound
    37  			}
    38  			return entities.ContextedProfile{}, core_err.Rethrow("getting profile in a service", err)
    39  		}
    40  		contextedProfile, err := addContext(profile, caller)
    41  		if err != nil {
    42  			return entities.ContextedProfile{}, core_err.Rethrow("adding context to profile", err)
    43  		}
    44  		return contextedProfile, nil
    45  	}
    46  }
    47  
    48  func NewFollowToggler(toggleLike likeable.LikeToggler) FollowToggler {
    49  	return FollowToggler(toggleLike)
    50  }
    51  
    52  func NewFollowsGetter(getUserLikes likeable.UserLikesGetter, getProfile ProfileGetter) FollowsGetter {
    53  	return func(target, caller core_values.UserId) ([]entities.ContextedProfile, error) {
    54  		followIds, err := getUserLikes(target)
    55  		if err != nil {
    56  			return []entities.ContextedProfile{}, core_err.Rethrow("getting a list of profile ids that target follows", err)
    57  		}
    58  		follows, err := helpers.MapForEachWithErr(followIds, func(followId string) (entities.ContextedProfile, error) {
    59  			return getProfile(followId, caller)
    60  		})
    61  		if err != nil {
    62  			return []entities.ContextedProfile{}, core_err.Rethrow("getting profiles of follows", err)
    63  		}
    64  		return follows, nil
    65  	}
    66  }
    67  
    68  func NewProfileUpdater(validate validators.ProfileUpdateValidator, update store.StoreProfileUpdater, get ProfileGetter) ProfileUpdater {
    69  	return func(user core_entities.User, updateData values.ProfileUpdateData) (entities.ContextedProfile, error) {
    70  		if clientError, ok := validate(updateData); !ok {
    71  			return entities.ContextedProfile{}, clientError
    72  		}
    73  		err := update(user.Id, updateData)
    74  		if err != nil {
    75  			return entities.ContextedProfile{}, fmt.Errorf("got an error while updating profile in a service: %w", err)
    76  		}
    77  		updatedProfile, err := get(user.Id, user.Id)
    78  		if err != nil {
    79  			return entities.ContextedProfile{}, err
    80  		}
    81  		return updatedProfile, nil
    82  	}
    83  }
    84  
    85  const DefaultAbout = ""
    86  const DefaultAvatarPath = ""
    87  
    88  // NewProfileCreator this should be invoked when a new user is registered
    89  func NewProfileCreator(storeProfileCreator store.StoreProfileCreator) ProfileCreator {
    90  	return func(user core_entities.User) (entities.Profile, error) {
    91  		newProfile := models.ProfileModel{
    92  			Id:         user.Id,
    93  			Username:   user.Username,
    94  			About:      DefaultAbout,
    95  			AvatarPath: DefaultAvatarPath,
    96  		}
    97  		err := storeProfileCreator(newProfile)
    98  		if err != nil {
    99  			return entities.Profile{}, fmt.Errorf("got an error while creating a profile in a service: %w", err)
   100  		}
   101  		createdProfile := entities.Profile{
   102  			ProfileModel: newProfile,
   103  			Follows:      0,
   104  			Followers:    0,
   105  		}
   106  		return createdProfile, nil
   107  	}
   108  }
   109  
   110  func NewAvatarUpdater(validator validators.AvatarValidator, storeAvatar store.StoreAvatarUpdater) AvatarUpdater {
   111  	return func(user core_entities.User, avatar values.AvatarData) (core_values.FileURL, error) {
   112  		if clientError, ok := validator(avatar); !ok {
   113  			return "", clientError
   114  		}
   115  
   116  		avatarPath, err := storeAvatar(user.Id, avatar)
   117  		if err != nil {
   118  			return "", fmt.Errorf("got an error while storing updated avatar: %w", err)
   119  		}
   120  
   121  		return static_store.PathToURL(avatarPath), nil
   122  	}
   123  }