8

Mi chiedo se c'è un modo di chiamare la 'password dimenticata' procedura senza forzare il mio utente di effettuare il logoutDevise Hai dimenticato per clienti registrati

Il caso che sto funzionando in è: 1. un utente accede con facebook, viene generata una password falsa per loro 2. l'utente desidera quindi modificare la propria email/nome/password, o semplicemente utilizzare login non facebook

poiché devise richiede una password per modificare questi campi, come dovrebbe, l'utente non è in grado di modificarli

Avevo pensato solo a non forzare la password da impostare ma non ha senso di sicurezza, quindi invece visualizzo i campi come testo e informo l'utente di seguire la procedura "password dimenticata" per impostare una password e quindi possono modificare i campi

il problema allora è che non posso semplicemente un collegamento a questo dal profilo utente dal concepire dirà l'utente che non possono fare questo mentre già loggato.

Così, c'è un modo di sovrascrivendo la password dimenticata o/users/password/edit metodo in modo che un utente connesso possa eseguire anche questa azione?

risposta

2

La mia soluzione completa qui, perché ho anche appreso che l'utente dovrebbe disconnettersi dopo aver fatto clic sul collegamento nell'e-mail, era aggiungere alcune azioni UserController aggiuntive per modificare effettivamente la password e salvarla. Questa non è una soluzione ideale e il freddo probabilmente si fa in un modo migliore ma funziona per me.

controllore utenti; aggiunto metodi per eseguire il reset

before_filter :authenticate_user!, :except => [:do_reset_password, :reset_password_edit] 

    def reset_password 
     id = params[:id] 
     if id.nil? 
      id = current_user.id 
     end  
     if (!user_signed_in? || current_user.id.to_s != id.to_s) 
     flash[:alert] = "You don't have that right." 
      redirect_to '/home' 
      return 
     end 

     @user = User.find(id) 
     @user.send_reset_password_instructions 

     respond_to do |format| 
      format.html { redirect_to '/users/edit', notice: 'You will receive an email with instructions about how to reset your password in a few minutes.' } 
     end 
    end 


    def do_reset_password 
     id = params[:id] 
     if id.nil? && !current_user.nil? 
      id = current_user.id 
     end 

     if id.nil? 
      @user = User.where(:reset_password_token => params[:user][:reset_password_token]).first 
     else 
      @user = User.find(id) 
     end 
     if @user.nil? || @user.reset_password_token.to_s != params[:user][:reset_password_token] 
      flash[:alert] = "Url to reset was incorrect, please resend reset email." 
      redirect_to '/home' 
      return 
     end 

     # there may be a better way of doing this, devise should be able to give us these messages 
     if params[:user][:password] != params[:user][:password_confirmation] 
      flash[:alert] = "Passwords must match." 
       redirect_to :back 
       return 
     end 
     if @user.reset_password!(params[:user][:password],params[:user][:password_confirmation]) 
      @user.hasSetPassword = true 
      @user.save 
      respond_to do |format| 
       format.html { redirect_to '/home', notice: 'Your password has been changed.' } 
      end 
     else 
      flash[:alert] = "Invalid password, must be at least 6 charactors." 
       redirect_to :back 
     end 
    end 

    def reset_password_edit 
     @user = User.where(:reset_password_token => params[:reset_password_token]).first 
     if @user.nil? || [email protected]_password_period_valid? 
      flash[:alert] = "Password reset period expired, please resend reset email" 
      redirect_to "/home" 
      return 
     end 
    end 

visualizzazioni/dispositivo/registrazioni/modifica; cambiato la vista di non lasciare che i campi di modifica utente che richiedono una password

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> 
     <%= devise_error_messages! %> 

     <% if !resource.hasSetPassword %>           
      <%= f.label :name %><br /> 
      <p style="line-height:24px;"><b><%= @user.name %></b></p>    
      <div><%= f.label :email %><br /> 
       <p style="line-height:24px;"><b><%= @user.email %> </b></p> 
       <p style="position:relative; left:150px; width:420px;"> 
       <i>you cannot change any settings because you have not set a password <br />yet, you can do so by following the </i> 
       <%= link_to "Forgot your password", "https://stackoverflow.com/users/reset_password" %> <i> procedure</i> 
       </p> 
      </div> 
     <% else %>      
      <p><%= f.label :name %><br /> 
      <%= f.text_field :name %></p>   
      <div><%= f.label :email %><br /> 
      <%= f.email_field :email %></div> 

      <div><%= f.label :password %> <br /> 
      <%= f.password_field :password %><i>(leave blank if you don't want to change it)</i></div> 

      <div><%= f.label :password_confirmation %><br /> 
      <%= f.password_field :password_confirmation %></div> 

      <div><%= f.label :current_password %> <br /> 
      <%= f.password_field :current_password %> 
      <i>(we need your current password to confirm your changes)</i> 
      </div> 
     <div><%= f.submit "Update" %></div> 
     <% end %> 
    <% end %> 

views/escogitare/mailer/reset_password_instructions; ha dovuto cambiare per indicare l'URL proprio nel nostro nuovo caso

<p>Hello <%= @resource.email %>!</p> 

    <p>Someone has requested a link to change your password, and you can do this through the link below.</p> 

    <% if [email protected] %> 
     <p><%= link_to 'Change my password', 'http://streetsbehind.me/users/reset_password_edit?reset_password_token='[email protected]_password_token %></p> 
    <!-- todo: there's probably a better way of doing this than just hardcoding streetsbehind.me --> 
    <% else %> 
     <p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %></p> 
    <% end %> 
    <p>If you didn't request this, please ignore this email.</p> 
    <p>Your password won't change until you access the link above and create a new one.</p> 

viste/utenti/reset_password_edit.erb

<%= form_for(@user, :url => url_for(:action => :do_reset_password) , :html => { :method => :post }) do |f| %> 

    <%= f.hidden_field :reset_password_token %> 

    <div><%= f.label :password, "New password" %><br /> 
    <%= f.password_field :password %></div> 

    <div><%= f.label :password_confirmation, "Confirm new password" %><br /> 
    <%= f.password_field :password_confirmation %></div> 

    <div><%= f.submit "Change my password" %></div> 
<% end %> 

config/routes.rb

get "users/reset_password" 
get "users/reset_password_edit" 

resource :users do 
    post 'do_reset_password' 
end 
4

È possibile utilizzare lo @user.send_reset_password_instructions per generare il token di reimpostazione della password e inviare l'e-mail. Se si chiama direttamente il mailer, non verrà generato un token di reimpostazione della password per autenticare il ripristino.

+0

che ha funzionato molto meglio. – fiestacasey

15

La ragione per cui non è possibile reimpostare la password perché il dispositivo tenta di autenticare l'utente con la sessione corrente e, in caso di esito positivo, viene automaticamente reindirizzato a qualunque percorso si debba raggiungere. Quello di cui hai bisogno è sovrascrivere la modifica e aggiornare l'azione del controller delle password per saltare questo passaggio.

Ecco il codice. Nel controller delle tue password aggiungi i seguenti codici (puoi chiedere a devise di generare i controller per te, oppure puoi semplicemente creare il seguente controller). L'override per l'aggiornamento è necessario perché altrimenti un utente che ha effettuato l'accesso verrà automaticamente cancellato dopo la reimpostazione della password.(O se si vuole che sia così si può sbarazzarsi del l'override #update)

class PasswordsController < Devise::PasswordsController 
    # here we need to skip the automatic authentication based on current session for the following two actions 
    # edit: shows the reset password form. need to skip, otherwise it will go directly to root 
    # update: updates the password, need to skip otherwise it won't even reset if already logged in 
    skip_before_filter :require_no_authentication, :only => [:edit, :update] 

    # we need to override the update, too. 
    # After a password is reset, all outstanding sessions are gone. 
    # When already logged in, sign_in is a no op, so the session will expire, too. 
    # The solution is to logout and then re-login which will make the session right. 
    def update 
    super 
    if resource.errors.empty? 
     sign_out(resource_name) 
     sign_in(resource_name, resource) 
    end 
    end 
end 

I percorsi sono come la seguente

# config/routes.rb 
devise_for :users, :controllers => {:passwords => 'passwords'} 
Problemi correlati