7.6. Access Control

Now that we have identified the user and know his role assignments, we can use that information to say which controllers and actions, and optionally which objects, he has access to.

As with authentication and roles, we don't need to instantiate a separate access-control object on our own. Instead, the registered Solar_User object has an $access property that it sets up automatically.

7.6.1. Adapters

Solar provides different adapters allowing you to discover access-control information from different backends. The current adapters shipped with Solar are as follows:

[Note] Note

Note that these adapters are read-only. They do not create or manage access control lists for you, they only look up which the authorizations for a particular user and roles.

An authenticated identity will never change during the login period. However, access controls might change during the same session; e.g., being promoted from a moderator to an author while logged in. For this reason, the access adapters re-read the control lists from the storage backend on each new page request.

Solar uses a Solar_Access factory to create the adapter instance, so you need to configure the factory to create the kind of adapter you want to use for access control discovery. You can do so in the config file like this:

<?php
$config['Solar_Access'] = array(
    'adapter'    => 'Solar_Access_Adapter_File',
);

7.6.2. Configuration

Now that we have told the factory what adapter to create, we need to configure the adapter itself. Access adapters are much easier to configure than authentication adapters, but each has its own settings. You can look up the config keys for each of them on the following pages:

For example, the configuration for a file-based access adapter to use an access control list at SYSTEM/config/access.txt would look like this:

<?php
$config['Solar_Access_Adapter_File'] = array(
    'file'      => "$system/config/access.txt",
);

7.6.3. List Format

Access control lists have one row per entry, and each entry has five elements.

flag

(string) Does this entry 'allow' access, or 'deny' it?

type

(string) Does this entry specify to a user 'handle', a user 'role', or the 'owner' of a particular object? (More on "ownership access" in a later section.)

name

(string) If the entry type is 'handle', this identifies the user handle being controlled. There are two special values for this element: '*' means "all users" (even anonymous/unauthenticated users), and '+' means "all *authenticated* users".

(string) Alternatively, if the entry type is 'role', this identifies the user role being controlled. The special value '*' means "all roles".

(string) Finally, if the entry type is 'owner', this value has no effect. You can leave it blank, or put in a '*' if you want. (More on "ownership access" in a later section.)

class

(string) What class does this access control apply to? (Typically this is a page-controller class name.) The special value '*' means "all classes".

action

(string) What action name does this access control apply to? (Typcially this is the name of a page-controller action.) The special value '*' means "all actions".

Here's an example of a file-based access control list:

# flag      type        name        class                   action
# ----      ----        ----        -----                   ------

# allow any user with an "admin" role access to all actions in all classes
allow       role        admin       *                       *

# allow all users access to the actionRead() method in all classes
allow       handle      *           *                       read

# allow only authenticated users access to actionComment() in all classes
allow       handle      +           *                       comment

# allow only authors to add new pages
allow       role        author      Vendor_App_Page         add

# allow any user with a "moderator" role acces to Vendor_App_Comments::actionDelete()
allow       role        moderator   Vendor_App_Comments     delete

# deny all users access to Vendor_App_Page::actionEdit() ...
deny        handle      *           Vendor_App_Page         edit

# ... except for user authenticated as "kornblum"
allow       handle      kornblum    Vendor_App_Page         edit
[Note] Note

Control lists are processed from top-to-bottom, with later entries overriding previous ones.

Access controls are "deny by default", so if there's no entry for it, the control will be reported as "deny".

7.6.4. Usage

Let's say we are using the file-based access adapter to read from a file with the above entries. Let's also say that the user 'kornblum' has just logged in; he has only one role in the system ('moderator').

The Solar_User object, which has a Solar_Access_Adapter instance inside it, automatically goes to access control file and fetches the entries that apply to Kornblum. We can then use the following Solar_Access_Adapter methods to determine if Andy's should be allowed access to particular pages and actions. (Remember, we use a Solar_User object instead of instantiating a separate role adapter instance.)

<?php
$class = 'Vendor_App_Page';

$user = Solar_Registry::get('user');
$user->auth->handle; // 'kornblum'

$user->access->isAllowed($class, 'read'); // true
$user->access->isAllowed($class, 'comment'); // true (if not logged in, false)
$user->access->isAllowed($class, 'add'); // false (not an author)
$user->access->isAllowed($class, 'edit'); // true
$user->access->isAllowed($class, 'foobar'); // false (deny-by-default)


Local