From 5a19a14042924687240f7f5ae591df24e188861f Mon Sep 17 00:00:00 2001 From: Andy Brett Date: Fri, 5 Mar 2021 14:44:40 -0800 Subject: [PATCH 1/6] rename to v0 --- .rubocop_todo.yml | 2 +- .../admin/bulk_product_update.js.coffee | 4 +- .../directives/delete_resource.js.coffee | 2 +- .../index_utils/services/resources.js.coffee | 2 +- .../services/exchange_product.js.coffee | 2 +- .../services/product_image_service.js.coffee | 2 +- .../resources/enterprise_resource.js.coffee | 6 +- .../resources/order_resource.js.coffee | 6 +- .../resources/product_resource.js.coffee | 2 +- .../admin/services/bulk_products.js.coffee | 4 +- .../variant_overrides_controller.js.coffee | 2 +- .../controllers/hub_node_controller.js.coffee | 2 +- .../producer_node_controller.js.coffee | 2 +- .../darkswarm/services/customer.js.coffee | 2 +- .../enterprise_image_service.js.coffee | 2 +- .../services/enterprise_modal.js.coffee | 2 +- .../enterprise_registration_service.js.coffee | 4 +- .../services/order_cycle_resource.js.coffee | 8 +- .../services/shops_resource.js.coffee | 4 +- app/controllers/api/base_controller.rb | 103 ----------- app/controllers/api/customers_controller.rb | 37 ---- .../api/enterprise_attachment_controller.rb | 42 ----- .../api/enterprise_fees_controller.rb | 21 --- app/controllers/api/enterprises_controller.rb | 78 --------- .../api/exchange_products_controller.rb | 100 ----------- app/controllers/api/logos_controller.rb | 16 -- .../api/order_cycles_controller.rb | 101 ----------- app/controllers/api/orders_controller.rb | 67 ------- .../api/product_images_controller.rb | 19 -- app/controllers/api/products_controller.rb | 159 ----------------- .../api/promo_images_controller.rb | 16 -- app/controllers/api/shipments_controller.rb | 112 ------------ app/controllers/api/shops_controller.rb | 27 --- app/controllers/api/states_controller.rb | 44 ----- app/controllers/api/statuses_controller.rb | 16 -- app/controllers/api/taxonomies_controller.rb | 12 -- app/controllers/api/taxons_controller.rb | 76 -------- .../api/terms_and_conditions_controller.rb | 18 -- app/controllers/api/v0/base_controller.rb | 107 ++++++++++++ .../api/v0/customers_controller.rb | 41 +++++ .../v0/enterprise_attachment_controller.rb | 44 +++++ .../api/v0/enterprise_fees_controller.rb | 25 +++ .../api/v0/enterprises_controller.rb | 82 +++++++++ .../api/v0/exchange_products_controller.rb | 102 +++++++++++ app/controllers/api/v0/logos_controller.rb | 20 +++ .../api/v0/order_cycles_controller.rb | 105 +++++++++++ app/controllers/api/v0/orders_controller.rb | 71 ++++++++ .../api/v0/product_images_controller.rb | 23 +++ app/controllers/api/v0/products_controller.rb | 163 ++++++++++++++++++ .../api/v0/promo_images_controller.rb | 20 +++ .../api/v0/shipments_controller.rb | 116 +++++++++++++ app/controllers/api/v0/shops_controller.rb | 29 ++++ app/controllers/api/v0/states_controller.rb | 46 +++++ app/controllers/api/v0/statuses_controller.rb | 20 +++ .../api/v0/taxonomies_controller.rb | 16 ++ app/controllers/api/v0/taxons_controller.rb | 78 +++++++++ .../api/v0/terms_and_conditions_controller.rb | 20 +++ app/controllers/api/v0/variants_controller.rb | 81 +++++++++ app/controllers/api/variants_controller.rb | 77 --------- .../spree/admin/products_controller.rb | 2 +- app/views/spree/admin/shared/_routes.html.erb | 6 +- app/views/spree/admin/taxonomies/edit.haml | 2 +- config/routes/api.rb | 122 ++++++------- .../cookies_banner_controller.js.coffee | 2 +- .../web/api/cookies_consent_controller.rb | 30 ---- .../web/api/v0/cookies_consent_controller.rb | 32 ++++ engines/web/config/routes.rb | 4 +- .../api/{ => v0}/base_controller_spec.rb | 4 +- .../api/{ => v0}/customers_controller_spec.rb | 2 +- .../enterprise_fees_controller_spec.rb | 2 +- .../{ => v0}/enterprises_controller_spec.rb | 2 +- .../exchange_products_controller_spec.rb | 4 +- .../api/{ => v0}/logos_controller_spec.rb | 2 +- .../{ => v0}/order_cycles_controller_spec.rb | 2 +- .../api/{ => v0}/orders_controller_spec.rb | 2 +- .../product_images_controller_spec.rb | 2 +- .../api/{ => v0}/products_controller_spec.rb | 2 +- .../{ => v0}/promo_images_controller_spec.rb | 2 +- .../api/{ => v0}/shipments_controller_spec.rb | 2 +- .../api/{ => v0}/shops_controller_spec.rb | 2 +- .../api/{ => v0}/states_controller_spec.rb | 2 +- .../api/{ => v0}/statuses_controller_spec.rb | 2 +- .../{ => v0}/taxonomies_controller_spec.rb | 2 +- .../api/{ => v0}/taxons_controller_spec.rb | 2 +- .../terms_and_conditions_controller_spec.rb | 2 +- .../api/{ => v0}/variants_controller_spec.rb | 2 +- .../spree/admin/products_controller_spec.rb | 2 +- ...lex_editing_multiple_product_pages_spec.rb | 2 +- .../consumer/caching/shops_caching_spec.rb | 4 +- .../admin/bulk_product_update_spec.js.coffee | 8 +- .../services/enterprises_spec.js.coffee | 8 +- .../line_items_controller_spec.js.coffee | 2 +- .../orders/services/orders_spec.js.coffee | 2 +- .../services/bulk_products_spec.js.coffee | 8 +- .../services/credit_cards_spec.js.coffee | 2 +- .../services/customer_spec.js.coffee | 6 +- .../services/customers_spec.js.coffee | 2 +- .../enterprise_registration_spec.js.coffee | 10 +- .../services/products_spec.js.coffee | 2 +- spec/requests/api/orders_spec.rb | 4 +- 100 files changed, 1394 insertions(+), 1320 deletions(-) delete mode 100644 app/controllers/api/base_controller.rb delete mode 100644 app/controllers/api/customers_controller.rb delete mode 100644 app/controllers/api/enterprise_attachment_controller.rb delete mode 100644 app/controllers/api/enterprise_fees_controller.rb delete mode 100644 app/controllers/api/enterprises_controller.rb delete mode 100644 app/controllers/api/exchange_products_controller.rb delete mode 100644 app/controllers/api/logos_controller.rb delete mode 100644 app/controllers/api/order_cycles_controller.rb delete mode 100644 app/controllers/api/orders_controller.rb delete mode 100644 app/controllers/api/product_images_controller.rb delete mode 100644 app/controllers/api/products_controller.rb delete mode 100644 app/controllers/api/promo_images_controller.rb delete mode 100644 app/controllers/api/shipments_controller.rb delete mode 100644 app/controllers/api/shops_controller.rb delete mode 100644 app/controllers/api/states_controller.rb delete mode 100644 app/controllers/api/statuses_controller.rb delete mode 100644 app/controllers/api/taxonomies_controller.rb delete mode 100644 app/controllers/api/taxons_controller.rb delete mode 100644 app/controllers/api/terms_and_conditions_controller.rb create mode 100644 app/controllers/api/v0/base_controller.rb create mode 100644 app/controllers/api/v0/customers_controller.rb create mode 100644 app/controllers/api/v0/enterprise_attachment_controller.rb create mode 100644 app/controllers/api/v0/enterprise_fees_controller.rb create mode 100644 app/controllers/api/v0/enterprises_controller.rb create mode 100644 app/controllers/api/v0/exchange_products_controller.rb create mode 100644 app/controllers/api/v0/logos_controller.rb create mode 100644 app/controllers/api/v0/order_cycles_controller.rb create mode 100644 app/controllers/api/v0/orders_controller.rb create mode 100644 app/controllers/api/v0/product_images_controller.rb create mode 100644 app/controllers/api/v0/products_controller.rb create mode 100644 app/controllers/api/v0/promo_images_controller.rb create mode 100644 app/controllers/api/v0/shipments_controller.rb create mode 100644 app/controllers/api/v0/shops_controller.rb create mode 100644 app/controllers/api/v0/states_controller.rb create mode 100644 app/controllers/api/v0/statuses_controller.rb create mode 100644 app/controllers/api/v0/taxonomies_controller.rb create mode 100644 app/controllers/api/v0/taxons_controller.rb create mode 100644 app/controllers/api/v0/terms_and_conditions_controller.rb create mode 100644 app/controllers/api/v0/variants_controller.rb delete mode 100644 app/controllers/api/variants_controller.rb delete mode 100644 engines/web/app/controllers/web/api/cookies_consent_controller.rb create mode 100644 engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb rename spec/controllers/api/{ => v0}/base_controller_spec.rb (96%) rename spec/controllers/api/{ => v0}/customers_controller_spec.rb (97%) rename spec/controllers/api/{ => v0}/enterprise_fees_controller_spec.rb (91%) rename spec/controllers/api/{ => v0}/enterprises_controller_spec.rb (97%) rename spec/controllers/api/{ => v0}/exchange_products_controller_spec.rb (95%) rename spec/controllers/api/{ => v0}/logos_controller_spec.rb (98%) rename spec/controllers/api/{ => v0}/order_cycles_controller_spec.rb (99%) rename spec/controllers/api/{ => v0}/orders_controller_spec.rb (99%) rename spec/controllers/api/{ => v0}/product_images_controller_spec.rb (95%) rename spec/controllers/api/{ => v0}/products_controller_spec.rb (99%) rename spec/controllers/api/{ => v0}/promo_images_controller_spec.rb (98%) rename spec/controllers/api/{ => v0}/shipments_controller_spec.rb (99%) rename spec/controllers/api/{ => v0}/shops_controller_spec.rb (96%) rename spec/controllers/api/{ => v0}/states_controller_spec.rb (98%) rename spec/controllers/api/{ => v0}/statuses_controller_spec.rb (93%) rename spec/controllers/api/{ => v0}/taxonomies_controller_spec.rb (96%) rename spec/controllers/api/{ => v0}/taxons_controller_spec.rb (98%) rename spec/controllers/api/{ => v0}/terms_and_conditions_controller_spec.rb (96%) rename spec/controllers/api/{ => v0}/variants_controller_spec.rb (98%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index cd62dcf638..c55ed2673e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -719,7 +719,7 @@ Style/FrozenStringLiteralComment: - 'engines/order_management/app/services/reports/renderers/base.rb' - 'engines/order_management/app/services/reports/report_data/base.rb' - 'engines/web/app/controllers/web/angular_templates_controller.rb' - - 'engines/web/app/controllers/web/api/cookies_consent_controller.rb' + - 'engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb' - 'engines/web/app/controllers/web/application_controller.rb' - 'engines/web/app/helpers/web/cookies_policy_helper.rb' - 'engines/web/lib/web/cookies_consent.rb' diff --git a/app/assets/javascripts/admin/bulk_product_update.js.coffee b/app/assets/javascripts/admin/bulk_product_update.js.coffee index 4e2bd45d70..f2d8f9ddcf 100644 --- a/app/assets/javascripts/admin/bulk_product_update.js.coffee +++ b/app/assets/javascripts/admin/bulk_product_update.js.coffee @@ -147,7 +147,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout if confirm("Are you sure?") $http( method: "DELETE" - url: "/api/products/" + product.id + url: "/api/v0/products/" + product.id ).success (data) -> $scope.products.splice $scope.products.indexOf(product), 1 DirtyProducts.deleteProduct product.id @@ -162,7 +162,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout if confirm(t("are_you_sure")) $http( method: "DELETE" - url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + url: "/api/v0/products/" + product.permalink_live + "/variants/" + variant.id ).success (data) -> $scope.removeVariant(product, variant) else diff --git a/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee b/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee index ba37f0518f..7e7a8206c4 100644 --- a/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee +++ b/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee @@ -1,7 +1,7 @@ angular.module('admin.enterpriseFees').directive 'spreeDeleteResource', -> (scope, element, attrs) -> if scope.enterprise_fee.id - url = '/api/enterprise_fees/' + scope.enterprise_fee.id + url = '/api/v0/enterprise_fees/' + scope.enterprise_fee.id html = '' #var html = 'Delete Delete'; element.append html diff --git a/app/assets/javascripts/admin/index_utils/services/resources.js.coffee b/app/assets/javascripts/admin/index_utils/services/resources.js.coffee index 65dad204d4..58664b6895 100644 --- a/app/assets/javascripts/admin/index_utils/services/resources.js.coffee +++ b/app/assets/javascripts/admin/index_utils/services/resources.js.coffee @@ -1,5 +1,5 @@ angular.module("admin.indexUtils").factory "resources", ($resource) -> - LineItem = $resource '/api/orders/:order_number/line_items/:line_item_id.json', + LineItem = $resource '/api/v0/orders/:order_number/line_items/:line_item_id.json', { order_number: '@order_number', line_item_id: '@line_item_id'}, 'update': { method: 'PUT' } Customer = $resource '/admin/customers/:customer_id.json', diff --git a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee index f21698da33..79e0dd6ce6 100644 --- a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee @@ -1,5 +1,5 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> - ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, { + ExchangeProductResource = $resource('/api/v0/exchanges/:exchange_id/products.json', {}, { 'index': { method: 'GET' } 'variant_count': { method: 'GET', params: { action_name: "variant_count" }} }) diff --git a/app/assets/javascripts/admin/products/services/product_image_service.js.coffee b/app/assets/javascripts/admin/products/services/product_image_service.js.coffee index 8b0f273e8b..3d36d0a914 100644 --- a/app/assets/javascripts/admin/products/services/product_image_service.js.coffee +++ b/app/assets/javascripts/admin/products/services/product_image_service.js.coffee @@ -8,7 +8,7 @@ angular.module("ofn.admin").factory "ProductImageService", (FileUploader, SpreeA autoUpload: true configure: (product) => - @imageUploader.url = "/api/product_images/#{product.id}" + @imageUploader.url = "/api/v0/product_images/#{product.id}" @imagePreview = product.image_url @imageUploader.onSuccessItem = (image, response) => product.thumb_url = response.thumb_url diff --git a/app/assets/javascripts/admin/resources/resources/enterprise_resource.js.coffee b/app/assets/javascripts/admin/resources/resources/enterprise_resource.js.coffee index e7e773a42a..f3d2128e20 100644 --- a/app/assets/javascripts/admin/resources/resources/enterprise_resource.js.coffee +++ b/app/assets/javascripts/admin/resources/resources/enterprise_resource.js.coffee @@ -9,12 +9,12 @@ angular.module("admin.resources").factory 'EnterpriseResource', ($resource) -> 'update': method: 'PUT' 'removeLogo': - url: '/api/enterprises/:id/logo.json' + url: '/api/v0/enterprises/:id/logo.json' method: 'DELETE' 'removePromoImage': - url: '/api/enterprises/:id/promo_image.json' + url: '/api/v0/enterprises/:id/promo_image.json' method: 'DELETE' 'removeTermsAndConditions': - url: '/api/enterprises/:id/terms_and_conditions.json' + url: '/api/v0/enterprises/:id/terms_and_conditions.json' method: 'DELETE' }) diff --git a/app/assets/javascripts/admin/resources/resources/order_resource.js.coffee b/app/assets/javascripts/admin/resources/resources/order_resource.js.coffee index 534833d1c9..a6642072ab 100644 --- a/app/assets/javascripts/admin/resources/resources/order_resource.js.coffee +++ b/app/assets/javascripts/admin/resources/resources/order_resource.js.coffee @@ -1,17 +1,17 @@ angular.module("admin.resources").factory 'OrderResource', ($resource) -> $resource('/admin/orders/:id/:action.json', {}, { 'index': - url: '/api/orders.json' + url: '/api/v0/orders.json' method: 'GET' 'update': method: 'PUT' 'capture': - url: '/api/orders/:id/capture.json' + url: '/api/v0/orders/:id/capture.json' method: 'PUT' params: id: '@id' 'ship': - url: '/api/orders/:id/ship.json' + url: '/api/v0/orders/:id/ship.json' method: 'PUT' params: id: '@id' diff --git a/app/assets/javascripts/admin/resources/resources/product_resource.js.coffee b/app/assets/javascripts/admin/resources/resources/product_resource.js.coffee index b630c1f8cd..7d842d8eed 100644 --- a/app/assets/javascripts/admin/resources/resources/product_resource.js.coffee +++ b/app/assets/javascripts/admin/resources/resources/product_resource.js.coffee @@ -1,6 +1,6 @@ angular.module("admin.resources").factory 'ProductResource', ($resource) -> $resource('/admin/product/:id/:action.json', {}, { 'index': - url: '/api/products/bulk_products.json' + url: '/api/v0/products/bulk_products.json' method: 'GET' }) diff --git a/app/assets/javascripts/admin/services/bulk_products.js.coffee b/app/assets/javascripts/admin/services/bulk_products.js.coffee index 72e9715c9e..1c33fcb6cf 100644 --- a/app/assets/javascripts/admin/services/bulk_products.js.coffee +++ b/app/assets/javascripts/admin/services/bulk_products.js.coffee @@ -10,8 +10,8 @@ angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetche angular.extend(@pagination, data.pagination) cloneProduct: (product) -> - $http.post("/api/products/" + product.id + "/clone").success (data) => - dataFetcher("/api/products/" + data.id + "?template=bulk_show").then (newProduct) => + $http.post("/api/v0/products/" + product.id + "/clone").success (data) => + dataFetcher("/api/v0/products/" + data.id + "?template=bulk_show").then (newProduct) => @unpackProduct newProduct @insertProductAfter(product, newProduct) diff --git a/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee b/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee index b890d2ffd5..51dc72be08 100644 --- a/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee @@ -42,7 +42,7 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", $scope.fetchProducts() $scope.fetchProducts = -> - url = "/api/products/overridable?page=::page::;per_page=100" + url = "/api/v0/products/overridable?page=::page::;per_page=100" PagedFetcher.fetch url, $scope.addProducts $scope.addProducts = (data) -> diff --git a/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee index f96d2d454f..4f1d935aec 100644 --- a/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee @@ -24,7 +24,7 @@ Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, CurrentHub, $http, $scope.shopfront_loading = true $scope.toggle_tab(event) - $http.get("/api/shops/" + $scope.hub.id) + $http.get("/api/v0/shops/" + $scope.hub.id) .success (data) -> $scope.shopfront_loading = false $scope.hub = data diff --git a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee index 3aa5045bee..230592a7a6 100644 --- a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee @@ -24,7 +24,7 @@ Darkswarm.controller "ProducerNodeCtrl", ($scope, HashNavigation, $anchorScroll, $scope.shopfront_loading = true $scope.toggle_tab(event) - $http.get("/api/shops/" + $scope.producer.id) + $http.get("/api/v0/shops/" + $scope.producer.id) .success (data) -> $scope.shopfront_loading = false $scope.producer = data diff --git a/app/assets/javascripts/darkswarm/services/customer.js.coffee b/app/assets/javascripts/darkswarm/services/customer.js.coffee index fa3b1b532f..7bad3a7b89 100644 --- a/app/assets/javascripts/darkswarm/services/customer.js.coffee +++ b/app/assets/javascripts/darkswarm/services/customer.js.coffee @@ -1,5 +1,5 @@ angular.module("Darkswarm").factory 'Customer', ($resource, $injector, Messages) -> - Customer = $resource('/api/customers/:id/:action.json', {}, { + Customer = $resource('/api/v0/customers/:id/:action.json', {}, { 'index': method: 'GET' isArray: true diff --git a/app/assets/javascripts/darkswarm/services/enterprise_image_service.js.coffee b/app/assets/javascripts/darkswarm/services/enterprise_image_service.js.coffee index c8cd64e93a..13cd140cc4 100644 --- a/app/assets/javascripts/darkswarm/services/enterprise_image_service.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprise_image_service.js.coffee @@ -8,5 +8,5 @@ Darkswarm.factory "EnterpriseImageService", (FileUploader, spreeApiKey) -> autoUpload: true configure: (enterprise) => - @imageUploader.url = "/api/enterprises/#{enterprise.id}/update_image" + @imageUploader.url = "/api/v0/enterprises/#{enterprise.id}/update_image" @imageUploader.onSuccessItem = (image, response) => @imageSrc = response diff --git a/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee b/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee index 37dafef776..4eab4d79ac 100644 --- a/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee @@ -5,7 +5,7 @@ Darkswarm.factory "EnterpriseModal", ($modal, $rootScope, $http)-> scope = $rootScope.$new(true) # Spawn an isolate to contain the enterprise scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1 - $http.get("/api/shops/" + enterprise.id).success (data) -> + $http.get("/api/v0/shops/" + enterprise.id).success (data) -> scope.enterprise = data $modal.open(templateUrl: "enterprise_modal.html", scope: scope) .error (data) -> diff --git a/app/assets/javascripts/darkswarm/services/enterprise_registration_service.js.coffee b/app/assets/javascripts/darkswarm/services/enterprise_registration_service.js.coffee index dc9f6617ee..019f293117 100644 --- a/app/assets/javascripts/darkswarm/services/enterprise_registration_service.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprise_registration_service.js.coffee @@ -18,7 +18,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService, Loading.message = t('creating') + " " + @enterprise.name $http( method: "POST" - url: "/api/enterprises" + url: "/api/v0/enterprises" data: enterprise: @prepare() params: @@ -42,7 +42,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService, Loading.message = t('updating') + " " + @enterprise.name $http( method: "PUT" - url: "/api/enterprises/#{@enterprise.id}" + url: "/api/v0/enterprises/#{@enterprise.id}" data: enterprise: @prepare() params: diff --git a/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee b/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee index ba8d5266fe..b8dd81d42c 100644 --- a/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee +++ b/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee @@ -1,21 +1,21 @@ Darkswarm.factory 'OrderCycleResource', ($resource) -> - $resource('/api/order_cycles/:id.json', {}, { + $resource('/api/v0/order_cycles/:id.json', {}, { 'products': method: 'GET' isArray: true - url: '/api/order_cycles/:id/products.json' + url: '/api/v0/order_cycles/:id/products.json' params: id: '@id' 'taxons': method: 'GET' isArray: true - url: '/api/order_cycles/:id/taxons.json' + url: '/api/v0/order_cycles/:id/taxons.json' params: id: '@id' 'properties': method: 'GET' isArray: true - url: '/api/order_cycles/:id/properties.json' + url: '/api/v0/order_cycles/:id/properties.json' params: id: '@id' }) diff --git a/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee b/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee index 2726b25496..946eb21832 100644 --- a/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee +++ b/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee @@ -1,7 +1,7 @@ Darkswarm.factory 'ShopsResource', ($resource) -> - $resource('/api/shops/:id.json', {}, { + $resource('/api/v0/shops/:id.json', {}, { 'closed_shops': method: 'GET' isArray: true - url: '/api/shops/closed_shops.json' + url: '/api/v0/shops/closed_shops.json' }) diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb deleted file mode 100644 index 3ec78c85d4..0000000000 --- a/app/controllers/api/base_controller.rb +++ /dev/null @@ -1,103 +0,0 @@ -# Base controller for OFN's API -require_dependency 'spree/api/controller_setup' -require "spree/core/controller_helpers/ssl" - -module Api - class BaseController < ActionController::Metal - include RawParams - include ActionController::StrongParameters - include ActionController::RespondWith - include Spree::Api::ControllerSetup - include Spree::Core::ControllerHelpers::SSL - include ::ActionController::Head - include ::ActionController::ConditionalGet - include ActionView::Layouts - - layout false - - attr_accessor :current_api_user - - before_action :set_content_type - before_action :authenticate_user - - rescue_from Exception, with: :error_during_processing - rescue_from CanCan::AccessDenied, with: :unauthorized - rescue_from ActiveRecord::RecordNotFound, with: :not_found - - helper Spree::Api::ApiHelpers - - ssl_allowed - - # Include these because we inherit from ActionController::Metal - # rather than ActionController::Base and these are required for AMS - include ActionController::Serialization - include ActionController::UrlFor - include Rails.application.routes.url_helpers - - use_renderers :json - check_authorization - - def respond_with_conflict(json_hash) - render json: json_hash, status: :conflict - end - - private - - # Use logged in user (spree_current_user) for API authentication (current_api_user) - def authenticate_user - return if @current_api_user = spree_current_user - - if api_key.blank? - # An anonymous user - @current_api_user = Spree.user_class.new - return - end - - return if @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s) - - invalid_api_key - end - - def set_content_type - headers["Content-Type"] = "application/json" - end - - def error_during_processing(exception) - Bugsnag.notify(exception) - - render(json: { exception: exception.message }, - status: :unprocessable_entity) && return - end - - def current_ability - Spree::Ability.new(current_api_user) - end - - def api_key - request.headers["X-Spree-Token"] || params[:token] - end - helper_method :api_key - - def invalid_resource!(resource) - @resource = resource - render(json: { error: I18n.t(:invalid_resource, scope: "spree.api"), - errors: @resource.errors }, - status: :unprocessable_entity) - end - - def invalid_api_key - render(json: { error: I18n.t(:invalid_api_key, key: api_key, scope: "spree.api") }, - status: :unauthorized) && return - end - - def unauthorized - render(json: { error: I18n.t(:unauthorized, scope: "spree.api") }, - status: :unauthorized) && return - end - - def not_found - render(json: { error: I18n.t(:resource_not_found, scope: "spree.api") }, - status: :not_found) && return - end - end -end diff --git a/app/controllers/api/customers_controller.rb b/app/controllers/api/customers_controller.rb deleted file mode 100644 index 7cb702a824..0000000000 --- a/app/controllers/api/customers_controller.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Api - class CustomersController < Api::BaseController - skip_authorization_check only: :index - - def index - @customers = current_api_user.customers - render json: @customers, each_serializer: CustomerSerializer - end - - def update - @customer = Customer.find(params[:id]) - authorize! :update, @customer - - client_secret = RecurringPayments.setup_for(@customer) if params[:customer][:allow_charges] - - if @customer.update(customer_params) - add_recurring_payment_info(client_secret) - render json: @customer, serializer: CustomerSerializer, status: :ok - else - invalid_resource!(@customer) - end - end - - private - - def add_recurring_payment_info(client_secret) - return unless client_secret - - @customer.gateway_recurring_payment_client_secret = client_secret - @customer.gateway_shop_id = @customer.enterprise.stripe_account&.stripe_user_id - end - - def customer_params - params.require(:customer).permit(:code, :email, :enterprise_id, :allow_charges) - end - end -end diff --git a/app/controllers/api/enterprise_attachment_controller.rb b/app/controllers/api/enterprise_attachment_controller.rb deleted file mode 100644 index d9b619ab8e..0000000000 --- a/app/controllers/api/enterprise_attachment_controller.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -require 'api/admin/enterprise_serializer' - -module Api - class EnterpriseAttachmentController < Api::BaseController - class MissingImplementationError < StandardError; end - class UnknownEnterpriseAuthorizationActionError < StandardError; end - - before_action :load_enterprise - - respond_to :json - - def destroy - return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message) unless @enterprise.public_send("#{attachment_name}?") - - @enterprise.update!(attachment_name => nil) - render json: @enterprise, serializer: Admin::EnterpriseSerializer, spree_current_user: spree_current_user - end - - protected - - def attachment_name - raise MissingImplementationError, "Method attachment_name should be defined" - end - - def enterprise_authorize_action - raise MissingImplementationError, "Method enterprise_authorize_action should be defined" - end - - def load_enterprise - @enterprise = Enterprise.find_by(permalink: params[:enterprise_id].to_s) - raise UnknownEnterpriseAuthorizationActionError if enterprise_authorize_action.blank? - - authorize!(enterprise_authorize_action, @enterprise) - end - - def destroy_attachment_does_not_exist_error_message - I18n.t("api.enterprise_#{attachment_name}.destroy_attachment_does_not_exist") - end - end -end diff --git a/app/controllers/api/enterprise_fees_controller.rb b/app/controllers/api/enterprise_fees_controller.rb deleted file mode 100644 index 3252961f97..0000000000 --- a/app/controllers/api/enterprise_fees_controller.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Api - class EnterpriseFeesController < Api::BaseController - respond_to :json - - def destroy - authorize! :destroy, enterprise_fee - - if enterprise_fee.destroy - render plain: I18n.t(:successfully_removed), status: :no_content - else - render plain: enterprise_fee.errors.full_messages.first, status: :forbidden - end - end - - private - - def enterprise_fee - @enterprise_fee ||= EnterpriseFee.find_by id: params[:id] - end - end -end diff --git a/app/controllers/api/enterprises_controller.rb b/app/controllers/api/enterprises_controller.rb deleted file mode 100644 index bcec80f3a6..0000000000 --- a/app/controllers/api/enterprises_controller.rb +++ /dev/null @@ -1,78 +0,0 @@ -module Api - class EnterprisesController < Api::BaseController - before_action :override_owner, only: [:create, :update] - before_action :check_type, only: :update - before_action :override_sells, only: [:create, :update] - before_action :override_visible, only: [:create, :update] - respond_to :json - - def create - authorize! :create, Enterprise - - # params[:user_ids] breaks the enterprise creation - # We remove them from params and save them after creating the enterprise - user_ids = enterprise_params.delete(:user_ids) - @enterprise = Enterprise.new(enterprise_params) - if @enterprise.save - @enterprise.user_ids = user_ids - render json: @enterprise.id, status: :created - else - invalid_resource!(@enterprise) - end - end - - def update - @enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id]) - authorize! :update, @enterprise - - if @enterprise.update(enterprise_params) - render json: @enterprise.id, status: :ok - else - invalid_resource!(@enterprise) - end - end - - def update_image - @enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id]) - authorize! :update, @enterprise - - if params[:logo] && @enterprise.update( logo: params[:logo] ) - render plain: @enterprise.logo.url(:medium), status: :ok - elsif params[:promo] && @enterprise.update( promo_image: params[:promo] ) - render plain: @enterprise.promo_image.url(:medium), status: :ok - else - invalid_resource!(@enterprise) - end - end - - private - - def override_owner - enterprise_params[:owner_id] = current_api_user.id - end - - def check_type - enterprise_params.delete :type unless current_api_user.admin? - end - - def override_sells - has_hub = current_api_user.owned_enterprises.is_hub.any? - new_enterprise_is_producer = !!enterprise_params[:is_primary_producer] - - enterprise_params[:sells] = if has_hub && !new_enterprise_is_producer - 'any' - else - 'unspecified' - end - end - - def override_visible - enterprise_params[:visible] = false - end - - def enterprise_params - @enterprise_params ||= PermittedAttributes::Enterprise.new(params).call. - to_h.with_indifferent_access - end - end -end diff --git a/app/controllers/api/exchange_products_controller.rb b/app/controllers/api/exchange_products_controller.rb deleted file mode 100644 index b43321841c..0000000000 --- a/app/controllers/api/exchange_products_controller.rb +++ /dev/null @@ -1,100 +0,0 @@ -# frozen_string_literal: true - -# This controller lists products that can be added to an exchange -# -# Pagination is optional and can be required by using param[:page] -module Api - class ExchangeProductsController < Api::BaseController - include PaginationData - DEFAULT_PER_PAGE = 100 - - skip_authorization_check only: [:index] - - # If exchange_id is present in the URL: - # Lists Products that can be added to that Exchange - # - # If exchange_id is not present in the URL: - # Lists Products of the Enterprise given that can be added to the given Order Cycle - # In this case parameters are: enterprise_id, order_cycle_id and incoming - # (order_cycle_id is not necessary for incoming exchanges) - def index - if exchange_params[:exchange_id].present? - load_data_from_exchange - else - load_data_from_other_params - end - - render_variant_count && return if params[:action_name] == "variant_count" - - render_paginated_products paginated_products - end - - private - - def render_variant_count - render plain: { - count: variants.count - }.to_json - end - - def variants - renderer.exchange_variants(@incoming, @enterprise) - end - - def products - renderer.exchange_products(@incoming, @enterprise) - end - - def renderer - @renderer ||= ExchangeProductsRenderer. - new(@order_cycle, spree_current_user) - end - - def paginated_products - return products unless pagination_required? - - products. - page(params[:page]). - per(params[:per_page] || DEFAULT_PER_PAGE) - end - - def load_data_from_exchange - exchange = Exchange.find_by(id: exchange_params[:exchange_id]) - - @order_cycle = exchange.order_cycle - @incoming = exchange.incoming - @enterprise = exchange.sender - end - - def load_data_from_other_params - @enterprise = Enterprise.find_by(id: exchange_params[:enterprise_id]) - - # This will be a string (eg "true") when it arrives via params, but we want a boolean - @incoming = ActiveModel::Type::Boolean.new.cast exchange_params[:incoming] - - if exchange_params[:order_cycle_id] - @order_cycle = OrderCycle.find_by(id: exchange_params[:order_cycle_id]) - elsif !@incoming - raise "order_cycle_id is required to list products for new outgoing exchange" - end - end - - def render_paginated_products(paginated_products) - serialized_products = ActiveModel::ArraySerializer.new( - paginated_products, - each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer, - order_cycle: @order_cycle - ) - - render json: { - products: serialized_products, - pagination: pagination_data(paginated_products) - } - end - - def exchange_params - params.permit(:enterprise_id, :exchange_id, :order_cycle_id, :incoming). - to_h.with_indifferent_access - end - end -end diff --git a/app/controllers/api/logos_controller.rb b/app/controllers/api/logos_controller.rb deleted file mode 100644 index 0c4b4c2f45..0000000000 --- a/app/controllers/api/logos_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -module Api - class LogosController < Api::EnterpriseAttachmentController - private - - def attachment_name - :logo - end - - def enterprise_authorize_action - case action_name.to_sym - when :destroy - :remove_logo - end - end - end -end diff --git a/app/controllers/api/order_cycles_controller.rb b/app/controllers/api/order_cycles_controller.rb deleted file mode 100644 index c40ec641b2..0000000000 --- a/app/controllers/api/order_cycles_controller.rb +++ /dev/null @@ -1,101 +0,0 @@ -module Api - class OrderCyclesController < Api::BaseController - include EnterprisesHelper - include ApiActionCaching - - skip_authorization_check - skip_before_action :authenticate_user, :ensure_api_key, only: [:taxons, :properties] - - caches_action :taxons, :properties, - expires_in: CacheService::FILTERS_EXPIRY, - cache_path: proc { |controller| controller.request.url } - - def products - return render_no_products unless order_cycle.open? - - products = ProductsRenderer.new( - distributor, - order_cycle, - customer, - search_params - ).products_json - - render plain: products - rescue ProductsRenderer::NoProducts - render_no_products - end - - def taxons - taxons = Spree::Taxon. - joins(:products). - where(spree_products: { id: distributed_products }). - select('DISTINCT spree_taxons.*') - - render plain: ActiveModel::ArraySerializer.new( - taxons, each_serializer: Api::TaxonSerializer - ).to_json - end - - def properties - render plain: ActiveModel::ArraySerializer.new( - product_properties | producer_properties, each_serializer: Api::PropertySerializer - ).to_json - end - - private - - def render_no_products - render status: :not_found, json: {} - end - - def product_properties - Spree::Property. - joins(:products). - where(spree_products: { id: distributed_products }). - select('DISTINCT spree_properties.*') - end - - def producer_properties - producers = Enterprise. - joins(:supplied_products). - where(spree_products: { id: distributed_products }) - - Spree::Property. - joins(:producer_properties). - where(producer_properties: { producer_id: producers }). - select('DISTINCT spree_properties.*') - end - - def search_params - permitted_search_params = params.slice :q, :page, :per_page - - if permitted_search_params.key? :q - permitted_search_params[:q].slice!(*permitted_ransack_params) - end - - permitted_search_params - end - - def permitted_ransack_params - [:name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont, - :properties_id_or_supplier_properties_id_in_any, - :primary_taxon_id_in_any] - end - - def distributor - @distributor ||= Enterprise.find_by(id: params[:distributor]) - end - - def order_cycle - @order_cycle ||= OrderCycle.find_by(id: params[:id]) - end - - def customer - @current_api_user.andand.customer_of(distributor) || nil - end - - def distributed_products - OrderCycleDistributedProducts.new(distributor, order_cycle, customer).products_relation - end - end -end diff --git a/app/controllers/api/orders_controller.rb b/app/controllers/api/orders_controller.rb deleted file mode 100644 index a0a4a0c013..0000000000 --- a/app/controllers/api/orders_controller.rb +++ /dev/null @@ -1,67 +0,0 @@ -module Api - class OrdersController < Api::BaseController - include PaginationData - - def show - authorize! :read, order - render json: order, serializer: Api::OrderDetailedSerializer, current_order: order - end - - def index - authorize! :admin, Spree::Order - - orders = SearchOrders.new(params, current_api_user).orders - - render json: { - orders: serialized_orders(orders), - pagination: pagination_data(orders) - } - end - - def ship - authorize! :admin, order - - if order.ship - render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok - else - render json: { error: I18n.t('api.orders.failed_to_update') }, status: :unprocessable_entity - end - end - - def capture - authorize! :admin, order - - pending_payment = order.pending_payments.first - - return payment_capture_failed unless order.payment_required? && pending_payment - - if pending_payment.capture! - render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok - else - payment_capture_failed - end - rescue Spree::Core::GatewayError => e - error_during_processing(e) - end - - private - - def payment_capture_failed - render json: { error: I18n.t(:payment_processing_failed) }, status: :unprocessable_entity - end - - def serialized_orders(orders) - ActiveModel::ArraySerializer.new( - orders, - each_serializer: Api::Admin::OrderSerializer - ) - end - - def order - @order ||= Spree::Order. - where(number: params[:id]). - includes(line_items: { variant: [:product, :stock_items, :default_price] }). - first! - end - end -end diff --git a/app/controllers/api/product_images_controller.rb b/app/controllers/api/product_images_controller.rb deleted file mode 100644 index e688a03e6e..0000000000 --- a/app/controllers/api/product_images_controller.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Api - class ProductImagesController < Api::BaseController - respond_to :json - - def update_product_image - @product = Spree::Product.find(params[:product_id]) - authorize! :update, @product - - if @product.images.first.nil? - @image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant') - render json: @image, serializer: ImageSerializer, status: :created - else - @image = @product.images.first - @image.update(attachment: params[:file]) - render json: @image, serializer: ImageSerializer, status: :ok - end - end - end -end diff --git a/app/controllers/api/products_controller.rb b/app/controllers/api/products_controller.rb deleted file mode 100644 index d8fab1067a..0000000000 --- a/app/controllers/api/products_controller.rb +++ /dev/null @@ -1,159 +0,0 @@ -require 'open_food_network/permissions' -require 'spree/core/product_duplicator' - -module Api - class ProductsController < Api::BaseController - include PaginationData - respond_to :json - DEFAULT_PER_PAGE = 15 - - before_action :set_default_available_on, only: :create - - skip_authorization_check only: [:show, :bulk_products, :overridable] - - def show - @product = find_product(params[:id]) - render json: @product, serializer: Api::Admin::ProductSerializer - end - - def create - authorize! :create, Spree::Product - @product = Spree::Product.new(product_params) - - begin - if @product.save - render json: @product, serializer: Api::Admin::ProductSerializer, status: :created - else - invalid_resource!(@product) - end - rescue ActiveRecord::RecordNotUnique - @product.permalink = nil - retry - end - end - - def update - authorize! :update, Spree::Product - @product = find_product(params[:id]) - if @product.update(product_params) - render json: @product, serializer: Api::Admin::ProductSerializer, status: :ok - else - invalid_resource!(@product) - end - end - - def destroy - authorize! :delete, Spree::Product - @product = find_product(params[:id]) - authorize! :delete, @product - @product.destroy - render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content - end - - def bulk_products - product_query = OpenFoodNetwork::Permissions. - new(current_api_user). - editable_products. - merge(product_scope) - - if params[:import_date].present? - product_query = product_query. - imported_on(params[:import_date]). - group_by_products_id - end - - @products = product_query. - ransack(query_params_with_defaults). - result. - page(params[:page] || 1). - per(params[:per_page] || DEFAULT_PER_PAGE) - - render_paged_products @products - end - - def overridable - producer_ids = OpenFoodNetwork::Permissions.new(current_api_user). - variant_override_producers.by_name.select('enterprises.id') - - @products = paged_products_for_producers producer_ids - - render_paged_products @products, ::Api::Admin::ProductSimpleSerializer - end - - # POST /api/products/:product_id/clone - # - def clone - authorize! :create, Spree::Product - original_product = find_product(params[:product_id]) - authorize! :update, original_product - - @product = original_product.duplicate - - render json: @product, serializer: Api::Admin::ProductSerializer, status: :created - end - - private - - def find_product(id) - product_scope.find_by!(permalink: id.to_s) - rescue ActiveRecord::RecordNotFound - product_scope.find(id) - end - - def product_scope - if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present? - scope = Spree::Product - if params[:show_deleted] - scope = scope.with_deleted - end - else - scope = Spree::Product.active - end - - scope.includes(product_query_includes) - end - - def product_query_includes - [ - master: [:images], - variants: [:default_price, :stock_locations, :stock_items, :variant_overrides, - { option_values: :option_type }] - ] - end - - def paged_products_for_producers(producer_ids) - Spree::Product.where(nil). - merge(product_scope). - includes(variants: [:product, :default_price, :stock_items]). - where(supplier_id: producer_ids). - by_producer.by_name. - ransack(params[:q]).result. - page(params[:page]).per(params[:per_page]) - end - - def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer) - serialized_products = ActiveModel::ArraySerializer.new( - products, - each_serializer: product_serializer - ) - - render json: { - products: serialized_products, - pagination: pagination_data(products) - } - end - - def query_params_with_defaults - (params[:q] || {}).reverse_merge(s: 'created_at desc') - end - - def product_params - @product_params ||= - params.permit(product: PermittedAttributes::Product.attributes)[:product].to_h - end - - def set_default_available_on - product_params[:available_on] ||= Time.zone.now - end - end -end diff --git a/app/controllers/api/promo_images_controller.rb b/app/controllers/api/promo_images_controller.rb deleted file mode 100644 index 9cdb799931..0000000000 --- a/app/controllers/api/promo_images_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -module Api - class PromoImagesController < Api::EnterpriseAttachmentController - private - - def attachment_name - :promo_image - end - - def enterprise_authorize_action - case action_name.to_sym - when :destroy - :remove_promo_image - end - end - end -end diff --git a/app/controllers/api/shipments_controller.rb b/app/controllers/api/shipments_controller.rb deleted file mode 100644 index b9a5f4340b..0000000000 --- a/app/controllers/api/shipments_controller.rb +++ /dev/null @@ -1,112 +0,0 @@ -require 'open_food_network/scope_variant_to_hub' - -module Api - class ShipmentsController < Api::BaseController - respond_to :json - - before_action :find_order - before_action :find_and_update_shipment, only: [:ship, :ready, :add, :remove] - - def create - variant = scoped_variant(params[:variant_id]) - quantity = params[:quantity].to_i - @shipment = get_or_create_shipment(params[:stock_location_id]) - - @order.contents.add(variant, quantity, nil, @shipment) - - @shipment.refresh_rates - @shipment.save! - - render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok - end - - def update - authorize! :read, Spree::Shipment - @shipment = @order.shipments.find_by!(number: params[:id]) - params[:shipment] ||= [] - unlock = params[:shipment].delete(:unlock) - - if unlock == 'yes' - @shipment.fee_adjustment.open - end - - @shipment.update(shipment_params[:shipment]) - - if unlock == 'yes' - @shipment.fee_adjustment.close - end - - render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok - end - - def ready - authorize! :read, Spree::Shipment - unless @shipment.ready? - if @shipment.can_ready? - @shipment.ready! - else - render(json: { error: I18n.t(:cannot_ready, scope: "spree.api.shipment") }, - status: :unprocessable_entity) && return - end - end - render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok - end - - def ship - authorize! :read, Spree::Shipment - unless @shipment.shipped? - @shipment.ship! - end - render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok - end - - def add - variant = scoped_variant(params[:variant_id]) - quantity = params[:quantity].to_i - - @order.contents.add(variant, quantity, nil, @shipment) - - render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok - end - - def remove - variant = scoped_variant(params[:variant_id]) - quantity = params[:quantity].to_i - - @order.contents.remove(variant, quantity, @shipment) - @shipment.reload if @shipment.persisted? - - render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok - end - - private - - def find_order - @order = Spree::Order.find_by!(number: params[:order_id]) - authorize! :read, @order - end - - def find_and_update_shipment - @shipment = @order.shipments.find_by!(number: params[:id]) - @shipment.update(shipment_params[:shipment]) if shipment_params[:shipment].present? - @shipment.reload - end - - def scoped_variant(variant_id) - variant = Spree::Variant.find(variant_id) - OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant) - variant - end - - def get_or_create_shipment(stock_location_id) - @order.shipment || @order.shipments.create(stock_location_id: stock_location_id) - end - - def shipment_params - params.permit( - [:id, :order_id, :variant_id, :quantity, - { shipment: [:tracking, :selected_shipping_rate_id] }] - ) - end - end -end diff --git a/app/controllers/api/shops_controller.rb b/app/controllers/api/shops_controller.rb deleted file mode 100644 index 377e849378..0000000000 --- a/app/controllers/api/shops_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module Api - class ShopsController < BaseController - respond_to :json - skip_authorization_check only: [:show, :closed_shops] - - def show - enterprise = Enterprise.find_by(id: params[:id]) - - render plain: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok - end - - def closed_shops - @active_distributor_ids = [] - @earliest_closing_times = [] - - serialized_closed_shops = ActiveModel::ArraySerializer.new( - ShopsListService.new.closed_shops, - each_serializer: Api::EnterpriseSerializer, - data: OpenFoodNetwork::EnterpriseInjectionData.new - ) - - render json: serialized_closed_shops - end - end -end diff --git a/app/controllers/api/states_controller.rb b/app/controllers/api/states_controller.rb deleted file mode 100644 index 0ad0b991d4..0000000000 --- a/app/controllers/api/states_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -module Api - class StatesController < Api::BaseController - respond_to :json - - skip_authorization_check - - def index - render json: states, each_serializer: Api::StateSerializer, status: :ok - end - - def show - @state = scope.find(params[:id]) - render json: @state, serializer: Api::StateSerializer, status: :ok - end - - private - - def scope - if params[:country_id] - @country = Spree::Country.find(params[:country_id]) - @country.states - else - Spree::State.all - end - end - - def states - states = scope.ransack(params[:q]).result. - includes(:country).order('name ASC') - - if pagination? - states = states.page(params[:page]).per(params[:per_page]) - end - - states - end - - def pagination? - params[:page] || params[:per_page] - end - end -end diff --git a/app/controllers/api/statuses_controller.rb b/app/controllers/api/statuses_controller.rb deleted file mode 100644 index 24714b6a0d..0000000000 --- a/app/controllers/api/statuses_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -module Api - class StatusesController < ::BaseController - respond_to :json - - def job_queue - render json: { alive: job_queue_alive? } - end - - private - - def job_queue_alive? - Spree::Config.last_job_queue_heartbeat_at.present? && - Time.parse(Spree::Config.last_job_queue_heartbeat_at).in_time_zone > 6.minutes.ago - end - end -end diff --git a/app/controllers/api/taxonomies_controller.rb b/app/controllers/api/taxonomies_controller.rb deleted file mode 100644 index 356d84d676..0000000000 --- a/app/controllers/api/taxonomies_controller.rb +++ /dev/null @@ -1,12 +0,0 @@ -module Api - class TaxonomiesController < Api::BaseController - respond_to :json - - skip_authorization_check only: :jstree - - def jstree - @taxonomy = Spree::Taxonomy.find(params[:id]) - render json: @taxonomy.root, serializer: Api::TaxonJstreeSerializer - end - end -end diff --git a/app/controllers/api/taxons_controller.rb b/app/controllers/api/taxons_controller.rb deleted file mode 100644 index 491cf75954..0000000000 --- a/app/controllers/api/taxons_controller.rb +++ /dev/null @@ -1,76 +0,0 @@ -module Api - class TaxonsController < Api::BaseController - respond_to :json - - skip_authorization_check only: [:index, :show, :jstree] - - def index - @taxons = if taxonomy - taxonomy.root.children - elsif params[:ids] - Spree::Taxon.where(id: raw_params[:ids].split(",")) - else - Spree::Taxon.ransack(raw_params[:q]).result - end - render json: @taxons, each_serializer: Api::TaxonSerializer - end - - def jstree - @taxon = taxon - render json: @taxon.children, each_serializer: Api::TaxonJstreeSerializer - end - - def create - authorize! :create, Spree::Taxon - @taxon = Spree::Taxon.new(taxon_params) - @taxon.taxonomy_id = params[:taxonomy_id] - taxonomy = Spree::Taxonomy.find_by(id: params[:taxonomy_id]) - - if taxonomy.nil? - @taxon.errors[:taxonomy_id] = I18n.t(:invalid_taxonomy_id, scope: 'spree.api') - invalid_resource!(@taxon) && return - end - - @taxon.parent_id = taxonomy.root.id unless params.dig(:taxon, :parent_id) - - if @taxon.save - render json: @taxon, serializer: Api::TaxonSerializer, status: :created - else - invalid_resource!(@taxon) - end - end - - def update - authorize! :update, Spree::Taxon - if taxon.update(taxon_params) - render json: taxon, serializer: Api::TaxonSerializer, status: :ok - else - invalid_resource!(taxon) - end - end - - def destroy - authorize! :delete, Spree::Taxon - taxon.destroy - render json: taxon, serializer: Api::TaxonSerializer, status: :no_content - end - - private - - def taxonomy - return if params[:taxonomy_id].blank? - - @taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id]) - end - - def taxon - @taxon ||= taxonomy.taxons.find(params[:id]) - end - - def taxon_params - return if params[:taxon].blank? - - params.require(:taxon).permit([:name, :parent_id]) - end - end -end diff --git a/app/controllers/api/terms_and_conditions_controller.rb b/app/controllers/api/terms_and_conditions_controller.rb deleted file mode 100644 index d49721c04a..0000000000 --- a/app/controllers/api/terms_and_conditions_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Api - class TermsAndConditionsController < Api::EnterpriseAttachmentController - private - - def attachment_name - :terms_and_conditions - end - - def enterprise_authorize_action - case action_name.to_sym - when :destroy - :remove_terms_and_conditions - end - end - end -end diff --git a/app/controllers/api/v0/base_controller.rb b/app/controllers/api/v0/base_controller.rb new file mode 100644 index 0000000000..83ed8578d5 --- /dev/null +++ b/app/controllers/api/v0/base_controller.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +# Base controller for OFN's API +require_dependency 'spree/api/controller_setup' +require "spree/core/controller_helpers/ssl" + +module Api + module V0 + class BaseController < ActionController::Metal + include RawParams + include ActionController::StrongParameters + include ActionController::RespondWith + include Spree::Api::ControllerSetup + include Spree::Core::ControllerHelpers::SSL + include ::ActionController::Head + include ::ActionController::ConditionalGet + include ActionView::Layouts + + layout false + + attr_accessor :current_api_user + + before_action :set_content_type + before_action :authenticate_user + + rescue_from Exception, with: :error_during_processing + rescue_from CanCan::AccessDenied, with: :unauthorized + rescue_from ActiveRecord::RecordNotFound, with: :not_found + + helper Spree::Api::ApiHelpers + + ssl_allowed + + # Include these because we inherit from ActionController::Metal + # rather than ActionController::Base and these are required for AMS + include ActionController::Serialization + include ActionController::UrlFor + include Rails.application.routes.url_helpers + + use_renderers :json + check_authorization + + def respond_with_conflict(json_hash) + render json: json_hash, status: :conflict + end + + private + + # Use logged in user (spree_current_user) for API authentication (current_api_user) + def authenticate_user + return if @current_api_user = spree_current_user + + if api_key.blank? + # An anonymous user + @current_api_user = Spree.user_class.new + return + end + + return if @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s) + + invalid_api_key + end + + def set_content_type + headers["Content-Type"] = "application/json" + end + + def error_during_processing(exception) + Bugsnag.notify(exception) + + render(json: { exception: exception.message }, + status: :unprocessable_entity) && return + end + + def current_ability + Spree::Ability.new(current_api_user) + end + + def api_key + request.headers["X-Spree-Token"] || params[:token] + end + helper_method :api_key + + def invalid_resource!(resource) + @resource = resource + render(json: { error: I18n.t(:invalid_resource, scope: "spree.api"), + errors: @resource.errors }, + status: :unprocessable_entity) + end + + def invalid_api_key + render(json: { error: I18n.t(:invalid_api_key, key: api_key, scope: "spree.api") }, + status: :unauthorized) && return + end + + def unauthorized + render(json: { error: I18n.t(:unauthorized, scope: "spree.api") }, + status: :unauthorized) && return + end + + def not_found + render(json: { error: I18n.t(:resource_not_found, scope: "spree.api") }, + status: :not_found) && return + end + end + end +end diff --git a/app/controllers/api/v0/customers_controller.rb b/app/controllers/api/v0/customers_controller.rb new file mode 100644 index 0000000000..a10b65bed7 --- /dev/null +++ b/app/controllers/api/v0/customers_controller.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Api + module V0 + class CustomersController < Api::V0::BaseController + skip_authorization_check only: :index + + def index + @customers = current_api_user.customers + render json: @customers, each_serializer: CustomerSerializer + end + + def update + @customer = Customer.find(params[:id]) + authorize! :update, @customer + + client_secret = RecurringPayments.setup_for(@customer) if params[:customer][:allow_charges] + + if @customer.update(customer_params) + add_recurring_payment_info(client_secret) + render json: @customer, serializer: CustomerSerializer, status: :ok + else + invalid_resource!(@customer) + end + end + + private + + def add_recurring_payment_info(client_secret) + return unless client_secret + + @customer.gateway_recurring_payment_client_secret = client_secret + @customer.gateway_shop_id = @customer.enterprise.stripe_account&.stripe_user_id + end + + def customer_params + params.require(:customer).permit(:code, :email, :enterprise_id, :allow_charges) + end + end + end +end diff --git a/app/controllers/api/v0/enterprise_attachment_controller.rb b/app/controllers/api/v0/enterprise_attachment_controller.rb new file mode 100644 index 0000000000..3a61f548b1 --- /dev/null +++ b/app/controllers/api/v0/enterprise_attachment_controller.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'api/admin/enterprise_serializer' + +module Api + module V0 + class EnterpriseAttachmentController < Api::V0::BaseController + class MissingImplementationError < StandardError; end + class UnknownEnterpriseAuthorizationActionError < StandardError; end + + before_action :load_enterprise + + respond_to :json + + def destroy + return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message) unless @enterprise.public_send("#{attachment_name}?") + + @enterprise.update!(attachment_name => nil) + render json: @enterprise, serializer: Admin::EnterpriseSerializer, spree_current_user: spree_current_user + end + + protected + + def attachment_name + raise MissingImplementationError, "Method attachment_name should be defined" + end + + def enterprise_authorize_action + raise MissingImplementationError, "Method enterprise_authorize_action should be defined" + end + + def load_enterprise + @enterprise = Enterprise.find_by(permalink: params[:enterprise_id].to_s) + raise UnknownEnterpriseAuthorizationActionError if enterprise_authorize_action.blank? + + authorize!(enterprise_authorize_action, @enterprise) + end + + def destroy_attachment_does_not_exist_error_message + I18n.t("api.enterprise_#{attachment_name}.destroy_attachment_does_not_exist") + end + end + end +end diff --git a/app/controllers/api/v0/enterprise_fees_controller.rb b/app/controllers/api/v0/enterprise_fees_controller.rb new file mode 100644 index 0000000000..45957672a7 --- /dev/null +++ b/app/controllers/api/v0/enterprise_fees_controller.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Api + module V0 + class EnterpriseFeesController < Api::V0::BaseController + respond_to :json + + def destroy + authorize! :destroy, enterprise_fee + + if enterprise_fee.destroy + render plain: I18n.t(:successfully_removed), status: :no_content + else + render plain: enterprise_fee.errors.full_messages.first, status: :forbidden + end + end + + private + + def enterprise_fee + @enterprise_fee ||= EnterpriseFee.find_by id: params[:id] + end + end + end +end diff --git a/app/controllers/api/v0/enterprises_controller.rb b/app/controllers/api/v0/enterprises_controller.rb new file mode 100644 index 0000000000..0cd9435963 --- /dev/null +++ b/app/controllers/api/v0/enterprises_controller.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +module Api + module V0 + class EnterprisesController < Api::V0::BaseController + before_action :override_owner, only: [:create, :update] + before_action :check_type, only: :update + before_action :override_sells, only: [:create, :update] + before_action :override_visible, only: [:create, :update] + respond_to :json + + def create + authorize! :create, Enterprise + + # params[:user_ids] breaks the enterprise creation + # We remove them from params and save them after creating the enterprise + user_ids = enterprise_params.delete(:user_ids) + @enterprise = Enterprise.new(enterprise_params) + if @enterprise.save + @enterprise.user_ids = user_ids + render json: @enterprise.id, status: :created + else + invalid_resource!(@enterprise) + end + end + + def update + @enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id]) + authorize! :update, @enterprise + + if @enterprise.update(enterprise_params) + render json: @enterprise.id, status: :ok + else + invalid_resource!(@enterprise) + end + end + + def update_image + @enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id]) + authorize! :update, @enterprise + + if params[:logo] && @enterprise.update( logo: params[:logo] ) + render plain: @enterprise.logo.url(:medium), status: :ok + elsif params[:promo] && @enterprise.update( promo_image: params[:promo] ) + render plain: @enterprise.promo_image.url(:medium), status: :ok + else + invalid_resource!(@enterprise) + end + end + + private + + def override_owner + enterprise_params[:owner_id] = current_api_user.id + end + + def check_type + enterprise_params.delete :type unless current_api_user.admin? + end + + def override_sells + has_hub = current_api_user.owned_enterprises.is_hub.any? + new_enterprise_is_producer = !!enterprise_params[:is_primary_producer] + + enterprise_params[:sells] = if has_hub && !new_enterprise_is_producer + 'any' + else + 'unspecified' + end + end + + def override_visible + enterprise_params[:visible] = false + end + + def enterprise_params + @enterprise_params ||= PermittedAttributes::Enterprise.new(params).call. + to_h.with_indifferent_access + end + end + end +end diff --git a/app/controllers/api/v0/exchange_products_controller.rb b/app/controllers/api/v0/exchange_products_controller.rb new file mode 100644 index 0000000000..fde6abf174 --- /dev/null +++ b/app/controllers/api/v0/exchange_products_controller.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +# This controller lists products that can be added to an exchange +# +# Pagination is optional and can be required by using param[:page] +module Api + module V0 + class ExchangeProductsController < Api::V0::BaseController + include PaginationData + DEFAULT_PER_PAGE = 100 + + skip_authorization_check only: [:index] + + # If exchange_id is present in the URL: + # Lists Products that can be added to that Exchange + # + # If exchange_id is not present in the URL: + # Lists Products of the Enterprise given that can be added to the given Order Cycle + # In this case parameters are: enterprise_id, order_cycle_id and incoming + # (order_cycle_id is not necessary for incoming exchanges) + def index + if exchange_params[:exchange_id].present? + load_data_from_exchange + else + load_data_from_other_params + end + + render_variant_count && return if params[:action_name] == "variant_count" + + render_paginated_products paginated_products + end + + private + + def render_variant_count + render plain: { + count: variants.count + }.to_json + end + + def variants + renderer.exchange_variants(@incoming, @enterprise) + end + + def products + renderer.exchange_products(@incoming, @enterprise) + end + + def renderer + @renderer ||= ExchangeProductsRenderer. + new(@order_cycle, spree_current_user) + end + + def paginated_products + return products unless pagination_required? + + products. + page(params[:page]). + per(params[:per_page] || DEFAULT_PER_PAGE) + end + + def load_data_from_exchange + exchange = Exchange.find_by(id: exchange_params[:exchange_id]) + + @order_cycle = exchange.order_cycle + @incoming = exchange.incoming + @enterprise = exchange.sender + end + + def load_data_from_other_params + @enterprise = Enterprise.find_by(id: exchange_params[:enterprise_id]) + + # This will be a string (eg "true") when it arrives via params, but we want a boolean + @incoming = ActiveModel::Type::Boolean.new.cast exchange_params[:incoming] + + if exchange_params[:order_cycle_id] + @order_cycle = OrderCycle.find_by(id: exchange_params[:order_cycle_id]) + elsif !@incoming + raise "order_cycle_id is required to list products for new outgoing exchange" + end + end + + def render_paginated_products(paginated_products) + serialized_products = ActiveModel::ArraySerializer.new( + paginated_products, + each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer, + order_cycle: @order_cycle + ) + + render json: { + products: serialized_products, + pagination: pagination_data(paginated_products) + } + end + + def exchange_params + params.permit(:enterprise_id, :exchange_id, :order_cycle_id, :incoming). + to_h.with_indifferent_access + end + end + end +end diff --git a/app/controllers/api/v0/logos_controller.rb b/app/controllers/api/v0/logos_controller.rb new file mode 100644 index 0000000000..0e710d8bf2 --- /dev/null +++ b/app/controllers/api/v0/logos_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Api + module V0 + class LogosController < Api::V0::EnterpriseAttachmentController + private + + def attachment_name + :logo + end + + def enterprise_authorize_action + case action_name.to_sym + when :destroy + :remove_logo + end + end + end + end +end diff --git a/app/controllers/api/v0/order_cycles_controller.rb b/app/controllers/api/v0/order_cycles_controller.rb new file mode 100644 index 0000000000..88241b23a4 --- /dev/null +++ b/app/controllers/api/v0/order_cycles_controller.rb @@ -0,0 +1,105 @@ +# frozen_string_literal: true + +module Api + module V0 + class OrderCyclesController < Api::V0::BaseController + include EnterprisesHelper + include ApiActionCaching + + skip_authorization_check + skip_before_action :authenticate_user, :ensure_api_key, only: [:taxons, :properties] + + caches_action :taxons, :properties, + expires_in: CacheService::FILTERS_EXPIRY, + cache_path: proc { |controller| controller.request.url } + + def products + return render_no_products unless order_cycle.open? + + products = ProductsRenderer.new( + distributor, + order_cycle, + customer, + search_params + ).products_json + + render plain: products + rescue ProductsRenderer::NoProducts + render_no_products + end + + def taxons + taxons = Spree::Taxon. + joins(:products). + where(spree_products: { id: distributed_products }). + select('DISTINCT spree_taxons.*') + + render plain: ActiveModel::ArraySerializer.new( + taxons, each_serializer: Api::TaxonSerializer + ).to_json + end + + def properties + render plain: ActiveModel::ArraySerializer.new( + product_properties | producer_properties, each_serializer: Api::PropertySerializer + ).to_json + end + + private + + def render_no_products + render status: :not_found, json: {} + end + + def product_properties + Spree::Property. + joins(:products). + where(spree_products: { id: distributed_products }). + select('DISTINCT spree_properties.*') + end + + def producer_properties + producers = Enterprise. + joins(:supplied_products). + where(spree_products: { id: distributed_products }) + + Spree::Property. + joins(:producer_properties). + where(producer_properties: { producer_id: producers }). + select('DISTINCT spree_properties.*') + end + + def search_params + permitted_search_params = params.slice :q, :page, :per_page + + if permitted_search_params.key? :q + permitted_search_params[:q].slice!(*permitted_ransack_params) + end + + permitted_search_params + end + + def permitted_ransack_params + [:name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont, + :properties_id_or_supplier_properties_id_in_any, + :primary_taxon_id_in_any] + end + + def distributor + @distributor ||= Enterprise.find_by(id: params[:distributor]) + end + + def order_cycle + @order_cycle ||= OrderCycle.find_by(id: params[:id]) + end + + def customer + @current_api_user.andand.customer_of(distributor) || nil + end + + def distributed_products + OrderCycleDistributedProducts.new(distributor, order_cycle, customer).products_relation + end + end + end +end diff --git a/app/controllers/api/v0/orders_controller.rb b/app/controllers/api/v0/orders_controller.rb new file mode 100644 index 0000000000..f7e363700e --- /dev/null +++ b/app/controllers/api/v0/orders_controller.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module Api + module V0 + class OrdersController < Api::V0::BaseController + include PaginationData + + def show + authorize! :read, order + render json: order, serializer: Api::OrderDetailedSerializer, current_order: order + end + + def index + authorize! :admin, Spree::Order + + orders = SearchOrders.new(params, current_api_user).orders + + render json: { + orders: serialized_orders(orders), + pagination: pagination_data(orders) + } + end + + def ship + authorize! :admin, order + + if order.ship + render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok + else + render json: { error: I18n.t('api.orders.failed_to_update') }, status: :unprocessable_entity + end + end + + def capture + authorize! :admin, order + + pending_payment = order.pending_payments.first + + return payment_capture_failed unless order.payment_required? && pending_payment + + if pending_payment.capture! + render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok + else + payment_capture_failed + end + rescue Spree::Core::GatewayError => e + error_during_processing(e) + end + + private + + def payment_capture_failed + render json: { error: I18n.t(:payment_processing_failed) }, status: :unprocessable_entity + end + + def serialized_orders(orders) + ActiveModel::ArraySerializer.new( + orders, + each_serializer: Api::Admin::OrderSerializer + ) + end + + def order + @order ||= Spree::Order. + where(number: params[:id]). + includes(line_items: { variant: [:product, :stock_items, :default_price] }). + first! + end + end + end +end diff --git a/app/controllers/api/v0/product_images_controller.rb b/app/controllers/api/v0/product_images_controller.rb new file mode 100644 index 0000000000..e35adfd42c --- /dev/null +++ b/app/controllers/api/v0/product_images_controller.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Api + module V0 + class ProductImagesController < Api::V0::BaseController + respond_to :json + + def update_product_image + @product = Spree::Product.find(params[:product_id]) + authorize! :update, @product + + if @product.images.first.nil? + @image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant') + render json: @image, serializer: ImageSerializer, status: :created + else + @image = @product.images.first + @image.update(attachment: params[:file]) + render json: @image, serializer: ImageSerializer, status: :ok + end + end + end + end +end diff --git a/app/controllers/api/v0/products_controller.rb b/app/controllers/api/v0/products_controller.rb new file mode 100644 index 0000000000..571b16b3e0 --- /dev/null +++ b/app/controllers/api/v0/products_controller.rb @@ -0,0 +1,163 @@ +# frozen_string_literal: true + +require 'open_food_network/permissions' +require 'spree/core/product_duplicator' + +module Api + module V0 + class ProductsController < Api::V0::BaseController + include PaginationData + respond_to :json + DEFAULT_PER_PAGE = 15 + + before_action :set_default_available_on, only: :create + + skip_authorization_check only: [:show, :bulk_products, :overridable] + + def show + @product = find_product(params[:id]) + render json: @product, serializer: Api::Admin::ProductSerializer + end + + def create + authorize! :create, Spree::Product + @product = Spree::Product.new(product_params) + + begin + if @product.save + render json: @product, serializer: Api::Admin::ProductSerializer, status: :created + else + invalid_resource!(@product) + end + rescue ActiveRecord::RecordNotUnique + @product.permalink = nil + retry + end + end + + def update + authorize! :update, Spree::Product + @product = find_product(params[:id]) + if @product.update(product_params) + render json: @product, serializer: Api::Admin::ProductSerializer, status: :ok + else + invalid_resource!(@product) + end + end + + def destroy + authorize! :delete, Spree::Product + @product = find_product(params[:id]) + authorize! :delete, @product + @product.destroy + render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content + end + + def bulk_products + product_query = OpenFoodNetwork::Permissions. + new(current_api_user). + editable_products. + merge(product_scope) + + if params[:import_date].present? + product_query = product_query. + imported_on(params[:import_date]). + group_by_products_id + end + + @products = product_query. + ransack(query_params_with_defaults). + result. + page(params[:page] || 1). + per(params[:per_page] || DEFAULT_PER_PAGE) + + render_paged_products @products + end + + def overridable + producer_ids = OpenFoodNetwork::Permissions.new(current_api_user). + variant_override_producers.by_name.select('enterprises.id') + + @products = paged_products_for_producers producer_ids + + render_paged_products @products, ::Api::Admin::ProductSimpleSerializer + end + + # POST /api/products/:product_id/clone + # + def clone + authorize! :create, Spree::Product + original_product = find_product(params[:product_id]) + authorize! :update, original_product + + @product = original_product.duplicate + + render json: @product, serializer: Api::Admin::ProductSerializer, status: :created + end + + private + + def find_product(id) + product_scope.find_by!(permalink: id.to_s) + rescue ActiveRecord::RecordNotFound + product_scope.find(id) + end + + def product_scope + if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present? + scope = Spree::Product + if params[:show_deleted] + scope = scope.with_deleted + end + else + scope = Spree::Product.active + end + + scope.includes(product_query_includes) + end + + def product_query_includes + [ + master: [:images], + variants: [:default_price, :stock_locations, :stock_items, :variant_overrides, + { option_values: :option_type }] + ] + end + + def paged_products_for_producers(producer_ids) + Spree::Product.where(nil). + merge(product_scope). + includes(variants: [:product, :default_price, :stock_items]). + where(supplier_id: producer_ids). + by_producer.by_name. + ransack(params[:q]).result. + page(params[:page]).per(params[:per_page]) + end + + def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer) + serialized_products = ActiveModel::ArraySerializer.new( + products, + each_serializer: product_serializer + ) + + render json: { + products: serialized_products, + pagination: pagination_data(products) + } + end + + def query_params_with_defaults + (params[:q] || {}).reverse_merge(s: 'created_at desc') + end + + def product_params + @product_params ||= + params.permit(product: PermittedAttributes::Product.attributes)[:product].to_h + end + + def set_default_available_on + product_params[:available_on] ||= Time.zone.now + end + end + end +end diff --git a/app/controllers/api/v0/promo_images_controller.rb b/app/controllers/api/v0/promo_images_controller.rb new file mode 100644 index 0000000000..13822324ff --- /dev/null +++ b/app/controllers/api/v0/promo_images_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Api + module V0 + class PromoImagesController < Api::V0::EnterpriseAttachmentController + private + + def attachment_name + :promo_image + end + + def enterprise_authorize_action + case action_name.to_sym + when :destroy + :remove_promo_image + end + end + end + end +end diff --git a/app/controllers/api/v0/shipments_controller.rb b/app/controllers/api/v0/shipments_controller.rb new file mode 100644 index 0000000000..ec452b2869 --- /dev/null +++ b/app/controllers/api/v0/shipments_controller.rb @@ -0,0 +1,116 @@ +# frozen_string_literal: true + +require 'open_food_network/scope_variant_to_hub' + +module Api + module V0 + class ShipmentsController < Api::V0::BaseController + respond_to :json + + before_action :find_order + before_action :find_and_update_shipment, only: [:ship, :ready, :add, :remove] + + def create + variant = scoped_variant(params[:variant_id]) + quantity = params[:quantity].to_i + @shipment = get_or_create_shipment(params[:stock_location_id]) + + @order.contents.add(variant, quantity, nil, @shipment) + + @shipment.refresh_rates + @shipment.save! + + render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok + end + + def update + authorize! :read, Spree::Shipment + @shipment = @order.shipments.find_by!(number: params[:id]) + params[:shipment] ||= [] + unlock = params[:shipment].delete(:unlock) + + if unlock == 'yes' + @shipment.fee_adjustment.open + end + + @shipment.update(shipment_params[:shipment]) + + if unlock == 'yes' + @shipment.fee_adjustment.close + end + + render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok + end + + def ready + authorize! :read, Spree::Shipment + unless @shipment.ready? + if @shipment.can_ready? + @shipment.ready! + else + render(json: { error: I18n.t(:cannot_ready, scope: "spree.api.shipment") }, + status: :unprocessable_entity) && return + end + end + render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok + end + + def ship + authorize! :read, Spree::Shipment + unless @shipment.shipped? + @shipment.ship! + end + render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok + end + + def add + variant = scoped_variant(params[:variant_id]) + quantity = params[:quantity].to_i + + @order.contents.add(variant, quantity, nil, @shipment) + + render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok + end + + def remove + variant = scoped_variant(params[:variant_id]) + quantity = params[:quantity].to_i + + @order.contents.remove(variant, quantity, @shipment) + @shipment.reload if @shipment.persisted? + + render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok + end + + private + + def find_order + @order = Spree::Order.find_by!(number: params[:order_id]) + authorize! :read, @order + end + + def find_and_update_shipment + @shipment = @order.shipments.find_by!(number: params[:id]) + @shipment.update(shipment_params[:shipment]) if shipment_params[:shipment].present? + @shipment.reload + end + + def scoped_variant(variant_id) + variant = Spree::Variant.find(variant_id) + OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant) + variant + end + + def get_or_create_shipment(stock_location_id) + @order.shipment || @order.shipments.create(stock_location_id: stock_location_id) + end + + def shipment_params + params.permit( + [:id, :order_id, :variant_id, :quantity, + { shipment: [:tracking, :selected_shipping_rate_id] }] + ) + end + end + end +end diff --git a/app/controllers/api/v0/shops_controller.rb b/app/controllers/api/v0/shops_controller.rb new file mode 100644 index 0000000000..a76a506a85 --- /dev/null +++ b/app/controllers/api/v0/shops_controller.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Api + module V0 + class ShopsController < BaseController + respond_to :json + skip_authorization_check only: [:show, :closed_shops] + + def show + enterprise = Enterprise.find_by(id: params[:id]) + + render plain: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok + end + + def closed_shops + @active_distributor_ids = [] + @earliest_closing_times = [] + + serialized_closed_shops = ActiveModel::ArraySerializer.new( + ShopsListService.new.closed_shops, + each_serializer: Api::EnterpriseSerializer, + data: OpenFoodNetwork::EnterpriseInjectionData.new + ) + + render json: serialized_closed_shops + end + end + end +end diff --git a/app/controllers/api/v0/states_controller.rb b/app/controllers/api/v0/states_controller.rb new file mode 100644 index 0000000000..c64a077f76 --- /dev/null +++ b/app/controllers/api/v0/states_controller.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Api + module V0 + class StatesController < Api::V0::BaseController + respond_to :json + + skip_authorization_check + + def index + render json: states, each_serializer: Api::StateSerializer, status: :ok + end + + def show + @state = scope.find(params[:id]) + render json: @state, serializer: Api::StateSerializer, status: :ok + end + + private + + def scope + if params[:country_id] + @country = Spree::Country.find(params[:country_id]) + @country.states + else + Spree::State.all + end + end + + def states + states = scope.ransack(params[:q]).result. + includes(:country).order('name ASC') + + if pagination? + states = states.page(params[:page]).per(params[:per_page]) + end + + states + end + + def pagination? + params[:page] || params[:per_page] + end + end + end +end diff --git a/app/controllers/api/v0/statuses_controller.rb b/app/controllers/api/v0/statuses_controller.rb new file mode 100644 index 0000000000..17a0eaa3cf --- /dev/null +++ b/app/controllers/api/v0/statuses_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Api + module V0 + class StatusesController < ::BaseController + respond_to :json + + def job_queue + render json: { alive: job_queue_alive? } + end + + private + + def job_queue_alive? + Spree::Config.last_job_queue_heartbeat_at.present? && + Time.parse(Spree::Config.last_job_queue_heartbeat_at).in_time_zone > 6.minutes.ago + end + end + end +end diff --git a/app/controllers/api/v0/taxonomies_controller.rb b/app/controllers/api/v0/taxonomies_controller.rb new file mode 100644 index 0000000000..bf6077a9e1 --- /dev/null +++ b/app/controllers/api/v0/taxonomies_controller.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Api + module V0 + class TaxonomiesController < Api::V0::BaseController + respond_to :json + + skip_authorization_check only: :jstree + + def jstree + @taxonomy = Spree::Taxonomy.find(params[:id]) + render json: @taxonomy.root, serializer: Api::TaxonJstreeSerializer + end + end + end +end diff --git a/app/controllers/api/v0/taxons_controller.rb b/app/controllers/api/v0/taxons_controller.rb new file mode 100644 index 0000000000..12ed6a15a4 --- /dev/null +++ b/app/controllers/api/v0/taxons_controller.rb @@ -0,0 +1,78 @@ +module Api + module V0 + class TaxonsController < Api::V0::BaseController + respond_to :json + + skip_authorization_check only: [:index, :show, :jstree] + + def index + @taxons = if taxonomy + taxonomy.root.children + elsif params[:ids] + Spree::Taxon.where(id: raw_params[:ids].split(",")) + else + Spree::Taxon.ransack(raw_params[:q]).result + end + render json: @taxons, each_serializer: Api::TaxonSerializer + end + + def jstree + @taxon = taxon + render json: @taxon.children, each_serializer: Api::TaxonJstreeSerializer + end + + def create + authorize! :create, Spree::Taxon + @taxon = Spree::Taxon.new(taxon_params) + @taxon.taxonomy_id = params[:taxonomy_id] + taxonomy = Spree::Taxonomy.find_by(id: params[:taxonomy_id]) + + if taxonomy.nil? + @taxon.errors[:taxonomy_id] = I18n.t(:invalid_taxonomy_id, scope: 'spree.api') + invalid_resource!(@taxon) && return + end + + @taxon.parent_id = taxonomy.root.id unless params.dig(:taxon, :parent_id) + + if @taxon.save + render json: @taxon, serializer: Api::TaxonSerializer, status: :created + else + invalid_resource!(@taxon) + end + end + + def update + authorize! :update, Spree::Taxon + if taxon.update(taxon_params) + render json: taxon, serializer: Api::TaxonSerializer, status: :ok + else + invalid_resource!(taxon) + end + end + + def destroy + authorize! :delete, Spree::Taxon + taxon.destroy + render json: taxon, serializer: Api::TaxonSerializer, status: :no_content + end + + private + + def taxonomy + return if params[:taxonomy_id].blank? + + @taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id]) + end + + def taxon + @taxon ||= taxonomy.taxons.find(params[:id]) + end + + def taxon_params + return if params[:taxon].blank? + + params.require(:taxon).permit([:name, :parent_id]) + end + end + end +end diff --git a/app/controllers/api/v0/terms_and_conditions_controller.rb b/app/controllers/api/v0/terms_and_conditions_controller.rb new file mode 100644 index 0000000000..e5089c5c2e --- /dev/null +++ b/app/controllers/api/v0/terms_and_conditions_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Api + module V0 + class TermsAndConditionsController < Api::V0::EnterpriseAttachmentController + private + + def attachment_name + :terms_and_conditions + end + + def enterprise_authorize_action + case action_name.to_sym + when :destroy + :remove_terms_and_conditions + end + end + end + end +end diff --git a/app/controllers/api/v0/variants_controller.rb b/app/controllers/api/v0/variants_controller.rb new file mode 100644 index 0000000000..e1846ebe32 --- /dev/null +++ b/app/controllers/api/v0/variants_controller.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +module Api + module V0 + class VariantsController < Api::V0::BaseController + respond_to :json + + skip_authorization_check only: [:index, :show] + before_action :product + + def index + @variants = scope.includes(option_values: :option_type).ransack(params[:q]).result + render json: @variants, each_serializer: Api::VariantSerializer + end + + def show + @variant = scope.includes(option_values: :option_type).find(params[:id]) + render json: @variant, serializer: Api::VariantSerializer + end + + def create + authorize! :create, Spree::Variant + @variant = scope.new(variant_params) + if @variant.save + render json: @variant, serializer: Api::VariantSerializer, status: :created + else + invalid_resource!(@variant) + end + end + + def update + authorize! :update, Spree::Variant + @variant = scope.find(params[:id]) + if @variant.update(variant_params) + render json: @variant, serializer: Api::VariantSerializer, status: :ok + else + invalid_resource!(@product) + end + end + + def destroy + authorize! :delete, Spree::Variant + @variant = scope.find(params[:id]) + authorize! :delete, @variant + + VariantDeleter.new.delete(@variant) + render json: @variant, serializer: Api::VariantSerializer, status: :no_content + end + + private + + def product + @product ||= Spree::Product.find_by(permalink: params[:product_id]) if params[:product_id] + end + + def scope + if @product + variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted] + @product.variants_including_master.with_deleted + else + @product.variants_including_master + end + else + variants = Spree::Variant.where(nil) + if current_api_user.has_spree_role?("admin") + unless params[:show_deleted] + variants = Spree::Variant.active + end + else + variants = variants.active + end + end + variants + end + + def variant_params + params.require(:variant).permit(PermittedAttributes::Variant.attributes) + end + end + end +end diff --git a/app/controllers/api/variants_controller.rb b/app/controllers/api/variants_controller.rb deleted file mode 100644 index 47b12e1e92..0000000000 --- a/app/controllers/api/variants_controller.rb +++ /dev/null @@ -1,77 +0,0 @@ -module Api - class VariantsController < Api::BaseController - respond_to :json - - skip_authorization_check only: [:index, :show] - before_action :product - - def index - @variants = scope.includes(option_values: :option_type).ransack(params[:q]).result - render json: @variants, each_serializer: Api::VariantSerializer - end - - def show - @variant = scope.includes(option_values: :option_type).find(params[:id]) - render json: @variant, serializer: Api::VariantSerializer - end - - def create - authorize! :create, Spree::Variant - @variant = scope.new(variant_params) - if @variant.save - render json: @variant, serializer: Api::VariantSerializer, status: :created - else - invalid_resource!(@variant) - end - end - - def update - authorize! :update, Spree::Variant - @variant = scope.find(params[:id]) - if @variant.update(variant_params) - render json: @variant, serializer: Api::VariantSerializer, status: :ok - else - invalid_resource!(@product) - end - end - - def destroy - authorize! :delete, Spree::Variant - @variant = scope.find(params[:id]) - authorize! :delete, @variant - - VariantDeleter.new.delete(@variant) - render json: @variant, serializer: Api::VariantSerializer, status: :no_content - end - - private - - def product - @product ||= Spree::Product.find_by(permalink: params[:product_id]) if params[:product_id] - end - - def scope - if @product - variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted] - @product.variants_including_master.with_deleted - else - @product.variants_including_master - end - else - variants = Spree::Variant.where(nil) - if current_api_user.has_spree_role?("admin") - unless params[:show_deleted] - variants = Spree::Variant.active - end - else - variants = variants.active - end - end - variants - end - - def variant_params - params.require(:variant).permit(PermittedAttributes::Variant.attributes) - end - end -end diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index 0860d5a5a5..1ab8005090 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -80,7 +80,7 @@ module Spree product_set.collection.each { |p| authorize! :update, p } if product_set.save - redirect_to main_app.bulk_products_api_products_path(bulk_index_query) + redirect_to main_app.bulk_products_api_v0_products_path(bulk_index_query) elsif product_set.errors.present? render json: { errors: product_set.errors }, status: :bad_request else diff --git a/app/views/spree/admin/shared/_routes.html.erb b/app/views/spree/admin/shared/_routes.html.erb index 438d257af9..418359b5e7 100644 --- a/app/views/spree/admin/shared/_routes.html.erb +++ b/app/views/spree/admin/shared/_routes.html.erb @@ -7,8 +7,8 @@ } Spree.routes = <%== { :variants_search => spree.admin_search_variants_path(:format => 'json'), - :taxons_search => main_app.api_taxons_path(:format => 'json'), - :orders_api => main_app.api_orders_path, - :states_search => main_app.api_states_path(:format => 'json') + :taxons_search => main_app.api_v0_taxons_path(:format => 'json'), + :orders_api => main_app.api_v0_orders_path, + :states_search => main_app.api_v0_states_path(:format => 'json') }.to_json %>; diff --git a/app/views/spree/admin/taxonomies/edit.haml b/app/views/spree/admin/taxonomies/edit.haml index eb43b8fa84..7f37454aec 100755 --- a/app/views/spree/admin/taxonomies/edit.haml +++ b/app/views/spree/admin/taxonomies/edit.haml @@ -17,7 +17,7 @@ = label_tag nil, t("spree.tree") %br/ :javascript - Spree.routes.taxonomy_taxons_path = "#{main_app.api_taxonomy_taxons_path(@taxonomy)}"; + Spree.routes.taxonomy_taxons_path = "#{main_app.api_v0_taxonomy_taxons_path(@taxonomy)}"; Spree.routes.admin_taxonomy_taxons_path = "#{spree.admin_taxonomy_taxons_path(@taxonomy)}"; #taxonomy_tree.tree #progress{style: "display:none;"} diff --git a/config/routes/api.rb b/config/routes/api.rb index 6bdfd5dcb3..5fa9db4e97 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -1,80 +1,84 @@ Openfoodnetwork::Application.routes.draw do namespace :api do - resources :products do - collection do - get :bulk_products - get :overridable - end - post :clone + namespace :v0 do + resources :products do + collection do + get :bulk_products + get :overridable + end + post :clone - resources :variants - end - - resources :variants, :only => [:index] - - resources :orders, only: [:index, :show] do - member do - put :capture - put :ship + resources :variants end - resources :shipments, :only => [:create, :update] do + resources :variants, :only => [:index] + + resources :orders, only: [:index, :show] do member do - put :ready + put :capture put :ship - put :add - put :remove + end + + resources :shipments, :only => [:create, :update] do + member do + put :ready + put :ship + put :add + put :remove + end end end - end - resources :enterprises do - post :update_image, on: :member + resources :enterprises do + post :update_image, on: :member - resource :logo, only: [:destroy] - resource :promo_image, only: [:destroy] - resource :terms_and_conditions, only: [:destroy] - end - - resources :shops, only: [:show] do - collection do - get :closed_shops + resource :logo, only: [:destroy] + resource :promo_image, only: [:destroy] + resource :terms_and_conditions, only: [:destroy] end - end - resources :order_cycles do - get :products, on: :member - get :taxons, on: :member - get :properties, on: :member - end - - resources :exchanges, only: [:show], to: 'exchange_products#index' do - get :products, to: 'exchange_products#index' - end - - resource :status do - get :job_queue - end - - resources :customers, only: [:index, :update] - - resources :enterprise_fees, only: [:destroy] - - post '/product_images/:product_id', to: 'product_images#update_product_image' - - resources :states, :only => [:index, :show] - - resources :taxons, :only => [:index] - - resources :taxonomies do - member do - get :jstree + resources :shops, only: [:show] do + collection do + get :closed_shops + end end - resources :taxons do + + resources :order_cycles do + get :products, on: :member + get :taxons, on: :member + get :properties, on: :member + end + + resources :exchanges, only: [:show], to: 'exchange_products#index' do + get :products, to: 'exchange_products#index' + end + + resource :status do + get :job_queue + end + + resources :customers, only: [:index, :update] + + resources :enterprise_fees, only: [:destroy] + + post '/product_images/:product_id', to: 'product_images#update_product_image' + + resources :states, :only => [:index, :show] + + resources :taxons, :only => [:index] + + resources :taxonomies do member do get :jstree end + resources :taxons do + member do + get :jstree + end + end end end + + match '*path', to: redirect("/api/v0/%{path}"), via: :all, constraints: { path: /(?!.*v0).+/ } end end diff --git a/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_controller.js.coffee b/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_controller.js.coffee index a35951943a..b9ee459a78 100644 --- a/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_controller.js.coffee +++ b/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_controller.js.coffee @@ -1,6 +1,6 @@ Darkswarm.controller "CookiesBannerCtrl", ($scope, CookiesBannerService, $http, $window)-> $scope.acceptCookies = -> - $http.post('/api/cookies/consent') + $http.post('/api/v0/cookies/consent') CookiesBannerService.close() CookiesBannerService.disable() diff --git a/engines/web/app/controllers/web/api/cookies_consent_controller.rb b/engines/web/app/controllers/web/api/cookies_consent_controller.rb deleted file mode 100644 index e0ea13bafe..0000000000 --- a/engines/web/app/controllers/web/api/cookies_consent_controller.rb +++ /dev/null @@ -1,30 +0,0 @@ -require_dependency 'web/cookies_consent' - -module Web - module Api - class CookiesConsentController < BaseController - include ActionController::Cookies - respond_to :json - - def show - render json: { cookies_consent: cookies_consent.exists? } - end - - def create - cookies_consent.set - show - end - - def destroy - cookies_consent.destroy - show - end - - private - - def cookies_consent - @cookies_consent ||= Web::CookiesConsent.new(cookies, request.host) - end - end - end -end diff --git a/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb b/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb new file mode 100644 index 0000000000..ce163a0e16 --- /dev/null +++ b/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb @@ -0,0 +1,32 @@ +require_dependency 'web/cookies_consent' + +module Web + module Api + module V0 + class CookiesConsentController < BaseController + include ActionController::Cookies + respond_to :json + + def show + render json: { cookies_consent: cookies_consent.exists? } + end + + def create + cookies_consent.set + show + end + + def destroy + cookies_consent.destroy + show + end + + private + + def cookies_consent + @cookies_consent ||= Web::CookiesConsent.new(cookies, request.host) + end + end + end + end +end diff --git a/engines/web/config/routes.rb b/engines/web/config/routes.rb index 4b6440e06a..b2a060617a 100644 --- a/engines/web/config/routes.rb +++ b/engines/web/config/routes.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true Openfoodnetwork::Application.routes.append do - scope '/api/cookies' do - resource :consent, only: [:show, :create, :destroy], controller: "web/api/cookies_consent" + scope '/api/v0/cookies' do + resource :consent, only: [:show, :create, :destroy], controller: "web/api/v0/cookies_consent" end get "/angular-templates/:id", to: "web/angular_templates#show", constraints: { name: %r{[\/\w\.]+} } diff --git a/spec/controllers/api/base_controller_spec.rb b/spec/controllers/api/v0/base_controller_spec.rb similarity index 96% rename from spec/controllers/api/base_controller_spec.rb rename to spec/controllers/api/v0/base_controller_spec.rb index 385e2cfe10..ec9875723b 100644 --- a/spec/controllers/api/base_controller_spec.rb +++ b/spec/controllers/api/v0/base_controller_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' -describe Api::BaseController do +describe Api::V0::BaseController do render_views - controller(Api::BaseController) do + controller(Api::V0::BaseController) do skip_authorization_check only: :index def index diff --git a/spec/controllers/api/customers_controller_spec.rb b/spec/controllers/api/v0/customers_controller_spec.rb similarity index 97% rename from spec/controllers/api/customers_controller_spec.rb rename to spec/controllers/api/v0/customers_controller_spec.rb index 2034d3118e..f06116a5ab 100644 --- a/spec/controllers/api/customers_controller_spec.rb +++ b/spec/controllers/api/v0/customers_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe CustomersController, type: :controller do + describe V0::CustomersController, type: :controller do include AuthenticationHelper render_views diff --git a/spec/controllers/api/enterprise_fees_controller_spec.rb b/spec/controllers/api/v0/enterprise_fees_controller_spec.rb similarity index 91% rename from spec/controllers/api/enterprise_fees_controller_spec.rb rename to spec/controllers/api/v0/enterprise_fees_controller_spec.rb index 85979beacb..40ed1e78e2 100644 --- a/spec/controllers/api/enterprise_fees_controller_spec.rb +++ b/spec/controllers/api/v0/enterprise_fees_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe EnterpriseFeesController, type: :controller do + describe V0::EnterpriseFeesController, type: :controller do include AuthenticationHelper let!(:unreferenced_fee) { create(:enterprise_fee) } diff --git a/spec/controllers/api/enterprises_controller_spec.rb b/spec/controllers/api/v0/enterprises_controller_spec.rb similarity index 97% rename from spec/controllers/api/enterprises_controller_spec.rb rename to spec/controllers/api/v0/enterprises_controller_spec.rb index cfc29f9358..32a1c067e2 100644 --- a/spec/controllers/api/enterprises_controller_spec.rb +++ b/spec/controllers/api/v0/enterprises_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Api::EnterprisesController, type: :controller do +describe Api::V0::EnterprisesController, type: :controller do render_views let(:enterprise) { create(:distributor_enterprise) } diff --git a/spec/controllers/api/exchange_products_controller_spec.rb b/spec/controllers/api/v0/exchange_products_controller_spec.rb similarity index 95% rename from spec/controllers/api/exchange_products_controller_spec.rb rename to spec/controllers/api/v0/exchange_products_controller_spec.rb index a0ae941c8a..01394ec215 100644 --- a/spec/controllers/api/exchange_products_controller_spec.rb +++ b/spec/controllers/api/v0/exchange_products_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe ExchangeProductsController, type: :controller do + describe V0::ExchangeProductsController, type: :controller do include AuthenticationHelper let(:order_cycle) { create(:order_cycle) } @@ -54,7 +54,7 @@ module Api let(:products_relation) { Spree::Product.includes(:variants).where("spree_variants.id": exchange.variants.map(&:id)) } before do - stub_const("#{Api::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) + stub_const("#{Api::V0::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) end describe "when a specific page is requested" do diff --git a/spec/controllers/api/logos_controller_spec.rb b/spec/controllers/api/v0/logos_controller_spec.rb similarity index 98% rename from spec/controllers/api/logos_controller_spec.rb rename to spec/controllers/api/v0/logos_controller_spec.rb index e6e929d423..32815be1c4 100644 --- a/spec/controllers/api/logos_controller_spec.rb +++ b/spec/controllers/api/v0/logos_controller_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" module Api - describe LogosController, type: :controller do + describe V0::LogosController, type: :controller do include AuthenticationHelper let(:admin_user) { create(:admin_user) } diff --git a/spec/controllers/api/order_cycles_controller_spec.rb b/spec/controllers/api/v0/order_cycles_controller_spec.rb similarity index 99% rename from spec/controllers/api/order_cycles_controller_spec.rb rename to spec/controllers/api/v0/order_cycles_controller_spec.rb index d41d26aa43..274b9152fd 100644 --- a/spec/controllers/api/order_cycles_controller_spec.rb +++ b/spec/controllers/api/v0/order_cycles_controller_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" module Api - describe OrderCyclesController, type: :controller do + describe V0::OrderCyclesController, type: :controller do let!(:distributor) { create(:distributor_enterprise) } let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor]) } let!(:exchange) { order_cycle.exchanges.to_enterprises(distributor).outgoing.first } diff --git a/spec/controllers/api/orders_controller_spec.rb b/spec/controllers/api/v0/orders_controller_spec.rb similarity index 99% rename from spec/controllers/api/orders_controller_spec.rb rename to spec/controllers/api/v0/orders_controller_spec.rb index d310aef486..cfae14f85a 100644 --- a/spec/controllers/api/orders_controller_spec.rb +++ b/spec/controllers/api/v0/orders_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe OrdersController, type: :controller do + describe V0::OrdersController, type: :controller do include AuthenticationHelper render_views diff --git a/spec/controllers/api/product_images_controller_spec.rb b/spec/controllers/api/v0/product_images_controller_spec.rb similarity index 95% rename from spec/controllers/api/product_images_controller_spec.rb rename to spec/controllers/api/v0/product_images_controller_spec.rb index b4858ae49e..311654b745 100644 --- a/spec/controllers/api/product_images_controller_spec.rb +++ b/spec/controllers/api/v0/product_images_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe ProductImagesController, type: :controller do + describe V0::ProductImagesController, type: :controller do include AuthenticationHelper render_views diff --git a/spec/controllers/api/products_controller_spec.rb b/spec/controllers/api/v0/products_controller_spec.rb similarity index 99% rename from spec/controllers/api/products_controller_spec.rb rename to spec/controllers/api/v0/products_controller_spec.rb index f0ee86d736..8af0985e48 100644 --- a/spec/controllers/api/products_controller_spec.rb +++ b/spec/controllers/api/v0/products_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'spree/core/product_duplicator' -describe Api::ProductsController, type: :controller do +describe Api::V0::ProductsController, type: :controller do render_views let(:supplier) { create(:supplier_enterprise) } diff --git a/spec/controllers/api/promo_images_controller_spec.rb b/spec/controllers/api/v0/promo_images_controller_spec.rb similarity index 98% rename from spec/controllers/api/promo_images_controller_spec.rb rename to spec/controllers/api/v0/promo_images_controller_spec.rb index 9fe559456e..6c8d0f1319 100644 --- a/spec/controllers/api/promo_images_controller_spec.rb +++ b/spec/controllers/api/v0/promo_images_controller_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" module Api - describe PromoImagesController, type: :controller do + describe V0::PromoImagesController, type: :controller do include AuthenticationHelper let(:admin_user) { create(:admin_user) } diff --git a/spec/controllers/api/shipments_controller_spec.rb b/spec/controllers/api/v0/shipments_controller_spec.rb similarity index 99% rename from spec/controllers/api/shipments_controller_spec.rb rename to spec/controllers/api/v0/shipments_controller_spec.rb index f82b30e1e5..26e6a6b29c 100644 --- a/spec/controllers/api/shipments_controller_spec.rb +++ b/spec/controllers/api/v0/shipments_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Api::ShipmentsController, type: :controller do +describe Api::V0::ShipmentsController, type: :controller do render_views let!(:shipment) { create(:shipment) } diff --git a/spec/controllers/api/shops_controller_spec.rb b/spec/controllers/api/v0/shops_controller_spec.rb similarity index 96% rename from spec/controllers/api/shops_controller_spec.rb rename to spec/controllers/api/v0/shops_controller_spec.rb index 0e699b2e73..2863aaef53 100644 --- a/spec/controllers/api/shops_controller_spec.rb +++ b/spec/controllers/api/v0/shops_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Api::ShopsController, type: :controller do +describe Api::V0::ShopsController, type: :controller do include AuthenticationHelper render_views diff --git a/spec/controllers/api/states_controller_spec.rb b/spec/controllers/api/v0/states_controller_spec.rb similarity index 98% rename from spec/controllers/api/states_controller_spec.rb rename to spec/controllers/api/v0/states_controller_spec.rb index 548fcb0ad1..e9d9d11ad9 100644 --- a/spec/controllers/api/states_controller_spec.rb +++ b/spec/controllers/api/v0/states_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe StatesController do + describe V0::StatesController do render_views let!(:state) { create(:state, name: "Victoria") } diff --git a/spec/controllers/api/statuses_controller_spec.rb b/spec/controllers/api/v0/statuses_controller_spec.rb similarity index 93% rename from spec/controllers/api/statuses_controller_spec.rb rename to spec/controllers/api/v0/statuses_controller_spec.rb index 40132eed5c..e79dca33a3 100644 --- a/spec/controllers/api/statuses_controller_spec.rb +++ b/spec/controllers/api/v0/statuses_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe StatusesController, type: :controller do + describe V0::StatusesController, type: :controller do render_views describe "job queue status" do diff --git a/spec/controllers/api/taxonomies_controller_spec.rb b/spec/controllers/api/v0/taxonomies_controller_spec.rb similarity index 96% rename from spec/controllers/api/taxonomies_controller_spec.rb rename to spec/controllers/api/v0/taxonomies_controller_spec.rb index 8f080c9748..8948465864 100644 --- a/spec/controllers/api/taxonomies_controller_spec.rb +++ b/spec/controllers/api/v0/taxonomies_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Api - describe TaxonomiesController do + describe V0::TaxonomiesController do render_views let(:taxonomy) { create(:taxonomy) } diff --git a/spec/controllers/api/taxons_controller_spec.rb b/spec/controllers/api/v0/taxons_controller_spec.rb similarity index 98% rename from spec/controllers/api/taxons_controller_spec.rb rename to spec/controllers/api/v0/taxons_controller_spec.rb index f006bc3b6c..8f2b18c942 100644 --- a/spec/controllers/api/taxons_controller_spec.rb +++ b/spec/controllers/api/v0/taxons_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Api::TaxonsController do +describe Api::V0::TaxonsController do render_views let(:taxonomy) { create(:taxonomy) } diff --git a/spec/controllers/api/terms_and_conditions_controller_spec.rb b/spec/controllers/api/v0/terms_and_conditions_controller_spec.rb similarity index 96% rename from spec/controllers/api/terms_and_conditions_controller_spec.rb rename to spec/controllers/api/v0/terms_and_conditions_controller_spec.rb index ca6a38290c..68439f74cf 100644 --- a/spec/controllers/api/terms_and_conditions_controller_spec.rb +++ b/spec/controllers/api/v0/terms_and_conditions_controller_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" module Api - describe TermsAndConditionsController, type: :controller do + describe V0::TermsAndConditionsController, type: :controller do include AuthenticationHelper let(:enterprise_owner) { create(:user) } diff --git a/spec/controllers/api/variants_controller_spec.rb b/spec/controllers/api/v0/variants_controller_spec.rb similarity index 98% rename from spec/controllers/api/variants_controller_spec.rb rename to spec/controllers/api/v0/variants_controller_spec.rb index 4a26422b62..a7b3d70b81 100644 --- a/spec/controllers/api/variants_controller_spec.rb +++ b/spec/controllers/api/v0/variants_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Api::VariantsController, type: :controller do +describe Api::V0::VariantsController, type: :controller do render_views let(:supplier) { FactoryBot.create(:supplier_enterprise) } diff --git a/spec/controllers/spree/admin/products_controller_spec.rb b/spec/controllers/spree/admin/products_controller_spec.rb index 081b85ebd8..7ee42b9aa2 100644 --- a/spec/controllers/spree/admin/products_controller_spec.rb +++ b/spec/controllers/spree/admin/products_controller_spec.rb @@ -66,7 +66,7 @@ describe Spree::Admin::ProductsController, type: :controller do ] expect(response).to redirect_to( - '/api/products/bulk_products' + '/api/v0/products/bulk_products' ) end end diff --git a/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb b/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb index c13e0dd8b1..892438c003 100644 --- a/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb +++ b/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb @@ -16,7 +16,7 @@ feature ' let!(:new_product) { create(:product, supplier: supplier_enterprise) } before do - stub_const("#{Api::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) + stub_const("#{Api::V0::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) login_as_admin_and_visit admin_order_cycle_incoming_path(order_cycle) expect(page).to have_content "1 / 2 selected" diff --git a/spec/features/consumer/caching/shops_caching_spec.rb b/spec/features/consumer/caching/shops_caching_spec.rb index f9684c2378..25ac1a1918 100644 --- a/spec/features/consumer/caching/shops_caching_spec.rb +++ b/spec/features/consumer/caching/shops_caching_spec.rb @@ -47,8 +47,8 @@ feature "Shops caching", js: true, caching: true do let(:exchange) { order_cycle.exchanges.to_enterprises(distributor).outgoing.first } let(:test_domain) { "#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}" } - let(:taxons_key) { "views/#{test_domain}/api/order_cycles/#{order_cycle.id}/taxons.json?distributor=#{distributor.id}" } - let(:properties_key) { "views/#{test_domain}/api/order_cycles/#{order_cycle.id}/properties.json?distributor=#{distributor.id}" } + let(:taxons_key) { "views/#{test_domain}/api/v0/order_cycles/#{order_cycle.id}/taxons.json?distributor=#{distributor.id}" } + let(:properties_key) { "views/#{test_domain}/api/v0/order_cycles/#{order_cycle.id}/properties.json?distributor=#{distributor.id}" } let(:options) { { expires_in: CacheService::FILTERS_EXPIRY } } before do diff --git a/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee b/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee index 81ea716f98..9369342591 100644 --- a/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee +++ b/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee @@ -820,7 +820,7 @@ describe "AdminProductEditCtrl", -> } ] $scope.dirtyProducts = {} - $httpBackend.expectDELETE("/api/products/13").respond 200, "data" + $httpBackend.expectDELETE("/api/v0/products/13").respond 200, "data" $scope.deleteProduct $scope.products[1] $httpBackend.flush() @@ -839,7 +839,7 @@ describe "AdminProductEditCtrl", -> DirtyProducts.addProductProperty 9, "someProperty", "something" DirtyProducts.addProductProperty 13, "name", "P1" - $httpBackend.expectDELETE("/api/products/13").respond 200, "data" + $httpBackend.expectDELETE("/api/v0/products/13").respond 200, "data" $scope.deleteProduct $scope.products[1] $httpBackend.flush() expect($scope.products).toEqual [ @@ -901,7 +901,7 @@ describe "AdminProductEditCtrl", -> } ] $scope.dirtyProducts = {} - $httpBackend.expectDELETE("/api/products/apples/variants/3").respond 200, "data" + $httpBackend.expectDELETE("/api/v0/products/apples/variants/3").respond 200, "data" $scope.deleteVariant $scope.products[0], $scope.products[0].variants[0] $httpBackend.flush() @@ -931,7 +931,7 @@ describe "AdminProductEditCtrl", -> DirtyProducts.addVariantProperty 9, 4, "price", 6.0 DirtyProducts.addProductProperty 13, "name", "P1" - $httpBackend.expectDELETE("/api/products/apples/variants/3").respond 200, "data" + $httpBackend.expectDELETE("/api/v0/products/apples/variants/3").respond 200, "data" $scope.deleteVariant $scope.products[0], $scope.products[0].variants[0] $httpBackend.flush() expect($scope.products[0].variants).toEqual [ diff --git a/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee b/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee index 47c669e105..0e2101f0af 100644 --- a/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee +++ b/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee @@ -127,7 +127,7 @@ describe "Enterprises service", -> beforeEach -> enterprise = new EnterpriseResource({ id: 15, permalink: "enterprise1", name: "Enterprise 1", logo: {} }) - $httpBackend.expectDELETE("/api/enterprises/enterprise1/logo.json").respond 200, { id: 15, name: "Enterprise 1"} + $httpBackend.expectDELETE("/api/v0/enterprises/enterprise1/logo.json").respond 200, { id: 15, name: "Enterprise 1"} Enterprises.removeLogo(enterprise).then( -> resolved = true) $httpBackend.flush() @@ -144,7 +144,7 @@ describe "Enterprises service", -> beforeEach -> enterprise = new EnterpriseResource( { id: 15, permalink: "enterprise1", name: "Enterprise 1" } ) - $httpBackend.expectDELETE("/api/enterprises/enterprise1/logo.json").respond 409, { error: "obj" } + $httpBackend.expectDELETE("/api/v0/enterprises/enterprise1/logo.json").respond 409, { error: "obj" } Enterprises.removeLogo(enterprise).catch( -> rejected = true) $httpBackend.flush() @@ -162,7 +162,7 @@ describe "Enterprises service", -> beforeEach -> enterprise = new EnterpriseResource({ id: 15, permalink: "enterprise1", name: "Enterprise 1", promo_image: {} }) - $httpBackend.expectDELETE("/api/enterprises/enterprise1/promo_image.json").respond 200, { id: 15, name: "Enterprise 1"} + $httpBackend.expectDELETE("/api/v0/enterprises/enterprise1/promo_image.json").respond 200, { id: 15, name: "Enterprise 1"} Enterprises.removePromoImage(enterprise).then( -> resolved = true) $httpBackend.flush() @@ -179,7 +179,7 @@ describe "Enterprises service", -> beforeEach -> enterprise = new EnterpriseResource( { id: 15, permalink: "enterprise1", name: "Enterprise 1" } ) - $httpBackend.expectDELETE("/api/enterprises/enterprise1/promo_image.json").respond 409, { error: "obj" } + $httpBackend.expectDELETE("/api/v0/enterprises/enterprise1/promo_image.json").respond 409, { error: "obj" } Enterprises.removePromoImage(enterprise).catch( -> rejected = true) $httpBackend.flush() diff --git a/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee b/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee index 4bc5513310..31a32f256a 100644 --- a/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee @@ -45,7 +45,7 @@ describe "LineItemsCtrl", -> index: jasmine.createSpy('index').and.returnValue(lineItem) all: [lineItem] - httpBackend.expectGET("/api/orders.json?q%5Bcompleted_at_gteq%5D=SomeDate&q%5Bcompleted_at_lt%5D=SomeDate&q%5Bcompleted_at_not_null%5D=true&q%5Bdistributor_id_eq%5D=&q%5Border_cycle_id_eq%5D=&q%5Bstate_not_eq%5D=canceled").respond {orders: [order], pagination: {page: 1, pages: 1, results: 1}} + httpBackend.expectGET("/api/v0/orders.json?q%5Bcompleted_at_gteq%5D=SomeDate&q%5Bcompleted_at_lt%5D=SomeDate&q%5Bcompleted_at_not_null%5D=true&q%5Bdistributor_id_eq%5D=&q%5Border_cycle_id_eq%5D=&q%5Bstate_not_eq%5D=canceled").respond {orders: [order], pagination: {page: 1, pages: 1, results: 1}} httpBackend.expectGET("/admin/enterprises/visible.json?ams_prefix=basic&q%5Bsells_in%5D%5B%5D=own&q%5Bsells_in%5D%5B%5D=any").respond [distributor] httpBackend.expectGET("/admin/order_cycles.json?ams_prefix=basic&as=distributor&q%5Borders_close_at_gt%5D=SomeDate").respond [orderCycle] httpBackend.expectGET("/admin/enterprises/visible.json?ams_prefix=basic&q%5Bis_primary_producer_eq%5D=true").respond [supplier] diff --git a/spec/javascripts/unit/admin/orders/services/orders_spec.js.coffee b/spec/javascripts/unit/admin/orders/services/orders_spec.js.coffee index 8372ee6819..9c19b2268d 100644 --- a/spec/javascripts/unit/admin/orders/services/orders_spec.js.coffee +++ b/spec/javascripts/unit/admin/orders/services/orders_spec.js.coffee @@ -19,7 +19,7 @@ describe "Orders service", -> beforeEach -> response = { orders: [{ id: 5, name: 'Order 1'}], pagination: {page: 1, pages: 1, results: 1} } - $httpBackend.expectGET('/api/orders.json').respond 200, response + $httpBackend.expectGET('/api/v0/orders.json').respond 200, response result = Orders.index() $httpBackend.flush() diff --git a/spec/javascripts/unit/admin/services/bulk_products_spec.js.coffee b/spec/javascripts/unit/admin/services/bulk_products_spec.js.coffee index 4fc1cca031..ece9d1f244 100644 --- a/spec/javascripts/unit/admin/services/bulk_products_spec.js.coffee +++ b/spec/javascripts/unit/admin/services/bulk_products_spec.js.coffee @@ -13,9 +13,9 @@ describe "BulkProducts service", -> BulkProducts.products = [ id: 13 ] - $httpBackend.expectPOST("/api/products/13/clone").respond 201, + $httpBackend.expectPOST("/api/v0/products/13/clone").respond 201, id: 17 - $httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, [ + $httpBackend.expectGET("/api/v0/products/17?template=bulk_show").respond 200, [ id: 17 ] BulkProducts.cloneProduct BulkProducts.products[0] @@ -30,8 +30,8 @@ describe "BulkProducts service", -> spyOn(BulkProducts, "insertProductAfter") spyOn(BulkProducts, "unpackProduct") BulkProducts.products = [originalProduct] - $httpBackend.expectPOST("/api/products/16/clone").respond 201, clonedProduct - $httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, clonedProduct + $httpBackend.expectPOST("/api/v0/products/16/clone").respond 201, clonedProduct + $httpBackend.expectGET("/api/v0/products/17?template=bulk_show").respond 200, clonedProduct BulkProducts.cloneProduct BulkProducts.products[0] $httpBackend.flush() expect(BulkProducts.unpackProduct).toHaveBeenCalledWith clonedProduct diff --git a/spec/javascripts/unit/darkswarm/services/credit_cards_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/credit_cards_spec.js.coffee index 6e614cffe6..8b421e33ec 100644 --- a/spec/javascripts/unit/darkswarm/services/credit_cards_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/credit_cards_spec.js.coffee @@ -36,7 +36,7 @@ describe 'CreditCards service', -> it "loads a success flash", -> CreditCards.setDefault(card2) - $httpBackend.expectGET('/api/customers.json').respond 200, [] + $httpBackend.expectGET('/api/v0/customers.json').respond 200, [] $httpBackend.flush() expect(RailsFlashLoader.loadFlash).toHaveBeenCalledWith({success: t('js.default_card_updated')}) diff --git a/spec/javascripts/unit/darkswarm/services/customer_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/customer_spec.js.coffee index 33a1d72cdc..a3f9a561ac 100644 --- a/spec/javascripts/unit/darkswarm/services/customer_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/customer_spec.js.coffee @@ -17,14 +17,14 @@ describe 'Customer', -> it "nests the params inside 'customer'", -> $httpBackend - .expectPUT('/api/customers/3.json', { customer: { id: 3 } }) + .expectPUT('/api/v0/customers/3.json', { customer: { id: 3 } }) .respond 200, response customer.update() $httpBackend.flush() describe "when the request succeeds", -> it "shows a success flash", -> - $httpBackend.expectPUT('/api/customers/3.json').respond 200, response + $httpBackend.expectPUT('/api/v0/customers/3.json').respond 200, response customer.update() $httpBackend.flush() expect(RailsFlashLoaderMock.loadFlash) @@ -32,7 +32,7 @@ describe 'Customer', -> describe "when the request fails", -> it "shows a error flash", -> - $httpBackend.expectPUT('/api/customers/3.json').respond 400, { error: 'Some error' } + $httpBackend.expectPUT('/api/v0/customers/3.json').respond 400, { error: 'Some error' } customer.update() $httpBackend.flush() expect(RailsFlashLoaderMock.loadFlash) diff --git a/spec/javascripts/unit/darkswarm/services/customers_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/customers_spec.js.coffee index 9680b89341..eaf788e9fe 100644 --- a/spec/javascripts/unit/darkswarm/services/customers_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/customers_spec.js.coffee @@ -16,7 +16,7 @@ describe 'Customers', -> it "asks for customers and returns @all, promises to populate via @load", -> spyOn(Customers,'load').and.callThrough() - $httpBackend.expectGET('/api/customers.json').respond 200, customerList + $httpBackend.expectGET('/api/v0/customers.json').respond 200, customerList result = Customers.index() $httpBackend.flush() expect(Customers.load).toHaveBeenCalled() diff --git a/spec/javascripts/unit/darkswarm/services/enterprise_registration_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/enterprise_registration_spec.js.coffee index 4952c3c4fc..db1c801729 100644 --- a/spec/javascripts/unit/darkswarm/services/enterprise_registration_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/enterprise_registration_spec.js.coffee @@ -32,7 +32,7 @@ describe "EnterpriseRegistrationService", -> describe "success", -> beforeEach -> spyOn(RegistrationServiceMock, "select") - $httpBackend.expectPOST("/api/enterprises?token=keykeykeykey").respond 200, 6 + $httpBackend.expectPOST("/api/v0/enterprises?token=keykeykeykey").respond 200, 6 EnterpriseRegistrationService.create() $httpBackend.flush() @@ -46,7 +46,7 @@ describe "EnterpriseRegistrationService", -> beforeEach -> spyOn(RegistrationServiceMock, "select") spyOn(window, "alert") - $httpBackend.expectPOST("/api/enterprises?token=keykeykeykey").respond 400, 6 + $httpBackend.expectPOST("/api/v0/enterprises?token=keykeykeykey").respond 400, 6 EnterpriseRegistrationService.create() $httpBackend.flush() @@ -60,7 +60,7 @@ describe "EnterpriseRegistrationService", -> beforeEach -> spyOn(RegistrationServiceMock, "select") spyOn(window, "alert") - $httpBackend.expectPOST("/api/enterprises?token=keykeykeykey").respond 400, {"error": "Invalid resource. Please fix errors and try again.", "errors": {"name": ["has already been taken. If this is your enterprise and you would like to claim ownership, please contact the current manager of this profile at owner@example.com."], "permalink": [] }} + $httpBackend.expectPOST("/api/v0/enterprises?token=keykeykeykey").respond 400, {"error": "Invalid resource. Please fix errors and try again.", "errors": {"name": ["has already been taken. If this is your enterprise and you would like to claim ownership, please contact the current manager of this profile at owner@example.com."], "permalink": [] }} EnterpriseRegistrationService.create() $httpBackend.flush() @@ -78,7 +78,7 @@ describe "EnterpriseRegistrationService", -> describe "success", -> beforeEach -> - $httpBackend.expectPUT("/api/enterprises/78?token=keykeykeykey").respond 200, 6 + $httpBackend.expectPUT("/api/v0/enterprises/78?token=keykeykeykey").respond 200, 6 EnterpriseRegistrationService.update('step') $httpBackend.flush() @@ -88,7 +88,7 @@ describe "EnterpriseRegistrationService", -> describe "failure", -> beforeEach -> spyOn(window, "alert") - $httpBackend.expectPUT("/api/enterprises/78?token=keykeykeykey").respond 400, 6 + $httpBackend.expectPUT("/api/v0/enterprises/78?token=keykeykeykey").respond 400, 6 EnterpriseRegistrationService.update('step') $httpBackend.flush() diff --git a/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee index d0114c05dd..df6446b433 100644 --- a/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee @@ -13,7 +13,7 @@ describe 'Products service', -> properties = null taxons = null GmapsGeo = {} - endpoint = "/api/order_cycles/1/products.json?distributor=1" + endpoint = "/api/v0/order_cycles/1/products.json?distributor=1" beforeEach -> product = diff --git a/spec/requests/api/orders_spec.rb b/spec/requests/api/orders_spec.rb index 50b2c677ff..556ff4a619 100644 --- a/spec/requests/api/orders_spec.rb +++ b/spec/requests/api/orders_spec.rb @@ -2,8 +2,8 @@ require 'swagger_helper' -describe 'api/orders', type: :request do - path '/api/orders' do +describe 'api/v0/orders', type: :request do + path '/api/v0/orders' do get('list orders') do tags 'Orders' # type should be replaced with swagger 3.01 valid schema: {type: string} when rswag #317 is resolved: From ef38abed285723f637a7fabbe7286bc15e26c6b0 Mon Sep 17 00:00:00 2001 From: Andy Brett Date: Sat, 6 Mar 2021 14:09:10 -0800 Subject: [PATCH 2/6] preserve GET params in url --- config/routes/api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes/api.rb b/config/routes/api.rb index 5fa9db4e97..7a314b7c0c 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -79,6 +79,6 @@ Openfoodnetwork::Application.routes.draw do end end - match '*path', to: redirect("/api/v0/%{path}"), via: :all, constraints: { path: /(?!.*v0).+/ } + match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all, constraints: { path: /(?!.*v0).+/ } end end From 0b9c62284a49541c09d59edbcfbbdd1b0a148169 Mon Sep 17 00:00:00 2001 From: Andy Brett Date: Sat, 6 Mar 2021 14:11:19 -0800 Subject: [PATCH 3/6] only match `v0` immediately following `api/` in the path --- config/routes/api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes/api.rb b/config/routes/api.rb index 7a314b7c0c..c919378aa2 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -79,6 +79,6 @@ Openfoodnetwork::Application.routes.draw do end end - match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all, constraints: { path: /(?!.*v0).+/ } + match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all, constraints: { path: /(?!v0).+/ } end end From 51d075166ae5d092392666f16e576d5e5a55943d Mon Sep 17 00:00:00 2001 From: Andy Brett Date: Sat, 6 Mar 2021 14:14:13 -0800 Subject: [PATCH 4/6] match any API version --- config/routes/api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes/api.rb b/config/routes/api.rb index c919378aa2..69f41549f2 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -79,6 +79,6 @@ Openfoodnetwork::Application.routes.draw do end end - match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all, constraints: { path: /(?!v0).+/ } + match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all, constraints: { path: /(?!v[0-9]).+/ } end end From 025f1f2725456972666ef3e2e70159e948f23d9c Mon Sep 17 00:00:00 2001 From: Andy Brett Date: Sat, 6 Mar 2021 14:42:57 -0800 Subject: [PATCH 5/6] add routing tests --- spec/requests/api/routes_spec.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 spec/requests/api/routes_spec.rb diff --git a/spec/requests/api/routes_spec.rb b/spec/requests/api/routes_spec.rb new file mode 100644 index 0000000000..fa7d1b20bc --- /dev/null +++ b/spec/requests/api/routes_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# test a single endpoint to make sure the redirects are working as intended. +require 'spec_helper' + +describe 'Orders Cycles endpoint', type: :request do + let(:distributor) { create(:distributor_enterprise) } + let(:order_cycle) { create(:order_cycle, distributors: [distributor]) } + + context "requesting the latest version" do + let(:path) { "/api/order_cycles/#{order_cycle.id}/products?distributor=#{distributor.id}" } + + it "redirects to v0, preserving URL params" do + get path + expect(response).to redirect_to( + "/api/v0/order_cycles/#{order_cycle.id}/products?distributor=#{distributor.id}" + ) + end + end + + context "requesting a specific API version" do + let(:path) { "/api/v0/order_cycles/#{order_cycle.id}/products?distributor=#{distributor.id}" } + + it "does not redirect" do + get path + expect(response.status).to eq(200) + end + end +end From d92510db5648f96dd327915dcc1290c46e346961 Mon Sep 17 00:00:00 2001 From: Andy Brett Date: Mon, 8 Mar 2021 09:40:03 -0800 Subject: [PATCH 6/6] fix some easy rubocop offenses --- .../api/v0/enterprise_attachment_controller.rb | 9 +++++++-- app/controllers/api/v0/orders_controller.rb | 3 ++- app/controllers/api/v0/product_images_controller.rb | 6 +++++- .../controllers/web/api/v0/cookies_consent_controller.rb | 2 ++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v0/enterprise_attachment_controller.rb b/app/controllers/api/v0/enterprise_attachment_controller.rb index 3a61f548b1..6e183371a1 100644 --- a/app/controllers/api/v0/enterprise_attachment_controller.rb +++ b/app/controllers/api/v0/enterprise_attachment_controller.rb @@ -6,6 +6,7 @@ module Api module V0 class EnterpriseAttachmentController < Api::V0::BaseController class MissingImplementationError < StandardError; end + class UnknownEnterpriseAuthorizationActionError < StandardError; end before_action :load_enterprise @@ -13,10 +14,14 @@ module Api respond_to :json def destroy - return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message) unless @enterprise.public_send("#{attachment_name}?") + unless @enterprise.public_send("#{attachment_name}?") + return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message) + end @enterprise.update!(attachment_name => nil) - render json: @enterprise, serializer: Admin::EnterpriseSerializer, spree_current_user: spree_current_user + render json: @enterprise, + serializer: Admin::EnterpriseSerializer, + spree_current_user: spree_current_user end protected diff --git a/app/controllers/api/v0/orders_controller.rb b/app/controllers/api/v0/orders_controller.rb index f7e363700e..48a40e13cc 100644 --- a/app/controllers/api/v0/orders_controller.rb +++ b/app/controllers/api/v0/orders_controller.rb @@ -27,7 +27,8 @@ module Api if order.ship render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok else - render json: { error: I18n.t('api.orders.failed_to_update') }, status: :unprocessable_entity + render json: { error: I18n.t('api.orders.failed_to_update') }, + status: :unprocessable_entity end end diff --git a/app/controllers/api/v0/product_images_controller.rb b/app/controllers/api/v0/product_images_controller.rb index e35adfd42c..fbceddb4fe 100644 --- a/app/controllers/api/v0/product_images_controller.rb +++ b/app/controllers/api/v0/product_images_controller.rb @@ -10,7 +10,11 @@ module Api authorize! :update, @product if @product.images.first.nil? - @image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant') + @image = Spree::Image.create( + attachment: params[:file], + viewable_id: @product.master.id, + viewable_type: 'Spree::Variant' + ) render json: @image, serializer: ImageSerializer, status: :created else @image = @product.images.first diff --git a/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb b/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb index ce163a0e16..606ad3e237 100644 --- a/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb +++ b/engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_dependency 'web/cookies_consent' module Web