Customize Devise sign_in to accommodate two flows - ruby-on-rails

I'm using Rails 4.0 and Devise 3.3.0
I have two sign_in flows I'd like to provide. One that is the usual sign_in and another that transfers a bunch of photos a guest_user uploaded to the current_user's account. I have the functionality working for each of these so that isn't a problem.
For the guest -> signed_in flow, I basically want to sign the user in and then transfer the content.
It looks like:
def sign_in_and_save (resource_or_scope, *args)
super
move_content guest_user, current_user
end
The problem is I'm not sure how to tell Devise to use this method for this scenario instead of the usual sign_in flow. I could modify the current sign_in method, but I would still have to pass a parameter in the form (I'm assuming) to tell the method there is a special case.
The views are the same. In scenario 1 I display: Sign In and scenario 2 I display: Sign In and Save in the navigation.
Is there a preference and why and how would I go about it?

Related

Sign-Out Any Other Devise User Types On Sign-In

I have three Devise User types: Admin, User and Subscriber. I would like to ensure that if a User signs in (or registers), any current_admin or current_subscriber is signed out, and likewise for each of the other user types, so essentially only a single user type can be signed in at one time.
It doesn't seem that Devise handles this out of the box. Handling this in a subclassed sessions controller doesn't seem like the correct approach as this would not work in cases where a user was signed in after registration.
It appears that Devise:DatabaseAuthenticatable::after_database_authentication might be appropriate. But this means exposing Devise ..._signed_in? to each user type model. And this doesn't really belong in a model anyway.
# Post authentication hook
def after_database_authentication
sign_out current_user if user_signed_in?
sign_out current_subscriber if subscriber_signed_in?
end
However placing the logic in a subclass of the Devise::SessionsController isn't much good as this will never get run during/after registration.
How should I handle this?

How to programmatically sign in a user through Devise in Rails

I need to have a custom mechanism for signing in using Devise with Rails 4. So I found the sign_in method in Devise's test helpers section of their documentation:
sign_in #user # sign_in(resource)
But is that the proper way to sign someone in from the web? In particular, will it do all the things Devise does when a user signs in, like recording the date/time stamps, IP addresses, sign in counts, etc? Or is this just for testing purposes?
Devise offers a bunch of helpers, two of which are these:
sign_in(resource_or_scope, *args)
sign_in_and_redirect(resource_or_scope, *args)
You can use these from any controller.
If using sign_in already works for you but leaves the user on a blank page, check your logfile to see if there is a redirect going on, and where it redirects to. Or just make the redirect explicit by using the second of the helpers above.
References:
https://stackoverflow.com/a/8123646/2034097
It is the proper and standard way to programatically sign a user in. Looking at the devise login code sessions#create you can see they use this method as well.
Long story short: Yes, sign_in #user does all the things that devise would normally do when a user signs in. It could be useful, for example, allowing an Administrator to sign in as one of their users.
How To: Sign in as another user if you are an admin

Logout users with devise gem rails

In admin section, I'm showing a list of currently logged in users.
Now admin can select one or more user/users and destroy their session(logout them).
I'm not able to figure where to start from,please help me.
You can use the sign_out method in the controller action by passing in the user object:
# Make sure only admins can do this
def sign_out_user
#user = User.find(params[:id])
sign_out #user
end
More info here:
http://rubydoc.info/github/plataformatec/devise/master/Devise/TestHelpers%3asign_out
Considering users is the collection of your required users,
for user in users
sign_out user
end
It should solve your issue.
Hope it helps :)
The sign_out method provided by Devise won't help. I know the documentation says that it will logout the "resource" you requested, but if you dig into the gems themselves (devise and warden) you'll find that when you give it an object, like a user, it merely figures out what scope (ie, :user) that object belongs to, and it logs out that entire scope.
A scope in Devise is a namespace for logins. You might have a Customer model that requires logins, but also a Vendor model that also requires logins, and you'd use different scopes for those. Most applications only use a single scope, tied to the User model.
You're probably using :cookie_store for your session storage, which is the Rails default. In this case, it isn't possible to log out any single user except yourself. Devise stores your login info in the session, which is stored in a cookie, and not in your database. Their browser has the credentials, so you can't directly remove that.

How to redirect based on the type of model in devise?

I am working on a new rails 3 application. In this application I have 2 different types of resources(admin and garage) both with different views and with 2 different login screens using devise. The admin can create a garage and can generate a password for the garage using which the garage manager can login to the application. Till now I am able to implement this.
One problem that I am facing in the above implementation is that the garage manager, once logged in, is able to view the admin section by changing the url in the browser and can make changes like an admin user.
Now what I am trying to implement is to have a single log in/sign in form for both the models and when someone logs in, depending on their model type they should be redirected to their respective views. Also, I would like to restrict all the users but admin from using the admin section.
What should be my approach to implement this. I am using devise for authentication.
resource is an instance of one of your models here:
def after_sign_in_path_for(resource)
return admin_route_path if resource.is_a?(Admin)
return garage_route_path if resource.is_a?(Garage)
end
resource is a symbol of the model name here:
def after_sign_out_path_for(resource)
return "/admin" if resource == :admin
return "/" if resource == :garage
end
Normally goes in application_controller.rb
One problem that I am facing in the above implementation is that the garage manager, once logged in, is able to view the admin section by changing the url in the browser and can make changes like an admin user.
As for this, it's an authorization problem and not an authentication problem. Though you can do some simple stuff within devise to manage this, like an admin flag or something of that nature so you can differentiate the two. Just redirecting won't solve this issue entirely.
Take a look at cancan, declarative authorization and I'm sure there are many others.

Rails 3 Devise confirmation filter

I'm wondering if it's possible to selectively require confirmation for certain controller actions using Devise.
Basically: I want users to sign up for an account (which will trigger a confirmation email), be automatically logged in, and be able to immediately explore certain parts of the site as a signed in (but still unconfirmed) user. Access to certain areas (e.g., payment) would require the user to first confirm their email.
I'm hoping for something like before_filter: user_is_confirmed, only: [payment_related_stuff]
I searched for a while and could not find a way to do this out of the box, so I thought creating a hacky solution in which all possibly protected areas would still require before_filter: authenticate!, but I would override the Devise SessionsController's create to permissibly allow access to certain areas before confirmation. However, I'm not sure if this is the right way to go.
Using built in solution in devise, you could use allow_unconfirmed_access_for 1.year in combination with current_user.confirmed? in your before filter

Resources