declarative_authorization Authorization.current_user error - ruby-on-rails-3

I have authlogic set up and want to use declarative_authorization. In Ryan Bates's railcast #188 he uses
before_filter {|c| Authorization.current_user = c.current_user}
If I do the same I get an error:
`private method 'current_user' called for #<UsersController:0xa6025e8>`
The current_user method is in application controller and is private (as in the Authlogic setup example) and if I make it public, this works. It also works if I just say current_user (current_user method is also a helper) instead of c.current_user in the before filter block.
So would it actually be ok if I would just do before_filter {Authorization.current_user = current_user}?

Try this:
application_controller.rb
Add before_filter :set_current_user
Put this method into protected
def set_current_user
Authorization.current_user = current_user
end

Related

NoMethodError undefined method `admin?' for nil:NilClass Pundit, Devise Rails

I'm trying to integrate pundit with my active admin and devise configuration. But the app works weirdly. It takes in model/record as current_user.
my policy file:
class AdminUserPolicy
attr_reader :current_user, :model
def initialize(current_user, model)
Rails.logger.info '--------------- initialize called-------------------'
Rails.logger.info current_user
Rails.logger.info model
#current_user = current_user
#record = model
end
def index?
#current_user.admin?
end
end
controller:
controller do
include Pundit
protect_from_forgery
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
before_action :authenticate_admin_user!
def index
authorize current_admin_user
super
end
private
def user_not_authorized
flash[:alert]="Access denied"
redirect_to (request.referrer || admin_root_path)
end
end
The log is as follows:
--------------- initialize called----------------------------------------
#<AdminUser:0x007f27733f8a80>
Completed 500 Internal Server Error in 364ms (ActiveRecord: 312.8ms)
NoMethodError (undefined method `admin?' for nil:NilClass):
app/policies/admin_user_policy.rb:13:in `index?'
app/admin/dashboard.rb:19:in `index'
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (4.8ms)
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.5ms)
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.1ms)
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (39.5ms)
The weird part is, according to logs, current_user=nil and model=#<AdminUser:0x007f27733f8a80>
I swapped current_user with model my policy file as
def index?
#record.admin?
end
And it works!
I don't understand this strange behaviour.
Pundit policy doc says that it calls the current_user method to retrieve what to send into the first argument of the initialize method inside the Policy class. If you have configured ActiveAdmin to retrieve the current logged in user by using current_admin_user, then you have to override the pundit default method in your ApplicationController class like so: Ref
class ApplicationController < ActionController::Base
// ...
def pundit_user
current_admin_user // or whatever based on ActiveAdmin initializer config
end
end
In order to make the defined policy working, you have to invoke authorize inside the controller action with the instance of the corresponding policy model. So if you have a PostPolicy and you want to authorize the update action, you have to do the following:
controller do
def update
#post = Post.find(params[:id])
authorize #post // the current user will be automatically sent to the PostPolicy
super
end
end
The authorize method automatically infers that Post will have a matching PostPolicy class, and instantiates this class, handing in the current user and the given record. It then infers from the action name, that it should call update? on this instance of the policy. In this case, you can imagine that authorize would have done something like this:
unless PostPolicy.new(current_user, #post).update?
raise Pundit::NotAuthorizedError, "not allowed to update? this #{#post.inspect}"
end
Having all these, in your case, if you want that a user should be authorized before viewing the list of all users, you can define the AdminUserPolicy like you have done already. Then in the index action of your AdminUserController,
controller do
def index
#users = AdminUser.all
authorize #users // NOT `authorize current_admin_user`
super
end
end
You can pass a second argument to authorize if the name of the permission you want to check doesn't match the action name. For example:
def publish
#post = Post.find(params[:id])
authorize #post, :update?
#post.publish!
redirect_to #post
end

Devise: the method resource is not called properly

I am using devise. In a view partial, I have:
<%= simple_form_for resource, :as => :user, ...
In my application helper:
# #see http://stackoverflow.com/questions/4541075/what-is-the-devise-mapping-variable-and-how-can-i-include-it
def resource_class
devise_mapping.to
end
# #see http://stackoverflow.com/questions/4081744/devise-form-within-a-different-controller
def resource_name
:user
end
def resource
# with some controllers (homepage, static, this method is called)
# with other controllers (Item, it's not called: I don't see the abort call)
abort('should stop here')
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
On some controllers, my form works fine. On others, I get this error:
Couldn't find Item without an ID
The problem is that the method I have defined is not called. With some controllers, ApplicationHelper.resrouce is called, on others, it's an other method resource (Item.resource ?), and I don't know where it's defined.
How the method resource can be defined elsewhere ? Why is the method resource of my application helper not called on certain pages ?
Note: I am using the gem inherited_resources that defines the method resource. Maybe this create the conflict. But I don't know how the method is inherited
After seeing http://railscasts.com/episodes/230-inherited-resources, it all became clear.
I defined resource in ItemsController:
class ItemsController < InheritedResources::Base
# #see http://stackoverflow.com/questions/16831095/devise-the-method-resource-is-not-called-properly
def resource
# this solves my problem. It looks super wrong tough
#resource ||= User.new
#view_context.resource # tried that, but doesn't work
end
# ...
And now it works. The method resource was being re-defined by the gem for that controller...

can't find method in application controller

I've been trying to get authentication working with devise, and then omniauth, but I haven't been able to get the user session.
In my application controller, I have
class ApplicationController < ActionController::Base
protect_from_forgery
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
which I got from the updated railscast https://github.com/railscasts/241-simple-omniauth/blob/master/revised/blog-after/app/controllers/application_controller.rb
In my app, I call
<% if current_user %>
but this always errors out as undefined local variable or method 'current_user'
why is this? is it a problem with my application controller, or maybe a session error with rails?

After initializer change 'alias_method' undefined method 'current_user' for class 'ApplicationController'

I've got the following initializer:
app/config/initializers/store_location.rb
module StoreLocation
def self.skip_store_location
[
Devise::SessionsController,
Devise::RegistrationsController,
Devise::PasswordsController
].each do |controller|
controller.skip_before_filter :store_location
end
end
self.skip_store_location
end
Relevant parts of my ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :convert_legacy_cookies
before_filter :store_location
alias_method :devise_current_user, :current_user
def current_user
# do something
end
private
def store_location
# store location
end
Plus this in
config/environments/development.rb
Foo::Application.configure do
# normal rails stuff
config.to_prepare do
StoreLocation.skip_store_location
end
end
If I let RSpec/Rails run the self.skip_store_location I'm getting the following error:
/foo/app/controllers/application_controller.rb:7:in `alias_method': undefined method `current_user' for class `ApplicationController' (NameError)
If I remove the call, everything is back to normal (except the filter is run, as expected). I'm guessing that I mess up dependency loading somehow?
The problem is that you use alias_method before the method is defined in ApplicationController. To fix the problem, move the line
alias_method :devise_current_user, :current_user
below
def current_user
# do something
end
It's a bit misleading that the error appears when running skip_store_location. I assume that happens because skip_store_location loads several controllers, and one of them is a subclass of ApplicationController.

Call back to Application Controller error - NameError (undefined local variable or method

I'm upgrading an application from Rails 2 to 3. I use a Rights and Role approach for authentication that worked fine under Rails 2. In my Application Controller (application.rb) I have:
class ApplicationController < ActionController::Base
def check_authentication
unless session[:user]
session[:intended_resource] = request.request_uri
session[:intended_action] = action_name
session[:intended_controller] = controller_name
redirect_to :controller => "sessions", :action => "new"
return false
end
end
def check_authorization
user = User.find(session[:user])
unless user.roles.detect{|role|
role.rights.detect{|right|
right.action == action_name && right.controller == self.class.controller_path
}
}
flash[:notice] = "You are not authorized to view the page you requested"
request.env["HTTP_REFERER"] ? (redirect_to :back) : (redirect_to :controller => "sessions", :action => "new")
return false
end
end
end
In my other controllers I've included a before filter.
before_filter :check_authentication,:check_authorization
I'm getting the following error message, for example, when I go to my Dashboard Controller.
NameError (undefined local variable or method `check_authentication' for DashboardController:0x0000010291a0c0):
Is there something else I need to change or add to make this work in Rails 3?
Thanks,
Aaron
Make sure that your DashboardController is inheriting from ApplicationController i.e. DashboardController < ApplicationController.
Problem solved. Somehow during my upgrade I had a file named application.rb and application_controller.rb in my controllers folder. Both were defined as ApplicationController < ActionController::Base. The code for my "real" Application Controller was sitting in application.rb and not in application_controller.rb, which was empty. A simple copy-n-paste and things were fine. I don't know how that happened. Running the rails_upgrade plugin didn't go as smoothly as planned.