scambra / devise_invitable

An invitation strategy for devise
MIT License
2.65k stars 551 forks source link

Devise invitable breaks devise custom controllers #877

Open jonibatista opened 2 years ago

jonibatista commented 2 years ago

Steps to reproduce

Before adding devise_invitable gem my route files looked like this:

Rails.application.routes.draw do
  ...
  devise_for :users, module: :users
  devise_scope :user do
    get 'sign_in', to: 'users/sessions#new'
    get 'sign_up', to: 'users/registrations#new'
    get 'activate_account', to: 'users/confirmations#activate_account'
  end
  ...
end

I used module users to customize my devise controllers.

          new_user_session GET    /users/sign_in(.:format)            users/sessions#new
              user_session POST   /users/sign_in(.:format)            users/sessions#create
      destroy_user_session DELETE /users/sign_out(.:format)           users/sessions#destroy
         new_user_password GET    /users/password/new(.:format)       users/passwords#new
        edit_user_password GET    /users/password/edit(.:format)      users/passwords#edit
             user_password PATCH  /users/password(.:format)           users/passwords#update
                           PUT    /users/password(.:format)           users/passwords#update
                           POST   /users/password(.:format)           users/passwords#create
  cancel_user_registration GET    /users/cancel(.:format)             users/registrations#cancel
     new_user_registration GET    /users/sign_up(.:format)            users/registrations#new
    edit_user_registration GET    /users/edit(.:format)               users/registrations#edit
         user_registration PATCH  /users(.:format)                    users/registrations#update
                           PUT    /users(.:format)                    users/registrations#update
                           DELETE /users(.:format)                    users/registrations#destroy
                           POST   /users(.:format)                    users/registrations#create
     new_user_confirmation GET    /users/confirmation/new(.:format)   users/confirmations#new
         user_confirmation GET    /users/confirmation(.:format)       users/confirmations#show
                           POST   /users/confirmation(.:format)       users/confirmations#create
           new_user_unlock GET    /users/unlock/new(.:format)         users/unlocks#new
               user_unlock GET    /users/unlock(.:format)             users/unlocks#show
                           POST   /users/unlock(.:format)             users/unlocks#create
                   sign_in GET    /sign_in(.:format)                  users/sessions#new
                   sign_up GET    /sign_up(.:format)                  users/registrations#new
          activate_account GET    /activate_account(.:format)         users/confirmations#activate_account

Then I added devise_invitable without customizing its controller but my registrations controller was overridden by devise_invitable gem.

...
cancel_user_registration GET    /users/cancel(.:format)    devise_invitable/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)   devise_invitable/registrations#new
  edit_user_registration GET    /users/edit(.:format)      devise_invitable/registrations#edit
       user_registration PATCH  /users(.:format)           devise_invitable/registrations#update
                         PUT    /users(.:format)           devise_invitable/registrations#update
                         DELETE /users(.:format)           devise_invitable/registrations#destroy
                         POST   /users(.:format)           devise_invitable/registrations#create
...

Temporary fix

I was able to bypass the problem by specifying each overridden controller in my routes file.

Rails.application.routes.draw do
  ...  
  # devise_for :users, module: :users
  # replaced by:
  devise_for :users, controllers: {confirmations: "users/confirmations", passwords: "users/passwords", 
    registrations: "users/registrations", sessions: "users/sessions", 
    unlocks: "users/unlocks"}
  ...
end

        new_user_session GET    /users/sign_in(.:format)            users/sessions#new
            user_session POST   /users/sign_in(.:format)            users/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)           users/sessions#destroy
       new_user_password GET    /users/password/new(.:format)       users/passwords#new
      edit_user_password GET    /users/password/edit(.:format)      users/passwords#edit
           user_password PATCH  /users/password(.:format)           users/passwords#update
                         PUT    /users/password(.:format)           users/passwords#update
                         POST   /users/password(.:format)           users/passwords#create
cancel_user_registration GET    /users/cancel(.:format)             users/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)            users/registrations#new
  edit_user_registration GET    /users/edit(.:format)               users/registrations#edit
       user_registration PATCH  /users(.:format)                    users/registrations#update
                         PUT    /users(.:format)                    users/registrations#update
                         DELETE /users(.:format)                    users/registrations#destroy
                         POST   /users(.:format)                    users/registrations#create
   new_user_confirmation GET    /users/confirmation/new(.:format)   users/confirmations#new
       user_confirmation GET    /users/confirmation(.:format)       users/confirmations#show
                         POST   /users/confirmation(.:format)       users/confirmations#create
         new_user_unlock GET    /users/unlock/new(.:format)         users/unlocks#new
             user_unlock GET    /users/unlock(.:format)             users/unlocks#show
                         POST   /users/unlock(.:format)             users/unlocks#create
  accept_user_invitation GET    /users/invitation/accept(.:format)  devise/invitations#edit
  remove_user_invitation GET    /users/invitation/remove(.:format)  devise/invitations#destroy
     new_user_invitation GET    /users/invitation/new(.:format)     devise/invitations#new
         user_invitation PATCH  /users/invitation(.:format)         devise/invitations#update
                         PUT    /users/invitation(.:format)         devise/invitations#update
                         POST   /users/invitation(.:format)         devise/invitations#create
                 sign_in GET    /sign_in(.:format)                  users/sessions#new
                 sign_up GET    /sign_up(.:format)                  users/registrations#new
        activate_account GET    /activate_account(.:format)         users/confirmations#activate_account

Any reason for this behavior or is it something that can be improved?

System configuration

Rails version: 7.0.3.1

Ruby version: 3.0.2p107

scambra commented 2 years ago

Maybe I didn't know the option :module, or it was added after I created this gem. It must be fixed in lib/devise_invitable/mapping.rb

Can you try changing it to this?

      def default_controllers(options)
        unless options[:module]
          options[:controllers] ||= {}
          options[:controllers][:registrations] ||= 'devise_invitable/registrations'
        end
        super
      end

Otherwise, I will test it when I have more time

chrise86 commented 1 year ago

Maybe I didn't know the option :module, or it was added after I created this gem. It must be fixed in lib/devise_invitable/mapping.rb

Can you try changing it to this?

      def default_controllers(options)
        unless options[:module]
          options[:controllers] ||= {}
          options[:controllers][:registrations] ||= 'devise_invitable/registrations'
        end
        super
      end

Otherwise, I will test it when I have more time

@scambra this works well for me 👍