Securing reports???
Closed this issue · 4 comments
Is there a mechanism which can protect reports from being accessed by non-authenitcated users, or even better, some way to control access by CanCan?
For instance, I use Rolify and CanCan to protect certain controller actions from regular authenticated users so they can only be accessed by a User that has the Admin role.
Without a feature like this, it seems that anyone can access any report. Maybe there are other mechanisms that I am just not yet aware of??
Matt,
If you use dossier report instances in your own controllers, you can obviously provide whatever protections you want for them.
If you're using the normal Dossier::ReportsController (eg, yourapp.com/reports/employee
), you can use a config initializer to configure that controller. As an example:
# config/initializers/dossier.rb
Rails.application.config.to_prepare do
# Basic "you must be logged in"
Dossier::ReportsController.before_filter :authenticate_user!
end
I'll try to get back to you with an example of more detailed control soon.
I'm using Devise for user authentication, and I use Rolify to assign roles to each user. I know how to use these assets in the regular Rails Controller actions, but I am not very familiar with hooking into an Engine-based tool like Dossier, but I would like to attempt using the Dossier::ReportsController approach directly because I think I would learn some new things about this kind of stuff by learning how to get it working... (remember, I'm kind of new at Ruby/Rails, but not a total beginner.)
So, I followed your instruction to add an initializer, and kinda guessed at how I could place a method in that same file to test @current_user and test their role for admin level, and sure enough, the darn thing works as I had hoped. In my use case, only an Admin can run "reports". So, I first confirm that I have a @current_user logged in, then it confirms that the user has the admin role. If this fails either of these, it redirects out of the report and gives them a nag screen "Not authorized to view the requested information."
So here's what I came up with:
# config/initializers/dossier.rb
include CanCan::Ability
# config/initializers/dossier.rb
Rails.application.config.to_prepare do
# Basic "you must be logged in"
Dossier::ReportsController.before_filter :authenticate_admin
end
def authenticate_admin
if @current_user.nil? || !@current_user.has_role?(:admin)
render_not_authorized() #see application_controller.rb
end
end
YeeHa!! Problem solved. Thanks for pointing me in the right direction.
Matt,
Glad that worked for you. A couple of points, though:
- If someone isn't signed in, you probably want to make them sign in, right? If you use
authenticate_user!
, it should handle that. - You can add
authenticate_admin
as a secondbefore_filter
- It looks like you're defining
authenticate_admin
as a global method (I'm actually not sure what scope it's getting). Dossier::Controller subclasses ApplicationController, so I think you could just define that method in your ApplicationController. If so, I think that would be cleaner.