I'm attempting to configure a devise :confirmable
account, in which a user selects his password once he confirms the account (this is an officially documented modification, the details of which can be found here).
The problem: Without the modification (in which I set the password when I first create the account), the confirmation works just fine. However, under the modification I get a 401 error (unauthorized). The log of which is below:
Started POST "/users/sign_in" for 192.168.1.8 at 2016-01-31 01:53:54 -0700
Processing by Users::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"O7mUtX/5i3Cw2sgAtn8+i4VAuytkHpcxZ0ZnKL6rmfmQsRj0MblP4OGY4K3dxqXQ7qjVMsqpYEIs7Oqkm9G3JA==", "user"=>{"email"=>"neanderslob@neanderslob.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "button"=>""}
^[[1m^[[36mUser Load (0.8ms)^[[0m ^[[1mSELECT "users".* FROM "users" WHERE "users"."email" = $1 ORDER BY "users"."id" ASC LIMIT 1^[[0m [["email", "neanderslob@neanderslob.com"]]
^[[1m^[[35m (0.2ms)^[[0m BEGIN
^[[1m^[[36m (0.1ms)^[[0m ^[[1mCOMMIT^[[0m
Completed 401 Unauthorized in 70ms (ActiveRecord: 1.1ms)
Of course no password was entered, as this shouldn't be necessary.
Attached is my custom ConfirmationsController
class Users::ConfirmationsController < Devise::ConfirmationsController
# Remove the first skip_before_filter (:require_no_authentication) if you
# don't want to enable logged users to access the confirmation page.
skip_before_filter :require_no_authentication
skip_before_filter :authenticate_user!
# GET /resource/confirmation/new
def new
super
end
# POST /resource/confirmation
def create
super
end
# GET /resource/confirmation?confirmation_token=abcdef
def show
with_unconfirmed_confirmable do
if @confirmable.has_no_password?
do_show
else
do_confirm
end
end
unless @confirmable.errors.empty?
self.resource = @confirmable
render 'devise/confirmations/new' #Change this if you don't have the views on default path
end
end
# PUT /resource/confirmation
def update
with_unconfirmed_confirmable do
if @confirmable.has_no_password?
@confirmable.attempt_set_password(params[:user])
if @confirmable.valid? and @confirmable.password_match?
do_confirm
else
do_show
@confirmable.errors.clear #so that we wont render :new
end
else
@confirmable.errors.add(:email, :password_already_set)
end
end
if !@confirmable.errors.empty?
self.resource = @confirmable
render 'devise/confirmations/new' #Change this if you don't have the views on default path
end
end
protected
# The path used after resending confirmation instructions.
def after_resending_confirmation_instructions_path_for(resource_name)
super(resource_name)
end
# The path used after confirmation.
def after_confirmation_path_for(resource_name, resource)
super(resource_name, resource)
end
def with_unconfirmed_confirmable
@confirmable = User.find_or_initialize_with_error_by(:confirmation_token, params[:confirmation_token])
if !@confirmable.new_record?
@confirmable.only_if_unconfirmed {yield}
end
end
def do_show
@confirmation_token = params[:confirmation_token]
@requires_password = true
self.resource = @confirmable
render 'devise/confirmations/show' #Change this if you don't have the views on default path
end
def do_confirm
@confirmable.confirm!
set_flash_message :notice, :confirmed
sign_in_and_redirect(resource_name, @confirmable)
end
end
Some wild speculation: It also might be worth mentioning that this is all being done on my localhost. This means that the url it generates is from http://localhost:3000... where my app is built to respond to a custom domain. Before the customization, I was able to just change the confirmation link from localhost:3000
over to mydomain.com:3000
and everything was alright. However I don't know if this isn't allowed under my customization (honestly don't have a deep enough knowledge to say one way or another for sure).
Anyway, thanks for any ideas you might have!
Edit: My sessions controller (the relevant controller to the error message, as was pointed out to me) is as follows... note the commented out create method
class Users::SessionsController < Devise::SessionsController
# GET /resource/sign_in
def new
super
end
# POST /resource/sign_in
# def create
# super
# end
# DELETE /resource/sign_out
def destroy
super
end
end