Падрино Адми - Omniauth - Не удается получить доступ к ограниченному пространству после успешного входа в систему

В основном я работаю с PHP и ASP.NET. Недавно я связался с Руби и начал интересные отношения с Padrino. Не слишком похоже на Rails и не менее похоже на Sinatra.

Я делаю первое серьезное приложение, используя Padrino, и это не заняло много времени, и я был бы признателен за вашу помощь.

Проблема с тем, что я считаю, с Padrino Admin. Я пытаюсь заставить пользователей входить на мой веб-сайт, используя Facebook и Omniauth.

Я следовал этому руководству: Обзор Padrino и Omniauth.

Приложение размещено по адресу Heroku.

Результат: при входе Facebook учетная запись создается (в базе данных). Но когда я попадаю в запретную зону, меня перенаправляют обратно на страницу входа.

Вот что у меня есть.

app.rb

module PDeen
  class App < Padrino::Application

    register Padrino::Admin::AccessControl

    register SassInitializer
    register Padrino::Rendering
    register Padrino::Mailer
    register Padrino::Helpers

    enable :sessions

    # get '/' do 
    #   "Welcome to me @ internet"
    # end

    use OmniAuth::Builder do
      provider :facebook,  'xxxx', 'yyyy' 
      # provider :facebook, 'app_id', 'app_secret'
    end

    set :login_page, "/login" # determines the url login occurs

    access_control.roles_for :any do |role|
      role.protect "/profile"
      role.protect "/admin" # here a demo path
    end

    # now we add a role for users
    access_control.roles_for :users do |role|
      role.allow "/profile"
    end

    get :index do 
      'Hi'
    end

    get :login do
      slim :'index'
    end

    get :profile do
      content_type :text
      current_account.to_yaml
    end

    get :destroy do
      set_current_account(nil)
      redirect url(:index)
    end

    get :auth, :map => '/auth/:provider/callback' do
      auth    = request.env["omniauth.auth"]
      # account = Account.find_by_provider_and_uid(auth["provider"], auth["uid"]) || 
      #           Account.create_with_omniauth(auth)
      # 
      account = User.first( :provider => auth["provider"], :uid => auth["uid"] )

      if ! account.nil?
        set_current_account(account)  
        redirect :existing
      end

      if account.nil? 
        # Create account
        account           = User.new 
        account.uid       = auth['uid']
        account.name      = auth['name']
        account.provider  = auth['provider']
        account.email     = auth['user_info']['email'] if auth['user_info']
        account.role      = 'users'

        account.save
      end 

      set_current_account(account)
      #redirect "http://" + request.env["HTTP_HOST"] + url(:profile)
      redirect :new
    end

    get :existing do 
      'existing'
    end

    get '/session/test' do 
      session[:test] = 'This is a test'
    end

    get '/session/print' do 
      "You saved: #{session[:test]}"
    end
  end
end

User.rb

class User
  include DataMapper::Resource

  # property <name>, <type>
  property :id, Serial
  property :name, String
  property :email, String
  property :role, String
  property :uid, String
  property :provider, String

end

Что происходит >>

  1. Пункт списка
  2. Я иду на [server]/profile ~> перенаправляет на [server]/login
  3. Я нажимаю на Facebook ~> переходит на страницу, чтобы принять приложение ~> перенаправляет обратно в приложение
  4. Я иду на [server]/profile ~> перенаправляет на [server]/login

Я думал, что сеансы не работают. Когда я работал над своим первым PHP-приложением, у меня была аналогичная проблема с сеансом. Но оказалось, что это работает. Вот тут-то и появились [server]/session/test и [server]/session/print.

Когда я вхожу в Padriono console в Heroku и использую User.all, я вижу запись.

Я также вижу, что пользователь проходит аутентификацию. Что-то должно быть с `

Я проверил модальное окно Padrino admin Accounts. Я думаю, что важными параметрами будут id и role.

Я сделал что-то не так?

Заранее спасибо. Любая помощь высоко ценится.


person Ziyan Junaideen    schedule 15.09.2013    source источник
comment
Похоже, в соответствии с этот Аутентификация padrino принимает модальное имя Accont.   -  person Ziyan Junaideen    schedule 15.09.2013


Ответы (1)


Просмотрев исходный код Padrino, я заметил, что он ожидает класс Account для аутентификации Padrino Admin.

Я предполагал, что могу создать любой класс и просто использовать его. Но на данный момент я изменил модальное окно Account.rb и вместо User (см. выше) использовал Account.

Я пишу это так же, как я это решил, поэтому раздел проверки модального окна закомментирован.

class Account
  include DataMapper::Resource
  include DataMapper::Validate
  attr_accessor :password, :password_confirmation

  # Properties
  property :id,               Serial
  property :name,             String
  property :surname,          String
  property :email,            String
  property :crypted_password, String, :length => 70
  property :role,             String

  property :uid,              String
  property :display_name,     String
  property :provider,         String

  # # Validations
  # validates_presence_of      :email, :role
  # validates_presence_of      :password,                          :if => :password_required
  # validates_presence_of      :password_confirmation,             :if => :password_required
  # validates_length_of        :password, :min => 4, :max => 40,   :if => :password_required
  # validates_confirmation_of  :password,                          :if => :password_required
  # validates_length_of        :email,    :min => 3, :max => 100
  # validates_uniqueness_of    :email,    :case_sensitive => false
  # validates_format_of        :email,    :with => :email_address
  # validates_format_of        :role,     :with => /[A-Za-z]/

  # Callbacks
  before :save, :encrypt_password

  ##
  # This method is for authentication purpose
  #
  def self.authenticate(email, password)
    account = first(:conditions => ["lower(email) = lower(?)", email]) if email.present?
    account && account.has_password?(password) ? account : nil
  end

  ##
  # This method is used by AuthenticationHelper
  #
  def self.find_by_id(id)
    get(id) rescue nil
  end

  def has_password?(password)
    ::BCrypt::Password.new(crypted_password) == password
  end

  private
  def password_required
    crypted_password.blank? || password.present?
  end

  def encrypt_password
    self.crypted_password = ::BCrypt::Password.create(password) if password.present?
  end
end

Обратите внимание, что сразу после роли я добавил еще 3 поля, а именно uid, display_name и provider.

Кажется, что uid provder и role важны для контроля доступа.

controller / route такие же, за исключением одного незначительного изменения. Это название модели.

  if account.nil? 
    # Create account
    account               = Account.new 

Было бы интересно использовать собственное модальное окно с Omniauth и Padrino Admin helpers. Но на данный момент это здорово!

person Ziyan Junaideen    schedule 15.09.2013