diff --git a/app/decorators/controllers/solidus_jwt/spree/api/base_controller_decorator.rb b/app/decorators/controllers/solidus_jwt/spree/api/base_controller_decorator.rb new file mode 100644 index 0000000..2e2365b --- /dev/null +++ b/app/decorators/controllers/solidus_jwt/spree/api/base_controller_decorator.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module SolidusJwt + module Spree + module Api + module BaseControllerDecorator + def self.prepended(base) + base.rescue_from JWT::DecodeError do + render "spree/api/errors/invalid_api_key", status: :unauthorized + end + end + + ## + # Overrides Solidus + # @see https://github.com/solidusio/solidus/blob/master/api/app/controllers/spree/api/base_controller.rb + # + def load_user + return super if json_web_token.blank? + + # rubocop:disable Naming/MemoizedInstanceVariableName + @current_api_user ||= ::Spree.user_class.for_jwt(json_web_token['sub'] || json_web_token['id']) + # rubocop:enable Naming/MemoizedInstanceVariableName + end + + def json_web_token + @json_web_token ||= SolidusJwt.decode(api_key).first + rescue JWT::DecodeError + # Allow spree to try and authenticate if we still allow it. Otherwise + # raise an error + return if SolidusJwt::Config.allow_spree_api_key + + raise + end + + if SolidusSupport.api_available? + ::Spree::Api::BaseController.prepend self + end + end + end + end +end diff --git a/app/decorators/models/solidus_jwt/spree/user_decorator.rb b/app/decorators/models/solidus_jwt/spree/user_decorator.rb new file mode 100644 index 0000000..4575c30 --- /dev/null +++ b/app/decorators/models/solidus_jwt/spree/user_decorator.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module SolidusJwt + module Spree + module UserDecorator + def self.prepended(base) + base.extend ClassMethods + base.has_many :auth_tokens, class_name: 'SolidusJwt::Token' + end + + module ClassMethods + ## + # Find user based on subject claim in + # our json web token + # @see https://tools.ietf.org/html/rfc7519#section-4.1.2 + # + # @example get user token + # payload = SolidusJwt.decode(token).first + # user = Spree::User.for_jwt(payload['sub']) + # + # @param sub [string] The subject claim of jwt + # @return [Spree.user_class, NilClass] If a match is found, returns the user, + # otherwise, returns nil + # + def for_jwt(sub) + find_by(id: sub) + end + end + + ## + # Generate a json web token + # @see https://github.com/jwt/ruby-jwt + # @return [String] + # + def generate_jwt(expires_in: nil) + SolidusJwt.encode(payload: as_jwt_payload, expires_in: expires_in) + end + alias generate_jwt_token generate_jwt + + ## + # Serializes user attributes to hash and applies + # the sub jwt claim. + # + # @return [Hash] The payload for json web token + # + def as_jwt_payload + options = SolidusJwt::Config.jwt_options + claims = { sub: id } + + as_json(options) + .merge(claims) + .as_json + end + + ::Spree.user_class.prepend self + end + end +end diff --git a/app/decorators/solidus_jwt/spree/api/base_controller_decorator.rb b/app/decorators/solidus_jwt/spree/api/base_controller_decorator.rb deleted file mode 100644 index da2151e..0000000 --- a/app/decorators/solidus_jwt/spree/api/base_controller_decorator.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -module Spree - module Api - module BaseControllerDecorator - def self.prepended(base) - base.rescue_from JWT::DecodeError do - render "spree/api/errors/invalid_api_key", status: :unauthorized - end - end - - ## - # Overrides Solidus - # @see https://github.com/solidusio/solidus/blob/master/api/app/controllers/spree/api/base_controller.rb - # - def load_user - return super if json_web_token.blank? - - # rubocop:disable Naming/MemoizedInstanceVariableName - @current_api_user ||= ::Spree.user_class.for_jwt(json_web_token['sub'] || json_web_token['id']) - # rubocop:enable Naming/MemoizedInstanceVariableName - end - - def json_web_token - @json_web_token ||= SolidusJwt.decode(api_key).first - rescue JWT::DecodeError - # Allow spree to try and authenticate if we still allow it. Otherwise - # raise an error - return if SolidusJwt::Config.allow_spree_api_key - - raise - end - - if SolidusSupport.api_available? - ::Spree::Api::BaseController.prepend self - end - end - end -end diff --git a/app/decorators/solidus_jwt/spree/user_decorator.rb b/app/decorators/solidus_jwt/spree/user_decorator.rb deleted file mode 100644 index 6951fad..0000000 --- a/app/decorators/solidus_jwt/spree/user_decorator.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -module Spree - module UserDecorator - def self.prepended(base) - base.extend ClassMethods - base.has_many :auth_tokens, class_name: 'SolidusJwt::Token' - end - - module ClassMethods - ## - # Find user based on subject claim in - # our json web token - # @see https://tools.ietf.org/html/rfc7519#section-4.1.2 - # - # @example get user token - # payload = SolidusJwt.decode(token).first - # user = Spree::User.for_jwt(payload['sub']) - # - # @param sub [string] The subject claim of jwt - # @return [Spree.user_class, NilClass] If a match is found, returns the user, - # otherwise, returns nil - # - def for_jwt(sub) - find_by(id: sub) - end - end - - ## - # Generate a json web token - # @see https://github.com/jwt/ruby-jwt - # @return [String] - # - def generate_jwt(expires_in: nil) - SolidusJwt.encode(payload: as_jwt_payload, expires_in: expires_in) - end - alias generate_jwt_token generate_jwt - - ## - # Serializes user attributes to hash and applies - # the sub jwt claim. - # - # @return [Hash] The payload for json web token - # - def as_jwt_payload - options = SolidusJwt::Config.jwt_options - claims = { sub: id } - - as_json(options) - .merge(claims) - .as_json - end - - ::Spree.user_class.prepend self - end -end diff --git a/app/controllers/spree/api/oauths_controller.rb b/lib/controllers/api/spree/api/oauths_controller.rb similarity index 100% rename from app/controllers/spree/api/oauths_controller.rb rename to lib/controllers/api/spree/api/oauths_controller.rb