Переключение между веб-интерфейсом и сенсорным интерфейсом при входе в Facebook с использованием Omniauth и Rails 3 - PullRequest
7 голосов
/ 01 апреля 2011

Ситуация:

Используя Rails 3 и OmniAuth, у меня есть приложение, которое аутентифицируется с помощью стратегии Facebook.Это приложение было разработано так, чтобы одинаково хорошо работать с веб-интерфейсами и мобильными интерфейсами (ala Jquery-Mobile).

Задача состоит в том, чтобы заставить OmniAuth предоставлять мобильную версию экрана входа Facebook для мобильных устройств и веб-версиюна настольные устройства.

Я собрал решение, которое я поставлю в качестве ответа.

Ответы [ 5 ]

5 голосов
/ 19 мая 2011

На самом деле, поскольку OmniAuth :: Strategies уже являются промежуточным программным обеспечением Rack, это еще проще. Просто переопределите метод request_phase и проверьте переменную экземпляра @env, присутствующую в стратегии для мобильного user_agent:

module OmniAuth
  module Strategies
    class Facebook < OAuth2

      MOBILE_USER_AGENTS =  'webos|ipod|iphone|mobile'

      def request_phase
        options[:scope] ||= "email,offline_access"
        options[:display] = mobile_request? ? 'touch' : 'page'
        super
      end

      def mobile_request?
        ua = Rack::Request.new(@env).user_agent.to_s
        ua.downcase =~ Regexp.new(MOBILE_USER_AGENTS)
      end

    end
  end
end
4 голосов
/ 30 мая 2012

Для современного devise / omniauth (> = 1.0) используйте это в вашем config / initializers / devise.rb:

FACEBOOK_SETUP_PROC = lambda do |env|
  request = Rack::Request.new(env)
  mobile_device = request.user_agent =~ /Mobile|webOS/i
  request.env['omniauth.strategy'].options[:display] = mobile_device ? "touch" : "page"
end

config.omniauth :facebook, FACEBOOK_APP_ID, FACEBOOK_APP_SECRET,
  :scope => 'email,offline_access', :setup => FACEBOOK_SETUP_PROC,
  :client_options => { :ssl => { :ca_file => Rails.root.join("config/ca-bundle.crt").to_s }}
1 голос
/ 11 ноября 2011

Утвержденный ответ работает, кроме меня пришлось поменять одну строку. Для текущей версии omniauth-facebook мне пришлось установить опцию отображения, например:

options[:authorize_params] = mobile_request? ? { :display => 'touch' } : { :display => 'page' }

Вы можете использовать «всплывающее окно», «сенсорный» или «страницу» из того, что я нашел.

1 голос
/ 14 августа 2011

Я попробовал первое решение, но не смог заставить его работать. После долгих поисков я обнаружил, что в Omniauth есть опция ": setup => true", которая позволяет динамически устанавливать аргументы, такие как опция: display, необходимая для Facebook OAuth.

Сначала включите опцию: setup.

config.omniauth :facebook, APP_CONFIG["fb_app_id"], APP_CONFIG["fb_app_secret"], 
    {:scope => 'email, offline_access', :setup => true}

Затем добавьте второй маршрут (настройка маршрута):

  devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
    get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
    get '/users/auth/:provider/setup' => 'users/omniauth_callbacks#setup'
  end

Добавьте этот контроллер. Возможно, он у вас уже есть, если вы следовали руководству по разработке.

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def setup
    request.env['omniauth.strategy'].options[:display] = mobile_device? ? "touch" : "page"
    render :text => "Setup complete.", :status => 404
  end
end

Добавьте этот метод в свой ApplicationController:

def mobile_device?
  if session[:mobile_param]
    session[:mobile_param] == "1"
  else
    request.user_agent =~ /Mobile|webOS/        
  end
end

Готово!

0 голосов
/ 01 апреля 2011

Мое решение довольно сложное и требует как изменения стратегии OmniAuth Facebook, так и добавления промежуточного программного обеспечения Rack.

Сначала я добавил атрибут класса и изменил метод в OmniAuth :: Strategies :: Facebook (я поставил этов конце моего файла конфигурации omniauth.rb, но он находится в каталоге lib):

module OmniAuth
  module Strategies
    class Facebook < OAuth2
      cattr_accessor :display # new

      def request_phase
        options[:scope] ||= "email,offline_access"
        options[:display] = OmniAuth::Strategies::Facebook.display || nil # new
        super
      end
    end
  end
end

Во-вторых, я добавил часть промежуточного ПО Rack, чтобы определить, был ли запрос с мобильного устройства, а затемустановите соответствующий дисплей:

module Rack
  class FacebookMobileOmniauth
    def initialize(app)
      @app = app
    end

    MOBILE_USER_AGENTS =  'palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|' +
                              'audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|' +
                              'x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|' +
                              'pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|' +
                              'webos|amoi|novarra|cdm|alcatel|pocket|ipad|iphone|mobileexplorer|' +
                              'mobile'

    def call(env)
      request = Request.new(env)
      if request.user_agent.to_s.downcase =~ Regexp.new(MOBILE_USER_AGENTS)
        OmniAuth::Strategies::Facebook.display = 'touch'
      else
        OmniAuth::Strategies::Facebook.display = nil
      end   
      return @app.call(env)
    end
  end
end

И, наконец, я добавил промежуточное программное обеспечение Rack в свой config.ru:

    require ::File.expand_path('../config/environment',  __FILE__)
    use Rack::FacebookMobileOmniauth # new
    run Mystupid::Application
...