The OpenACS 5.9.0 Permissions system allows developers and
+administrators to set access control policies at the object level,
+that is, any application or system object represented by a row in
+the acs_objects
table can be
+access-controlled via a PL/SQL or Tcl interface. The permissions
+system manages a data model that then allows scripts to check
+permissions using another API call.
Although object level permissions seems appropriate, no +developer or administrator wants to explicitly set access control rights for +every user and every object on a site. Therefore, +OpenACS has two auxiliary mechanisms for making this easier:
the Groups system allows users to be grouped together in +flexible ways.
the object model defines a notion of object context, which allows +applications to group objects together into larger security +domains.
The rest of this document discusses each of these parts, and how +they fit together with the permissions system.
+OpenACS 5.9.0 has an abstraction called a party. Parties have a recursive
+definition. We can illustrate how it works with the following
+simplified data model. First, we define the parties
table, where each party has an
+email address and a URL for contact information.
+ +create table parties ( + party_id integer not null references acs_objects(object_id), + email varchar(100), + url varchar(100) +) + +
Now we define two subtypes of party, one for persons, and one +for groups:
+ +create table groups ( + group_id not null references parties(party_id), + group_name varchar(100) not null +) + +create table persons ( + person_id not null references parties(party_id), + first_names varchar(100) not null, + last_name varchar(100) not null +) + +
The users
table is also
+defined in this data model as a subtype of person
.
Finally, we define two relations, one for group membership and one for group +composition.
The composition relation expresses that every member of group A +should also be a member of group B. This relation allows us to +define a hierarchy of groups.
The membership relation maps groups to parties. Each member of a group is a +party rather than just a user. That is, groups consist of members +that are either a person or an entire group. This allows us to say +that group A should be a member of another group B.
The groups data model is recursive. Modelling parties as either +a person or a group provides a way to model complex hierarchical +groupings of persons and groups.
The full details of the groups data model is beyond the scope of +this tutorial. See Parties in OpenACS or OpenACS 4 Groups +Design for more details.
+NOTE: Much more detailed information about the permissions +system and how to use it is available in the OpenACS Permissions +Tediously Explained document.
The permissions data model is a mapping between privileges, parties and objects. Parties +and objects have already been discussed. Now we focus on +privileges.
In OpenACS, a privilege describes the right to perform some +operation on some object. Privileges are the basic units out of +which we build access control policies. For example in the Unix +filesystem, access is controlled by granting users some combination +of read, write, or execute privileges on files and directories. In +OpenACS 5.9.0, the table of privileges is organized hierarchically +so that developers can define privileges that aggregate some set of +privileges together. For example, if we have read, write, create +and delete privileges, it might be convenient to combine them into +a new privilege called "admin". Then, when a user is +granted "admin" privilege, she is automatically granted +all the child privileges that the privilege contains. The OpenACS +5.9.0 kernel data model defines these privileges:
+# +begin + acs_privilege.create_privilege('read'); + acs_privilege.create_privilege('write'); + acs_privilege.create_privilege('create'); + acs_privilege.create_privilege('delete'); + acs_privilege.create_privilege('admin'); + + acs_privilege.add_child('admin', 'read'); + acs_privilege.add_child('admin', 'write'); + acs_privilege.add_child('admin', 'create'); + acs_privilege.add_child('admin', 'delete'); + + commit; +end; + +
Note that a user does not gain admin privileges when granted +read, write, create and delete privileges, because some operations +explicitly require admin privileges. No substitutions.
To give a user permission to perform a particular operation on a
+particular object you call acs_permission.grant_permission
like
+this:
+# sql code + acs_permission.grant_permission ( + object_id => some_object_id, + grantee_id => some_party_id, + privilege => 'some_privilege_name' + ); + +
Using just these mechanisms is enough for developers and +administrators to effectively define access control for every +object in a system.
Explicitly defining permissions to every object individually +would become very tedious. OpenACS provides a object contexts as a +means for controlling permissions of a large group of objects at +the same time.
+In OpenACS 5.9.0, object context is a scoping mechanism.
+"Scoping" and "scope" are terms best explained
+by example: consider some hypothetical rows in the address_book
table:
... | scope | user_id | group_id | ... | +
---|---|---|---|---|
... | user | 123 | ... | +|
... | group | 456 | ... | +|
... | public | ... | +
The first row represents an entry in User 123's personal +address book, the second row represents an entry in User Group +456's shared address book, and the third row represents an +entry in the site's public address book. In this way, the +scoping columns identify the security context in which a given +object belongs, where each context is either a person or a group of people or the general public (itself a group of +people).
Every object lives in a single context. A context is just an another
+object that represents the security domain to which the object
+belongs. By convention, if an object A does not have any
+permissions explicitly attached to it, then the system will look at
+the context_id
column in
+acs_objects
and check the
+context object there for permissions. Two things control the scope
+of this search:
the structure of the context hierarchy itself, and
the value of the security_inherit_p
flag in each object.
If security_inherit_p
flag
+is set to 't'
, then the
+automatic search through the context happens, otherwise it does
+not. You might set this field to 'f'
if you want to override the
+default permissions in a subtree of some context.
For an example of how to use context hierarchy, consider the
+forums application. With only row-level permissions it is not
+obvious how to reasonably initialize the access control list when
+creating a message. At best, we have to explicitly grant various
+read and write privileges whenever we create a message, which is
+tedious. A reasonable thing to do is to create an object
+representing a forum, and point the context_id
field of a new message at the
+forum. Then, suppose we grant every user in the system read-access
+to this forum. By default, they will automatically have read-access
+to the new message we just inserted, since the system automatically
+checks permissions on the message's context. To allow the
+creator of the message to change the message after it has been
+posted we grant the user write-access on the message, and we are
+done.
This mechanism allows developers and administrators to define a +hierarchy that matches the structure they need for access control +in their application. The following picture shows a typical context +hierarchy for a hypothetical site:
The top two contexts in the diagram are called "magic"
+numbers, because in some sense, they are created by default by
+OpenACS for a specific purpose. The object default_context
represents the root of the
+context hierarchy for the entire site. All permission searches walk
+up the tree to this point and then stop. If you grant permissions
+on this object, then by default those permissions will hold for
+every object in the system, regardless of which subsite they happen
+to live in. The object security_context_root
has a slightly
+different role. If some object has no permissions attached to it,
+and its value for security_inherit_p
is 'f'
, or context_id
is null, this context is used by
+default.
See the package developer tutorials for examples on how to use +permissions code.
+OpenACS 5.9.0 defines three separate mechanisms for specifying +access control in applications.
The Groups data model allows you to define hierarchical +organizations of users and groups of users.
The Permissions data model allows you to define a hierarchy of +user rights.
The Context hierarchy allows you to define organize default +permissions in a hierarchical fashion.
A PL/SQL or Tcl API is then used to check permissions in +application pages.