Kaydolmak için Devise yolunu nasıl kaldırırım?


147

Bir Rails 3 uygulamasında Devise kullanıyorum, ancak bu durumda, bir kullanıcı hangi izinlere sahip olacağını belirleyen mevcut bir kullanıcı tarafından oluşturulmalıdır.

Bundan dolayı şunu istiyorum:

  • To kullanıcıların kaydolmak için rotayı kaldırmak .
  • İçin hala düzenlemek için kullanıcılar, profillerinin izin (değiştir e-posta adresi ve şifre) sonra onlar kaydettik

Bunu nasıl yapabilirim?

Şu anda, aşağıdakileri daha önce yerleştirerek bu rotayı etkili bir şekilde kaldırıyorum devise_for :users:

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

Bu işe yarıyor, ama daha iyi bir yol olduğunu düşünüyorum, değil mi?

Güncelleme

Benoit Garret'in dediği gibi, benim durumumdaki en iyi çözüm, kayıt rotalarını toplu olarak oluşturmayı atlamak ve sadece gerçekten istediklerimi oluşturmaktır.

Bunu yapmak için önce koştum rake routes, sonra çıktıyı istediklerimi yeniden oluşturmak için kullandım. Sonuç şuydu:

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

Bunu not et:

  • Hala var :registerablebenim de Usermodeli
  • devise/registrations e-posta ve şifrenin güncellenmesini sağlar
  • Diğer kullanıcı özniteliklerinin (izinler vb.) Güncellenmesi farklı bir denetleyici tarafından gerçekleştirilir

Gerçek cevap:

Varsayılan Geliştirme yolları için yolu kaldırın; yani:

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

4
Aslında orijinal çözümünüzün çok daha basit ve net olduğunu düşünüyorum. Güvenlik açısından herhangi bir gerçek sorun var mı?
counterbeing

Bazı nedenlerden dolayı güncellenmiş çözümünüz kimliğe ihtiyacım olduğunu söyleyen bir hata veriyordu. Bir saatlik zorlama ve birçok sunucu yeniden başladıktan sonra, bir şekilde kendi kendine düzeldi. Hiçbir fikrim yok ... ama başka biri bunu yaşarsa, denemeye devam edin!
Erik Trautman

@counterbeing - bildiğim kadarıyla sorun değil, sadece kullanılmayan rotalara sahip olmaktan veya siparişe güvenmekten hoşlanmadım.
Nathan Long

1
"Gerçek Yanıt", plan denetleyicisi içinden yeniden yönlendirilirse yolu tamamlamaz. GET rotasını beğenirseniz, varsayılan davranış sizi kayıt yoluna yönlendirmeye devam edecektir https://example.com/users/. Aşağıdaki cevabıma bakın.
lacostenycoder

1
Güvenlik Kusuru! Gösterilen "Gerçek cevap" sadece kayıt formundan kurtulur, kullanıcıyı gerçekten oluşturan POST yolundan KURTULMAZ.
Eric Terry

Yanıtlar:


54

Ben de bunu yapmaya çalıştım, ancak google group grubundaki bir konu beni gerçekten temiz bir çözüm aramaktan vazgeçirdi.

José Valim'den (Devise geliştiricisi) alıntı yapacağım:

Basit bir seçenek yok. Bir yama sağlayabilir veya şunu kullanabilirsiniz: skip =>: kaydedilebilir ve yalnızca istediğiniz rotaları ekleyebilirsiniz.

Asıl soru şuydu:

Rails'ten belirli bir rotayı (silme rotası) kaldırmanın iyi bir yolu var mı?


4
Oldukça doğru. Aslında, bir yama önerdim ve o kibarca reddetti: "Bugün, tüm denetleyiciyi atlayabilirsiniz. Kullanım açısından uygun değildir, ancak tüm denetleyici için yolları manuel olarak ayarlamak oldukça basittir. Yolları hariç tutmanın isme göre yol oluşturma kodunu daha karmaşık hale getirecek (halihazırda olduğundan) çünkü Rails yardımcılarını (kaynak, kaynaklar ve arkadaşlar gibi) kullanamayacağız ". github.com/plataformatec/devise/issues/…
Nathan Long

2
Bu cevabın orijinal olarak yazıldığı sırada durum bu muydu bilmiyorum ama José'den alıntıdaki kod yanlış. Devise 3.4.1'de öyle :skip => :registrationsdeğil :skip => :registerable.
GMA

90

bunu modelinde yapabilirsin

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

şu şekilde değiştirin:

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

sembolün :registerablekaldırıldığına dikkat edin

İşte bu, başka hiçbir şeye gerek yok. Kayıt sayfasına giden tüm rotalar ve bağlantılar da sihirli bir şekilde kaldırılır.


21
Maalesef bu edit_user_registration, ihtiyacım olan rotayı da ortadan kaldırıyor . Dediğim gibi, "yine de profillerini düzenleyebilmeliler."
Nathan Long

1
Ahh, tamam, normalde bunu , kullanıcıların yeniden kaydedilebilir nesne kaldırılmış olsa bile hesaplarını düzenleyebilecekleri yere gitmelerine olanak tanıyan rails_admin gem yükleyerek aşarımlocalhost:3000/admin . Bu uygulanabilir bir çözüm değilse, bir kaynağa kimin erişip erişemeyeceğini belirlemenize izin veren CanCan'a bir göz atın . "Yönetici" veya "moderatör" gibi roller ekleme eğilimindeyim ve diğer herkesi kayıt sayfalarından kilitledim.
stephenmurdoch

28
Kullanıcılara kendi profillerini düzenlemeleri için bir yol sağlamak için (rastgele kayıtların düzenlenmesine izin vermek için oluşturulmuş) bir yönetici bölümü kullanmak, uzun zamandır duyduğum en kötü fikir. Lütfen bunu kimse yapmasın
Jeremy

sign_inÜretimde nasıl devre dışı bırakılır ?
WM

30

Benzer bir sorun yaratma ve yeni için devise_invitable yollarını kaldırmaya çalıştım :

önce:

 devise_for :users

tırmık yolları

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

sonra

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

tırmık yolları

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

not 1 kapsam tasarlayın https://github.com/plataformatec/devise#configuring-routes

not 2 Bunu devise_invitable üzerinde uyguluyorum ancak tasarlanabilen * herhangi bir özellik ile çalışacak

Önemli not: devise_scope'un kullanıcılar değil kullanıcılar üzerinde olduğunu görüyor musunuz? bu doğru, buna dikkat edin! Size bu sorunu veren çok fazla acıya neden olabilir:

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]

Tam olarak aradığım için teşekkürler. Bu çözümü kullanan diğerleri için rota tanımına /: id eklemem gerekiyordu.
John

21

Buna benzer başka bir gönderi buldum ve @chrisnicola'nın verdiği bir cevabı paylaşmak istedim. Gönderide, yalnızca üretim sırasında kullanıcı kayıtlarını engellemeye çalışıyorlardı.

Kayıt denetleyicisini de değiştirebilirsiniz. Bunun gibi bir şey kullanabilirsiniz:

In "app / kontrolörleri / 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

Bu, devise'ın denetleyicisini geçersiz kılacak ve bunun yerine yukarıdaki yöntemleri kullanacaktır. Birisinin bir şekilde kayıt sayfasına girmesi durumunda flaş mesajlar eklediler. Yönlendirmeyi istediğiniz herhangi bir yola da değiştirebilmelisiniz.

Ayrıca "config / route.rb" dosyasında şunu ekleyebilirsiniz:

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

Bu şekilde bırakmak, profilinizi düzenlemek için standart düzeni kullanmanıza olanak tanır. Dilerseniz profil düzenleme seçeneğini de dahil ederek geçersiz kılabilirsiniz.

  def update
  end

içinde "app / kontrolörleri / registrations_controller.rb"


13

Bu eski bir soru - ancak yakın zamanda aynı sorunu çözdüm ve şunlardan çok daha zarif bir çözüm buldum:

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

Ve cancel_user_registrationaşırı derecede ayrıntılı olmadan , adlandırılmış yollar için varsayılan isimleri (gibi ) verir .

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 varsayılan tasarım modülleri ile çıktı:

                  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

"Devise_scope" öğesini "devise_for" dan önce yerleştirerek geçersiz kılabilirsiniz.

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

devise_for :users

Bunun en iyi yol olup olmadığından emin değilim, ancak şu anda benim çözümüm, çünkü oturum açma sayfasına geri dönüyor.


1
Ben de benzer bir yaklaşım izledim, ancak URL'nin de değişmesini istedim, bu yüzden "get" / users / sign_up ",: to => redirect (" / ")`
dinjas

Çok basit ve en kolay çözme. Ancak bu çözmenin bir dakikalık sorunu var. Adres kaldı. Girerseniz, /users/sign_upo zaman erişime sahip sites#indexolmayacaksınız sign_upancak adres hala kalacak /users/sign_up.
Penguen

5

@ Max'ın cevabını beğendim , ancak kullanmaya çalışırken devise_mappingsıfır olduğu için bir hatayla karşılaştım .

Çözümünü, sorunu ele alıyor gibi görünen bir çözümle değiştirdim. Aramayı resourceiçeriye sarmak gerekiyordu 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

Not devise_scopetekil bekler :userise resourceçoğul beklentiden :users.


4

Bunu route.rb içinde yapın

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

şimdi oturum açma sayfasına geldiğinizde, düzeltmek için bir hata alacaksınız. Bu değişikliği şurada yapın: 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 %>

Bu benim için çalıştı (sadece devise_forve asbloğunu kullandım) ve :registerablemodelden çıkarmak zorunda kaldım .
dusan

3

Bunun rotalarla uğraşmadan veya uygulama denetleyici yöntemleri eklemeden iyi çalıştığını buldum. Benim yaklaşımım, tasarlama yöntemini geçersiz kılmaktır. Bu ekle app/controllers/devise/registrations_controller.rb ben kısalık için başka yöntemler ihmal ettik.

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

Ayrıca bu yolun diğer görünümlerden hala ulaşılabilir olduğu yanılsamasını ortadan kaldırmak için bu kodu da kaldırmak isteyebilirsiniz. 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

Benim durumumdaki diğerleri için.
İle devise (3.5.2).
Kaydolmak için rotaları başarıyla kaldırdım, ancak aşağıdaki kodla profili düzenlemek için olanları sakladım.

#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

İşte gittiğim biraz farklı rota. devise/shared/_links.html.erbGörünümü geçersiz kılmanıza gerek kalmaması için yapar .

İçinde app/models/user.rb:

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

İçinde 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

Önce:

$ 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

Sonra:

$ 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

Gereksiz rotalara sahip olmak istemiyorsanız, tüm varsayılan rotaları atlayın, yanidevise_for :users, skip: :all
elquimista

0

Aynı sorunu yaşadım ve kullanıcıları kayıt sayfasından yönlendirmenin biraz kötü bir uygulama olduğunu gördüm. Yani benim çözümüm temelde hiç kullanmıyor :registrable.

Yaptığım şey, aşağıdaki gibi görünen kullanıcı ayrıntılarını düzenlemek gibi benzer bir sayfa oluşturmaktı:

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

Bu nedenle, bu form, şifreyi güncelleyen yeni bir son bitiş noktasına gönderilir ve şuna benzer:

  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

Daha sonra @result, kullanıcıya parolanın güncellenip güncellenmediğini söylemek için görünümünüzdeki öğesini kullanabilirsiniz.


0

Rotaları değiştirerek, bununla birlikte gelen bir sürü başka sorun var. Bulduğum en kolay yöntem aşağıdakileri yapmaktır.

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

Çalışıyor, ancak bu yöntemi her eylemde gerçekten çalıştırmak istiyor musunuz?
lacostenycoder

0

Zor bir çözüm aramak yerine. Aşağıdaki yaklaşımları kullandım.

  1. Sign_up formunu sayfadan silin (path devise / registrations / new.html.erb) ve özel bilgilerle değiştirin.

  2. Gelen trafiği başka bir sayfaya yönlendirin. Aşağıdaki gibiroutes.rb

    get "/users/sign_up", to: redirect('/')

    post "/users/sign_up", to: redirect('/')

Daha önce yazdığından emin ol devise_for :users


-7

deviseCevherin kendisini değiştirebilirsiniz . Öncelikle, kullanım kurulu konumunu bulmak için bu komutu çalıştırın:

gem which devise

Diyelim ki yol: /usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise

Sonra şuraya git

/usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise/lib/devise/railsve routes.rbbu dizinde düzenleyin . def devise_registration(mapping, controllers)Yeni eylemden kurtulmak için değiştirebileceğiniz bir yöntem var . Ayrıca için eşlemeleri tamamen kaldırabilirsiniz.devise_registration


Alternatif bir öneri için +1, ancak bir mücevheri çatallamak benim için rotalarıma garip bir kod koymaktan daha az cazip görünüyor.
Nathan Uzun

4
genel uygulamada bu büyük Hayır-Hayır! Eğer onlar gibi taşlar tutmak ve gereken değişikliğin şey sadece maymun yama onlara gerekirse
equivalent8

Bu durumda size katılıyorum, ancak genel olarak bir grup farklı yerde maymun yama koduna alternatif olarak kullandığınız kitaplıklarda / mücevherlerde değişiklik yapmaktan çekinmemelisiniz. İhtiyaçlarınıza göre bir kitaplık oluşturma yeteneği, açık kaynak kodlu IMO kullanmanın en büyük artılarından biridir.
Ankit Soni

Eğer mücevheri değiştirecekseniz, en azından onu çatal ve Gemfile'ınızı maymun yamalı geminize yöneltin (örneğin github'da). Bunu birkaç kez yaptım. İşlem şu şekildedir: çatal mücevher, çatalınızı yerel olarak klonlayın, maymun yerel sürümünüzü yama, uzak deponuza itin ve Gemfile'ı ona yönlendirin. (yani gem 'devise', github: 'yourusername/devise', branch: "master")
lacostenycoder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.