mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-11 23:17:48 +00:00
Add the access token logic, light version
This commit is contained in:
12
Gemfile.lock
12
Gemfile.lock
@@ -56,16 +56,18 @@ GIT
|
||||
rails-i18n
|
||||
spree_core (>= 1.1)
|
||||
|
||||
PATH
|
||||
remote: engines/dfc_provider
|
||||
specs:
|
||||
dfc_provider (0.0.1)
|
||||
|
||||
PATH
|
||||
remote: engines/catalog
|
||||
specs:
|
||||
catalog (0.0.1)
|
||||
|
||||
PATH
|
||||
remote: engines/dfc_provider
|
||||
specs:
|
||||
dfc_provider (0.0.1)
|
||||
jwt (~> 2.2)
|
||||
rspec (~> 3.9)
|
||||
|
||||
PATH
|
||||
remote: engines/order_management
|
||||
specs:
|
||||
|
||||
@@ -3,11 +3,24 @@
|
||||
# Controller used to provide the API products for the DFC application
|
||||
module DfcProvider
|
||||
module Api
|
||||
class ProductsController < ::Api::BaseController
|
||||
skip_before_filter :authenticate_user
|
||||
before_filter :set_enterprise
|
||||
before_filter :authenticate_user
|
||||
skip_authorization_check
|
||||
class ProductsController < ::ActionController::Metal
|
||||
include ActionController::Head
|
||||
include AbstractController::Rendering
|
||||
include ActionController::Rendering
|
||||
include ActionController::Renderers::All
|
||||
include ActionController::MimeResponds
|
||||
include ActionController::ImplicitRender
|
||||
include AbstractController::Callbacks
|
||||
# To access 'base_url' helper
|
||||
include ActionController::UrlFor
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
before_filter :check_authorization,
|
||||
:check_enterprise,
|
||||
:check_user,
|
||||
:check_accessibility
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
products = @enterprise.
|
||||
@@ -23,17 +36,45 @@ module DfcProvider
|
||||
|
||||
private
|
||||
|
||||
def authenticate_user
|
||||
@current_api_user = @enterprise.owner
|
||||
def check_enterprise
|
||||
@enterprise = ::Enterprise.where(id: params[:enterprise_id]).first
|
||||
|
||||
return if @enterprise.present?
|
||||
|
||||
head :not_found
|
||||
end
|
||||
|
||||
def set_enterprise
|
||||
@enterprise = ::Enterprise.find(params[:enterprise_id])
|
||||
def check_authorization
|
||||
return if access_token.present?
|
||||
|
||||
head :unauthorized
|
||||
end
|
||||
|
||||
def check_user
|
||||
@user = authorization_control.process
|
||||
|
||||
return if @user.present?
|
||||
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
||||
def check_accessibility
|
||||
return if @enterprise.owner == @user
|
||||
|
||||
head :forbidden
|
||||
end
|
||||
|
||||
def base_url
|
||||
"#{root_url}api/dfc_provider"
|
||||
end
|
||||
|
||||
def access_token
|
||||
request.headers['Authorization'].to_s.split(' ').last
|
||||
end
|
||||
|
||||
def authorization_control
|
||||
DfcProvider::AuthorizationControl.new(access_token)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Service used to authorize the user on DCF Provider API
|
||||
# It controls an OICD Access token and an enterprise.
|
||||
module DfcProvider
|
||||
class AuthorizationControl
|
||||
def initialize(access_token)
|
||||
@access_token = access_token
|
||||
end
|
||||
|
||||
def process
|
||||
decode_token
|
||||
find_ofn_user
|
||||
end
|
||||
|
||||
def decode_token
|
||||
data = JWT.decode(
|
||||
@access_token,
|
||||
nil,
|
||||
false
|
||||
)
|
||||
|
||||
@header = data.last
|
||||
@payload = data.first
|
||||
end
|
||||
|
||||
def find_ofn_user
|
||||
Spree::User.where(email: @payload['email']).first
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,13 +6,17 @@ $LOAD_PATH.push File.expand_path('lib', __dir__)
|
||||
require "dfc_provider/version"
|
||||
|
||||
# Describe your gem and declare its dependencies:
|
||||
Gem::Specification.new do |s|
|
||||
s.name = 'dfc_provider'
|
||||
s.version = DfcProvider::VERSION
|
||||
s.authors = ['Admin OFF']
|
||||
s.email = ['admin@openfoodfrance.org']
|
||||
s.summary = 'Provides an API stack implementing DFC semantic specifications'
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = 'dfc_provider'
|
||||
spec.version = DfcProvider::VERSION
|
||||
spec.authors = ['Admin OFF']
|
||||
spec.email = ['admin@openfoodfrance.org']
|
||||
spec.summary = 'Provides an API stack implementing DFC semantic ' \
|
||||
'specifications'
|
||||
|
||||
s.files = Dir["{app,config,db,lib}/**/*"] + ['README.rdoc']
|
||||
s.test_files = Dir['test/**/*']
|
||||
spec.files = Dir["{app,config,lib}/**/*"] + ['README.md']
|
||||
spec.test_files = Dir['spec/**/*']
|
||||
|
||||
spec.add_dependency 'jwt', '~> 2.2'
|
||||
spec.add_dependency 'rspec', '~> 3.9'
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe DfcProvider::Api::ProductsController, type: :controller do
|
||||
@@ -13,22 +15,82 @@ describe DfcProvider::Api::ProductsController, type: :controller do
|
||||
variant: product.variants.first,
|
||||
visible: true)
|
||||
end
|
||||
let(:user) { enterprise.owner }
|
||||
|
||||
describe('.index') do
|
||||
before do
|
||||
allow(controller)
|
||||
.to receive(:spree_current_user) { enterprise.owner }
|
||||
context 'with authorization token' do
|
||||
before do
|
||||
request.env['Authorization'] = 'Bearer 123456.abcdef.123456'
|
||||
end
|
||||
|
||||
get :index, enterprise_id: enterprise.id
|
||||
context 'with an enterprise' do
|
||||
context 'with a linked user' do
|
||||
before do
|
||||
allow_any_instance_of(DfcProvider::AuthorizationControl)
|
||||
.to receive(:process)
|
||||
.and_return(user)
|
||||
end
|
||||
|
||||
context 'with valid accessibility' do
|
||||
before do
|
||||
get :index, enterprise_id: enterprise.id
|
||||
end
|
||||
|
||||
it 'is successful' do
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
|
||||
it 'renders the related product' do
|
||||
expect(response.body)
|
||||
.to include("\"DFC:description\":\"#{product.variants.first.name}\"")
|
||||
end
|
||||
end
|
||||
|
||||
context 'without valid accessibility' do
|
||||
before do
|
||||
get :index, enterprise_id: create(:enterprise).id
|
||||
end
|
||||
|
||||
it 'returns unauthorized head' do
|
||||
expect(response.status).to eq 403
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a linked user' do
|
||||
before do
|
||||
allow_any_instance_of(DfcProvider::AuthorizationControl)
|
||||
.to receive(:process)
|
||||
.and_return(nil)
|
||||
end
|
||||
|
||||
before do
|
||||
get :index, enterprise_id: enterprise.id
|
||||
end
|
||||
|
||||
it 'returns unprocessable_entity head' do
|
||||
expect(response.status).to eq 422
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a recorded enterprise' do
|
||||
before do
|
||||
get :index, enterprise_id: '123456'
|
||||
end
|
||||
|
||||
it 'returns not_found head' do
|
||||
expect(response.status).to eq 404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'is successful' do
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
context 'without an authorization token' do
|
||||
before { get :index, enterprise_id: enterprise.id }
|
||||
|
||||
it 'renders the related product' do
|
||||
expect(response.body)
|
||||
.to include("\"DFC:description\":\"#{product.variants.first.name}\"")
|
||||
it 'returns unauthorized head' do
|
||||
expect(response.status).to eq 401
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "../../spec/spec_helper.rb"
|
||||
|
||||
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
||||
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f }
|
||||
|
||||
Reference in New Issue
Block a user