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:
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?
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:
:registerable
dans mon modèle User
devise/registrations
gère la mise à jour de l'email et du mot de passeSupprimez la route pour les chemins par défaut Devise; c'est à dire.:
devise_for :users, path_names: {
sign_up: ''
}
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?
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.
J'ai eu un problème similaire essayé de supprimer devise_invitable chemins pour créer et nouveau:
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
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]
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"
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.
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
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 %>
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
.
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
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 -%>
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
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.