Clone this wiki locally
"Authorization" is how we will determine access levels for data and content within the system.
All interaction with data in Concerto 2 is performed through HTTP requests. HTTP requests might not be authenticated, in which case the data that may be read or modified will be very limited. To gain more access to the system, requests may be authenticated, in which case additional privileges may be granted depending on the accessor type (user, screen, or API), and the accessor's connections to the data they are accessing (group member, feed moderator, etc.). See authentication for more information.
For each of the following types of data, we will want to specify a clear set of rules so that no matter what controller and action is used to access the data, privileges will be consistent.
- Rows in the database themselves, and their general existence
- The particular fields within each row
The test plan for authorization is simple, and two-fold:
- Unit tests should extensively flex the can? and cannot? methods for each target (Any model with permissions) given each possible accessor (User, User.new, Screen, Screen.new)
- Integration tests should extensively flex the workflow and make sure people can't actually do that stuff
Unit tests are written in the targets unit test file. So a test exercising if a user can write to feed belongs in the test/unit/feed_test.rb, and a test exercising if a screen can write to a user (it shouldn't) would be stored in test/unit/user_test.rb.
Access (Nearly Final)
We will define authorization on a model-by-model basis. For convenience, we'll consider some join tables to simply be properties of the tables they connect.
(So far we only cover the core CMS: user data, content, and feeds. Eventually, policies must be developed for all data, but let's focus on these first.)
- Public access: the first and last name of a user may be seen by anyone who can view a piece of data owned by the user. For example, if a piece of content is available publicly (by non-authenticated users), then no log-on is required to see the author's name.
- Access by other users: logged on users may view a user's profile page, which will include their name and associated data (group memberships, submitted content that is accessible to the accessor, etc.). No one besides the super user will be able to view a list of all the users. E-mail addresses are still private.
- Private access: users may see and edit all data about themselves. However, password resets and e-mail address changes will involve e-mail verification. Password changes will require password re-entry for verification.
Admin user access: system administrators may see and edit all data about a user, excluding the password. E-mail changes need not be verified. System administrators may initiate a password reset, but that process must be completed by the user: the administrator may not choose the user's password at any time. Defined with
- User creation: a system configuration object will determine whether sign-up is open to all comers, or whether users must be invited/approved (this procedure is not yet fleshed out).
An important system requirement is that on installation, the installer may easily achieve the necessary privileges to configure the system. Similarly, if the administrator ever gets locked out, there must be a procedure to regain control of the system.
Access to basic group data should be fairly straightforward.
- A list of group administrators will be available for any group that is publicly accessible.
- A group is publicly accessible if it owns at least one public object (screen || feed).
- Full group membership rosters will only be available to group members.
- The group's ownership of public feeds and public screens should be freely view-able.
Users may be a group moderator or a regular member.
Moderators may edit all group information, and add or remove members, other admins, and have full control to moderate content on the group's feed. Defined with
- Regular members do not perform a particular role within a group. They exist only to provide access for users to view content shown to private objects (screens || feeds) that are owned by the group.
Feed access is controlled through two boolean values, creating a total of 4 different feed states. Both values are defined in terms of public access, members of the owning group always have access to submit and subscribe content.
is_submittable controls if the public can submit content to the feed.
is_viewable controls if the feed can be viewed by public users or subscribed to public screens.
This presents the possibility for 4 states:
- Public feeds (True, True) are the default feed type. All content can be seen and subscribed by any user of the system and any authenticated user can submit content.
- Private feeds (False, False) present the opposite construct of public feeds. Private feeds can only be seen by members and screens of the owning group. Content can only be submitted by group members.
- Restricted feeds (viewable => T, submittable => F) are for use where only a restricted set of users should be submitting content to a feed but the public should be able to consume this content. This makes sense for feeds where an authoritative source for the information is critical or there are a limited number of people that have content of value to add to the feed. An example might include a Dining Menu or Public Safety feed.
- Hidden feeds (viewable => F, submittable => T) probably shouldn't be used in the system without throwing a warning. These "blackholes" enable public users to submit content to feeds that they can't see. This makes sense when you consider cases where content may semantically belong on private feeds in addition to their public counterparts but the submitter is not a member of the private group. As an example, the VCC Screensaver feed is hidden so that it can only be subscribed to by the VCC computers but RCOS member Paul would like to advertise the new print queue checking website he made for the plotters. This content is submitted to both the public campus computing and hidden VCC screensaver feed for maximum exposure.
Any logged-in member may submit content to feeds that are
is_submittable (True). Group members may always content to feeds that are owned by their group, regardless of that feed's
Anyone may access content after it has been approved on one or more
is_viewable (Public, Restricted) feeds. This includes the content's general metadata (such as the title and owner), the content (image, text, or what have you), and the list of public feeds on which it is approved.
Content submitted to non-viewable (Private, Hidden) feeds is accessible to it's creator, and, once it has been approved on one or more non-viewable feeds feeds, to members of any private groups that own the respective feed.
This is a big question. Currently, we are in the process of evaluating appropriate technology to handle the dynamic roles that exist in Concerto. Technologies under consideration include:
- ActiveRecord's new "roles" feature (this will likely be too limited)
- can_can, a widely used authorization tool which stores role-based information in a central file
- Authenticates Access, a rails 2.x solution developed by some of the current Concerto 2 developers (would need to be updated)
- A custom solution involving passing authenticated accessor information to the model along with each request to manipulate data
The following general behavior may act as a starting point:
- If a view displays information from the database, it must run a check to ensure that the current accessor has permission to view that piece of data before displaying it, and hide it otherwise.
- If a view displays a link to show more detail about a piece of data, the view should check that the accessor has permission to view those details before providing a link. Similarly, if a view displays a link to edit an object, it should check that the accessor has permssion to write all or some of the fields of that object before displaying the link.
- If a controller recieves a form submission for which the accessor is not authorized, an exception should immediately be thrown, either from the controller or the model. Rails must be configured to catch such exceptions and render an appropriate access error.