Having problems figuring this out.
trying to do a
rescue_from NoMethodError, :with => :try_some_options
But its not working.
EDITED:
For testing I'm doing a simple redirect
def try_some_options
redirect_to root_url
end
EDITED 2:
Sample of my controller. Added (exception) as recommended below.
I know the reason I'm getting the error. Using Authlogic and authlogic_facebook_connect plugin. When user is created from the facebook plugin the "MyCar" model, which is associated with a user is not created like it normally is created if a user registers locally. Since I do call on the user model and reference the users car throughout different parts of the site, I would like to do something like what you see below and eventually put it in my application_controller.
class UsersController < ApplicationController
before_filter :login_required, :except => [:new, :create]
rescue_from NoMethodError, :with => :try_some_options
...
def show
store_target_location
#user = current_user
end
def create
#user = User.new(params[:user])
if #user.save
MyCar.create!(:user => #user)
flash[:notice] = "Successfully created profile."
redirect_to profile_path
else
render :action => 'new'
end
end
...
protected
def try_some_options(exception)
if logged_in? && current_user.my_car.blank?
MyCar.create!(:user => current_user)
redirect_to_target_or_default profile_path
end
end
...
end
EDITED 3: Hacked it for now since I know why the error is showing up, but would like to figure out how to rescue_from NoMethodError
class UsersController < ApplicationController
before_filter :login_required, :except => [:new, :create]
before_filter :add_car_if_missing
def add_car_if_missing
if logged_in? && current_user.my_car.blank?
MyCar.create!(:user => current_user)
end
end
end
I just read your post when trying to come up with a solution to the same problem. In the end I did the following:
class ExampleController < ApplicationController
rescue_from Exception, :with => :render_404
...
private
def render_404(exception = nil)
logger.info "Exception, redirecting: #{exception.message}" if exception
render(:action => :index)
end
end
This worked well for me. It is a catch all situation yet it just may help you. All the best.
Related
I have defined my own method authorize_user in one of my controllers, as:
def authorize_user
if !((current_user.has_role? :admin, #operator) || (current_user.has_role? :super_admin))
raise CanCan::AccessDenied
end
end
I want to rescue from the CanCan exception (or any other exception for that matter). I have used Rolify in my app. How do I rescue and redirect to the root_url of my app with a custom message?
I have tried the following options, but none of them worked:
Try 1:
rescue CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
Error in this case: syntax error, unexpected keyword_do, expecting '('
Try 2:
rescue CanCan::AccessDenied
redirect_to root_url, :alert => "Unauthorized Access"
Error in this case: Render and/or redirect were called multiple times in this action
How do I solve this issue?
This is my controller code:
class CabsController < ApplicationController
before_action :set_cab, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
after_action :authorize_user
# Some basic CRUD actions
private
def set_cab
#cab = Cab.find(params[:id])
#operator = Operator.find(params[:operator_id])
end
def cab_params
params.require(:cab).permit(:category, :number)
end
def authorize_user
if !((current_user.has_role? :admin, #operator) || (current_user.has_role? :super_admin))
raise CanCan::AccessDenied
end
end
end
I think you could try the rescue_from method.
For example, your ApplicationController, would look like this:
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied, with: :not_authorized
#other stuff
private
def not_authorized
redirect_to root_url, alert: "Unauthorized Access"
end
end
Since the question was updated with more code, here is additional information:
Some suggestions:
Make the :authorize_user a before_action as well. That way you don't need to worry about code running in the action even when the user was not allowed to do stuff.
You might also need to add the same :only option as for the :set_cab since you use the #operator instance variable.
Last, a personal code style preference is that I would have changed the if ! to unless to increase reading flow.
Try redirect_to(...) and return.
Agreeing with Jakob W I would like to point, that authorization (and authentication) MUST be performed only before action. What is the purpose of any authorization and exception raising when DB transaction, reading/writing to filesystem etc have been already done?
And using before_action has no problem with Render and/or redirect were called multiple times in this action - there will be only one redirect - in exception handling before controller method call.
So, I recommend next code (updated Jakob W's sample):
class CabsController < ApplicationController
#...
before_action :authorize_user
private
#...
def authorize_user
if !((current_user.has_role? :admin, #operator) || (current_user.has_role? :super_admin))
raise CanCan::AccessDenied
end
end
end
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied, with: :not_authorized
#other stuff
private
def not_authorized
redirect_to(request.referrer || root_path), alert: "Unauthorized Access"
end
end
Could I recommend another authorization gem? I think this one is flexible and easy to use - pundit (https://github.com/elabs/pundit). Page on github has some useful tips on authorization.
I am building an API in Rails and using Devise for Authentication. My front-end is an AngularJS app. I am able to log in and create a new session on the Rails end, but as soon as I try to access the current_user method in my UsersController it's nil. Am I missing something here?
Appreciate any help. Thanks
SessionsController:
class SessionsController < Devise::SessionsController
respond_to :json
def create
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
render :status => 200,
:json => { :success => true,
:info => "Logged in",
:user => current_user
}
end......
UsersController:
class UsersController < ApplicationController
before_filter :authenticate_user!, :except => [:create, :show]
respond_to :json
def show
render :json => {:info => "Current User", :user => current_user}, :status => 200
end....
I had to define current_user and run a custom authentication filter in my API to get the information straight from warden. I got the information below from a conglomeration of a few places here and here and a lot of trial and error with a debugger.
before_filter :api_session_authenticate!
private
def current_user
warden.user
end
def warden
env['warden']
end
def api_session_authenticate!
return not_authorized unless authenticate
end
def authenticate
warden.athenticated?
end
def not_authenicated
#render error messages and 401 status
end
Hi maybe this is a fool question, there are info in a lot of posts, but i do not understand because im learning rails..
I have made this controller, posts_controller.rb
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
def create
#post = Post.new(params[:post])
#post.save
redirect_to #post
end
def new
end
end
This is now public.. How can i make this just for admins, Im using devise. this is the controller for > SecureController
class SecureController < ApplicationController
before_filter :authenticate_user!
authorize_resource
def has_role?(current_user, role)
return !!current_user.roles.find_by_name(role)
end
rescue_from CanCan::AccessDenied do |exception|
render :file => "#{Rails.root}/public/403.html", :status => 403, :layout => false
end
end
Also Registratons controller
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
if current_user.user_type == 'player'
player_steps_path
elsif current_user.user_type == 'coach'
coach_steps_path
elsif current_user.user_type == 'elite'
candidates_path
end
end
end
How can i make that domain.com/posts/new is just available for Admin, but domain.com/posts is open to everyone..
Also i see there is views for admin... how can i make domain.com/admin/posts/new to work?
Any Documentation will be nice, but also a explanation, cause as i said, im just learning rails.
thanks
Use :except
before_filter :authenticate_user!, :except => [:new]
Using RSpec and Cancan, I have this test which fails with:
Failure/Error: User.should_receive(:new).and_return(#user)
expected: 1 time
received: 2 times
because
load_and_authorize_resource seems to call 'new' on the object as well. How do I work around this?
it "creates a new staff member" do
User.should_receive(:new).and_return(#user)
get :new, :format => "js"
end
-
class Admin::UsersController < ApplicationController
load_and_authorize_resource
def new
#user = User.new()
respond_to do |format|
format.js { render :action => "new" }
end
end
end
Well:
either replace load_and_authorize_resource with authorize_resource
Or:
remove #user = User.new() (which bears unnecessary parentheses)
You're definitely doing things twice here.
Just as a disclaimer I am new to rails and programming in general so apologize for misunderstanding something obvious.
I have Authlogic with activation up and running. So for my site I would like my users who are logged in to be able to register other users. The new user would pick their login and password through the activation email, but the existing user needs to put them in by email, position and a couple other attributes. I want that to be done by the existing user.
The problem I am running into, if I am logged in and then try and create a new user it just tries to update the existing user and doesn't create a new one. I am not sure if there is some way to fix this by having another session start??? If that is even right/possible I wouldn't know how to go about implementing it.
I realize without knowing fully about my application it may be difficult to answer this, but does this even sound like the right way to go about this? Am I missing something here?
Users Controller:
class UsersController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => [:show, :edit, :update]
def new
#user = User.new
end
def create
#user = User.new
if #user.signup!(params)
#user.deliver_activation_instructions!
flash[:notice] = "Your account has been created. Please check your e-mail for your account activation instructions!"
redirect_to profile_url
else
render :action => :new
end
end
def show
#user = #current_user
end
def edit
#user = #current_user
end
def update
#user = #current_user # makes our views "cleaner" and more consistent
if #user.update_attributes(params[:user])
flash[:notice] = "Account updated!"
redirect_to profile_url
else
render :action => :edit
end
end
end
My User_Session Controller:
class UserSessionsController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => :destroy
def new
#user_session = UserSession.new
end
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
if #user_session.user.position == 'Battalion Commander' : redirect_to battalion_path(#user_session.user.battalion_id)
else
end
else
render :action => :new
end
end
def destroy
current_user_session.destroy
flash[:notice] = "Logout successful!"
redirect_back_or_default new_user_session_url
end
end
Could you paste your users and users_session controller code?
I suggest using Ryan Bates' nifty_authentication gem. You can use authologic instead of default restful_authentication with
script/generate nifty_authentication --authlogic
Works like a charm.
I've done this with no probs, but know how hard it can be to port yourself to a new language and many new libraries! Hang in there! :)
I think that it might be the before_filter :require_no_user on new and create that blocks you.
What do you mean with this? Does it render the edit view? Or is this a result of a post/put?
it just tries to update the existing
user and doesn't create a new one.