I have a job show page where I want only sign users to apply and if user is not sign in I will show him the apply button and when they click in the button they will redirected to the sign up page and after sign up they will redirected to the job show page. I'm wondering how can I achieve this?
I was thinking to separate the job into 2 model job-details and job_apply and in the job_apply controller put this before_action :authenticate_user!, but I'm wondering if there another solutions?
You don't need to create another action. Don't add before_action :authenticate_user! for the show action.
You need to add before_action :authenticate_user! for the apply action. once the non-signed in user clicks the apply action, He/She will be redirected to sign_in.
I just use a helper method in application controller. This code obviously needs a current_user helper method as well.
def confirm_logged_in
if !current_user
redirect_to '/sessions/new'
flash[:login_failure] = 'You must be logged in to see this page'
session[:return_path] = request.original_url
end
end
then in your sessions controller use something like
redirect_to session[:return_path] || root_path
Related
I have a user model with two roles as enums
enum role: [:'Standard', :'Admin']
I am trying to redirect based on the user role to relevant page after sign-in with Devise, I have used the recommended way of doing it on the docs.
In my sesssions controller...
def create
super
sign_out :user
end
def after_sign_in_path_for(_resource)
if resource.role == "Standard"
redirect_to dashboards_path
else
redirect_to dashboards_admin_index_path
end
end
And in my controller...
before_action :authenticate_salesperson!
before_action :set_project, only: %i[show edit update destroy]
I get this error saying too many renders/redirects (highlights super in create method) when logging in and i'm wondering why?
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return"
How to work around this? Ty.
Would be nice if you paste the whole controllers, but it seems like the after_sign_in_path_for method gets called before each time you visit either page, which creates a loop and hence the error. You can easily verify this by logging some text in each of the if else methods to double check.
What you should do is to add this logic to the controller, which is the root path like so
class DashboardController < ApplicationController
before_action: :after_sign_in_path_for, only: :index
private
def after_sign_in_path_for
if current_user.standard?
redirect_to dashboards_path
else
redirect_to dashboards_admin_index_path
end
end
end
Thanks. This works after I removed the "redirect_to's" in the "after_sign_in" method in my sessions controller
def after_sign_in_path_for(_resource)
if current_salesperson.standard?
dashboards_path
elsif current_salesperson.admin?
dashboards_admin_index_path
end
end
And in my user model...
def admin?
role == "Admin"
end
def standard?
role == "Standard"
end
You are redirecting too many times in the same action, this is why the message: "Render and/or redirect were called multiple times in this action."
Just return the path, delete redirect sentence! You only can redirect once in every action method!
Greetings
I am using Devise 3.5.2. I have an Item model with a show action that anyone can access( before_filter :authenticate_user!, except: :show). On the show page I have a button that triggers a file upload dialog using jquery.
I only want this upload dialog to work for logged in users. If a user is logged out and they click the button I want it to bring them to my login page. When they login I want it to take them back to the show page.
How can I make it so clicking this link brings them to the login page and then after logging in they are redirected to the page they were just on and already had access to?
<% unless current_user %>
<%= link_to "Upload image", item_path #item, class: "btn btn-lg btn-success" %>
<% end %>
This won't work because they already have access to this page.
EDIT: I tried following this link here https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in but it doesn't seem to be working.
My sessions controller looks like this. Maybe my create method is causing a conflict?
class SessionsController < Devise::SessionsController
def new
self.resource = resource_class.new(sign_in_params)
store_location_for(resource, params[:redirect_to])
super
end
def create
self.resource = warden.authenticate!(auth_options)
if resource.deactivated?
set_flash_message(:notice, :reactivated) if is_flashing_format?
resource.reactivate
end
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
end
This sounds like you need some controller specific code.
When a user clicks on the link, have the corresponding action do something like this:
def image_action # Whatever the action name is
if current_user # current user is given to you by devise
# Do stuff that a logged in user would do
else
# redirect to login page
end
end
The idea being that you leave the logic out of the view, and instead either have the controller serve the logged in user the appropriate data / page or have an unauthenticated user redirected to the login page.
current_user is a method given to you by devise that evaluates either to the currently logged in user making the request or nil if the user is not logged in.
If you post your controller code, I'll file out more of my example code, I just didn't want to make it too specific at risk of being confusing.
Since you are already using before_action :authenticate_user! in your controller for validating logged_in users..you just need to override that method to redirect to whatever page you like e.g.
In your application_controller.rb,
def authenticate_user!
if user_signed_in?
super
else
redirect_to whatever_path
end
end
I'm currently trying to make it so that if a user is not an admin they cannot get onto the 'create & edit' pages and also cannot destroy entries.
I have this method within my controllers
def must_be_admin
unless current_user && current_user.admin?
redirect_to root_path, notice: "Admin Needed."
end
end
and I call it like so:
before_filter :must_be_admin, only: [:edit, :destroy, :create]
This seems to let unlogged in users on the create page, but doesn't let them do the actual create action. Is there anyway to NOT allow users on the actual pages as well?
Essentially don't allow any users that aren't admin to
create/edit/destroy (as well as not let them on the actual pages) and
just reroute them back to index.
Yes if you restrict the new and edit actions as well they will not be able to see any of the pages. If you have a standard CRUD controller just eliminate the "only" option in your before_action and all non-admins will be blocked.
You have to remember that while blocking the create action you are not blocking the "new" actions page displaying everything. Blocking the 'new' action as well will stop them from even seeing the page.
In my app, after a user logs in, he is redirected to the AccountsSelection controller. In there, I have an index action that basically will get all the potential accounts a user can use, and display them in a index view.
def index
#accounts = current_user.eligible_accounts
end
In that page the user can click in one of the accounts, and that should go to one of the actions in the controller, that will set this in the session:
def show
session[:selected_account] = params[:account_id]
redirect_to account_path
end
Right now I have made that action to be show (so the selection of the account is doing a GET request, but I am not sure if this is a RESTful way of approaching this). From my point of view this is not a PUT/POST because I am not changing any resource or creating any resource, but it seems weird to be using the show action to just set a session.
What would be a proper way of handling this? It is correct to use show?
It is not recommended to use session in this case. So the standard approach is to create a before_action to set the account_id.
Use like this:
before_action :set_account, only: [:show]
and create the function in private as:
private
def set_account
account_id = params[:account_id]
end
Hope this helps.
I want to restrict the access to my pannel admin (gem active_admin) for admin only.
That's my code
class ApplicationController < ActionController::Base
def authenticate_admin!
unless current_user.is_admin?
flash[:error] = "Access denied"
redirect_to root_path
end
end
and the problem is : undefined method `is_admin?' for nil:NilClass
there is a boolean admin (0 false, true 1) in my DB
I've to define my is_admin?, but i try and he is never found. So where do i have to do that ?
Thx for your help
The issue is in your error message. nil doesn't have the method 'is_admin?'. This means that your current user variable isn't being set. You need to redirect users who are not logged-in to a screen where they can do so. Then direct them either through this authenticate_admin! function either first to redirect all user who are admin to the /admin path or simply push all users to your home page allowing them to click an admin link.
It could be that current_user is being set correctly, but this method is being called when there is no logged in user.
You should use this method in conjunction with another filter which requires the user to be logged in, ie which requires current_user to be defined. This is typically called require_user
Eg, in your application controller (so it gets inherited by all controllers)
before_filter :require_user
protected
def require_user
unless current_user
redirect_to "/" and return
end
end
You then make exceptions for the non-logged-in actions, with skip_before_filter.
Now, you can add authenticate_admin! as a before filter in your admin controller: it will only ever by called when require_user has already been passed, so it should be safe.
Add try: <% if current_user.try(:is_admin?) %>
Try simply add before_action :authenticate_user! (if your user called 'user') before :authentificate_admin! method. After this change your app will redirect non-logged users to login form first and only after that will ask your user 'is he admin?'.