How to unit test authorization globally in CakePHP - unit-testing

We're using CakePHP v3.1.x with the CakeDC Users plugin.
We're trying to set up our unit tests to help prevent accidentally allowing non-admins to do things they should not be allowed to do. For example, imagine that a developer creates a new admin feature with a new action in a controller. During development she sets the permissions very lax so she doesn't have to log in each time to test it (or something... you get the idea). I'm trying to write a test that will fail if she tries to push this...
Here's my idea for how to do it:
Create a test that loops over all controllers / actions in the app, and checks to see if a non-admin user is authorized.
The test has a list of every action that a non-admin user can do.
The test fails if a non-admin is allowed to do anything that's not on the list.
The idea is that every time we intentionally let non-admin users do something, the test fails, and reminds us to go update the list of exceptions. But if we accidentally allow an action without knowing it, the test fails and we fix the mistake. It's a safety catch.
My question: Is this the right way to do this? And if so, how can we dynamically generate a list of all of the apps controllers/actions?

Is this the right way to do this?
Fix the problem not the symptoms: Fix your developers behavior of committing "test" and "debug" code or whatever you want to name it. Do peer reviews or have your team leader review the commits. You could try to ask on https://workplace.stackexchange.com/ about how to deal with this situation the best. Check this question for an example.
And if so, how can we dynamically generate a list of all of the apps controllers/actions?
Use this to get a list of folders with controllers:
App::path('Controller'); // App
App::path('Controller', 'MyPlugin'); // Some plugin
Use Plugin::loaded() to get a list of all plugins.
Then use the information to read the controller classes from all the folders. You can then generate test cases (maybe trough a new task of the bake shell?) automatically because you've got a list of controllers from your app and plugin. Use reflections to get a list of public methods from the controllers and filter known public methods like initialize().
Setting up testing auth is described here.
If you write a custom test that uses an array structure describing the controllers and actions and their permissions I'm pretty sure that you'll be able to automate it by running over that array structure and using the information to run the auth tests. But honestly, I'm not going to do that work here.
Or instead of testing the code directly use Codeception acceptance testing. CakePHP has plugin for that. This will allow you to test the "real" site by having automated click-through testing. It should be pretty easy to set up a specific users session and then test against URLs for access by expecting a redirect to the login action or whatever you do.

Related

Login and template errors deploying meteor to Digital Ocean / modulus.io

Apologies if this question is not asked correctly but I actually can't pinpoint the problem. Hence the lack of code in the question itself. I'm struggling with this error so please go easy on me....
I was developing a meteor app locally without too much difficulty. It seems to run well on localhost. But then I decided to deploy it and have been running into some problems as outlined below. I have deployed the app "successfully" using both mup/DO and modulus.io (with compose hosting the DB in both instances) and whole thing sort of works, but...
You can register fine but when you try to log in the button doesn't work...press it again and you login but the usename and password are in the URL... how does this happen?
When you login you can begin by creating a supplier, then create products for that supplier. Only thing is the suppliers are saved to the DB and they are in the product count but they are nowhere to be seen in the middle section page.
Once you create a new supplier, the add new products for the existing suppliers is no longer accessible.
I am so confounded that I don't know what code to put up so I'm giving access to my codebase - it's on github here and this is the modulus site here. Go ahead and register and you can see for yourself.
You will easily be able to see the errors in the console when you start trying to log into the site so there is no point in posting them here.
Many, many thanks in advance guys.
I have reviewed your code and I don't think that the errors occur due to the deployment.
Here's a list with a few suggestions that should help you to fix your code:
In your /client/helpers/config.js file, you try to configure the behaviour of {{> loginButtons}}. That does not make any sense, since you do not have the accounts-ui package installed.
The /client/templates/includes/header.html file references with pathFor to homepage. This route is currently not available in your /lib/router.js.
Users are able to access the /loggedIn path even if they are not logged in. Furthermore, you always redirect users to this path if the submit form event in the register template occurs. This means, they can easily bypass the registration just by clicking on the submit button.
Watch your console logs. There are a lot of template helper exceptions.
Unfortunately, I could not check the login bug you described, because I received an exception when invoking the submit event. I recommend to use a rather defensive programming approach, you should at least check if the variable's value is not undefined and if it is, then you should handle those situations accordingly.
For example, in your /client/templates/includes/login.js file, you have the following code:
var userId = Meteor.userId();
var supplier = Suppliers.findOne({userId: userId});
var supplierId = supplier._id;
This will raise an exception if supplier is undefined.
All in all, you should rethink your release planning and deployment, since your app is far from working. Furthermore, please try to break your issue into chunks next time and provide a clear problem statement, because your question won't be useful to other readers without it.

cancancan and devise testing for rails app

I've been researching how to test my Ability and Users for a small test rails wiki i'm building and i'm having difficulty wrapping my brain around how to test either or both ?.
I think i'd like to sign_in a user as admin/editor etc. and test that user behaves like it should. I'd like to also test that Pages are displaying the correct information for an authenticated user.
This is more then one problem and i'm looking for some basic nudging less then an answer :).
I use Rspec, Cancancan, Rails 4 and devise for authentication.
I've read up on a few ways none of which worked for me:
Cancan example
Another ex i tried for cancan
Devise and rails 4 I'm using route authentication for devise.
Devise and sign_in
In any case here are my files. I'll just link to my git repo
my abilities.rb
pages.rb
users.rb
pages_controller.rb
I have factories as well but what's the trick to doing the following
Signing in users: The examples suggest using the devise test helpers then creating a signed_in user stub. I haven't quite succeeded at this yet :( so a nudge in the right direction
Devise and abilities: My understanding is I need to use the cancan/matchers then make some factories for admin/editor or any views and then do my usual tests once i've logged in a user and instantiated abilities. also failed at all the examples I tried.
Finally testing the controller for pages: I required again logging in the user with the correct ability and then testing each action for each users to see if i received the correct records back?
Maybe i'm not separating out the roles enough or i'm missing some important steps from what I could read but even a small nudge on any of these would be much appreciated.
You may have seen this, but this CanCan page https://github.com/ryanb/cancan/wiki/Testing-Abilities describes some basic high-level methodology behind testing the ability class. TL;DR Focus heavily on testing the Ability class itself and keep the controller tests light.

templates to use with Zend/CodeIgniter framework?

I'm trying to build an online recruitment site using the Zend/CodeIgniter framework. I wanted to know which of the two frameworks is the easiest to use and which gives support for templates.I want to write minimum code as possible.
I has hoping I could use a template or some form of CMS that would allow me to quickly create (or automatically provide) an admin and user profile section. Users will need to enter their CV details, modify their account, search and apply for jobs. The admin will then be able to search for applicants based on qualifications, job role, etc.
are there any templates I can use on top of the Zend or CodeIgniter framework to get done the majority of the work?
Thanks
With your needs i like to go with cakePHP, it just need models to be ready and with scaffolding admin panel is good, with Auth and causal baking user section is ready too
With Zend, it usually takes some time to get the things done.

testing securityConfig mapping in grails + acegi

I'm writing test cases for a project which still uses the Acegi plugin (not the newer Spring Core Security plugin) and as of now, I've managed to do what this site (http://www.zorched.net/2008/09/01/grails-testing-acegi-security/)
has suggested regarding the detection of which user is currently logged in. However, in my controller, I have stuff that looks like this:
def list = {
// code for an "admin account"
}
def list_others = {
// code for other accounts
}
Now, I do not check in the controller the logged in user. Instead, I have these defined in the SecurityConfig.groovy like:
security {
...
requestMapString = """\
/someController/list=ROLE_ADMIN
/someController/list_others=ROLE_OTHERS
"""
...
}
Hence, if I had a test that looked like this:
void testTrial() {
// define here that otherUser has a role of ROLE_OTHERS
authenticate(otherUser, "other") // this calls the authenticate methode in the site I gave earlier
controller.list()
// I do an assertion here to check where this goes to
}
Thing is, when I do the assertion, of course list will tell me that it forwarded to list.gsp... even if the "logged in" user has a role of ROLE_OTHERS and not an admin.
However, what I need is how to test what a logged-in user is only supposed to access? In this case, given that the call is to *.list() and the logged in user has a ROLE_OTHERS role, I should have been forwarded to a "denied" page.
Help? Thanks!
You'll need functional tests for this. Unit tests are just Groovy or Java classes plus some mocking. There's no Spring application context, no Hibernate, no database, and most importantly for this case no plugins.
Integration tests give you more functionality, but even there requests are mostly simulated and since there's no container, no filters fire. Spring Security (which the Acegi plugin uses) is based on a chain of servlet filters. So if you want to test that your security rules are being applied correctly you'll need a running server, hence functional tests.
There are several options for functional testing, the most popular ones being WebTest: http://grails.org/plugin/webtest, the Functional Testing plugin: http://grails.org/plugin/functional-test, and the Selenium RC plugin: http://grails.org/plugin/selenium-rc.
The newest one is Geb: http://grails.org/plugin/geb. The manual is at http://geb.codehaus.org/ and there was a recent blog post written about it here: http://blog.springsource.com/2010/08/28/the-future-of-functional-web-testing/

Customizable Authencation backends not followed by Django's own login testcases. Why?

I learnt that using Customizable Authencation backends philosophy, one can create a website which accepts email addresses as usernames. But after building the corresponding logic and testing that my code is working fine, I found one issue with Django's own testcases. They were failing to follow the Customizable Authencation backend philosophy. Meaning, the testcases were actually having hardcoded values('username': 'testclient') for testing the "login" process. Why is that? Django always discourages Tight Coupling. But whats happening here?
I am not bashing Django by any means! I am a big fan and I will be, for years to come. Just want to know the reason behind this!
Update: As #dmishe pointed out those testcases should validate Django's own functionality. I understood that. But how do I let those "failing testcase" errors NOT show up when I run my testcases or run the whole project test suite?
As dmishe points out, it is not a problem that the contrib.auth tests test the functionality that is built in to the contrib.auth app. It is a problem that those tests are run for user projects by default, and it is easy to break them via normal settings customization. This is a problem the Django developers are aware of and working on possible solutions.
In the meantime, my solution is to define a simple bash script to test only the apps I want to. So instead of "./manage.py test" I run a script that does "./manage.py test app1 app2 app3...". Not perfect, but it's far from the worst of my problems :-)
Update: This commit might interest you.
I don't see a problem here, django.contrib.auth.tests should test auth app and nothing more. Thus, it should test built-in backend which is username/password combination.