I have a bunch of code that hands over stuff from a logged in user's guest/lazy registered account to his new account which I run when a new session is created.
class SessionsController < Devise::SessionsController
def new
super
end
def create
super
logging_in # this is the method which will run
end
def destroy
super
end
end
It works when the user logs in. However when Devise logs a user in after confirmation, the above does not get run. Where should I put the method if I want it to run after a user logs in? whether by logging in or confirmation.
Thanks nash. Here's how I did it.
class ConfirmationsController < Devise::ConfirmationsController
def new
super
end
def create
super
end
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
logging_in # Here it is
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end
protected
def after_resending_confirmation_instructions_path_for(resource_name)
new_session_path(resource_name)
end
def after_confirmation_path_for(resource_name, resource)
after_sign_in_path_for(resource)
end
end
It needs to be added after sign_in because my logging_in method uses current_user.
Related
I'm using devise to manage authentication. I have a User model and Admin model. I want to be able to allow both users and admins soft delete user accounts.
I have implemented the soft delete for users and everything works well, however, adding functionality for admins results in a 401 unauthorized and a redirect to the user sign in page. I'm not exactly sure how to get around this.
So far I have:
config/routes.rb
...
devise_for :users
devise_scope :user do
resources :users, only: [:destroy], controller: 'members/registrations', as: :user_registration do
get 'cancel'
end
end
...
controllers/members/registrations_controller.rb
class Members::RegistrationsController < Devise::RegistrationsController
def destroy
#user = User.find(params[:id])
not_authorized unless authorized?
#user.soft_delete
user_post_destroy if is_current_user?
end
private
def authorized?
if signed_in?
is_current_user?
else
session[:session_id] == #user.author_session_token
end
end
def not_authorized
flash[:error] = t('errors.messages.not_authorized')
flash.keep
redirect_back(fallback_location: root_path)
end
def user_post_destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed
yield resource if block_given?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
def is_current_user?
#user == current_user
end
end
models/user.rb
...
def soft_delete
update_attribute(:deleted_at, Time.current)
end
def active_for_authentication?
super && !deleted_at
end
def inactive_message
!deleted_at ? super : :deleted_account
end
...
I am trying to setup a registration form using devise and AJAX.
On a newly generated app it works perfectly but when I try and add it to a project, I do not have success
registration controller
https://gist.github.com/mosinski/8568126
my partial form:
https://gist.github.com/mosinski/8577429
my application.js:
https://gist.github.com/mosinski/8577480
my inicializer:
https://gist.github.com/mosinski/8577533
my application helper:
https://gist.github.com/mosinski/8577564
my form is partial in bootstrap modal.
The whole problem is that it not sending as js but as text/html why ?! ;]
1. Routes
Have you declared the custom controllers in your routes.rb file?
#config/routes.rb
devise_for :users, controllers: { sessions: "sessions", registrations: "registrations" }
2. Forms
Are you sure you're sending the request from your partial form?
Devise generates its own views (which you can typically find at /views/devise). If you're using the standard Devise forms, you'll be sending standard HTML mime-types, and so you'll have to ensure you're using your partial
That's all I can glean from your code currently! Of course we can discuss any fixes in the comments
Update
Here's our working registrations controller:
class RegistrationsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
before_filter :configure_permitted_parameters
prepend_view_path 'app/views/devise'
# GET /resource/sign_up
def new
build_resource({})
respond_with self.resource
end
# POST /resource
def create
build_resource(sign_up_params)
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_to do |format|
format.json { render :json => resource.errors, :status => :unprocessable_entity }
format.html { respond_with resource }
end
end
end
# GET /resource/edit
def edit
render :edit
end
# PUT /resource
# We need to use a copy of the resource because we don't want to change
# the current user in place.
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
if update_resource(resource, account_update_params)
if is_navigational_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
set_flash_message :notice, flash_key
end
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords resource
respond_with resource
end
end
# DELETE /resource
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed if is_navigational_format?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
def cancel
expire_session_data_after_sign_in!
redirect_to new_registration_path(resource_name)
end
protected
# Custom Fields
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name,
:email, :password, :password_confirmation)
end
end
def update_needs_confirmation?(resource, previous)
resource.respond_to?(:pending_reconfirmation?) &&
resource.pending_reconfirmation? &&
previous != resource.unconfirmed_email
end
# By default we want to require a password checks on update.
# You can overwrite this method in your own RegistrationsController.
def update_resource(resource, params)
resource.update_with_password(params)
end
# Build a devise resource passing in the session. Useful to move
# temporary session data to the newly created user.
def build_resource(hash=nil)
self.resource = resource_class.new_with_session(hash || {}, session)
end
# Signs in a user on sign up. You can overwrite this method in your own
# RegistrationsController.
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
end
# The path used after sign up. You need to overwrite this method
# in your own RegistrationsController.
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
respond_to?(:root_path) ? root_path : "/"
end
# The default url to be used after updating a resource. You need to overwrite
# this method in your own RegistrationsController.
def after_update_path_for(resource)
signed_in_root_path(resource)
end
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
def sign_up_params
devise_parameter_sanitizer.sanitize(:sign_up)
end
def account_update_params
devise_parameter_sanitizer.sanitize(:account_update)
end
end
I'm trying to achieve that when a user deletes his account, all his activities gets also deleted.
I'm on Rails 4 - Devise - Public Activity
My Registrations Controller:
class RegistrationsController < Devise::RegistrationsController
# DELETE /resource
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed if is_flashing_format?
yield resource if block_given?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
end
To Destroy the comments record after a user deleted his comment i used:
#activity = PublicActivity::Activity.find_by_trackable_id(params[:id])
#activity.destroy
I'm searching for something similar, only to destroy all activities after account cancelation.
Anyone a good Solution ?
in User.rb add a callback:
before_destroy :delete_activities
def delete_activities
acts = PublicActivity::Activity.where(owner_id: self.id, owner_type: "User")
acts.delete_all
end
I need to convert this code in my ConfirmationsController to work in Rails 4. I'm having difficulty with the requirements for Strong Parameters. The code I'm using is directly from the Devise page
I'm pretty sure that anything I am calling with params needs to be whitelisted but I can't quite figure out how to do that in this case. What is the best way to accomplish this.
class ConfirmationsController < Devise::ConfirmationsController
def show
self.resource = resource_class.find_by_confirmation_token(params[:confirmation_token]) if params[:confirmation_token].present?
super if resource.nil? or resource.confirmed?
end
def confirm
self.resource = resource_class.find_by_confirmation_token(params[resource_name][:confirmation_token]) if params[resource_name][:confirmation_token].present?
if resource.update_attributes(params[resource_name].except(:confirmation_token).permit(:password, :password_confirmation)) && resource.password_match?
self.resource = resource_class.confirm_by_token(params[resource_name][:confirmation_token])
set_flash_message :notice, :confirmed
sign_in_and_redirect(resource_name, resource)
else
render action: "show"
end
end
end
Try this:
class ConfirmationsController < Devise::ConfirmationsController
def show
self.resource = resource_class.find_by_confirmation_token(confirmation_token) if confirmation_token.present?
super if resource.nil? or resource.confirmed?
end
def confirm
self.resource = resource_class.find_by_confirmation_token(confirmation_token) if confirmation_token.present?
if resource.update_attributes(resource_params) && resource.password_match?
self.resource = resource_class.confirm_by_token(confirmation_token)
set_flash_message :notice, :confirmed
sign_in_and_redirect(resource_name, resource)
else
render action: "show"
end
end
private
def resource_params
# pry
# debugger
params.require(resource_name).permit :password, :password_confirmation
end
def confirmation_token
params.require(resource_name).permit :confirmation_token
end
end
More info: https://github.com/rails/strong_parameters
If you continue having trouble I'd recommend stuffing a debugger or pry in the middle and manipulating the params with permit | require until you have what you'd expect.
I need to call method before update to check if PayPal details are correct.
I added in User.rb this:
before_update :verify
private
def verify
require 'httpclient'
require 'xmlsimple'
clnt = HTTPClient.new
....
if account_status == "VERIFIED"
current_user.verified = "verified"
current_user.save
flash[:notice] = "Your account is verified"
else
redirect_to :back
flash[:error] = "Sorry, your account is not verified or you entered wrong credentials"
end
else
redirect_to :back
flash[:error] = "Your account is not verified or you entered wrong credentials"
...
end
end
EDIT:Tried this:
class RegistrationsController < Devise::RegistrationsController
before_filter :verify, :only => :update
def verify
...
end
end
but it isn't calling.
Maybe I should call if from here(but I don't know how and where) :
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
redirect_to :back
flash[:error] = "Your email has been already taken!"
end
end
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
params[:user].delete(:password) if params[:user][:password].blank?
params[:user].delete(:password_confirmation) if params[:user][:password_confirmation].blank?
if resource.update_attributes(params[resource_name])
set_flash_message :notice, :updated if is_navigational_format?
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords(resource)
respond_with_navigational(resource){ render_with_scope :edit }
end
end
Can someone notice some errors in code ?
In User.rb, use before_save macro instead of before_update since before_update does not exist
One more thing, in your User model, flashis not accessible since it is only injectid in controller. You shout throw validation error instead or
class User < ActiveRecord::Base
before_save :verify
private
def verify(record)
#... do checking ... and on error
record.errors ... #is accesable, set your error here if you want to read it in controller
# rise here error if you want
end
end
More about activerecord callbacks
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Here is right answer:
class RegistrationsController < Devise::RegistrationsController
before_filter :verify, :only => :update
def verify
...
end
end
Thanks for helping me