Elefant PHP Content Management System

Meet Sitellite's successor: Elefant CMS

A modern PHP framework and content management system based on the improved features of PHP 5.3+. Elefant is an extremely fast and easy to use CMS that inherits all the best of Sitellite, without the fat. Learn more »


Code Examples

In Sitellite, access control is granted or denied based on a few concepts that work together to form a complete and very flexible privilege system. First, I'll define each concept for you, then I'll discuss Sitellite's default permissions and workflow as an example scenario to help you configure your CMS system to your specific requirements. Rounding out the article, I'll look at integrating access control features into your custom PHP code.

Roles

The first concept in Sitellite's access control system is that of a Role. Users perform certain functions within a CMS that make up their job description within your website. We'll call these functions that a given user performs their Role. However, it's not so straight-forward to define functions or to describe what a user does, so instead we define the Role of a user based on their access to three things: Resources, Access Levels, and Document Statuses.

By limiting or granting access to these three things, a Role becomes a description of a user's function indirectly by defining the range of possible actions users of that Role are able to perform.

Let's look at these three things in more detail.

Resources

A resource in Sitellite can be just about anything. Each collection (ie. content type) and each app or module is a resource. You can also define custom resources for your own apps or even for specific parts of your apps. For example, the Image Manager app defines an additional resource for its delete function so that you can grant access to the Image Manager itself but restrict access to the ability to delete images separately.

Aside: Some apps and collections don't have resources defined for them. To add a resource for a collection, use the name of the collection definition file in inc/app/cms/conf/collections minus the .php suffix. To add a resource for an app, use the folder name of the app in inc/app prefixed with "app_". For example, the "imagechooser" app would be associated with the "app_imagechooser" resource.

Access Levels

Items in the system such as web pages, news stories, even boxes and forms within a given app have an access control value assigned to them. Examples of access levels include "public", "member" for members-only, and "private" among others. Public items are logically accessible to anyone. Members-only items are accessible only once a website member has logged in and has been authenticated by the CMS as a member of the website. Private items are intended for admin-level users only.

Document Statuses

A document can be in one of several states of completion during its lifetime. Defaults within Sitellite include "draft" for incomplete documents, "pending" for documents awaiting editor approval, "approved" for documents that are considered ready for public consumption, and "archived" for documents that should no longer be shown on the site but may still be needed for historical reference by site admins.

By restricting access to these three things, Sitellite is able to describe with a high degree of precision the functions a particular user role can perform. For example, if a user can only access a certain collection (ie. web pages) then their function pertains specifically to web pages. And if they can only access "draft" and "pending" access levels but not "approved" then they are obviously a content creator but not one with sufficient privilege to publish directly to the live website.

Read/Write

Adding further specificity, site administrators are able to grant Read and Write access separately to any of the above on a role-by-role basis. Read access means a user can view but not modify an item, and Write access means they can modify the item as well. This is a familiar concept to Unix system administrators and power users (ie. Linux, Mac OS X), where the filesystem splits permission on every file into Read, Write, and Execute.

Teams/Ownership

There are cases where you may need to grant editorial access for a given user to the website but you'd like to restrict that access to a particular area of the website, such as the Human Resources section of pages so that the editor can manage job postings but can't edit marketing copy for products or services. This is where the concepts of teams and ownership come in.

Teams break users up into groups that perform a series of tasks (their combined roles) on specific parts of a website. The parts (ie. web pages, news stories, etc.) that are available to that team are simply the ones owned by that team. Ownership is defined on an item-by-item basis under the State tab of the edit screen.

The writer who seeks approval for a particular modification to a web page will be looking for this approval from an editor, but specifically from the editor belonging to the same team.

Workflow

This combining of roles into teams creates a sort of natural workflow within the system. Each team's combination of user roles is another workflow cycle, since workflow really just means the series of tasks a group performs and the communication that occurs between them to facilitate the completion of those tasks. In this way, workflow usually centres around the Status property of documents and role definitions. Workflow cycle typically matches the document lifecycle.

Utilizing Sitellite's default workflow settings and setting up custom workflow systems is the topic of a previous tutorial however, so I won't repeat that here again.

Multiple Teams

There are cases where you need a user to be allowed to access items owned by other teams than their own. This is made possible on a per-user basis when adding/editing users, by allowing you to specify both the team they belong to, as well as a list of Read/Write privileges for all teams in the system. This is found under the Access tab of the user add/edit forms.

By default, Sitellite enables new users to Read and Write to all teams, so that team restrictions are something that must be enabled. This default setting helps keep the default privileges useful out-of-the-box for smaller websites that don't require anything beyond the default teams and roles.

You should be starting to get a feel for how all the pieces of Sitellite access control system work together to form a whole. At this point, some examples should help solidify these concepts some more.

The main built-in user roles are:

  • anonymous - A fictional public visitor role with read-only access to everything public (access level) and approved (status).
  • editor - A site contributor who approves content for use on the live website.
  • master - An all-powerful user role for performing administrative tasks.
  • member - A registered version of the anonymous visitor, which grants them additional access to the member access level.
  • writer - A site contributor whose content requires editor's approval before being shown on the website.

Sitellite's built-in workflow utilizes the writer and editor roles. A writer contributes content to the website but is not allowed to approve their own content, so their contributions require approval from an editor before they'll be seen on the website.

An editor is notified via email when a writer on their team has set the status of a content item to Pending. This means they feel the item is complete and ready for publishing.

The editor can then set the document to approved, in which case it becomes visible on the website, or to rejected, in which case an email is sent back to the creator of the item to correct the changes and resubmit it for approval if necessary.

Custom Configurations

Sitellite gives you the ability to define your own resources, teams, roles, access levels, and statuses. The defaults for most of these are usually a good starting point, but sometimes custom statuses for example are needed. All of these can be managed through the Admin menu in Sitellite's Control Panel. Creating a new status automatically makes this status available to each role in the role add/edit screens for example.

The most common customization is to require more strict team access. The steps for doing this are as follows:

1) Define all of the teams you will need for your website.

2) Create your users belonging to each of these teams and being of the appropriate user roles.

3) When creating the users, make sure you visit the Access tab on the add form and clearly define which teams the user should be able to access. Remember, the default is Read and Write to all teams.

4) Now these users will only be able to create and edit content owned by that team. Create this content and assign it to the appropriate team, or have the users from each team begin creating their own content.

Please note that a user will be able to assign team ownership to any team they can write to, not just their main team.

Next to team restrictions, another common customization is to require additional steps in the approval process. This can be accomplished as follows:

1) Define the additional steps of approval as individual statuses.

2) Create or edit the user roles as appropriate, granting Read and Write access to the specific statuses that a role must be limited to. Typically a user will need Read access to the step or status preceeding them, and Read and Write access to the status or statuses they can set an item to.

3) Create users for each of these steps. Make sure the users belong to the appropriate team. Users within a single workflow cycle must all be part of the same team, and identical or separate cycles can be performed by separate teams.

4) If workflow notifications are required to help communicate the next step to the appropriate user, you'll need to create a custom workflow action for that. Please refer to our workflow documentation for that. The cms_services_notice workflow action is a good example to work from as a starting point, since it provides the default notification behaviour built into the CMS already.

Sitellite's access control features can be accessed programmatically when you're building custom apps, from anywhere within your app libraries, boxes, forms, or properties. This is done using the following functions:

boolean session_allowed (mixed resource, string access, string type)

<?php

// Is the user allowed to access this app?

if (! session_allowed ('app_myapp', 'rw', 'resource')) {
	die ('Failed');
}

echo 'Passed';

// Is the user allowed to read the private access level?

if (! session_allowed ('private', 'r', 'access')) {
	die ('Failed');
}

echo 'Passed';

// Is the user allowed to view the archived status?

if (! session_allowed ('archived', 'r', 'status')) {
	die ('Failed');
}

echo 'Passed';

// Is the user allowed to write to the marketing team?

if (! session_allowed ('marketing', 'w', 'team')) {
	die ('Failed');
}

echo 'Passed';

// Is the user allowed to read a specific web page

$page = db_single (
	'select * from sitellite_page where id = ?',
	'some-page-id'
);

if (! session_allowed ($page, 'r')) {
	die ('Failed');
}

echo 'Passed';

?>

boolean session_is_resource (string name)

<?php

if (! session_is_resource ('app_myapp')) {
	die ('This app has not been defined as a resource by the site admin');
}

?>

boolean session_admin ()

<?php

if (! session_admin ()) {
	die ('The current user is not an admin-level user');
}

?>

boolean session_valid ()

<?php

if (! session_valid ()) {
	die ('The user is not logged in');
}

?>

string session_role ()

<?php

echo 'The user is a ' . session_role ();

?>

string session_team ()

<?php

echo 'The user is a member of ' . session_team ();

?>

string session_allowed_sql () string session_approved_sql ()

<?php

$sql = 'select * from sitellite_page where id = ? and ';

if (session_admin ()) {
	$sql .= session_allowed_sql ();
} else {
	$sql .= session_approved_sql ();
}

$page = db_single ($sql, 'some-page-id');

// ...

?>
As you can see, Sitellite's acces control system is very flexible and highly customizable at all levels. Now you have the concepts and examples to take full advantage of it.