I'm trying to make it so a Devise user has to be authenticated on the show action of a Rails controller unless show is a certain id. Is that possible? Is there something like the following?
before_action :authenticate_user!, except: [:show id: 1]
skip_before_filter :authenticate_user!, :only => :show, :if => "Provide Condition"
Use the above syntax to skip authentication for specific cases, in your case ids.
So I figured it out.
skip_before_filter :authenticate_user!, :only => :show, :if => lambda {
if params[:id]
#post = Post.find(params[:id])
if #post.id == 1
else
false
end
}
Related
I have a before filter that is supposed to stand down on the signup page (/signup) but it is still redirecting to login.
How do I fix this to leave out the signup page, which is my create/new action.
right now this is in my application_contorller.rb
before_filter :require_login
skip_before_filter :require_login, :except => [:create,:new,:accept]
private
def require_login
unless current_user
redirect_to login_url
end
end
end
Try this:
before_filter :require_login, :except => [:create, :new, :accept]
Alternatively, you can specify the pages that require login like this:
before_filter :require_login, :only => [:delete, :index, :another_controller_action_that_requires_login, :etc]
You'll likely want to move this before_filter to app/controllers/users_controller.rb (or whatever controller is responsible for user sign ups) instead of leaving it in app/controllers/application_controller.rb.
If you leave the :before_filter in application controller and have another :new or :create action in a separate controller (contact_form_controller.rb for example) then the before_filter will apply to that as well if it inherits from ApplicationController.
i've some problem with the skip_before action:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :require_login
before_action :inc_cookies
def inc_cookies
if cookies[:token] != nil
#name = cookies[:name]
#surname = cookies[:surname]
#user_roomate = cookies[:roomate]
end
end
def require_login
if cookies[:token] == nil
puts "No token"
redirect_to '/'
end
end
end
and my other controller:
class UsersController < ApplicationController
skip_before_action :require_login, :except => [:landing, :connect, :create]
end
I don't know why, but when I'm on the root (the :landing action from UsersController), Rails try to pass in the require_login...
I've misundertood something with this filter, or do I something wrong?
Thanks for any help!
This sounds normal to me - you've asked rails to skip your before action, except if the action is :landing, :connect or :create whereas it sounds as though you want the opposite. If you want those 3 actions not to execute the require_login then you should be doing
skip_before_action :require_login, :only => [:landing, :connect, :create]
There's URL like this
example.com/users/1376
Anyone can see this page even if the user is not signed-in.
There's also URL like this
example.com/users/1376?mode=1
Only signed-in user can see this page, otherwise the user will be redirected to sign-in page(new_users_session_path)
Could it be something like this?
before_filter :authenticate_user!, :only => [:show(params[:mode]=1)]
If not, please show me how to solve this.
Thanks
Have the before_filter (before_action for rails 4) call a method which renders or redirects if the action should not be run.
before_filter :test_for_mode, :only => :show
...
private
def test_for_mode
if (params[:mode] == '1') && !user_signed_in?
redirect_to new_user_session_path
end
For rails 3.2
before_filter :redirect_user, :only => :show
For rails 4
before_action :redirect_user, :only => :show
def redirect_user
if params[:mode] == 1 && current_user
redirect_to user_path(id: params[:id], mode: 1) #example.com/users/1376?mode=1
elsif !current_user && params[:mode].blank?
redirect_to user_path(id: params[:id])
else
redirect_to new_users_session_path
end
end
I have a before_filter in my application controller to keep a user's session alive (and log them out if a time out has been reached). This should be called on every action except /sessions/new and /sessions/destroy which are routed as /login and /logout.
The relevant parts of my application controller look like this;
class ApplicationController < ActionController::Base
before_filter :update_activity_time, :except => [:login, :logout]
private
def update_activity_time
if current_user
time_out = current_user.setting.remember_me ? 20160 : current_user.setting.user_timeout
from_now = time_out.minutes.from_now
end
if session[:expires_at].blank?
session[:expires_at] = from_now
else
time_left = (session[:expires_at].utc - Time.now.utc).to_i
if time_left <= 0
session_expiry
else
session[:expires_at] = from_now
end
end
end
def session_expiry
reset_session
flash[:notice] = 'Your session has expired. Please log back in.'
unless request.xhr?
session[:return_to] = request.request_uri
redirect_to login_url
else
session[:return_to] = request.referer
render :js => "window.location.replace(\"#{login_url}\")"
end
end
end
and my routes.rb contains the following;
map.login "login", :controller => "sessions", :action => "new"
map.logout "logout", :controller => "sessions", :action => "destroy"
The before_filter is being called when /login or /logout are being visited. This isn't a show-stopper but it does cause a few odd behaviours (e.g. when logging out from a page that has timed out).
Any ideas what I'm doing wrong? I'm using Rails 2.3.10.
The :except option takes action names, not url parts. Here's what you should do instead:
class ApplicationController < ActionController::Base
before_filter :update_activity_time
...
end
Then, in sessions_controller.rb:
class SessionsController < ApplicationController
skip_before_filter :update_activity_time, :only => [:new, :destroy]
...
end
You don't want to put the :except in ApplicationController because, if you did, the new and destroy actions for every one of your app's controllers wouldn't update the activity time.
Before any of my article controller crud actions can run (excluding index), i want to make sure that the article's active field is true.
I thought about doing this in a before_filter, but at that point #article has not been set, any ideas please?
Thanks
You could set the article in a helper method and remove some code duplication while you're at it.
class .. < ApplicationController
helper_method :current_article
def index
# your code etc..
end
private
def current_article
#article ||= Article.find(params[:id], :conditions => { :active => true }) ||
raise(ActiveRecord::RecordNotFound)
end
end
Basically you can now call current_article in your show, edit (etc) actions and views instead of #article.
You just need to do 2 before_filter.
1 with load the article and the second one to check if field exist
before_filter :load_article, :only => [:show, :edit, :update]
before_filter :has_field, :only => [:show, :edit, :update]
...
private
def load_article
#article = Article.find(params[:id])
end
def has_field
unless #article.active
redirect_to root_url
end
end