public Stream CreateProviderProduct(string provider, ProductData data)
        {
            try
            {
                // VERIFY

                if (data == null || string.IsNullOrEmpty(data.title)) throw new BadRequestException();
                _h.OneOf(data.type, Product.getListOfProductTypes());

                var invoker = _h.Authorize();

                // CREATE ACCOUNT

                data.published = false;
                data.owner = provider;

                ProductTypes.Product product = _c.Convert(data);

                var id = (uint) Product.persist(product).id;

                // SIGNAL SUCCESS

                _h.SetHeader("Location", "/accounts/" + provider + "/products/" + id);
                _h.Success(201);

                return _j.Json(_c.Convert(id));
            }
            catch (BadRequestException) { return _h.Failure(400); }
            catch (PermissionExceptions.PermissionDenied) { return _h.Failure(403); }
            catch (ProductExceptions.TooLargeData) { return _h.Failure(413); }
            catch (Exception) { return _h.Failure(500); }
        }
        public void UpdateProviderProduct(string provider, string id, ProductData data)
        {
            try
            {
                // VERIFY

                uint pId;
                try { pId = _h.Uint(id); }
                catch (BadRequestException) { throw new NotFoundException(); }

                var invoker = _h.Authorize();

                var product = Product.getProductById((int)pId);
                if (!Ops.compareUsernames(product.owner, provider)) throw new NotFoundException();

                // EXECUTE

                _p.UpdateProduct(id, data);
            }
            catch (PermissionExceptions.PermissionDenied) { _h.Failure(403); }
            catch (PermissionExceptions.AccountBanned) { _h.Failure(403); }
            catch (NotFoundException) { _h.Failure(404); }
            catch (ProductExceptions.NoSuchProduct) { _h.Failure(404); }
            catch (Exception) { _h.Failure(500); }
        }
        public void UpdateProduct(string id, ProductData data)
        {
            try
            {
                // VERIFY

                int pId = (int) _h.Uint(id);

                var invoker = _h.Authorize();

                // UPDATE DATA

                bool outdated = true;
                while (outdated)
                {
                    try
                    {
                        var product = Product.getProductById(pId);
                        var updated = _c.Merge(product, data);
                        Product.update(updated);

                        // If we get so far, the update went as planned, so we can quit the loop
                        outdated = false;
                    }
                    catch (ProductExceptions.OutdatedData) { /* Exception = load latest data and update based on it */ }
                }

                // SIGNAL SUCCESS

                _h.Success(204);
            }
            catch (PermissionExceptions.PermissionDenied) { _h.Failure(403); }
            catch (PermissionExceptions.AccountBanned) { _h.Failure(403); }
            catch (BadRequestException) { _h.Failure(404); } // Only thrown if id != uint
            catch (ProductExceptions.NoSuchProduct) { _h.Failure(404); }
            catch (ProductExceptions.TooLargeData) { _h.Failure(413); }
            catch (Exception) { _h.Failure(500); }
        }
 public Stream CreateProviderProduct(string provider, ProductData data)
 {
     return _provider.CreateProviderProduct(provider, data);
 }
 public void UpdateProviderProduct(string provider, string id, ProductData data)
 {
     _provider.UpdateProviderProduct(provider, id, data);
 }
 public void UpdateProduct(string id, ProductData data)
 {
     _product.UpdateProduct(id, data);
 }