Forum OpenACS Q&A: Proposal for a web service based rule engine

Using dotLRN since 2003 we had many requests to limit access to communities given different criteria like only master students or students studying economy or only members of the department foo. As you can see the possibilities to limit access to a community are endless. And the usage of rules for other areas as well. Why not limit access to file storage give a rule or to forums or to any other privilege of any object?

So here is the basic idea:

Any object can provide its web service and must provide three methods:

1. return the xml schema for an instance of the object
2. return the possible discrete values for the objects attributes
3. return an instance of the schema given a unique id

Example: Student service:

1. schema:
<?xml version="1.0" encoding="utf-8" ?>
<student name="Student">
<program name="Program of Study" />
<degree name="Degree" />
<status name="Status" />
<terms name="Terms of Studying"/>
</student>

2. Attribute values, here just the data:

Master
Bachelor
...

3. An actual instance:

<?xml version="1.0" encoding="utf-8" ?>
<student>
<program>Economics</program>
<degree>Master</degree>
<status>active</status>
<terms>5</terms>
</student>

As you can see
- schema and instance only differ in the attribute "name" for an editor (more on that later)
- this design is limit to simple objects
- this design is limited to discrete attribute values.

Still - I can deal with a many scenarios thru this already.

Now imagine a service registry package where the site-wide admin can register given institutional services like the above and make them available to different packages like dotlrn, file-storage...

Now a community admin can inside his community define rules given an editor. The rules are stored in a repository both in a machine and human readable way. The machine syntax is xpath. Then the community admin publishs a rule to predefined events like membership requests for a community. We can implement this easily with callbacks or some other way.

Once the rule is active and a student wants to request membership for a community the rule is tested against the xml instance for that student and access is granted or not depending wether the rule results true or not. If access is denied the human readable text of the rule is presented the student as an explanation for the denial.

Of course one issue is performance. Therefore the service registry package provides the option to cache xml instances during a session or a given time.

With this solution we could extend OpenACS with a very flexible xml/xpath based rule engine.

As I mentioned there are some limitations in the design that could be improved in the future. The biggest benefit I see is that you can define any rule you want simply by registering an institution specific service that resist outside of OpenACS.

The most important part is the editor. Since we cannot expect from users to know xpath it must be able to create that query on the fly displaying the human readable code.

Here a screen shot of a quick hack I developed:

https://dotlrn.uni-mannheim.de/screenshot.gif

Unfortunately it is in german but you will get the idea from the generated xpath query.

It wouldn't be too difficult to even allow the combination cross service rules where ids are equivalent.

For instance:

all students who study computer science and have posted more than 100 messages in forums.

Collapse
Posted by Nima Mazloumi on
Sorry - the usage of "schema" is incorrect here. What I meant is the xml structure.
Collapse
Posted by Jim Lynch on
The usual way to do that is apply the rule at the time the status changes (a new cs student is created as a user, say, or an existing student switches to cs) and then grant or revoke permissions on objects, or add/remove user to/from group which has the permission.

A problem I see with -just- having a rule, is then there will be more than one place to look for permissions (look at the permissions table, AND sequence thru each object, getting its attributes, look at each rule and see if it applies). The complexity would be close to O(n^3) (where n enumerates acs_objects or database rows). This doesn't seem scalable to me; besides, I just want to check the permission and be done with it.

So, if you're going to have a rule-based system, ok, but apply the rule and set permissions at the time when the user's status changes.

Collapse
Posted by Nima Mazloumi on
I agree. The problem is, that status changes take place in an external system. I could make it a requirement that OACS is informed via web services about those changes.
Collapse
Posted by Tom Jackson on
"The problem is, that status changes take place in an external system"

That is your basic problem. Essentially you have two or more independent systems, which is not good. Something occurs to me that you might be better off looking at an LDAP database for this type of problem. If you wish to use an external system, maybe use a separate-from-everything-else rule engine. Feed data into it from all sources which determine status and use the rule engine to make the decision, but first you need to get all the rule data into a single database. LDAP is difficult, but I can almost guarantee it is much easier than XML and xpath, and designed to be fast at this kind of task.

Collapse
Posted by Nima Mazloumi on
A first prototype is finished. Here is a demo: https://dotlrn.uni-mannheim.de/demo.swf
Collapse
Posted by Nima Mazloumi on
As you can see it supports caching of the data retrieved from the web service. The filter defined by the class admin has a description field that can be changed to a human readable text that is displayed to the student if the students status doesn't comply with the filter. The student will see a message in dotlrn that access is denied but also will receive an email.

If the web service is not available the system admin will receive a notification depending on the email specified for the service.

Since Javascript is not permitted to make cross site requests the registry service in dotlrn is serving as a proxy. Therefore it is also possible to cache data retrieved from the web service.

Collapse
Posted by Jim Lynch on
Nima Mazloumi on 06/04/07 01:33 AM:

"I agree. The problem is, that status changes take place in an external system. I could make it a requirement that OACS is informed via web services about those changes."

Sure, this is all true... and you could solve the -external- issue. But by "status change" I really just meant the following actions:

  • Adding a user to the system (which would somehow accept info about the user's status and then you set permissions accordingly)
  • user's external state change, where somehow this change is reported to the openacs instance, which responds by altering permissions

with the ultimate result being that:

  • all changes are (somehow) communicated to the -permission system-
  • no additional queries are needed in the openacs code beyond checking the -permission system-, and
  • therefore already-written code will already work for free, because it does check the -permission system- already.

The permission system is very robust, flexible, easy to use, nice api; overall it's great. I'd suggest using it!

Additionally, you will probably want to store the status in a table but only for the purpose of keeping together what could be a -set of- permission settings meant to implement -one- status. That way, it will be easy to undo changes; you can have API that lets you say "Freddie Freeloader's status has changed from Student-in-physics-classnumber-1234 to Teachers-assistant-for-physics-classnumber-1234" causing potentially many revocations and grants on many objects, as well as removals and adds to groups which already have appropriate permissions on appropriate objects.

Collapse
Posted by Nima Mazloumi on
Ok. I got your point. The first point is implemented. The status is checked once and the permissions are set accordingly. The second - reporting status changes back to oacs and altering permissions - is work in progress.

Would you rather pull or push this info? I could either provide a scheduled proc that asks for changes or provide an interface in oacs that is called when changes take place?

Collapse
Posted by Jim Lynch on
Why not table that decision by allowing both at the option of the user?