web-dev-qa-db-fra.com

Comment supprimer l'itinéraire Devise pour s'inscrire?

J'utilise Devise dans une application Rails 3, mais dans ce cas, un utilisateur doit être créé par un utilisateur existant, qui détermine les autorisations dont il disposera.

Pour cette raison, je veux:

  • Pour supprimer l'itinéraire pour permettre aux utilisateurs de s'inscrire
  • Pour autorise toujours les utilisateurs à modifier leur profil (changement d'adresse e-mail et de mot de passe) après ils se sont inscrits

Comment puis-je faire ceci?

Actuellement, je supprime effectivement cette route en plaçant les éléments suivants avant devise_for :users:

match 'users/sign_up' => redirect('/404.html')

Cela fonctionne, mais j'imagine qu'il existe un meilleur moyen, non?

Mettre à jour

Comme Benoît Garret l’a dit, la meilleure solution dans mon cas est de ne pas créer en masse les itinéraires d’enregistrement et de créer ceux que je veux réellement. 

Pour ce faire, j'ai d'abord exécuté rake routes, puis utilisé la sortie pour recréer celles que je voulais. Le résultat final était ceci:

devise_for :users, :skip => [:registrations] 
as :user do
  get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
  put 'users' => 'devise/registrations#update', :as => 'user_registration'
end

Notez que:

  • J'ai toujours :registerable dans mon modèle User
  • devise/registrations gère la mise à jour de l'email et du mot de passe
  • La mise à jour d'autres attributs d'utilisateur - autorisations, etc. - est gérée par un autre contrôleur.

Réponse actuelle:

Supprimez la route pour les chemins par défaut Devise; c'est à dire.:

devise_for :users, path_names: {
  sign_up: ''
}
144
Nathan Long

J'ai essayé de faire cela aussi, mais un fil sur le groupe Google Google m'a dissuadé de chercher une solution vraiment propre.

Je citerai José Valim (le responsable de Devise):

Il n'y a pas d'option directe. Vous pouvez soit fournir un patch ou utilisez: skip =>: enregistrable et ajoutez uniquement les itinéraires souhaités.

La question initiale était:

Existe-t-il un bon moyen de supprimer une route spécifique (la route de suppression) de Rails?

52
Benoit Garret

vous pouvez le faire dans votre modèle

# typical devise setup in User.rb
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

changez le en:

devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable

remarquez que le symbole :registerable a été supprimé

C'est ça, rien d'autre n'est requis. Tous les itinéraires et les liens vers la page d'inscription sont également supprimés comme par magie.

88
stephenmurdoch

J'ai eu un problème similaire essayé de supprimer devise_invitable chemins pour créer et nouveau:

avant:

 devise_for :users

_ {rake routes} _

accept_user_invitation GET    /users/invitation/accept(.:format)           devise/invitations#edit
       user_invitation POST   /users/invitation(.:format)                  devise/invitations#create
   new_user_invitation GET    /users/invitation/new(.:format)              devise/invitations#new
                       PUT    /users/invitation(.:format)                  devise/invitations#update

après

devise_for :users , :skip => 'invitation'
devise_scope :user do
  get "/users/invitation/accept", :to => "devise/invitations#edit",   :as => 'accept_user_invitation'
  put "/users/invitation",        :to => "devise/invitations#update", :as => nil
end

_ {rake routes} _

accept_user_invitation GET    /users/invitation/accept(.:format)                 devise/invitations#edit
                       PUT    /users/invitation(.:format)                        devise/invitations#update

note 1 devise scope https://github.com/plataformatec/devise#configuring-routes

note 2 Je l'applique sur un système invitable, mais cela fonctionnera avec n'importe quelle fonctionnalité imaginable

Remarque importante: voyez que carte_scope est sur utilisateur pas utilisateurs? c'est correct, faites attention à cela! Cela peut causer beaucoup de douleur en vous donnant ce problème:

Started GET "/users/invitation/accept?invitation_token=xxxxxxx" for 127.0.0.1 
Processing by Devise::InvitationsController#edit as HTML
  Parameters: {"invitation_token"=>"6Fy5CgFHtjWfjsCyr3hG"}
 [Devise] Could not find devise mapping for path "/users/invitation/accept?  invitation_token=6Fy5CgFHtjWfjsCyr3hG".
This may happen for two reasons:

1) You forgot to wrap your route inside the scope block. For example:

  devise_scope :user do
     match "/some/route" => "some_devise_controller"
  end

 2) You are testing a Devise controller bypassing the router.
   If so, you can explicitly tell Devise which mapping to use:

    @request.env["devise.mapping"] = Devise.mappings[:user]
30
equivalent8

J'ai trouvé un autre post semblable à celui-ci et je voulais partager une réponse donnée par @chrisnicola. Dans leur message, ils tentaient de ne bloquer que les inscriptions des utilisateurs pendant la production.

Vous pouvez également modifier le contrôleur des inscriptions. Vous pouvez utiliser quelque chose comme ceci:

Dans "app/controllers/registrations_controller.rb"

class RegistrationsController < Devise::RegistrationsController
  def new
    flash[:info] = 'Registrations are not open.'
    redirect_to root_path
  end

  def create
    flash[:info] = 'Registrations are not open.'
    redirect_to root_path
  end
end

Cela annulera le contrôleur de l'appareil et utilisera les méthodes ci-dessus à la place. Ils ont ajouté des messages flash au cas où quelqu'un arriverait à la page de connexion. Vous devriez également pouvoir changer la redirection vers n'importe quel chemin.

Également dans "config/routes.rb", vous pouvez ajouter ceci: 

devise_for :users, :controllers => { :registrations => "registrations" }

En le laissant ainsi, vous pourrez utiliser le montage standard pour éditer votre profil. Si vous le souhaitez, vous pouvez toujours remplacer l'option de modification du profil en incluant 

  def update
  end

dans le "app/controllers/registrations_controller.rb"

20
Daniel

Vous pouvez remplacer le "devise_scope" en le plaçant avant le "devise_for".

devise_scope :user do
  get "/users/sign_up",  :to => "sites#index"
end

devise_for :users

Je ne sais pas si c'est la meilleure façon, mais c'est actuellement ma solution, car elle redirige simplement la page de connexion.

12
Midnight

C’est une vieille question - mais j’ai récemment résolu le même problème et proposé une solution beaucoup plus élégante que:

devise_for :users, :skip => [:registrations] 
as :user do
  get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
  put 'users' => 'devise/registrations#update', :as => 'user_registration'
end

Et il donne les noms par défaut pour les routes nommées (comme cancel_user_registration) sans être excessivement prolixe.

devise_for :users, skip: [:registrations]

# Recreates the Devise registrations routes
# They act on a singular user (the signed in user)
# Add the actions you want in 'only:'
resource :users,
    only: [:edit, :update, :destroy],
    controller: 'devise/registrations',
    as: :user_registration do
  get 'cancel'
end

rake routes sortie avec les modules de carte par défaut:

                  Prefix Verb   URI Pattern                    Controller#Action
        new_user_session GET    /users/sign_in(.:format)       devise/sessions#new
            user_session POST   /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)      devise/sessions#destroy
           user_password POST   /users/password(.:format)      devise/passwords#create
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
                         PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
       user_registration PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy
11
max

Faites ceci dans routes.rb

devise_for :users, :controllers => {:registrations => "registrations"}, :skip => [:registrations]
  as :user do
    get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
    put 'users' => 'devise/registrations#update', :as => 'user_registration'
end

  devise_scope :user do
    get "/sign_in",  :to => "devise/sessions#new"
    get "/sign_up",  :to => "devise/registrations#new"
  end

vous obtiendrez une erreur maintenant pendant que vous venez de vous connecter à la page, pour la réparer. Faites-vous ce changement dans: app/views/inventer/partagé/_links.erb

<% if  request.path != "/sign_in" %>
    <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
        <%= link_to "Sign up", new_registration_path(resource_name) %><br />
    <% end -%>
<% end %>
4
Syed

J'ai aimé @/max's answer , mais en essayant de l'utiliser, j'ai rencontré une erreur car devise_mapping était nul.

J'ai légèrement modifié sa solution en une solution qui semble résoudre le problème. Il fallait encapsuler l'appel à resource dans devise_scope.

devise_for :users, skip: [:registrations]

devise_scope :user do
  resource :users,
           only: [:edit, :update, :destroy],
           controller: 'devise/registrations',
           as: :user_registration do
    get 'cancel'
  end
end

Notez que devise_scope attend le singulier :user alors que resource attend le pluriel :users.

4
dvanoni

Pour d'autres dans mon cas.
Avec devise (3.5.2).
J'ai supprimé avec succès les itinéraires d’inscription, mais j'ai gardé ceux pour éditer le profil, avec le code suivant.

#routes.rb
devise_for :users, skip: [:registrations]
as :user do
  get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
  put '/users(.:format)' => 'devise/registrations#update', as: 'user_registration'
  patch '/users(.:format)' => 'devise/registrations#update'
end
2
Micka

J'ai trouvé que cela fonctionnait bien sans jouer avec les itinéraires ou en ajoutant des méthodes de contrôleur d'application. Mon approche est de remplacer la méthode de calcul. Ajoutez ceci à app/controllers/devise/registrations_controller.rb J'ai omis les autres méthodes par souci de brièveté. 

class Devise::RegistrationsController < DeviseController
  ...
  # GET /resource/sign_up
  def new
    redirect_to root_path
  end
  ....
end

Aussi, pour supprimer l’illusion que ce chemin est toujours accessible depuis d’autres vues, vous pouvez également supprimer ce code de app/views/devise/shared/_links.erb

<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
2
lacostenycoder

En modifiant les itinéraires, de nombreux autres problèmes s’y rapportent. La méthode la plus simple que j'ai trouvée consiste à effectuer les opérations suivantes.

ApplicationController < ActionController::Base
  before_action :dont_allow_user_self_registration

  private

  def dont_allow_user_self_registration
    if ['devise/registrations','devise_invitable/registrations'].include?(params[:controller]) && ['new','create'].include?(params[:action])
      redirect_to root_path
    end
  end
end
0
Weston Ganger

J'ai eu le même problème et j'ai trouvé un peu une mauvaise pratique de rediriger les utilisateurs à partir de la page d'inscription. Donc, ma solution est essentiellement de ne pas utiliser :registrable du tout.

Ce que j'ai fait est de créer une page similaire, telle que la modification des informations utilisateur, qui ressemble à ceci:

<%= form_tag(update_user_update_path, method: :post) do %>  
    <br>
    <%= label_tag(:currPassword, 'Current password:') %> <%= password_field_tag(:currPassword) %> <br>
    <%= label_tag(:newPassword, 'New password:') %> <%= password_field_tag(:newPassword) %> <br>
    <%= label_tag(:newPasswordConfirm, 'Confirm new password:') %> <%= password_field_tag(:newPasswordConfirm) %> <br>
    <%= submit_tag('Update') %>
<% end %>

Donc, ce formulaire est envoyé dans un nouveau noeud final post qui met à jour le mot de passe, qui ressemble à ceci:

  def update
    currPass = params['currPassword']
    newPass1 = params['newPassword']
    newPass2 = params['newPasswordConfirm']
    currentUserParams = Hash.new()
    currentUserParams[:current_password] = currPass
    currentUserParams[:password] = newPass1
    currentUserParams[:password_confirmation] = newPass2
    @result = current_user.update_with_password(currentUserParams)
  end

Plus tard, vous pourrez utiliser le @result dans votre vue pour indiquer à l'utilisateur si le mot de passe est mis à jour ou non.

0
Sarp Kaya