I am using devise and i am trying to update extra fields has user log in. So in order for me to be able to update my user.longitude i had to create in new controller who is acting has the rails controller sessions. Here the code I have
class MysessionsController < Devise::SessionsController
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
self.resource.longitude = params[:longitude]
self.resource.update_attributes(params[:longitude])
respond_with resource, :location => after_sign_in_path_for(resource)
end
end
I know it doesn't follow restfull and it doesnt work but i need to be able to update my user field and i am not sure how to do, this doesn't give me anything wrong, but it doesn't also modify it properly. Thank for any help
Your line:
self.resource.update_attributes(params[:longitude])
Might return false if the record is invalid and silently fail. Check that out first.
Second, you might want to take a look into alias_method_chain instead of copying the content of the create action of your inherited controller.
Otherwise, this is to update a record after a user logged in. You should save the longitude AFTER he signs in. Wherever you redirect the user after he signs in, let the following call handle the longitude update. Easy way could be to store the longitude in session if it needs to survive.
Related
in my project I'm using devise and I want to create custom sign_in. I decided to override create action in SessionsController. Right now my SessionsController looks like that:
class SessionsController < Devise::SessionsController
def create
user_signed_in? # -> gives true if correct email and password
if !current_user.new_one? # -> I have access to current_user
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_flashing_format?
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
# even if condition is true, user is signed_in
end
end
I'm a little confused because even if I remove whole code from there then user will be signed_in anyway. Can someone explain me why user_signed_in? gives me true before sign_in(resource_name, resource)? It looks like the user is already logged in? In that case, how can specific users not be allowed to log in? I know there is method active_for_authentication?, but I don't want to override it, because I want to allow some users to log in to only part of the application, this method will not allow it and overriding this method will not allow me to do it.
When overriding Devise::SessionsController, you still expect some authentication over the params you have parametered (usually email/password).
user_signed_in? method does not the authentication, it's just a helper and it can check if the formerly processed authentication has succeded in the past or not.
The authentication is achieved with use of 'super' at some point of your code.
See :
https://rubydoc.info/github/heartcombo/devise/main/Devise/Controllers/SignInOut#signed_in%3F-instance_method
to find an answer to your first question
https://github.com/heartcombo/devise#controller-filters-and-helpers
https://github.com/heartcombo/devise#configuring-controllers (use of
super)
Hope it helps
I need to alter the Sessions controller create method to first check if the user has a column filled out for deactivation_date.
If that column has a value, the user IS deactivated and the sign in authentication should fail in the same way as if the user doesn't exist.
class Users::SessionsController < Devise::SessionsController
def create
logger.debug('create')
self.resource = warden.authenticate!(auth_options)
if self.resource.deactivation_date?
logger.debug('user has been deactivated')
flash.now[:notice] = "Sorry, this account has been deactivated."
else
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)
respond_with resource, location: after_sign_in_path_for(resource)
end
end
end
I've tried overriding the sessions controller as well as the create method.
My code above is only preventing a redirect. Once I refresh the page, the user is authenticated no matter what.
Could someone help point me in the right direction?
The most simple way to do this is really just add a custom valid_for_authentication? method in the resource devise is using, so in Users.rb:
def valid_for_authentication?
super && !deactivation_date?
end
Thanks to this question: Check if user is active before allowing user to sign in with devise (rails)
I was able to simply add a method to my User model and devise picked it up automatically
In my user model:
def active_for_authentication?
super && !self.deactivation_date
end
I didn't know at first the method name was specific to devise. has to be exactly active_for_authentication?
I have an app that allows a user to access it as a guest. My approach to this problem is to automatically add a user if there isn't one in session and set an is_guest flag on the user object. When/if the user creates an account, it actually updates the user credentials rather than creating a new user. This works perfectly.
I'm running into a corner case when the user tries to log into an existing account after having a guest user. I initially ran into trouble with the Devise before_action :require_no_authentication hook, which I had to override:
def require_no_authentication
return if user_signed_in? and current_user.is_guest?
super
end
That allows the user to actually hit the login page. But when the user submits the form, the default Session::create method in Devise isn't working:
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_flashing_format?
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
The problem is that, since the session already exists, the sign_in method does nothing. How can I swap out the user without invalidating the session?
Rails: 4.0.0,
Devise: 3.0.0rc
Devise seems not to add error messages to models at all, delegating that to validations. That's fine generally. But in the case of the SessionsController, would it make sense to add the errors to the model so that you can use field_with_errors or some such functionality and say 'email is required' if the user does not put their email in.
The snippet below is where I think I would have to modify Devise to get it to add errors to the model.
class Users::SessionsController < Devise::SessionsController
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
debugger
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_in_path_for(resource)
end
end
Does anyone have any recommendations on what to do? Is it even a good idea to add errors to the model on sign in via something like the following? error.add(:model, "error message")
It just seems that if I use the default flash[:notice] message, then I miss out on being able to attach the error messages to specific fields, which is my aim.
Your concept is right with any other controllers except SessionsController.
Such vague information is desired for signing in activity. If an user inputted wrong information, he can only see "Invalid email or password" or something similar but not precise error.
The reason is to reduce the chance of brute signing trials.
I'm using Devise to handle authentication in a Rails app, and I'm using permanent_records to soft delete users. The default scope for my User model is the undeleted users. If a user deletes (deactivates) his account, I want him to be able to reactivate his account by logging in, similar to the way Facebook does it. Problem is, since Devise doesn't know to look for deleted users, no account is found. I thought about overriding the sessions#create method
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_in_path_for(resource)
end
But since this is handled by Warden, it seems I'm out of luck. I'm afraid that if I start digging too deep I'm going to start breaking things.
Any ideas?
Thanks!
You need:
Overwrite find_for_authentication method in User model to allow finding for any users https://github.com/plataformatec/devise/blob/master/lib/devise/models/authenticatable.rb#L229
Redefine after_database_authentication method in your model to remove deleted flag here https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb#L98
That is all, I believe. No need to touch controller actions.
this works with the paranoia gem:
class << self
def find_for_authentication(conditions)
User.unscoped do
user = super(conditions)
user.restore!(recursive: true) if user.deleted?
user
end
end
end