sfPropelRowLevelAccessBehavior plugin
The sfPropelRowLevelAccessBehavior is a symfony plugin that adds
authorization on a per row basis; also known als Row Level Access or
Record Level Access.
This plugin provides you the means to enable Row Level Access in your
application by maintaining just a configuration file. The rest is done
automatically.
Installation
Install the plugin
$ symfony plugin:install sfPropelRowLevelAccessBehavior
Check your Propel settings
Make sure propel.builder.addBehaviors setting in config/propel.ini is
set to true.
Clear your cache
$ symfony cc
Create a new YML file in your /config folder named rla.yml
Setting up Row Level Access
With this plugin you can create an association between a field in a model
and a method in your user class. The general idea behind this is that that which
the user may view is limited by his properties.
For example:
The currently signed on user may only see the Contacts of the Customer he
represents. To be able to make this relation you would need a method
getCustomerId in the myUser class and 3 lines in the configuration file
rla.yml, which look like this
$ Contact:
$ field: ContactPeer::CUSTOMER_ID
$ user_method: getCustomerId
What this code does is create a relation between the CUSTOMER_ID field of
the Contact model and that which is returned from myUser->getCustomerId().
Thus, if getCustomerId returns 1, only the records where CUSTOMER_ID is equal
to 1 are returned in the Contact model.
Joining tables
Sometimes the data on which you want to place a relation does not reside in
same table. To solve this the plugin support adding joins to the relation
definition.
For example:
The currently signed on user may only see the Orders for a certain Customer
but Orders are not directly related to Customer but to Contact. To model this
you would add the next lines to your rla.yml,
$ Order:
$ field: ContactPeer::CUSTOMER_ID
$ user_method: getCustomerId
$ joins:
$ Contact: [OrderPeer::CONTACT_ID, ContactPeer::ID]
The joins index can contain an array of join statements. The key is not
mandatory but it is advised to give it the name of the model which you
are joining for readability.
The first parameter of the join is the field from which you want to join and
the second parameter is the field to which you want to join.
By doing this the Contact model becomes available to use in the field index.
Associating multiple values
Situations occur where you want to use multiple values to check against.
For example when the user is allowed to see the information of multiple
customers.
This can be solved by returning an array from the User's method, thus if
the getCustomerId returns array(1,2) instead of 1 the user will be
associated with both customers.
Extensibility
If all the power offered by the default behaviour is not enough then you can
always write your own Row Level Access Rule!
The actual handling of the restriction logic is done by supporting classes
which are extended from sfRlaRule. It is advised to place you own classes in
your project's /lib folder.
You can create your own rule by extending from this class and adding getters
and setters for all parameters which can be defined in the rla.yml file.
You should at least have a setter for every parameter, they will automatically
be called when your rule should apply.
The name of the setter is equal to set<CamelCase name of param>. Thus if you
have a parameter user_method, the name of the setter becomes setUserMethod.
In addition to these getters and setters you class must override the generate
method and manipulate the Criteria object to get the wanted results.
NOTE: Do not forget to return the Criteria object!
You can instruct the plugin to use your Rule instead of the default in 2 ways,
Set a new default type by adding the option
app_row_level_access_default_type in your app.yml and give it the
name of your class as value.
Set the type parameter in the rla.yml to the name of your class.
$ Contact:
$ type: myRowLevelAccessRule
$ myParam: 42
You can take a look at the sfRlaRuleFieldEqualsUserMethod class, which is
the default rule, to see an example of a working rule.