Guest handling in .LRN

by Andrew Grumet on 2004-02-23

A re-work of guest handling in .LRN was committed to the dotlrn-2-0 branch on February 20, 2004. Here's a summary of what was changed and why.

Background

In the US (and more so elsewhere), privacy laws govern what sorts of information educational institutions may share and with whom. The first versions of .LRN shipped with something called "Guest status" and an OpenACS permissions system privilege called "read_private_data". Historically guest status hasn't been well understood nor much applied. Over time, changes in OpenACS started to break the initial implementation, revealing it's weaknesses. This prompted the changes we describe here.

Definitions

Old implementation

Prior to .LRN 2.0.2, guest status was handled in the following way:

  1. Non-guests were granted the read_private_data privilege on the dotlrn instance mounted at "/dotlrn", as returned by dotlrn::get_package_id.
  2. Guests were not granted read_private_data.
  3. Packages wanting to protect private data would check for read_private_data on an appropriate object.
  4. The permission checks were routed through a wrapper, either in acs-tcl/tcl/acs-private-data-procs.tcl or dotlrn/tcl/dotlrn-security-procs.tcl which allowed ad-parameter-based overriding for backwards compatibility.

There are a few problems with this design. The first stems from initial confusion about how the permissions inheritance hierarchy should be set up. In early versions of .LRN, all communities inherited permissions from the main .LRN instance. Thus if a user was granted read_private_data on the main .LRN instance, they would automatically get read_private_data on every object under dotlrn. Unfortunately, this also meant that other privileges cascaded down from the main .LRN instance. This includes read, which all users are granted so that they can view shared, .LRN-wide pages such the "join communities" page. Because cascading read permission would have allowed users to view data in communities to which they didn't belong, permissions inheritance was turned off between the main .LRN instance and the communities below it.

But turning off permissions inheritance also meant that read_private_data did not cascade as originally envisioned. This led to bugs in areas where private data was protected, notably bug #1549 ("Regular users cannot post to forums").

Another limitation was revealed by a SloanSpace requirement that, in specific communities, it should be possible allow guests to view private data about members. Because a user's guest status is determined by whether or not they have a specific permission, there was no straightforward way to say "this person is a guest, but they should be able see private data in Community X." Sloan evolved some custom code to handle this case, which added wrappers to allow disabling of the permission check on a community-by-community basis.

New implementation

Files:

The new implementation separates the storage of Guest/Non-guest status from specific permission grants. Two new relationship types are created, dotlrn_guest_rel for Guests and dotlrn_non_guest_rel for Non-guests. A user's guest status is determined by which of these two relationships the user has with the Registered Users group, the "magic object" corresponding to registered_users. Two new relational segments are also created: "Registered .LRN Guests" for users having a dotlrn_guest_rel with Registered Users and "Registered .LRN Non-guests" for users having a dotlrn_non_guest_rel with Registered Users.

Permissions are selectively granted to these relational segments on a community by community basis. read_private_data is granted to Non-Guests on each community when the community is created. read_private_data may be granted to Non-guests by the .LRN site administrator for specific communities, from the community admin screen. This ability to open up private data is restricted to site administrators because of the legal implications.

Once granted, read_private_data permissions will cascade to all objects in the community which have permissions inheritance turned on (most or all objects). Permissions are checked with the standard OpenACS calls in packages/acs-tcl/tcl/acs-private-data-procs.tcl. These calls will bypass the permission check if the kernel parameter PrivacyControlEnabledP is set to 0. Thus it is safe to put permission checks in generic packages such as forums, which should protect private data when run in .LRN but not in a regular OpenACS site. Privacy control should be enabled on .LRN sites and disabled on regular OpenACS sites.