From 609e552cb9bfa3bd8b1de8a17b3b0d088b1d7a4f Mon Sep 17 00:00:00 2001
From: Ilya Zverev <zverik@textual.ru>
Date: Thu, 22 Dec 2016 15:49:22 +0300
Subject: [PATCH] Update, works now

---
 lib/omniauth-mapsme.rb                  |   1 +
 lib/omniauth-mapsme/version.rb          |  10 +-
 lib/omniauth/strategies/mapsme-base.rb  |  13 +++
 lib/omniauth/strategies/mapsme-token.rb | 127 +++++++++++++++++++++++
 lib/omniauth/strategies/mapsme.rb       | 129 +++++-------------------
 omniauth-mapsme.gemspec                 |  10 +-
 6 files changed, 182 insertions(+), 108 deletions(-)
 create mode 100644 lib/omniauth/strategies/mapsme-base.rb
 create mode 100644 lib/omniauth/strategies/mapsme-token.rb

diff --git a/lib/omniauth-mapsme.rb b/lib/omniauth-mapsme.rb
index 7c46a19..e73bfb5 100644
--- a/lib/omniauth-mapsme.rb
+++ b/lib/omniauth-mapsme.rb
@@ -1,2 +1,3 @@
 require "omniauth-mapsme/version"
 require "omniauth/strategies/mapsme"
+require "omniauth/strategies/mapsme-token"
diff --git a/lib/omniauth-mapsme/version.rb b/lib/omniauth-mapsme/version.rb
index 49686db..7a7cf2e 100644
--- a/lib/omniauth-mapsme/version.rb
+++ b/lib/omniauth-mapsme/version.rb
@@ -1,5 +1,9 @@
-module Omniauth
-  module Mapsme
-    VERSION = "0.1.1"
+module OmniAuth
+  module MapsMe
+    VERSION = "1.0.0"
+  end
+
+  module MapsMeToken
+    VERSION = MapsMe::VERSION
   end
 end
diff --git a/lib/omniauth/strategies/mapsme-base.rb b/lib/omniauth/strategies/mapsme-base.rb
new file mode 100644
index 0000000..f3b5a4f
--- /dev/null
+++ b/lib/omniauth/strategies/mapsme-base.rb
@@ -0,0 +1,13 @@
+module OmniAuth
+  module Strategies
+    module MapsMeBase
+      MAPSME_BASE = 'http://yershov.passport.map6.devmail.ru'
+
+      MAPSME_CLIENT_OPTIONS = {
+        :site => MAPSME_BASE,
+        :authorize_url => "#{MAPSME_BASE}/oauth/authorize",
+        :token_url => "#{MAPSME_BASE}/oauth/token"
+      }
+    end
+  end
+end
diff --git a/lib/omniauth/strategies/mapsme-token.rb b/lib/omniauth/strategies/mapsme-token.rb
new file mode 100644
index 0000000..5a34683
--- /dev/null
+++ b/lib/omniauth/strategies/mapsme-token.rb
@@ -0,0 +1,127 @@
+require 'oauth2'
+require 'omniauth'
+require_relative 'mapsme-base'
+
+module OmniAuth
+  module Strategies
+    class MapsMeToken
+      include OmniAuth::Strategy
+      include OmniAuth::Strategies::MapsMeBase
+
+      option :name, 'mapsme_token'
+
+      args [:client_id, :client_secret]
+
+      option :client_id, nil
+      option :client_secret, nil
+
+      option :client_options, MAPSME_CLIENT_OPTIONS
+
+      option :access_token_options, {
+        :header_format => 'OAuth %s',
+        :param_name => 'access_token'
+      }
+
+      attr_accessor :access_token
+
+      uid { raw_info['uid'].to_s }
+
+      info do
+        prune!({
+          'email' => raw_info['email'],
+          'name' => raw_info['name']
+        })
+      end
+
+      extra do
+        { :raw_info => raw_info }
+      end
+
+      credentials do
+        hash = {'token' => access_token.token}
+        hash.merge!('refresh_token' => access_token.refresh_token) if access_token.expires? && access_token.refresh_token
+        hash.merge!('expires_at' => access_token.expires_at) if access_token.expires?
+        hash.merge!('expires' => access_token.expires?)
+        hash
+      end
+
+      def authorize_params
+        super.tap do |params|
+          params[:scope] = 'user mail'
+        end
+      end
+
+      def raw_info
+        @raw_info ||= access_token.get('/user').parsed || {}
+      end
+
+      def info_options
+        options[:info_fields] ? {:params => {:fields => options[:info_fields]}} : {}
+      end
+
+      def client
+        ::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
+      end
+
+      def request_phase
+        form = OmniAuth::Form.new(:title => "User Token", :url => callback_path)
+        form.text_field "Access Token", "access_token"
+        form.button "Sign In"
+        form.to_response
+      end
+
+      def callback_phase
+        if !request.params['access_token'] || request.params['access_token'].to_s.empty?
+          raise ArgumentError.new("No access token provided.")
+        end
+
+        self.access_token = build_access_token
+        self.access_token = self.access_token.refresh! if self.access_token.expired?
+
+        # Instead of calling super, duplicate the functionality, but change the provider to 'mapsme'.
+        # So the list of accounts is single for both strategies.
+        hash = auth_hash
+        hash[:provider] = "mapsme"
+        self.env['omniauth.auth'] = hash
+        call_app!
+
+       rescue ::OAuth2::Error => e
+         fail!(:invalid_credentials, e)
+       rescue ::MultiJson::DecodeError => e
+         fail!(:invalid_response, e)
+       rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
+         fail!(:timeout, e)
+       rescue ::SocketError => e
+         fail!(:failed_to_connect, e)
+      end
+
+      protected
+
+      def deep_symbolize(hash)
+        hash.inject({}) do |h, (k,v)|
+          h[k.to_sym] = v.is_a?(Hash) ? deep_symbolize(v) : v
+          h
+        end
+      end
+
+      def build_access_token
+        # Options supported by `::OAuth2::AccessToken#initialize` and not overridden by `access_token_options`
+        hash = request.params.slice("access_token", "expires_at", "expires_in", "refresh_token")
+        hash.update(options.access_token_options)
+        ::OAuth2::AccessToken.from_hash(
+          client,
+          hash
+        )
+      end
+
+      def prune!(hash)
+        hash.delete_if do |_, value|
+          prune!(value) if value.is_a?(Hash)
+          value.nil? || (value.respond_to?(:empty?) && value.empty?)
+        end
+      end
+    end
+  end
+end
+
+OmniAuth.config.add_camelization 'mapsme', 'MapsMe'
diff --git a/lib/omniauth/strategies/mapsme.rb b/lib/omniauth/strategies/mapsme.rb
index ff53666..85705df 100644
--- a/lib/omniauth/strategies/mapsme.rb
+++ b/lib/omniauth/strategies/mapsme.rb
@@ -1,129 +1,56 @@
-require 'oauth2'
-require 'omniauth'
+require 'omniauth-oauth2'
+require_relative 'mapsme-base'
 
 module OmniAuth
   module Strategies
-    class MapsMeToken
-      include OmniAuth::Strategy
+    class MapsMe < OmniAuth::Strategies::OAuth2
+      include OmniAuth::Strategies::MapsMeBase
 
-      option :name, 'mapsme_token'
+      option :name, 'mapsme'
 
-      args [:client_id, :client_secret]
+      option :client_options, MAPSME_CLIENT_OPTIONS
 
-      option :client_id, nil
-      option :client_secret, nil
-
-      option :client_options, {
-        :site => 'https://passport.maps.me',
-        :authorize_url => 'https://passport.maps.me/oauth/authorize',
-        :token_url => 'https://passport.maps.me/oauth/access_token'
-      }
-
-      option :access_token_options, {
-        :header_format => 'OAuth %s',
-        :param_name => 'access_token'
-      }
-
-      attr_accessor :access_token
-
-      uid { raw_info['id'] }
+      uid { raw_info['uid'].to_s }
 
       info do
-        prune!({
+        {
           'email' => raw_info['email'],
           'name' => raw_info['name']
-        })
+        }
       end
 
       extra do
-        hash = {}
-        hash['raw_info'] = raw_info unless skip_info?
-        prune! hash
+        { :raw_info => raw_info }
       end
 
-      credentials do
-        hash = {'token' => access_token.token}
-        hash.merge!('refresh_token' => access_token.refresh_token) if access_token.expires? && access_token.refresh_token
-        hash.merge!('expires_at' => access_token.expires_at) if access_token.expires?
-        hash.merge!('expires' => access_token.expires?)
-        hash
+      def authorize_params
+        super.tap do |params|
+          params[:scope] = 'user mail'
+        end
       end
 
       def raw_info
-        @raw_info ||= access_token.get('/user', info_options).parsed || {}
+        @raw_info ||= access_token.get('/user').parsed || {}
       end
 
-      def info_options
-        options[:info_fields] ? {:params => {:fields => options[:info_fields]}} : {}
-      end
-
-      def client
-        ::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
-      end
-
-      def request_phase
-        form = OmniAuth::Form.new(:title => "User Token", :url => callback_path)
-        form.text_field "Access Token", "access_token"
-        form.button "Sign In"
-        form.to_response
-      end
-
-      def callback_phase
-        if !request.params['access_token'] || request.params['access_token'].to_s.empty?
-          raise ArgumentError.new("No access token provided.")
-        end
-
-        self.access_token = build_access_token
-        self.access_token = self.access_token.refresh! if self.access_token.expired?
-
-        # Validate that the token belong to the application
-        app_raw = self.access_token.get('/app').parsed
-        if app_raw["id"] != options.client_id.to_s
-          raise ArgumentError.new("Access token doesn't belong to the client.")
-        end
-
-        # Instead of calling super, duplicate the functionlity, but change the provider to 'mapsme'.
-        # In case we someday publish a mapsme auth provider.
-        hash = auth_hash
-        hash[:provider] = "mapsme"
-        self.env['omniauth.auth'] = hash
-        call_app!
-
-       rescue ::OAuth2::Error => e
-         fail!(:invalid_credentials, e)
-       rescue ::MultiJson::DecodeError => e
-         fail!(:invalid_response, e)
-       rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
-         fail!(:timeout, e)
-       rescue ::SocketError => e
-         fail!(:failed_to_connect, e)
-      end
-
-      protected
-
-      def deep_symbolize(hash)
-        hash.inject({}) do |h, (k,v)|
-          h[k.to_sym] = v.is_a?(Hash) ? deep_symbolize(v) : v
-          h
-        end
-      end
+      # Fix omniauth-oauth2 issue https://github.com/intridea/omniauth-oauth2/issues/76
 
       def build_access_token
-        # Options supported by `::OAuth2::AccessToken#initialize` and not overridden by `access_token_options`
-        hash = request.params.slice("access_token", "expires_at", "expires_in", "refresh_token")
-        hash.update(options.access_token_options)
-        ::OAuth2::AccessToken.from_hash(
-          client,
-          hash
-        )
+        options.token_params.merge!(:headers => {'Authorization' => basic_auth_header })
+        super
       end
 
-      def prune!(hash)
-        hash.delete_if do |_, value|
-          prune!(value) if value.is_a?(Hash)
-          value.nil? || (value.respond_to?(:empty?) && value.empty?)
-        end
+      def basic_auth_header
+        "Basic " + Base64.strict_encode64("#{options[:client_id]}:#{options[:client_secret]}")
+      end
+
+      # Fix omniauth-oauth2 issue https://github.com/intridea/omniauth-oauth2/issues/93
+
+      def callback_url
+        full_host + script_name + callback_path
       end
     end
   end
 end
+
+OmniAuth.config.add_camelization 'mapsme', 'MapsMe'
diff --git a/omniauth-mapsme.gemspec b/omniauth-mapsme.gemspec
index b9f5509..e5e0c9a 100644
--- a/omniauth-mapsme.gemspec
+++ b/omniauth-mapsme.gemspec
@@ -5,17 +5,19 @@ require 'omniauth-mapsme/version'
 
 Gem::Specification.new do |spec|
   spec.name          = "omniauth-mapsme"
-  spec.version       = Omniauth::Mapsme::VERSION
+  spec.version       = OmniAuth::MapsMe::VERSION
   spec.authors       = ["Ilya Zverev"]
   spec.email         = ["ilya@zverev.info"]
 
   spec.summary       = %q{MAPS.ME passport strategy for OmniAuth}
-  spec.description   = %q{MAPS.ME passport strategy for OmniAuth. Uses provided access token.}
-  spec.homepage      = "http://maps.me"
+  spec.description   = %q{MAPS.ME passport strategy for OmniAuth, complete with regual and access token strategies}
+  spec.homepage      = "http://maps.me/"
   spec.license       = "MIT"
 
   spec.files         = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
   spec.require_paths = ["lib"]
 
-  spec.add_dependency "omniauth-oauth2", ">= 1.1.1"
+  spec.add_dependency "omniauth", "~> 1.2"
+  spec.add_dependency "oauth2", "~> 1.0"
+  spec.add_dependency "omniauth-oauth2", "~> 1.4"
 end