8

Me pregunto si hay una forma de llamar al procedimiento 'se olvidó la contraseña' sin forzar mi usuario para cerrar la sesiónDiseñar olvidado la contraseña para el usuario conectado

El caso estoy corriendo en es: 1. un usuario inicia sesión con Facebook, se genera una contraseña falsa para ellos 2. el usuario quiere cambiar su correo electrónico/nombre/contraseña, o simplemente usa el inicio de sesión no facebook

ya que se requiere una contraseña para cambiar estos campos, como debería, el usuario no puede modificarlos

Pensé en simplemente no forc la contraseña que se debe configurar, pero eso no tiene sentido en cuanto a seguridad, así que simplemente visualizo los campos como texto y notifico al usuario que siga el procedimiento de 'contraseña olvidada' para establecer una contraseña y luego pueden cambiar los campos

la cuestión entonces es que no puedo simplemente enlazar a esto desde el perfil de usuario desde el legado le indicará al usuario que no pueden hacer esto mientras que ya se haya identificado.

entonces, ¿hay una manera de anular la contraseña olvidó o/users/password/edit method para que un usuario conectado pueda realizar esta acción también?

Respuesta

2

Mi solución completa aquí, porque también me enteré de que el usuario tendría que desconectarse después de hacer clic en el enlace del correo electrónico, fue agregar algunas acciones UserController adicionales para editar la contraseña y guardarla. Esta no es una solución ideal y es probable que se haga frío de una mejor manera, pero a mí me funciona.

usuario controlador; métodos agregados para hacer el restablecimiento

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 

vistas/idear/registros/editar; cambiado el fin de no dejar que los campos de edición del usuario que requieren una contraseña

<%= 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/idear/bolsas/reset_password_instructions; tenido que cambiar para que apunte a la URL correcta en nuestro nuevo 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> 

vistas/usuarios/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

Puede usar el @user.send_reset_password_instructions para generar el token de restablecimiento de contraseña y enviar el correo electrónico. Si solo llama directamente al remitente, no se generará un token de restablecimiento de contraseña para autenticar el reinicio.

+0

Eso funcionó mucho mejor. – fiestacasey

15

La razón por la que no se puede restablecer la contraseña porque el dispositivo intenta autenticar al usuario con la sesión actual y, cuando se realiza correctamente, se le redirige automáticamente a la ruta a la que se debe dirigir. Lo que necesita es anular la acción de edición y actualización del controlador de contraseñas para que omita este paso.

Aquí está el código. En su controlador de contraseñas, agregue los siguientes códigos (puede pedirle que cree los controladores para usted, o simplemente puede crear el siguiente controlador). La anulación de la actualización es necesaria porque, de lo contrario, un usuario conectado se desconectará automáticamente después de su contraseña de reinicio.(O si quieres que sea así que usted puede deshacerse de la anulación #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 

Las rutas son como los siguientes

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