2012-11-02 16 views
6

ho qualche convalida della password per il mio modello User, e un metodo create_with_omniauth per ottenere le informazioni dal account Facebook dell'utente:Come aggirare la convalida della password nel seguente metodo di accesso OmniAuth?

user.rb:

class User < ActiveRecord::Base 
    attr_accessible :name, :email, :password, :password_confirmation 

    has_secure_password 

    validates :name, presence: true, length: { maximum: 50 } 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, 
        format:  { with: VALID_EMAIL_REGEX }, 
        uniqueness: { case_sensitive: false } 
    validates :password, presence: true, length: { minimum: 6 } 
    validates :password_confirmation, presence: true 

    def self.create_with_omniauth(auth) 
    create! do |user| 
     user.provider = auth["provider"] 
     user.uid = auth["uid"] 
     user.name = auth["info"]["name"] 
     user.email = auth["info"]["email"] 
    end 
    end 
end 

Ora, quando clicco link_to "Sign in with Facebook, "auth/facebook" ottengo questo errore:

Validation failed: Password can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank

a causa di queste due linee nel modello User:

validates :password, presence: true, length: { minimum: 6 } 
validates :password_confirmation, presence: true 

Come ignorare tale convalida quando l'utente tenta di accedere con il metodo di accesso OmniAuth?

risposta

17

Questo può essere fatto in 2 modi.

1) Basta salvare un numero generato sicuro casuale nel campo della password (meglio perché è semplice e anche per mantenere la coerenza) personalmente ho applicato questo metodo in quanto gli utenti che hanno firmato un sito social non effettueranno l'accesso attraverso il sito accesso.

2) In alternativa, utilizzare un attr_accesor

:login_social (will be treated as boolean 
validates :password, presence: true, length: { minimum: 6 }, :if => !login_social? 
validates :password_confirmation, presence: true, :if => :login_social? 

Ogni volta che la registrazione attraverso qualsiasi sito di social basta fare questo campo vero. Ho seguito il secondo metodo, quindi ho scelto la prima soluzione perché era meglio.

Personalmente vi consiglio di andare per il primo metodo

+0

Hey, grazie per i suggerimenti! Scusa, sono un principiante di Rails. Potresti fornirmi un esempio del codice per generare la password casuale quando l'utente fa clic su Facebook? – alexchenco

+0

self.password = self.password_confirmation = SecureRandom.urlsafe_base64 (n = 6) –

+0

Grazie! Quindi dovrebbe andare nel metodo 'self.create_with_omniauth'? Non dovrebbe essere quindi 'user.password'? – alexchenco

1

La mia soluzione a questo è di aggiungere una password semplice da omniauth utenti, e l'impossibilità di accedere con le password se Rails rileva che sono gli utenti omniauth. Questo semplifica il mio modello utente in quanto posso ancora utilizzare has_secure_password e rende la password irrilevante (e impossibile da usare) se si utilizza un accesso social.

mia tabella del database utente ha le seguenti:

  • nome
  • email
  • la password
  • password_confirmation
  • uid
  • fornitore

sessions_controller.rb

def create 
    auth = request.env["omniauth.auth"] 
    if auth 
    sign_in_with_auth(auth) 
    else 
    sign_in_with_password 
    end 
end 

sessions_helper.rb

def sign_in_with_auth(auth) 
    user = User.find_by(uid: auth['uid']) 
    if user 
    #sign in the user 
    else 
    #create a user with any password. 
    user = User.create! do |user| 
     ... 
     user.password = 'bojanglesicedtea' 
     user.password_confirmation = 'bojanglesicedtea' 
     user.provider = auth['provider'] 
    end 
    #then sign in the user 
    end 
end 

def sign_in_with_password 
    user = User.find_by(email: params[:sessions][:email].downcase) 
    if user == user.authenticate(params[:sessions][:password]) && user.provider.nil? 
    #sign in the user 
    #user.provider.nil? will be true only if it is not a social login user 
    else 
    #direct to error notification 
    end 
end 
+0

solo per qualcuno che potrebbe aver bisogno di questo, se si utilizza has_secure_password e si dispone di convalide per la password, quindi è necessario fornire la password. Questo ha funzionato per me quando ho usato la gemma omniauth google oauth2. –

2

Come @Aayush suggerito di creare un campo per rilevare login sociale, allora invece di creare il proprio convalida è possibile ignorare questo metodo devise:

def password_required? 
    self.social_login? ? false : super 
end 

nel modello e.g User