I want to allow authorized users to create (and destroy) user accounts. I have gotten this part working according to hints I found in this and other questions.
But I also want to prevent unauthorized users from creating and destroying accounts.
I have my own registration_controller:
class RegistrationsController < Devise::RegistrationsController
skip_before_action :require_no_authentication, only: [:new, :create, :destroy]
skip_before_action :authenticate_scope!, only: [:destroy]
before_action :authenticate_user!, only: [:new, :create, :destroy] # why doesn't this work?
def new
super
end
def sign_up(resource_name, resource)
# don't sign in as the new user
end
def destroy
User.find(params[:id]).destroy
redirect_to(users_path)
end
end
And have directed my routes to use it in routes.rb:
# Standard devise setup but allow registration when logged in
# https://stackoverflow.com/a/31946248/1404185
devise_for :users, controllers: {:registrations => "registrations"}
# Work around already-existing session controller
# https://stackoverflow.com/a/21024350/1404185
devise_scope :user do
post '/sessions/user', to: 'devise/sessions#create', via: :post
delete '/users/:id', to: 'registrations#destroy', via: :delete
end
# Show and index for users
# https://stackoverflow.com/a/32056094/1404185
resources :users, :only => [:show,:index]
For some reason before_action :authenticate_user! does not work... unauthenticated users can still invoke these actions. I've also tried prepend_before_action :authenticate_user!, and I've tried putting the filters in different orders-- invoking the before_action first in my controller.
I've just upgraded my app to rails 6.0.3.5 and added devise 4.7.1.
Why do I want this unusual setup? This is a hobby project and only my girlfriend and I are users. We don't want just anybody on the internet to sign up. But we occasionally may want to give another person access, who will be sitting next to us (pandemic permitting) when creating their account.
I do have a workaround for now: Since the site will have an obfuscated URL and since it is an extremely low value target (I can't imagine anyone would be interested in our home inventory) I simply don't provide a link to the signup page unless someone is logged in. This opens the possibility that a knowledgeable hacker could craft a request manually, but the risk is very very low.
But I still like to do things the "right" way, so I am asking this question. I have looked at devise_invitable but that seems way too complex for my needs.
UPDATE: One experiment I tried was instead of instead of inheriting from Devise::RegistrationsController and overriding methods, I just copied it to my registrations_controller and edited it. Then I deleted the :require_no_authenticaton and :authenticate_scope! prepend_before_actions and replaced them with prepend_before_action :authenticate_user!
This should eliminate doubt about whether the before_actions were being processed in the wrong order and ensure that only :authenticate_user! was being called.
The experiment failed. Apparently :authenticate_user! always returns true at this point whether or not a user is really authenticated. Why?