Testing access control with cucumber & capybara - ruby-on-rails-3

I'm using rails_admin and devise in my rails 3 application and writing tests for access control in cucumber.
I want to test that someone not admin cannot access all the routes of rails_admin (for example)
If I explicitly test like so:
Scenario: An authenticated user cannot access site administration
Given I am an authenticated user "kate", "kate#example.com"
When I visit the administration page
Then I should see access denied
I can match the string "the administration page" to the route "rails_admin_dashboard_path" and make my test pass just fine. But this seems to be testing the application the wrong way around. I want to test ALL the routes (loop through them somehow) rather than imply them and maybe miss one or two.
Something like this:
Scenario: An authenticated user cannot access site administration
Given I am an authenticated user "kate", "kate#example.com"
When I visit ANY administration page
Then I should see access denied
Could anyone advise me on how to effectively test this? Am I taking the right approach? Should I be doing this in rspec instead?
As you might be able to tell, I am a bit of a n00b.

I don't think you should be aiming to test every possible route in your Cucumber scenarios. As Andrea S. suggests, if all your admin controllers have a common base, then it should be sufficient to check the admin home page.

One approach would be to create a base controller in your admin namespace that all other admin/controllers inherit from. You can put a before filter in that base controller to check for admin authentication. Like so:
#app/controllers/admin/base.rb
class Admin::Base < ApplicationController
before_filter :ensure_admin_logged_in
end
And have all your other controllers in the admin namespace inherit from this one:
#app/controllers/admin/Pages.rb
class Admin::PagesController < Admin::Base
layout "admin"
end

Related

Is there a way to register routes after the application is started?

I want to have app which has some default route and controller (Let's say Login page). I can register this at the Configure method but after the user successfully logs in I want to fetch the pages related to the user and register them so he can have access to it. Is there a way to achieve that?
As long as I read that's impossible but who knows, I'm new to ASP NET Core?
Based on the wording, this sounds like a security question. You only want users to have access to certain pages. If that's the case then I would look at something like role-based authorization.
If the question is more about showing the user a list of resources they can access, then the most obvious solution I can think of is to store that information in a relational database. When the user logs in, select the relevant pages / resources by user ID.
In any case, changing the registered routes is not the correct approach.

Rails 3: How Does One Restrict Access to IDs

This might be very simple; I don't know Rails very well.
I have a match myController/myAction/myID in my routes.rb that will direct hyperlinks to the proper page (using link_to). But here's the problem: I don't want people to be able to freely modify the id parameter, passing in via the URL whatever they like.
Is there a way to perhaps restrict access to routes to the link_to method only? Or maybe there's another way to go about this, using a passed in hidden variable param or something?
Users access you site via urls like: /controller/action/:id right? A user can change an id and must not view another non authorized resource. How to achieve this?, on your controller, return only those resources that user is allowed to access.
For example, suppose that you are using devise:
class AController < ApplicationController
def index
#resouces = current_user.find_all_by_id params[:id]
end
end
This way if the user tries to access something he does not have access to, he will get an error.
Hope this helps, if not please let me know and I'll try to elaborate.
About current_user, yes it is supposed to be the current logged in user, it doesn't have to be devise, you can implement your own session handling logic and then create a helper method to retrieve the currently logged in user.
About using devise, if you don't want to implement your own session handling logic, plus if you want features like:
remember me
already created views that you can fully customize
authentication
authorization
password encryption
many more (please look at the docs for further information)
Then devise is a good way to go.
Also, it is always a great idea, if possible and as a learning exercise, implement your own authentication and authorization layers, you won't regret.
Best regards
Emmanuel Delgado

Devise user management

I'm creating a Rails app using Devise for user management (Rails 3.0.10, Devise 1.4.2). I've got the basics going - signup, login / logout - but I can't seem to find any facility (or even documentation surrounding) user management.
In other Rails apps I've created, I've had a UsersController with an index method that allows an administrator to list all the users of a system, & to subsequently modify them through edit and update actions on the same controller.
I can't see an obvious way of doing this with Devise. I've used the Rake tasks that come with Devise to generate editable views, which is great, but I can't figure out how to do the equivalent with the Controller.
I fear I'm missing something fundamental here. Could someone please point me in the right direction?
Devise doesn't come with any sort of Admin interface. If you are the only administrator and don't mind a little crudeness - there is always the console and/or scaffolding.
There are also a lot of good gems that make setting up admin interfaces a cinch: Active Admin, Rails Admin and I'm sure there are a bunch more out there.

Rails 3 advice: Create new Admin User class or use CanCan?

I've got a rails 3 app in beta right now that uses Devise for authentication for users, and need some advice. I want to add an admin-user that has some additional abilities, but I will be the only admin user (or admin users can be created via terminal - ie people cannot sign up to be admin users). All regular users have the same abilities. I was just about to use cancan to separate abilities based on user roles. Then it occurred to me that using cancan may just be overkill. does it make sense to just create a different class of user instead? Am I giving anything up by doing this?
I can foresee in the future that if this app is successful, there may be different roles for users (a free versus paid account, etc). Even in that case, does it make sense to NOT have an admin user via devise? Thoughts?
Thanks!!
If you only have two types (users and admins) it seems perfectly fine to have two classes. It might even be easier to implement than a full-fledged role system. But if it is foreseeable that you will get more roles in the future it would be better to lay a solid foundation and use a role system from the start.
If you are the only admin, I would create a field in your user model called Admin and then when you are going to add a function that is only for you, use the admin? check in your code.
For most of my projects, I have been using Devise and then use Option 2 from their Admin Role Wiki which is super easy to implement.

Have CanCan use Active Admin user?

I'm using Devise and CanCan for authorization on the frontend of a Rails 3 app. I also have Active Admin as the interface for the backend. I'm trying to create different roles for admins in the backend. Both ends have a login form that uses different 'user' models & tables. The problem is that CanCan fetches the current user from the frontend (grabbing the current user object) and uses that to see if someone in the backend has the correct permissions.
So, how I can have CanCan correctly grab the admin user that's logged in?
If anyone needs more information, I'll be glad to supply it.
I have not used ActiveAdmin before, but have used Devise and Cancan in a couple of projects before.
Having looked at Active Admin Documentation,
Set the method that controllers should call to authenticate the current user with:
# config/initializers/active_admin.rb
config.authentication_method = :authenticate_admin_user!
Set the method to call within the view to access the current admin user
# config/initializers/active_admin.rb
config.current_user_method = :current_admin_user
You can override Cancan behaviour in your application, by looking at :current_admin_user instead of :current_user.
Refer here Cancan changing defaults.
If you still can't get it, post your problems, where you are stuck.