Files
openfoodnetwork/app/controllers/api/v1/base_controller.rb
2022-03-28 10:55:57 +11:00

115 lines
3.3 KiB
Ruby

# frozen_string_literal: true
module Api
module V1
class BaseController < ActionController::API
include CanCan::ControllerAdditions
include RequestTimeouts
include Pagy::Backend
include JsonApiPagination
include RaisingParameters
check_authorization
attr_accessor :current_api_user
before_action :authenticate_user
rescue_from StandardError, with: :error_during_processing
rescue_from CanCan::AccessDenied, with: :unauthorized
rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from Pagy::VariableError, with: :invalid_pagination
rescue_from ActionController::ParameterMissing, with: :missing_parameter
rescue_from ActionController::UnpermittedParameters, with: :unpermitted_parameters
private
def authenticate_user
return if (@current_api_user = request.env['warden'].user)
if api_key.blank?
# An anonymous user
@current_api_user = Spree::User.new
return
end
return if (@current_api_user = Spree::User.find_by(spree_api_key: api_key.to_s))
invalid_api_key
end
def current_ability
Spree::Ability.new(current_api_user)
end
def api_key
request.headers["X-Api-Token"] || params[:token]
end
def error_during_processing(exception)
Bugsnag.notify(exception)
if Rails.env.development? || Rails.env.test?
render status: :unprocessable_entity,
json: json_api_error(exception.message, meta: exception.backtrace)
else
render status: :unprocessable_entity,
json: json_api_error(I18n.t(:unknown_error, scope: "api"))
end
end
def invalid_pagination(exception)
render status: :unprocessable_entity,
json: json_api_error(exception.message)
end
def missing_parameter(error)
message = I18n.t(:missing_parameter, param: error.param, scope: :api)
render status: :unprocessable_entity,
json: json_api_error(message)
end
def unpermitted_parameters(error)
message = I18n.t(:unpermitted_parameters, params: error.params.join(", "), scope: :api)
render status: :unprocessable_entity,
json: json_api_error(message)
end
def invalid_resource!(resource = nil)
render status: :unprocessable_entity,
json: json_api_invalid(
I18n.t(:invalid_resource, scope: "api"),
resource&.errors
)
end
def invalid_api_key
render status: :unauthorized,
json: json_api_error(I18n.t(:invalid_api_key, key: api_key, scope: "api"))
end
def unauthorized
render status: :unauthorized,
json: json_api_error(I18n.t(:unauthorized, scope: "api"))
end
def not_found
render status: :not_found,
json: json_api_error(I18n.t(:resource_not_found, scope: "api"))
end
def json_api_error(message, **options)
{ errors: [{ detail: message }] }.merge(options)
end
def json_api_invalid(message, errors)
error_response = { errors: [{ detail: message }] }
error_response.merge!(meta: { validation_errors: errors.to_a }) if errors.any?
error_response
end
end
end
end