Extensible rule-based access pattern - php

I control access to some of my static web resources with some PHP logic. Because directory-based authorization through the webserver is not suitable or easily possible.
A combination of things determines whether access is granted or denied. And these rules change from time to time.
In the beginning it was a simple regex path match, and a check of one session variable. It's more complicated now as there's a few more variables involved.
I'm wondering how to go about refactoring this so it's quick and easy to change the rules. When it was a simple "if this AND this, then deliver, else 403." it was fine to do it in straight PHP. Now the conditions are more complex and there's a couple levels of nesting each with common but slightly different conditions within. This is all easy enough to refactor, but it's not the most intuitive and easy to update.
I'm thinking of one of two things.
Establish classes for each of the top level of conditions and use a Strategy Factory to pick the right one authorize. Derive them all from a base class containing the common bits and overload whatever's necessary. I think this could still be prone to some shuffling around when some conditions change.
Make a simple engine that iterates a 2d array of ordered rules sort of like firewall rules. Something like: <allow|deny>, <auth_group>, <path_regex>, <other vars>
I haven't fully thought this one through but it seems like it would be easier to update and also to read as a human.
What would you do? Is there an established pattern or library I can use for this?
I faced this similar problem in another app some time ago. Where I wanted an easy to update way of chaining rules and outcomes together based on several levels of conditions. This isn't as complicated as that app, but I'd be interested to hear about patterns people use to solve this kind of problem.

You might want to check out Zend_Acl, which is an object-oriented PHP class to manage hierarchies of privileges on hierarchies of resources. You might not be able to use this component as is, but it could give you some insight into how you want to implement your own system.
Zend_Acl is part of the Zend Framework PHP 5 class library, but like many classes in ZF, Zend_Acl can be used independently. There's no need to use the rest of Zend Framework.

You could also use a small logic engine (think prolog) to easily state facts and rules which would allow you to quickly query wether or not access to a resource should be allowed. Logic based rule engines like this are often very efficient and should allow you to very easily model a solution for this kind of problem domain.

I would use the Specification Pattern. It allows you to combine rules. You could even create a class to represent a compound rule that would be run (following the pattern) in the IsSatisfiedBy() method.

Related

Are action parameters bad design/architecture?

This question can be applied to any programming language, but as I am thinking of PHP, I will phrase it accordingly...
I'm wondering if it is considered bad design/architecture if a web application uses action parameters, versus seperate files for each action.
For example:
/index.php?action=edit
Versus
/edit.php or /index/edit.php
I know mod_rewrite can translate a pretty-url to a parametrized url, but I try to avoid uneeded complexity when not necessary.
Thanks.
Quite often, for big applications, (especially with Frameworks, such as symfony, Zend Framework, ...) we tend to use one entry point : index.php.
That entry point will receive some informations (like your action parameter), that will allow it to route the request to the correct controller (or any equivalent you might have).
So, to make things short : no, using action parameters is not bad design / architecture.
Of course, this depends on the kind of application -- but, generally speaking, have a unique entry-point is quite a good idea.
Well I don't think it is a bad design - of course there is other possibilities - but overall it is about your in-house agreements between the programmers how you do it. As much as you can you should split the PHP and HTML code to make the development easier further on.
I prefer the MVC-coding style, which splits the PHP and HTML from each other as much as you "want it to".
Hope this is helpful :)
I would call both your examples at least outdated or short of best practice.
/index.php?action=edit
Doesn't look good and is therefore not user friendly and isn't SE friendly either.
/edit.php
Means that there is indeed a single file for each action which clearly is bad practice in the 21st century where we have great MVC frameworks which enable us to get rid of this clutter and keep the concerns separated.
A good URL looks for example like that:
mysite.com/user/profile/edit
meaning where in the user module, the user-profile controller and the edit action.
There is nothing actually bad in either, both can be used all right
Separate files considered to be better for the small application, to avoid unnecessary complexity as you said.
Action way is considered better to serve complex applications featuring single entry-point working as a boot-strap, initializing all the site features first and then calling appropriate module.
I just have to warn you against using such action in silly way, doing include $_GET['action'] in the middle of main 'design' file. it's both insecure and unreliable.
It depends on your requirements and scale.
Using separate files is ok. However, you will probably find yourself copying code and not properly reusing code and techniques. It's easier to do this with small, ad hoc applications, but could very well turn into spaghetti code or a jungle nest over time.
If you use a single point of entry (class loading with url handlers), you do have to learn how that works (CodeIgniter and ExpressionEngine are good MVC systems to use if you're not real good at it yet), but it's more consistent in coding practice, and scales better than a bunch of separate pages or a switch() statement you pass everything through.
It's not a panacea, either way, but most professional operations use something like an entry point with a class loading system (such as MVC).
About using mod_rewrite: mod_rewrite was not created and should not be used as part of your PHP architecture.
About having one file per logical element. This is a very good and practical way of separating logical units in your app. It way better than creating huge files with a lot of mixed logic inside, which will become unmaintainable as the app grows. This has no contradiction on having one point of entry and an MVC architecture.
Having action parameters is the most normal approach for CRUD controllers for example where makes a lot of sense to group actions to a common controller
// blog controller
-> create blog entry
-> edit
-> view
-> delete
-> list ( this is a very common addition to CRUD
all this have a common architecture in the sense that almost all accept an id and do related thing.
If you are talking strictly about GET parameters than you'll see that creating medium/large application where you direct everything from a file and the only thing changing is the get parameters will outgrow you very fast. Computer architecture is like real architecture, try to split thing in small, simple (maybe reusable) units.

What's the best technique to build scalable (extensible), maintainable, and loosely coupled software?

I have been playing around with the concept of 'module' that some mvc frameworks implement and it seems like a good solution, and also with TDD, but I think there must be something more, like a design pattern I missed (I only know a few), that will let me build applications that can grow (in code) with no limits.
Any thoughts?
edit : Another good thing about modules is that they can be built in a way that they are application-independent, so they can be reused.
In "Facts and Fallacies of Software Engineering," Robert L. Glass says:
Fact 15. Reuse-in-the-small is a well-solved problem.
Fact 16. Reuse-in-the-large remains a mostly unsolved problem.
Fact 17. Reuse-in-the-large works best in families of related systems.
In other words, you can reuse modules, but only between applications that work very similarly. Trying to make modules so versatile that you can resuse them in any application is too hard. You end up making modules that are so configurable that they're overly complex to use, and contain lots of code to handle scenarios that are of no use to a given application.
You'd be better off coding a custom module for each application, that does just what that each application needs, and no more. This is especially important for a language like PHP, where code is loaded on each request, so the volume of code has a significant impact on performance.
Reusing more fine-grained functionality is different. The uses of say, logging, is reasonably similar between applications no matter how different the applications are from one another. This is why most frameworks do really well with general-purpose service-style classes.
Re comment from #A_Var:
You can make a class reusable if you know the range of possible functionality in advance, and therefore the parts that need to be extensible. This is relatively easy for a simple class that's used similarly in every app. I mentioned the example of logging. This is what Glass refers to as reuse-in-the-small.
But we're not talking about simple classes. If you try to do the same thing with a complex module (think of multiple classes to handle multiple screens, forms, different database schema, etc.), it's too hard to write the code to be generic enough to cover all the specific needs for each application. You end up needing more code in the generic module than the sum total code you'd need to write separate modules for each app.
Also, testing becomes very costly, because any change you make to the base module requires that you re-test all the apps that use and extend it.
In the end, it's less work to write a new module for each app, and you can gain what efficiency you can by employing reusable components that are more fine-grained.

Some ideas while planning php system

I am just about to undertake building a relatively large PHP system, I just need some ideas on how to implement a certain feature.
I will allow users to register. Once registered, the user will have a security level which will be assigned to their account.
So if I had security levels 1, 2 and 3, what would be the best way to show certain things to people with certain security levels ?
Thank you in advance.
Before you reinvent the wheel, be sure to look whether Zend_ACL is for you. I haven't used it myself but from what it promises in the docs, it can do what you need and much more.
Pekka's comments about looking at the Zend API's are good. Many of the Frameworks for PHP are currently (sadly) badly implemented junk (with hideously amateur code underneath), but the Zend API's are almost uniquely valuable.
If you do roll your own, which there is nothing wrong with doing if you can't find something that fits what you want (and can't be extended easily), then I'd take an OO approach and expose user properties via a class.
e.g.
$user = new User($session->userId);
if (!$user->isAdministrator && !$user->canViewReports)
someErrorHandler("You do not have permission to access this content.");
I'd avoid having fixed levels, but instead follow a roles based approach.
i.e. I'd avoid having levels like:
Staff
Manager
Administrator
And instead I'd go for properties (just as illustrative examples):
read_access
write_access
can_view_logs
can_view_reports
is_administrator
This allows you to be easily more explicit later, when you (inevitably) discover you want an additional permissions group you want have to go back and change existing code.
That doesn't mean putting users in groups is a bad idea (it's not and you could implement this using a groups system, e.g. where by a user could be in both "Reporting" and "Logs"), but assumptions about security levels being hierarchical are typically the wrong approach (e.g. Level 1=Staff, Level 2=Managers, Level 3=Admin) - this is because you almost always end up needing a system that's more flexible than a simple hierarchical system allows.
In practice if you do end up taking this approach, you may want to have a Permissions or Group class, to avoid having an overly large User class (which might end up full of stuff for getting user properties, setting new passwords, etc).
e.g.
$group = new Group($session->userId);
if (!$group->Administrators && !$group->Reporting)
someErrorHandler("You do not have permission to access this content.");

Best practices for an API in PHP : functions, or classes?

In my company we have developped some applications. We have to create an API for one application (say application A), so that the others can use it (an its data).
The question is : we already have developped PHP classes for the model of Application A, if we want to create an API, should we :
- re-use these classes (too much functionnalities for an API, too heavy...)
- create one PHP class, with some basic functions, that takes in input and returns only raw values (like strings, array... NOT complex classes)
- create another set of PHP classes, simpler, and designed only to be used by an external application (so only to get data easily)
Usually, an API is the 2nd solution (to be used as well with PHP than as a web service for example), but i find it too bad that we made a complex and usefull class modelisation, then we tear it apart just to have functions, strings and array.
The 3rd one seems to me to be the compromise, but a collegue of mine insist that this is not an API. Too bad...
What do you think ?
Solution number 3 might be the best one from an architectural point of view. Basically you are using a Facade Design Pattern to simplify your API. Since I am dealing with it at the moment: In Patterns Of Enterprise Application Architecture this approach is described as the service layer which makes totally sense since you don't want to expose any user (meaning whoever will deal with your API) to more complexity than is actually needed or desired.
This includes using the easiest possible interface and transfer objects (raw values if they make sense). As soon as your Facade is being called through remoting services (like a webservice) you will eventually have to break repsonses and requests down to raw values (data containers) anyway.
Build a set of Facade classes that simplify the public API.
Create some thin wrappers that implement simpler API over the original classes. DO NOT reimplement any business logic in the wrapper - that'd lead you into trouble if any of the logic changes, as you will surely lose track of which piece was modified and which was not. Keep the external inputs/outputs simple, if you need something more complex than string, use XML or JSON for structured data, but try to avoid too much complexity - if you have 2 things to pass two query parameters might be much better than one structure with 2 fields.
That's the 'Facade' pattern.
I would also say have a look at the Facade pattern.
Build a set of Facade classes that only offers the functionality that is really needed to be public. Those classes then for sure use your current core classes.
This gives you also the advantage that if you change the core classes, the API must not necessarily being changed.

Outlook-style rule engine

I am trying to construct a rule-based system for interpreting data. However, I am having issues deciding on a way to construct the logic for storing and interpreting rules.
Currently, there is a database structure that quite complex, but will deal with all aspects of storing the rule data. The idea is that the system will be able to mimic the way that MS Outlook allows a user to add rules.
My problems are as follows:
What pattern should I be using to store these rules inside objects?
Should I use eval() or proper object orientation to execute the rules?
And example rule might be:
Dog must have collar in area park
Where each element (dog, must have, collar, in area, park) is a separate piece of logic to be interpreted.
Any general advice to the above questions is much appreciated!
I've never implemented a system like you describe in a "real world" context, but I have played with them a considerable amount as hobby projects. My preferred approach is to use some kind of logic language like Prolog to make assertions and check them. You'd have assertions for where the park is, what it means to have something, what a dog is, and then you'd make a rule pretty much exactly like your example in parentheses at the bottom of your post. I'm sorry my Prolog is too rusty to give you a useful example... I've been playing with home-grown inference languages too long.
There are Prolog interpreters available for embedding in most languages, though I'm not sure about PHP5. You could throw together something simple that does forward-chaining inference on rule data structures of your own creation in fairly short order, if you can't find a Prolog interpreter. You may be interested in these notes on automated inference.
Probably this answer is too trivial / obvious for you but I just thought on how I would solve something like that in my current existing project which is a Zend Framework application. I thought of the filter- and validatorChains ZF uses. I assume you have a finit number of possible input objects, a finit number of conditions/constraints and a finit number of actions. In that case you would first instantiate an object and run it against a chain of conditions(validators), if all the conditions are satisfied you run the object against the actionChain. Here I would probably have to implement some kind of action priority system since some actions have to be carried out before others. Like 'sending a notification' and then 'delete' the object in question. So in ZF I would build a custom validator for every condition/constraint. I don't believe the Outlook system is very intelligent meaning that I don't think the validators are very generic.
In the db there could be a table for actual rules, one for the conditions and one for actions. Then there could be two many-to-many tables linking the rule with all needed conditions and actions.

Categories