I have gem devise and gem apartment which I want to use to create separate schema for each user. I'm looking for a good way to call Apartment::Database.create(current_user) when user sign_up.
I found this at devise's registrations_controller.rb:
# 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
but I'm not sure how it should be done.
I suppose it can be something similar to this at application_controller.rb:
def sign_up(user)
super user
Apartment::Database.create(current_user.username)
end
I wrote this looking at this sign_in override example but I have some concerns:
about user argument as super function uses different parameters (resource_name, resource).
I wish to call Apartment::Database.create only if user signed up successfully.
I'm not sure but I think user can be used here instead of current_user method (assuming it's used to sign up new user).
What about putting the create call at User model as after_create hook ? Is it a good idea ?
that way at model/User.rb
after_create :create_schema
private
def create_schema
Apartment::Database.create(self.username)
end
Above code seams to work fine but I'm not sure if it's a proper way and I would like to ask you to comment override concerns even if it is.
Thanks in advance for your help.
Related
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?
When I use a link from confirmation email to confirm my account, I'm redirected to login path, which is fine.
But for some users I want to skip confirmation, so I've applied a code like below in before validation collback:
if foo?
self.skip_confirmation!
end
Problem is that when I register as that user I'm auto logged, is it any way to prevent it ? I want to skip confirmation but not autologin.
You could try overriding devise's RegistrationsController and only override the sign_up method. The comment for that method in the devise source says "Signs in a user on sign up. You can overwrite this method in your own RegistrationsController". You could then override it like so:
def sign_up(resource_name, resource)
if !foo? # or you could use "if !resource.confirmed?" instead.
super # The current implementation just calls sign_in(resource_name, resource)
end
end
I haven't actually done this myself, but hopefully this helps.
I am using devise for authentication, devise automatically sign in after signing up,
i need just sign up but not sign in.
There is similar question link but it didn't help me
Disclaimer: The following code is not verified in my practice. Just in theory they are likely to work.
At first you need to use your custom RegistrationsController. You can check how to do that in Devise wiki.
After setting up, things are fairly easy. Do the following in your custom controller
class Users::RegistrationsController < Devise::RegistrationsController
def create
super #Nothing special here.
end
protected
def sign_up(resource_name, resource)
true
end
end
How does it work? In Devise's code, #create will call a protected method #sign_up after saving successfully. This method does nothing but sign in the user. What we need to do is to overwrite this method to stop that action. Of course you can even add more of your logic here if necessary.
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
I'm using Devise for authentication in my rails app and I'd like to be able to block certain accounts and prevent users from reregistering with a blocked email. I'm just not sure what the best way is to go about it.
My first thought was to override the sessions and registrations controllers to check the model for a user with a blocked bit, but I have a feeling there might be a more elegant way.
The best approach is to do it in Devise way:
Below assumes that you are using Devise database_authenticatable module and your application's users model names User.
1. Implement an account_active? method.
Add boolean account_active column in users table or define account_active? method in User model (you can chose your own method name). For example:
# app/models/user.rb
def account_active?
blocked_at.nil?
end
2. Overwrite the active_for_authentication? method in your model (User).
# app/models/user.rb
def active_for_authentication?
super && account_active?
end
3. Add method which returns translation for flash message.
Whenever active_for_authentication? returns false, Devise asks the reason why your model is inactive using the inactive_message method.
# app/models/user.rb
def inactive_message
account_active? ? super : :locked
end
And that's it. You don't need to care about sign_out or redirect_to user.
Moreover, user is locked immediately, with next request, not after next sign in.
More: devise/authenticatable.rb.
I would do it like this:
def after_sign_in_path_for(resource)
if resource.is_a?(User) && resource.banned?
sign_out resource
banned_user_path
else
super
end
end
A better solution is to override the active_for_authentication? method on the devise model (User). Like so:
def active_for_authentication?
super && !self.banned?
end