Is the user logged in? (restful-authentication) - ruby-on-rails

I have used restful-authentication and I have "public" layout and a completely different "members" layout. When someone visits my root (defaults to public) how can I check if they are logged in and redirect them to the member's section?

RestfulAuthentication provides some conditional methods/helpers including one called logged_in?. It returns true if the user is logged in.
Check out the authenticated_system.rb file for the list of all available methods.

You could define a method like this in application_controller.rb:
private
def require_user
# logic to check if session exists and redirect if not
end
Then add the following in your pages that require that the user be logged in:
before_filter :require_user
I'm not familiar with restful-auth so I don't know the exact check that would be required.
Good luck.

Related

How do you make sure that after sign in the user completes the profile form first before they can use the rest of the website functions.

How do you make sure that after sign in the user completes the profile form first before they can use the rest of the website functions. I am trying to make sure that after the member has completed the sign up form and then completes there email confirmation with devise that when they sign in that when they are redirected to the new_member_profile_path(current_member) form that they stay on this page and that if they decide to go to a link and click that that they will automatically be redirected back to the complete your profile page with the notice before please complete your profile first. I have it set already once they have completed the form they will be redirected to their member's page. I have looked in multi-forms with wicked - I really feel that because I am still am a Novice rails developer that this would be unnecessary. I am thinking about putting an if clause in the application.html.erb where the site nav template is based and putting a clause with <% if current_member_profile.blank ? %> then redirect back to new_member_profile_path(current_member) with a flash notice tag written in the html file. I have tried this if clause but does not work - comes up as undefined method. Please could someone point me in the right direction or give me the simple solution of getting this idea to work. Thanks in advance ;)
There are various approaches to achieve what you're trying to do. Perhaps the cleanest with the least amount of code needed would be to first authenticate the user with Devise's own authenticate_user! filter and then check for a field that can only be there when the profile has been filled in.
# in user.rb
def has_completed_profile?
first_name.present?
end
# in application_controller.rb
before_action :authenticate_user!
before_action :require_user_profile
private
def require_user_profile
# nothing needs to be done if the profile was already filled in
return if user_signed_in? && current_user.has_completed_profile?
redirect_to edit_profile_url, alert: "Please complete your profile first!"
return false
end
Notice how I've extracted has_completed_profile? into the User model instead of putting the name check directly into the controller. This way, if you need to change the logic of what makes a profile "complete", you don't need to touch the controller at all ("complete profile" is a business concept, not a routing/HTTP concept and thus doesn't belong in the controller).
In controllers where you don't want the additional profile check – e.g. the controller where the user actually completes their profile, where they presumably need to be logged in but can't have a profile yet – you just skip the additional filter:
# in profiles_controller.rb
skip_before_action :require_user_profile
Side note: Over the years I've learned that it's best to keep things like profile data, address data, phone numbers and what not in a separate model and don't extend Devise's User model. This prevents various issues and keeps the already huge User model (Devise includes dozens of methods into it and turns it into a God Object as it is) a bit slimmer. And if you think about it, it also makes sense in terms of business logic: A user has_one profile, has_one address (or has_many addresses) etc.
Hope that's clear.
You can add a new method in the application_controller.rb
For eg
def current_member_profile
current_user.name.blank?
end
Check the params which should not be blank when creating a member profile. I have added 'name' here for example. if the params is blank, then it will redirect as you have specified in your application.html.erb
Instead for putting an if condition on the application.html.erb, You can use a before_action in your application_controller.
Something like this.
application_controller.rb:
before_action :check_for_profile_completion
def check_for_profile_completion
// your code of redirection to the page if the profile is incomplete
end
Also you can skip this action on controller which you don't wanna restrict user to go. Like
skip_before_action :check_for_profile_completion, only: [://actions you wanna skip seperated by comma]

How to make devise gem go to specific page when the option 'Remember me' is ticked?

So, a returning user in my app who has ticked "Remember me" has to land in a different page inside the app instrad of the home page and being logged in there.
I went through the documentation but i cant find a function that does this.
I also struggle into make devise go to a different page when the user updates the profile and i use wrong methods for this. Can you give me the correct method and where to put it as well?
I tried using the method 'after_remembered' in my ApplicationController but it doesn't work while the method after_sign_in_path_for works!
Do i need to overwrite something?
Devise sets a remember_created_at value for the user if "Remember Me?" is selected. In the after_sign_in_path_for you could have it check for resource.remember_created_at and then perform the redirect there.
A quick example would be in app/controllers/application_controller.rb
def after_sign_in_path_for(resource)
resource.remember_created_at ? path_for_remember : path_not_for_remember
end
To handle redirects after updates you want to use the after_update_path_for which is set up the same way:
def after_update_path_for(resource)
some_path
end

How to set a session variable after sign in with Devise?

I'm trying to find out where to set a session variable once a user has logged in using Devise. I found this post (and others):
Set a session variable in devise on sign in
So I tried something like this:
protected
# when a user logs in
def after_sign_in_path_for(resource_or_scope)
session[:current_account_id] = current_user.accounts.find_by_is_default(true).id # get id of row where it's is_default is set as true
abort(session[:current_account_id])
end
..but no joy. I don't want to do an alternative redirect (as the issue in the link was asking), just set a session variable when the user logs in, so I'm not sure if this is the callback I'm wanting. Also, I may have my find_by_ method wrong but I was hoping I could debug (using abort) once the script gets that far - but it doesn't appear to be as abort doesn't seem to be called. Any help much appreciated. Thanks
Make sure the protected method is located inside of ApplicationController.

Have different view based on type of user

I have a user model that has a few different types, i.e. there is a user attribute that is set as either a usertype1, usertype2, or usertype3. How can I route the user to a different page based on the user type? I am using devise for authentication.
If you want to redirect the user after logging in then check this devise wiki. The specific code is
# app/controllers/application_controller.rb
def after_sign_in_path_for(resource)
if usertype1?
some_url
elsif usertype2?
another_url
elsif usertype3?
some_other_url
end
end
But if what you're looking for is more generic then that you probably want to define roles and give users access to certain parts of the site based on their roles - also known as authorization. For that I'd recommend using cancan. You can also watch the railscast episode if you want more info.
Edit:
See also this so question

rails devise hook into on_login

I'm looking to hook into devise after login / after session create. How would I go about doing this?
Basically I want to set a users location every time they login, and to do that I need an after login hook of sorts.
Devise is built on Warden, so you can use Warden's after_authentication hook.
Put this in an initializer:
Warden::Manager.after_authentication do |user,auth,opts|
# do something with user
end
The remote IP address and other request info is stored in auth.request (i.e. auth.request.remote_ip).
See https://github.com/hassox/warden/wiki/callbacks
Devise updates the value of the user.current_sign_in_at timestamp on successful login. So, you could simply add a before_save filter to your User model. In that filter, check to see if the value of this field has changed, and if it has, set the users location.
BTW - I'm not sure what you mean by "location" - if you mean IP address, Devise already stores that for you.
Here's a page from the devise wiki: How To: Redirect to a specific page on successful sign in.
In summary, the recommendation is to add the following method to the application controller:
app/controllers/application_controller.rb
def after_sign_in_path_for(resource)
custom_location_for(resource) || welcome_path
end
In the above code, resource means the object (user, account, etc) that you've implemented devise authentication for. (The object that has the devise_for in your routes.)

Resources