The idea of Horde Policy is to implement a replacement for the current prefs system, modeled after how Group Policy Objects work in a Microsoft Active Directory. Including a nice administrative GUI, meaning no more editing prefs.php files, and happier admins.
policy |-- name |-- targets | |-- target1 | `-- target2 |-- app1 (ie, imp) `-- app2 (ie, turba) |--attribute-group1 | |-- attribute-group2 | | `-- attribute1 | | `-- value | `-- attribute2 | `-- value `-- attribute3 `-- value
This structure should be easy to cache when a given app is loaded. something like if (!isset($policy[$app])) { load $policy[$app] from xml } .
In order to make Horde Policies as generic as possible, it's probably best to specify a new backend for them. Then we can write policy drivers for the various parts of Horde that might use them, such as Prefs.
I'm a big fan of the Datatree structure, slightly simplified, to hold the Policy information. The DataTree itself has proved not to scale very well, but I think by removing a few unneeded fields (for this application, at least), we can reduce the number of JOIN statements, and it should scale just fine. Another thing to think about is how many Horde Policies is a given site going to have? Probably no more than a handful on average.
Anyway, here's a new table structure idea:
horde_policy ------------ policy_id policy_name
horde_policy_attributes ----------------------- policy_id attribute_name attribute_scope attribute_state <-- mask for things like enabled, disabled, overridable, etc. attribute_hook <-- if defined, use it to get the default value for this attribute. attribute_type <-- what data type are we working with? attribute_value
horde_policy_targets -------------------- policy_id target_id <-- uid, gid, app-name, or global/default target_type <-- 'uid', 'gid', 'app', or 'global'/'default'
We can get the attribute group structure from the XML file. No need to worry about storing it, just need to enforce that all attributes for a given app have unique names. If there are two attributes with the same name, we should use the last one found in the XML file.
Listed by priority, highest-priority first. All levels would need to be checked, though, as some lower level might have the overridable bit set to false.
I haven't decided if it would be better to check from top to bottom, or bottom to top. bottom-to-top would give us quicker results if overridable is false at any level. top-to-bottom would give us the "real" value faster, assuming overridable is not false at some lower level.
Also, we need to work out a way to resolve collisions at a given level. For example, a user might be a member of various groups, and each group might have a different value set for a given attribute. If there is not a value set at a higher level, how do we decide which takes priority? Sort alphabetically? Give a priority to overridable?
At login, all applicable Policies should be loaded and cached. We should also try to do something to cache Policies for guest sessions.
Could we use Horde_Cache for this?
Some thoughts about an API for Horde_Policy
class Horde_Policy { var $name // policy name var $targets // array of targets var $attributes // array of attributes var $_params // storage parameters function name($name) {} // get/set policy name function attribute($attribute, $params) // set given attribute function addTarget() function removeTarget() function listTargets() static function getPolicyAttribute($attribute) // go through the cascading heirarchy, and return the value with priority (see Cascading Heirarchy above) }
Still need to be able to read from XML, not sure if that should be put in the constructor, or in the public API. Also need to be able to save to backend somehow.
http://www.microsoft.com/technet/itsolutions/msit/security/grppolobjectmgmt.mspx - gives a good overview on how MS GPO's work, and a nice graphic that really helped me visualize the internal workings.
- with something like this in place I think it would make more and
more sense to move everything that's at all user-related in conf.php
files to this system. Things like "user capabilities" in both Horde
and IMP - they can even be locked (overridable = false?) by default,
but letting people easily manage them on a per-group basis, or
whatever, sounds very good to me.
If there were a way to manage, say, IMAP server configs, or other
backend configurations (sieve servers, etc.) using this system, that
would be even better.