Devise 경로를 제거하여 가입하려면 어떻게해야합니까?


147

Rails 3 앱에서 Devise를 사용하고 있지만이 경우 기존 사용자가 사용자를 생성해야합니다.

이 때문에 나는 원한다 :

  • 사용자가 가입 할 수있는 경로제거 하려면 .
  • 사용자 가 가입 한 후에도 프로필을 편집 (이메일 주소 및 비밀번호 변경) 할 수 있도록 하려면

어떻게해야합니까?

현재 다음을 전에 배치 하여이 경로를 효과적으로 제거하고 있습니다 devise_for :users.

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

그것은 효과가 있지만 더 좋은 방법이 있다고 생각합니다.

최신 정보

Benoit Garret이 말했듯이, 제 경우 가장 좋은 해결책은 등록 경로 작성을 건너 뛰고 실제로 원하는 것을 작성하는 것입니다.

그렇게하기 위해 먼저을 실행 rake routes한 다음 출력을 사용하여 원하는 것을 다시 작성했습니다. 최종 결과는 다음과 같습니다.

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

참고 :

  • 나는 여전히 :registerableUser모델에
  • devise/registrations 이메일 및 비밀번호 업데이트 처리
  • 다른 사용자 속성 (권한 등) 업데이트는 다른 컨트롤러에서 처리합니다.

실제 답변 :

기본 Devise 경로의 경로를 제거하십시오. 즉 :

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

4
실제로 원래 솔루션은 훨씬 간단하고 명확하다고 생각합니다. 보안 현명한 문제가 있습니까?
counterbeing

어떤 이유로 업데이트 된 솔루션에서 ID가 필요하다는 오류가 계속 발생했습니다. 한 시간 동안 머리를 당기고 많은 서버를 다시 시작한 후 어떻게 든 고정되었습니다. 나는 모른다 ...하지만 다른 사람이 그것을 경험한다면, 계속 노력하십시오!
Erik Trautman

@counterbeing-내가 아는 문제는 없습니다. 미사용 경로를 사용하거나 주문에 의존하는 것을 좋아하지 않았습니다.
Nathan Long

1
"실제 답변"은 고안 컨트롤러 내에서 경로가 재 지정된 경우 경로 종료를 완료하지 않습니다. 과 같은 GET 경로를 누르면 기본 동작은 여전히 ​​가입 경로로 연결됩니다 https://example.com/users/. 아래 답변을 참조하십시오.
lacostenycoder

1
보안 결함! 표시되는 "실제 답변"은 가입 양식 만 제거하고 실제로는 사용자를 생성하는 POST 경로를 제거하지 않습니다.
Eric Terry

답변:


54

이 작업도 시도했지만 고안 된 Google 그룹의 스레드 로 인해 정말 깨끗한 솔루션을 찾지 못했습니다.

José Valim (Devise 관리자)을 인용하겠습니다.

간단한 옵션은 없습니다. 패치를 제공하거나 : skip => : registerable을 사용하고 원하는 경로 만 추가 할 수 있습니다.

원래 질문은 :

Rails에서 특정 경로 (삭제 경로)를 제거하는 좋은 방법이 있습니까?


4
꽤 맞습니다. 사실, 나는 패치를 제안했고 그는 정중하게 거절했다. "오늘 전체 컨트롤러를 건너 뛸 수 있습니다. 사용 측면에서 최적은 아니지만 수동으로 전체 컨트롤러에 대한 경로를 설정하는 것은 매우 간단합니다. 경로를 제외하는 것으로 생각합니다 우리는 Rails 헬퍼 (자원, 리소스, 친구 등)를 사용할 수 없기 때문에 라우트 생성 코드를 더 복잡하게 만들 것입니다. github.com/plataformatec/devise/issues/…
Nathan Long

2
이 답변이 처음 작성된 때인지는 모르겠지만 José의 인용 부호가 잘못되었습니다. Devise 3.4.1에서는 :skip => :registrations그렇지 않습니다 :skip => :registerable.
GMA

89

당신은 당신의 모델에서 이것을 할 수 있습니다

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

그것을 다음으로 변경하십시오 :

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

심볼 :registerable이 제거 되었음을 확인

그게 다야, 다른 것은 필요하지 않습니다. 등록 페이지에 대한 모든 경로와 링크도 마술처럼 제거됩니다.


21
불행히도 이렇게하면에 대한 경로가 제거 edit_user_registration됩니다. 내가 말했듯이 "그들은 여전히 ​​프로필을 편집 할 수 있어야합니다."
Nathan Long

1
아, 알았어요. 보통 rails_admin gem 을 설치하면이 문제를 해결할 수 있습니다. rails_admin gem은 사용자가 localhost:3000/admin저항 개체를 제거한 상태에서도 계정을 편집 할 수있는 곳으로 이동할 수 있습니다. 이것이 가능한 솔루션이 아니라면 CanCan 을 살펴보면 리소스에 액세스 할 수있는 사람과 액세스 할 수없는 사람을 지정할 수 있습니다. 'admin'또는 'moderator'와 같은 역할을 추가하고 sign_up 페이지에서 다른 모든 사용자를 잠그는 경향이 있습니다.
stephenmurdoch

28
사용자가 자신의 프로필을 편집 할 수있는 방법을 제공하기 위해 임의의 레코드를 편집 할 수있는 관리자 섹션을 사용하는 것은 오랫동안 들어 본 최악의 생각입니다. 아무도하지 마십시오
Jeremy

sign_in프로덕션 에서 비활성화하는 방법은 무엇입니까?
WM

30

비슷한 문제 가 createnew에 대한 devise_invitable 경로 를 제거하려고했습니다 .

전에:

 devise_for :users

갈퀴 길

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

갈퀴 길

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

참고 1 고안 범위 https://github.com/plataformatec/devise#configuring-routes

참고 2 devise_invitable에 적용하고 있지만 고안 가능한 기능으로 작동합니다.

중요 사항 : devise_scope가 사용자가 아닌 사용자에게 있음을 참조하십시오 . 맞습니다, 이것을 조심하십시오! 이 문제를 일으키는 많은 고통을 유발할 수 있습니다.

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]

내가 찾던 것에 감사드립니다. 이 솔루션을 사용하는 다른 사람들을 위해 put route 정의에 / : id를 추가해야했습니다.
John

21

나는 이 게시물 과 비슷한 다른 게시물을 발견 하고 @ chrisnicola가 준 답변을 공유하고 싶었습니다. 포스트에서 그들은 생산하는 동안 사용자 가입을 차단하려고했습니다.

등록 컨트롤러를 수정할 수도 있습니다. 다음과 같은 것을 사용할 수 있습니다.

에서 "응용 프로그램 / 컨트롤러 / 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

이것은 devise의 컨트롤러를 무시하고 대신 위의 방법을 사용합니다. 그들은 누군가가 어떻게 든 sign_up 페이지에 그것을 만들도록 플래시 메시지를 추가했습니다. 또한 원하는 경로로 경로 재 지정을 변경할 수 있어야합니다.

또한 "config / routes.rb"에서 다음을 추가 할 수 있습니다.

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

이렇게 남겨두면 표준 고안을 사용하여 프로필을 편집 할 수 있습니다. 원하는 경우 다음을 포함하여 여전히 프로필 편집 옵션을 무시할 수 있습니다

  def update
  end

에서 "응용 프로그램 / 컨트롤러 / registrations_controller.rb"


13

이것은 오래된 질문이지만 최근에 같은 문제를 해결했으며 다음보다 훨씬 우아한 솔루션을 생각해 냈습니다.

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

그리고 cancel_user_registration과도하게 자세하게 지정되지 않은 명명 된 경로 (예 :)의 기본 이름을 제공합니다 .

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 기본 고안 모듈로 출력 :

                  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_for"앞에 배치하여 "devise_scope"를 대체 할 수 있습니다.

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

devise_for :users

이것이 가장 좋은 방법인지 확실하지 않지만 현재 내 솔루션은 로그인 페이지로 다시 리디렉션되기 때문입니다.


1
비슷한 접근 방식을 취했지만 URL도 변경하고 싶었습니다.`get "/ users / sign_up", : to => redirect ( "/")`
dinjas

간단하고 쉬운 해결. 그러나이 해결에는 1 분의 문제가 있습니다. 주소가 남아 있습니다. 를 입력하면 /users/sign_up당신은에 액세스 할 수 있습니다 sites#index하지 sign_up그러나 주소가 여전히 남아 수 /users/sign_up.
펭귄

5

@max의 답변을 좋아 했지만 사용하려고 할 때 devise_mappingnil 때문에 오류가 발생했습니다 .

문제를 해결하기 위해 그의 솔루션을 약간 수정했습니다. resource내부에 호출을 래핑해야했습니다 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

참고 devise_scope단수 기대 :user반면 resource복수 예상하는가 :users.


4

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

로그인 페이지에서 오류를 수정하여 수정했습니다. 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 %>

이것은 나를 위해 일했고 ( devise_foras블록 만 사용했습니다 ) :registerable모델에서 제거해야했습니다 .
dusan

3

나는 경로를 엉망으로 만들거나 응용 프로그램 컨트롤러 메소드를 추가하지 않고도 잘 작동한다는 것을 알았습니다. 내 접근 방식은 고안 방법을 재정의하는 것입니다. 이 추가 app/controllers/devise/registrations_controller.rb 내가 간결을위한 다른 방법을 생략했습니다.

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

또한이 경로가 다른보기에서 여전히 도달 할 수 있다는 환상을 제거하기 위해이 코드를 제거 할 수도 있습니다 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

내 경우에는 다른 사람들을 위해.
devise (3.5.2).
가입 할 경로를 성공적으로 제거했지만 다음 코드를 사용하여 프로필을 수정하는 경로를 유지했습니다.

#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

여기 약간 다른 경로가 있습니다. devise/shared/_links.html.erb뷰 를 재정의 할 필요가 없도록합니다 .

에서 app/models/user.rb:

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

에서 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

전에:

$ 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

후:

$ 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

당신이 중복 경로를 갖고 싶어하지 않는 경우, 즉 모든 기본 경로 건너devise_for :users, skip: :all
elquimista

0

나는 같은 문제가 있었고 등록 페이지에서 사용자를 리디렉션하는 것이 약간 나쁜 습관이라는 것을 알았습니다. 그래서 내 솔루션은 기본적으로 전혀 사용하지 않습니다 :registrable.

내가 한 것은 다음과 같은 사용자 세부 정보 편집과 비슷한 페이지를 만드는 것입니다.

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

따라서이 양식은 다음과 같이 비밀번호를 업데이트하는 새로운 포스트 엔드 포인트로 제출됩니다.

  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

나중에보기에서를 사용 @result하여 비밀번호가 업데이트되었는지 여부를 사용자에게 알릴 수 있습니다.


0

경로를 변경하면 그와 관련된 다른 문제가 많이 있습니다. 내가 찾은 가장 쉬운 방법은 다음을 수행하는 것입니다.

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

작동하지만 모든 작업마다이 방법을 실행하고 싶습니까?
lacostenycoder

-7

devise보석 자체를 수정할 수 있습니다. 먼저이 명령을 실행하여 다음을 사용하여 설치된 위치를 찾으십시오.

gem which devise

경로가 다음과 같다고 가정 해 봅시다. /usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise

그런 다음

/usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise/lib/devise/railsroutes.rb해당 디렉토리에서 편집하십시오 . def devise_registration(mapping, controllers)새 조치를 제거하기 위해 수정할 수 있는 메소드 가 있습니다. 에 대한 매핑을 완전히 제거 할 수도 있습니다.devise_registration


대체 제안은 +1이지만 보석을 갈아 타는 것은 내 경로에 어색한 코드를 넣는 것보다 바람직하지 않습니다.
Nathan Long

4
일반적으로 이것은 큰 No-No입니다! 당신은있는 그대로 보석을 유지해야합니다 당신은 변경 뭔가 단지 원숭이 패치 그들에게 필요로하는 경우
equivalent8

나는이 경우에 동의하지만, 일반적으로 여러 곳에서 원숭이 패치 코드의 대안으로 사용하는 라이브러리 / 젬을 변경하는 것을 피해야한다고 생각하지 않습니다. 라이브러리를 요구에 맞게 만드는 기능은 오픈 소스 코드 IMO를 사용하는 데 큰 도움이됩니다.
Ankit Soni

gem을 수정하려는 경우 적어도 gem을 포크하고 Gemfile이 원숭이 패치 된 gem (예 : github)을 가리 킵니다. 나는 여러 번 이것을했다. 프로세스 : 포크 보석, 포크 로컬 복제, 원숭이 로컬 버전 패치, 원격 저장소로 푸시하고 Gemfile을 가리 키십시오. (예 gem 'devise', github: 'yourusername/devise', branch: "master")
lacostenycoder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.