From 13e15f823e94db1c0b120fdff574ee9f6f16b65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Turbelin?= Date: Wed, 12 Aug 2020 18:30:08 +0200 Subject: [PATCH] Add Read action for Enterprise and CatalogItem --- .../dfc_provider/api/base_controller.rb | 57 +++++++++++++++++++ .../api/enterprises_controller.rb | 27 +++++++++ .../dfc_provider/api/products_controller.rb | 47 ++------------- .../dfc_provider/catalog_item_serializer.rb | 12 +++- .../dfc_provider/enterprise_serializer.rb | 20 ++++--- engines/dfc_provider/config/routes.rb | 4 +- .../dfc_provider/api/enterprises_spec.rb | 48 ++++++++++++++++ .../api/products_controller_spec.rb | 51 +++++++++++++++++ 8 files changed, 214 insertions(+), 52 deletions(-) create mode 100644 engines/dfc_provider/app/controllers/dfc_provider/api/base_controller.rb create mode 100644 engines/dfc_provider/app/controllers/dfc_provider/api/enterprises_controller.rb create mode 100644 engines/dfc_provider/spec/controllers/dfc_provider/api/enterprises_spec.rb diff --git a/engines/dfc_provider/app/controllers/dfc_provider/api/base_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/api/base_controller.rb new file mode 100644 index 0000000000..37e46a2993 --- /dev/null +++ b/engines/dfc_provider/app/controllers/dfc_provider/api/base_controller.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +# Controller used to provide the API products for the DFC application +module DfcProvider + module Api + class BaseController < ::ActionController::Base + rescue_from ActiveRecord::RecordNotFound, with: :not_found + + before_filter :check_authorization, + :check_user, + :check_enterprise + + respond_to :json + + private + + def check_authorization + return if access_token.present? + + head :unprocessable_entity + end + + def check_user + @user = authorization_control.process + + return if @user.present? + + head :unauthorized + end + + def check_enterprise + @enterprise = + if params[:enterprise_id] == 'default' + @user.enterprises.first + else + @user.enterprises.where(id: params[:enterprise_id]).first + end + + return if @enterprise.present? + + head :not_found + end + + def access_token + request.headers['Authorization'].to_s.split(' ').last + end + + def authorization_control + DfcProvider::AuthorizationControl.new(access_token) + end + + def not_found + head :not_found + end + end + end +end diff --git a/engines/dfc_provider/app/controllers/dfc_provider/api/enterprises_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/api/enterprises_controller.rb new file mode 100644 index 0000000000..63cf10f406 --- /dev/null +++ b/engines/dfc_provider/app/controllers/dfc_provider/api/enterprises_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Controller used to provide the API products for the DFC application +module DfcProvider + module Api + class EnterprisesController < BaseController + def show + render json: @enterprise, serializer: DfcProvider::EnterpriseSerializer + end + + private + + def check_enterprise + @enterprise = + if params[:id] == 'default' + @user.enterprises.first + else + @user.enterprises.where(id: params[:id]).first + end + + return if @enterprise.present? + + head :not_found + end + end + end +end diff --git a/engines/dfc_provider/app/controllers/dfc_provider/api/products_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/api/products_controller.rb index eb7a778e50..0e96881a90 100644 --- a/engines/dfc_provider/app/controllers/dfc_provider/api/products_controller.rb +++ b/engines/dfc_provider/app/controllers/dfc_provider/api/products_controller.rb @@ -3,55 +3,20 @@ # Controller used to provide the API products for the DFC application module DfcProvider module Api - class ProductsController < ::ActionController::Base + class ProductsController < BaseController # To access 'base_url' helper include Rails.application.routes.url_helpers - before_filter :check_authorization, - :check_user, - :check_enterprise - - respond_to :json - def index render json: @user, serializer: DfcProvider::PersonSerializer end - private + def show + @variant = Spree::Variant.joins(product: :supplier) + .where('enterprises.id' => @enterprise.id) + .find(params[:id]) - def check_enterprise - @enterprise = - if params[:enterprise_id] == 'default' - @user.enterprises.first - else - @user.enterprises.where(id: params[:enterprise_id]).first - end - - return if @enterprise.present? - - head :not_found - end - - def check_authorization - return if access_token.present? - - head :unprocessable_entity - end - - def check_user - @user = authorization_control.process - - return if @user.present? - - head :unauthorized - end - - def access_token - request.headers['Authorization'].to_s.split(' ').last - end - - def authorization_control - DfcProvider::AuthorizationControl.new(access_token) + render json: @variant, serializer: DfcProvider::CatalogItemSerializer end end end diff --git a/engines/dfc_provider/app/serializers/dfc_provider/catalog_item_serializer.rb b/engines/dfc_provider/app/serializers/dfc_provider/catalog_item_serializer.rb index aded6e8258..e0d8612b07 100644 --- a/engines/dfc_provider/app/serializers/dfc_provider/catalog_item_serializer.rb +++ b/engines/dfc_provider/app/serializers/dfc_provider/catalog_item_serializer.rb @@ -16,7 +16,11 @@ module DfcProvider delegate :sku, to: :object def id - "/catalog_items/#{object.id}" + dfc_provider_routes.api_dfc_provider_enterprise_product_url( + enterprise_id: object.product.supplier_id, + id: object.id, + host: root_url + ) end def type @@ -35,5 +39,11 @@ module DfcProvider def offered_through [object] end + + private + + def dfc_provider_routes + DfcProvider::Engine.routes.url_helpers + end end end diff --git a/engines/dfc_provider/app/serializers/dfc_provider/enterprise_serializer.rb b/engines/dfc_provider/app/serializers/dfc_provider/enterprise_serializer.rb index f381e9e858..9d1dd73eb4 100644 --- a/engines/dfc_provider/app/serializers/dfc_provider/enterprise_serializer.rb +++ b/engines/dfc_provider/app/serializers/dfc_provider/enterprise_serializer.rb @@ -16,7 +16,10 @@ module DfcProvider serializer: DfcProvider::CatalogItemSerializer def id - "/entreprises/#{object.id}" + dfc_provider_routes.api_dfc_provider_enterprise_url( + id: object.id, + host: root_url + ) end def type @@ -30,20 +33,21 @@ module DfcProvider end def supplies - products + object. + supplied_products. + includes(variants: :product) end def manages - products.map(&:variants).flatten + Spree::Variant. + joins(product: :supplier). + where('enterprises.id' => object.id) end private - def products - @products ||= - object. - supplied_products. - includes(variants: :product) + def dfc_provider_routes + DfcProvider::Engine.routes.url_helpers end end end diff --git a/engines/dfc_provider/config/routes.rb b/engines/dfc_provider/config/routes.rb index b88e13e768..e4d8385a4f 100644 --- a/engines/dfc_provider/config/routes.rb +++ b/engines/dfc_provider/config/routes.rb @@ -3,8 +3,8 @@ DfcProvider::Engine.routes.draw do namespace :api do scope :dfc_provider, as: :dfc_provider, path: '/dfc_provider' do - resources :enterprises, only: :none do - resources :products, only: [:index] + resources :enterprises, only: [:show] do + resources :products, only: [:index, :show] end end end diff --git a/engines/dfc_provider/spec/controllers/dfc_provider/api/enterprises_spec.rb b/engines/dfc_provider/spec/controllers/dfc_provider/api/enterprises_spec.rb new file mode 100644 index 0000000000..989bd2bb8b --- /dev/null +++ b/engines/dfc_provider/spec/controllers/dfc_provider/api/enterprises_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe DfcProvider::Api::EnterprisesController, type: :controller do + render_views + + let!(:user) { create(:user) } + let!(:enterprise) { create(:distributor_enterprise, owner: user) } + let!(:product) { create(:simple_product, supplier: enterprise ) } + + describe('.show') do + context 'with authorization token' do + before do + request.headers['Authorization'] = 'Bearer 123456.abcdef.123456' + end + + context 'with an authenticated user' do + before do + allow_any_instance_of(DfcProvider::AuthorizationControl) + .to receive(:process) + .and_return(user) + end + + context 'with an enterprise' do + context 'given with an id' do + context 'related to the user' do + before { api_get :show, id: 'default' } + + it 'is successful' do + expect(response.status).to eq 200 + end + + it 'renders the required content' do + expect(response.body) + .to include(product.name) + expect(response.body) + .to include(product.sku) + expect(response.body) + .to include("offers/#{product.variants.first.id}") + end + end + end + end + end + end + end +end diff --git a/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb b/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb index 1cc911cd09..042d2cbbe9 100644 --- a/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb +++ b/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb @@ -98,4 +98,55 @@ describe DfcProvider::Api::ProductsController, type: :controller do end end end + + describe('.show') do + context 'with authorization token' do + before do + request.headers['Authorization'] = 'Bearer 123456.abcdef.123456' + end + + context 'with an authenticated user' do + before do + allow_any_instance_of(DfcProvider::AuthorizationControl) + .to receive(:process) + .and_return(user) + end + + context 'with an enterprise' do + context 'given with an id' do + context 'related to the user' do + before do + api_get :show, + enterprise_id: enterprise.id, + id: product.variants.first.id + end + + it 'is successful' do + expect(response.status).to eq 200 + end + + it 'renders the required content' do + expect(response.body) + .to include('dfc:CatalogItem') + expect(response.body) + .to include("offers/#{product.variants.first.id}") + end + end + + context 'with a variant not linked to the enterprise' do + before do + api_get :show, + enterprise_id: enterprise.id, + id: create(:simple_product).variants.first.id + end + + it 'returns a 404 error' do + expect(response.status).to eq 404 + end + end + end + end + end + end + end end