Come rimuovo il percorso Devise per registrarmi?


147

Sto usando Devise in un'app Rails 3, ma in questo caso, un utente deve essere creato da un utente esistente, che determina quali autorizzazioni avrà.

Per questo motivo, voglio:

  • Per rimuovere il percorso per la registrazione degli utenti .
  • Per consentire ancora agli utenti di modificare i loro profili (cambia indirizzo e-mail e password) dopo che hanno firmato

Come posso fare questo?

Attualmente, sto effettivamente rimuovendo questo percorso inserendo prima quanto segue devise_for :users:

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

Funziona, ma immagino che ci sia un modo migliore, giusto?

Aggiornare

Come ha detto Benoit Garret, la migliore soluzione nel mio caso è quella di saltare la creazione delle rotte di registrazione in massa e creare quelle che desidero davvero.

Per farlo, ho eseguito prima rake routes, quindi ho usato l'output per ricreare quelli che volevo. Il risultato finale è stato questo:

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

Nota che:

  • Ho ancora :registerablenel mioUser modello
  • devise/registrations gestisce l'aggiornamento di e-mail e password
  • L'aggiornamento di altri attributi utente - autorizzazioni, ecc. - è gestito da un controller diverso

Risposta effettiva:

Rimuovere il percorso per i percorsi Devise predefiniti; vale a dire:

devise_for :users, path_names: {
  sign_up: ''
}

4
In realtà penso che la tua soluzione originale fosse molto più semplice e chiara. C'è qualche vero problema in termini di sicurezza?
counterbeing

Per qualche motivo la tua soluzione aggiornata ha continuato a generare un errore che diceva che avevo bisogno dell'ID. Dopo un'ora di strappo e molti riavvii del server, si è in qualche modo risolto da solo. Non ne ho idea ... ma se qualcun altro lo sperimenta, continua a provare!
Erik Trautman,

@counterbeing - nessun problema che conosco, semplicemente non mi piaceva avere percorsi inutilizzati o fare affidamento su ordini.
Nathan Long

1
"Risposta effettiva" non termina il percorso se viene reindirizzato dall'interno del controller di ideazione. Il comportamento predefinito ti indirizzerà comunque al percorso di iscrizione se premi GET route come https://example.com/users/. Vedi la mia risposta qui sotto.
lacostenycoder

1
Difetto di sicurezza! La "risposta effettiva" che viene mostrata elimina solo il modulo di iscrizione, NON elimina la route POST che crea effettivamente l'utente.
Eric Terry,

Risposte:


54

Ho provato anche a fare questo, ma un thread sul gruppo google ideato mi ha dissuaso dal cercare una soluzione davvero pulita.

Citerò José Valim (il manutentore di Devise):

Non esiste un'opzione diretta. Puoi fornire una patch o utilizzare: skip =>: registrabile e aggiungere solo i percorsi desiderati.

La domanda originale era:

Esiste un buon modo per rimuovere un percorso specifico (il percorso di eliminazione) da Rails?


4
Abbastanza corretto In effetti, ho proposto una patch e lui ha cortesemente rifiutato: "Oggi puoi saltare l'intero controller. Non è ottimale in termini di utilizzo, ma impostare manualmente le route per l'intero controller è piuttosto diretto. Credo che escludere le route per nome renderà il codice di generazione delle rotte più complicato (di quanto non lo sia già) perché non saremo in grado di utilizzare gli helper di Rails (come risorse, risorse e amici) ". github.com/plataformatec/devise/issues/…
Nathan Long

2
Non so se questo fosse il caso in cui questa risposta era stata originariamente scritta, ma il codice nella citazione di José è sbagliato. In Devise 3.4.1 non lo :skip => :registrationsè :skip => :registerable.
GMA,

89

puoi farlo nel tuo modello

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

cambiarlo in:

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

notare che il simbolo è :registerablestato rimosso

Ecco fatto, nient'altro è richiesto. Anche tutti i percorsi e i collegamenti alla pagina di registrazione vengono rimossi magicamente.


21
Sfortunatamente, questo rimuove anche il percorso verso edit_user_registration, di cui ho bisogno. Come ho detto, "dovrebbero essere comunque in grado di modificare i loro profili".
Nathan Long,

1
Ahh, OK, bene, di solito mi aggiro installando rails_admin gem, che consente agli utenti di andare localhost:3000/admindove possono modificare il proprio account, anche con l'oggetto resisterable rimosso. Se questa non è una soluzione praticabile, dai un'occhiata a CanCan che ti consente di stabilire chi può e non può accedere a una risorsa. Tendo ad aggiungere ruoli come 'admin' o 'moderatore' e bloccare tutti gli altri fuori dalle pagine di sign_up.
Stephenmurdoch,

28
L'uso di una sezione di amministrazione (che è stata creata per consentire la modifica di record arbitrari) per fornire agli utenti un modo per modificare i propri profili è la peggiore idea che ho sentito da molto tempo. Per favore nessuno lo fa
Jeremy,

Come disabilitare sign_inin produzione?
WM,

30

Ho avuto un problema simile ho provato a rimuovere percorsi devise_invitable per creare e nuovo :

prima:

 devise_for :users

percorsi del rastrello

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

dopo

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

percorsi del rastrello

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

nota 1 ideare ambito https://github.com/plataformatec/devise#configuring-routes

nota 2 Lo sto applicando su devise_invitable ma funzionerà con qualsiasi funzione di ideazione *

Nota importante: vedi che devise_scope è su utente e non utenti ? è corretto, attenzione per questo! Può causare molto dolore dandoti questo problema:

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]

Grazie esattamente quello che stavo cercando. Per gli altri che usano questa soluzione, ho dovuto aggiungere /: id alla definizione del percorso put.
Giovanni

21

Ho trovato un altro post simile a questo e volevo condividere una risposta data da @chrisnicola. Nel post stavano tentando di bloccare la registrazione degli utenti solo durante la produzione.

È inoltre possibile modificare il controller delle registrazioni. Puoi usare qualcosa del genere:

In "app / controller / 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

Ciò sovrascriverà il controller di devise e utilizzerà invece i metodi di cui sopra. Hanno aggiunto messaggi flash nel caso in cui qualcuno fosse in qualche modo arrivato alla pagina sign_up. Dovresti anche essere in grado di modificare il reindirizzamento su qualsiasi percorso ti piaccia.

Inoltre in "config / route.rb" puoi aggiungere questo:

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

Lasciarlo in questo modo ti consentirà di utilizzare il metodo standard per modificare il tuo profilo. Se lo desideri, puoi sempre sostituire l'opzione di modifica del profilo includendo

  def update
  end

nell ' "app / controller / registrations_controller.rb"


13

Questa è una vecchia domanda, ma di recente ho risolto lo stesso problema e ho trovato una soluzione che è molto più elegante di:

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

E fornisce i nomi predefiniti per le route denominate (like cancel_user_registration) senza essere eccessivamente prolisso.

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 output con i moduli di default:

                  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

12

È possibile ignorare "devise_scope" posizionandolo prima di "devise_for".

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

devise_for :users

Non sono sicuro che questo sia il modo migliore, ma al momento è la mia soluzione, in quanto reindirizza alla pagina di accesso.


1
Ho adottato un approccio simile, ma volevo anche cambiare l'URL, quindi sono andato con `get" / users / sign_up ",: to => redirect (" / ")`
dinjas

Soluzione così semplice e facile. Ma questa soluzione ha un problema di un minuto. L'indirizzo è rimasto. Se entri /users/sign_up, avrai accesso al sites#indexno, sign_upma l'indirizzo rimarrà comunque /users/sign_up.
Pinguino

5

Mi è piaciuta la risposta di @ max , ma quando ho provato a usarla ho riscontrato un errore dovuto adevise_mapping zero.

Ho modificato leggermente la sua soluzione in una che sembra risolvere il problema. Richiedeva il wrapping della chiamata resourceall'interno 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

Si noti che si devise_scopeaspetta il singolare:user mentre si resourceaspetta il plurale :users.


4

Fallo in route.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

visualizzerai un errore ora mentre vieni per accedere alla pagina, per risolverlo. Apporta questa modifica in: app / views / devise / shared / _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 %>

Questo ha funzionato per me (ho usato solo devise_foril asblocco e) e ho dovuto rimuovere :registerableil modello.
Dusan,

3

Ho trovato che funziona bene senza fare confusione con i percorsi o aggiungendo metodi di controller dell'applicazione. Il mio approccio è quello di ignorare il metodo escogitato. Aggiungi questo a app/controllers/devise/registrations_controller.rb Ho omesso gli altri metodi per brevità.

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

Inoltre, per rimuovere l'illusione che questo percorso sia ancora raggiungibile da altre viste, potresti anche voler rimuovere questo codice 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

Per gli altri nel mio caso.
Con devise (3.5.2).
Ho rimosso con successo i percorsi per l'iscrizione, ma ho mantenuto quelli per modificare il profilo, con il seguente codice.

#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

1

Ecco la strada leggermente diversa che ho seguito. Lo rende quindi non è necessario ignorare ildevise/shared/_links.html.erb vista.

In app/models/user.rb:

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

In config/routes.rb:

devise_for :users
devise_scope :user do
  put 'users' => 'devise/registrations#update', as: 'user_registration'
  get 'users/edit' => 'devise/registrations#edit', as: 'edit_user_registration'
  delete 'users' => 'devise/registrations#destroy', as: 'registration'
end

Prima:

$ rake routes | grep devise
           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
          user_registration POST   /users(.:format)                            devise/registrations#create
      new_user_registration GET    /users/sign_up(.:format)                    devise/registrations#new
     edit_user_registration GET    /users/edit(.:format)                       devise/registrations#edit
                            PATCH  /users(.:format)                            devise/registrations#update
                            PUT    /users(.:format)                            devise/registrations#update
                            DELETE /users(.:format)                            devise/registrations#destroy

Dopo:

$ rake routes | grep devise
           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
          user_registration PUT    /users(.:format)                            devise/registrations#update
     edit_user_registration GET    /users/edit(.:format)                       devise/registrations#edit
               registration DELETE /users(.:format)                            devise/registrations#destroy

Se non si desidera disporre di percorsi ridondanti, saltare tutti i percorsi predefiniti, ad es.devise_for :users, skip: :all
elquimista

0

Ho avuto lo stesso problema e ho trovato un po 'brutta pratica reindirizzare gli utenti dalla pagina di registrazione. Quindi la mia soluzione non sta fondamentalmente usando:registrable affatto.

Quello che ho fatto è stato creare una pagina simile come modificare i dettagli dell'utente che sembrava:

<%= 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 %>

Quindi questo modulo invia in un nuovo end point post che aggiorna la password, che assomiglia a:

  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

Successivamente puoi utilizzare il @resultnella tua vista per dire all'utente se la password è aggiornata o meno.


0

Modificando i percorsi ci sono molti altri problemi che ne derivano. Il metodo più semplice che ho trovato è fare quanto segue.

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

Funziona, ma vuoi davvero eseguire questo metodo su ogni singola azione?
lacostenycoder

-7

È possibile modificare la devisegemma stessa. Innanzitutto, esegui questo comando per trovare la posizione installata di utilizzo:

gem which devise

Supponiamo che il percorso sia: /usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise

Quindi vai a

/usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise/lib/devise/railse modifica routes.rbin quella directory. Esiste un metodo chiamato def devise_registration(mapping, controllers)che è possibile modificare per eliminare la nuova azione. Puoi anche rimuovere completamente i mapping perdevise_registration


+1 per un suggerimento alternativo, ma biforcarmi una gemma mi sembra meno desiderabile che inserire un codice scomodo nei miei percorsi.
Nathan Long

4
in pratica questo è grande No-No! dovresti conservare le gemme così come sono e se hai bisogno di cambiare qualcosa, basta scimmia patch loro
equivalente8

Sono d'accordo con te in questo caso, ma in generale non penso che dovresti evitare di apportare modifiche alle librerie / gemme che usi come alternativa al codice di patching delle scimmie in un sacco di luoghi diversi. La capacità di modellare una libreria secondo le tue esigenze è uno dei maggiori vantaggi dell'utilizzo del codice IMO open-source.
Ankit Soni,

Se hai intenzione di modificare la gemma, almeno biforcala e punta il tuo Gemfile sulla gemma patchata dalla scimmia (su github per esempio). L'ho fatto in diverse occasioni. Il processo è: fork gem, clona il fork localmente, scimmia patch la tua versione locale, spingi sul repository remoto e punta Gemfile su di esso. (es. gem 'devise', github: 'yourusername/devise', branch: "master")
lacostenycoder
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.