github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/product/service.go (about) 1 package product 2 3 import ( 4 "context" 5 6 "github.com/kyma-incubator/compass/components/director/pkg/resource" 7 8 "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 9 "github.com/kyma-incubator/compass/components/director/internal/model" 10 "github.com/kyma-incubator/compass/components/director/pkg/log" 11 "github.com/pkg/errors" 12 ) 13 14 // ProductRepository missing godoc 15 // 16 //go:generate mockery --name=ProductRepository --output=automock --outpkg=automock --case=underscore --disable-version-string 17 type ProductRepository interface { 18 Create(ctx context.Context, tenant string, item *model.Product) error 19 CreateGlobal(ctx context.Context, model *model.Product) error 20 Update(ctx context.Context, tenant string, item *model.Product) error 21 UpdateGlobal(ctx context.Context, model *model.Product) error 22 Delete(ctx context.Context, tenant, id string) error 23 DeleteGlobal(ctx context.Context, id string) error 24 Exists(ctx context.Context, tenant, id string) (bool, error) 25 GetByID(ctx context.Context, tenant, id string) (*model.Product, error) 26 GetByIDGlobal(ctx context.Context, id string) (*model.Product, error) 27 ListByResourceID(ctx context.Context, tenantID, appID string, resourceType resource.Type) ([]*model.Product, error) 28 ListGlobal(ctx context.Context) ([]*model.Product, error) 29 } 30 31 // UIDService missing godoc 32 // 33 //go:generate mockery --name=UIDService --output=automock --outpkg=automock --case=underscore --disable-version-string 34 type UIDService interface { 35 Generate() string 36 } 37 38 type service struct { 39 productRepo ProductRepository 40 uidService UIDService 41 } 42 43 // NewService creates a new instance of Product Service. 44 func NewService(productRepo ProductRepository, uidService UIDService) *service { 45 return &service{ 46 productRepo: productRepo, 47 uidService: uidService, 48 } 49 } 50 51 // Create creates a new product. 52 func (s *service) Create(ctx context.Context, resourceType resource.Type, resourceID string, in model.ProductInput) (string, error) { 53 id := s.uidService.Generate() 54 product := in.ToProduct(id, resourceType, resourceID) 55 56 if err := s.createProduct(ctx, product, resourceType); err != nil { 57 return "", errors.Wrapf(err, "error occurred while creating a Product with id %s and title %s for %v with id %s", id, product.Title, resourceType, resourceID) 58 } 59 60 log.C(ctx).Debugf("Successfully created a Product with id %s and title %s for %s with id %s", id, product.Title, resourceType, resourceID) 61 62 return product.OrdID, nil 63 } 64 65 // CreateGlobal creates a new global product (with NULL app_id). 66 func (s *service) CreateGlobal(ctx context.Context, in model.ProductInput) (string, error) { 67 id := s.uidService.Generate() 68 product := in.ToProduct(id, "", "") 69 70 if err := s.productRepo.CreateGlobal(ctx, product); err != nil { 71 return "", errors.Wrapf(err, "error occurred while creating Global Product with id %s and title %s", id, product.Title) 72 } 73 log.C(ctx).Debugf("Successfully created a Global Product with id %s and title %s", id, product.Title) 74 75 return product.OrdID, nil 76 } 77 78 // Update updates an existing product. 79 func (s *service) Update(ctx context.Context, resourceType resource.Type, id string, in model.ProductInput) error { 80 product, err := s.getProduct(ctx, id, resourceType) 81 if err != nil { 82 return errors.Wrapf(err, "while getting Product with id %s", id) 83 } 84 85 product.SetFromUpdateInput(in) 86 87 if err = s.updateProduct(ctx, product, resourceType); err != nil { 88 return errors.Wrapf(err, "while updating Product with id %s", id) 89 } 90 91 return nil 92 } 93 94 // UpdateGlobal updates an existing product without tenant isolation. 95 func (s *service) UpdateGlobal(ctx context.Context, id string, in model.ProductInput) error { 96 product, err := s.productRepo.GetByIDGlobal(ctx, id) 97 if err != nil { 98 return errors.Wrapf(err, "while getting Product with id %s", id) 99 } 100 101 product.SetFromUpdateInput(in) 102 103 if err = s.productRepo.UpdateGlobal(ctx, product); err != nil { 104 return errors.Wrapf(err, "while updating Product with id %s", id) 105 } 106 return nil 107 } 108 109 // Delete deletes an existing product. 110 func (s *service) Delete(ctx context.Context, resourceType resource.Type, id string) error { 111 if err := s.deleteProduct(ctx, id, resourceType); err != nil { 112 return errors.Wrapf(err, "while deleting Product with id %s", id) 113 } 114 115 log.C(ctx).Infof("Successfully deleted Product with id %s", id) 116 117 return nil 118 } 119 120 // DeleteGlobal deletes an existing product without tenant isolation. 121 func (s *service) DeleteGlobal(ctx context.Context, id string) error { 122 if err := s.productRepo.DeleteGlobal(ctx, id); err != nil { 123 return errors.Wrapf(err, "while deleting Product with id %s", id) 124 } 125 126 return nil 127 } 128 129 // Exist checks if a product exists. 130 func (s *service) Exist(ctx context.Context, id string) (bool, error) { 131 tnt, err := tenant.LoadFromContext(ctx) 132 if err != nil { 133 return false, errors.Wrap(err, "while loading tenant from context") 134 } 135 136 exist, err := s.productRepo.Exists(ctx, tnt, id) 137 if err != nil { 138 return false, errors.Wrapf(err, "while getting Product with ID: %q", id) 139 } 140 141 return exist, nil 142 } 143 144 // Get returns a product by its ID. 145 func (s *service) Get(ctx context.Context, id string) (*model.Product, error) { 146 tnt, err := tenant.LoadFromContext(ctx) 147 if err != nil { 148 return nil, errors.Wrap(err, "while loading tenant from context") 149 } 150 151 product, err := s.productRepo.GetByID(ctx, tnt, id) 152 if err != nil { 153 return nil, errors.Wrapf(err, "while getting Product with ID: %q", id) 154 } 155 156 return product, nil 157 } 158 159 // ListByApplicationID returns a list of products for a given application ID. 160 func (s *service) ListByApplicationID(ctx context.Context, appID string) ([]*model.Product, error) { 161 tnt, err := tenant.LoadFromContext(ctx) 162 if err != nil { 163 return nil, err 164 } 165 166 return s.productRepo.ListByResourceID(ctx, tnt, appID, resource.Application) 167 } 168 169 // ListByApplicationTemplateVersionID returns a list of products for a given application ID. 170 func (s *service) ListByApplicationTemplateVersionID(ctx context.Context, appID string) ([]*model.Product, error) { 171 return s.productRepo.ListByResourceID(ctx, "", appID, resource.ApplicationTemplateVersion) 172 } 173 174 // ListGlobal returns a list of global products (with NULL app_id). 175 func (s *service) ListGlobal(ctx context.Context) ([]*model.Product, error) { 176 return s.productRepo.ListGlobal(ctx) 177 } 178 179 func (s *service) createProduct(ctx context.Context, product *model.Product, resourceType resource.Type) error { 180 if resourceType.IsTenantIgnorable() { 181 return s.productRepo.CreateGlobal(ctx, product) 182 } 183 184 tnt, err := tenant.LoadFromContext(ctx) 185 if err != nil { 186 return err 187 } 188 189 return s.productRepo.Create(ctx, tnt, product) 190 } 191 192 func (s *service) getProduct(ctx context.Context, id string, resourceType resource.Type) (*model.Product, error) { 193 if resourceType.IsTenantIgnorable() { 194 return s.productRepo.GetByIDGlobal(ctx, id) 195 } 196 197 return s.Get(ctx, id) 198 } 199 200 func (s *service) updateProduct(ctx context.Context, product *model.Product, resourceType resource.Type) error { 201 if resourceType.IsTenantIgnorable() { 202 return s.productRepo.UpdateGlobal(ctx, product) 203 } 204 205 tnt, err := tenant.LoadFromContext(ctx) 206 if err != nil { 207 return err 208 } 209 210 return s.productRepo.Update(ctx, tnt, product) 211 } 212 213 func (s *service) deleteProduct(ctx context.Context, id string, resourceType resource.Type) error { 214 if resourceType.IsTenantIgnorable() { 215 return s.productRepo.DeleteGlobal(ctx, id) 216 } 217 218 tnt, err := tenant.LoadFromContext(ctx) 219 if err != nil { 220 return errors.Wrap(err, "while loading tenant from context") 221 } 222 223 return s.productRepo.Delete(ctx, tnt, id) 224 }