The ability to execute an action can be restricted to users with certain privileges. The tools provided by symfony for this purpose allow the creation of secure applications, where users need to be authenticated before accessing some features or parts of the application. Securing an application requires two steps: declaring the security requirements for each action and logging in users with privileges so that they can access these secure actions.
Before being executed, every action passes by a special filter that checks if the current user has the privileges to access the requested action. In symfony, privileges are composed of two parts:
Restricting access to an action is simply made by creating and editing a YAML configuration file called security.yml in the module config/ directory. In this file, you can specify the security requirements that users must fulfill for each action or for all actions. Listing 6-21 shows a sample security.yml.
Listing 6-21 - Setting Access Restrictions, in apps/frontend/modules/mymodule/config/security.yml
read: is_secure: off # All users can request the read action update: is_secure: on # The update action is only for authenticated users delete: is_secure: on # Only for authenticated users credentials: admin # With the admin credential all: is_secure: off # off is the default value anyway
Actions are not secure by default, so when there is no security.yml or no mention of an action in it, actions are accessible by everyone. If there is a security.yml, symfony looks for the name of the requested action and, if it exists, checks the fulfillment of the security requirements. What happens when a user tries to access a restricted action depends on his credentials:
The default login and secure pages are pretty simple, and you will probably want to customize them. You can configure which actions are to be called in case of insufficient privileges in the application settings.yml by changing the value of the properties shown in Listing 6-22.
Figure 6-1 - The default secure action page

Listing 6-22 - Default Security Actions Are Defined in apps/frontend/config/settings.yml
all:
.actions:
login_module: default
login_action: login
secure_module: default
secure_action: secure
To get access to restricted actions, users need to be authenticated and/or to have certain credentials. You can extend a user's privileges by calling methods of the sfUser object. The authenticated status of the user is set by the setAuthenticated() method and can be checked with isAuthenticated(). Listing 6-23 shows a simple example of user authentication.
Listing 6-23 - Setting the Authenticated Status of a User
class myAccountActions extends sfActions { public function executeLogin($request) { if ($request->getParameter('login') == 'foobar') { $this->getUser()->setAuthenticated(true); } } public function executeLogout() { $this->getUser()->setAuthenticated(false); } }
Credentials are a bit more complex to deal with, since you can check, add, remove, and clear credentials. Listing 6-24 describes the credential methods of the sfUser class.
Listing 6-24 - Dealing with User Credentials in an Action
class myAccountActions extends sfActions { public function executeDoThingsWithCredentials() { $user = $this->getUser(); // Add one or more credentials $user->addCredential('foo'); $user->addCredentials('foo', 'bar'); // Check if the user has a credential echo $user->hasCredential('foo'); => true // Check if the user has both credentials echo $user->hasCredential(array('foo', 'bar')); => true // Check if the user has one of the credentials echo $user->hasCredential(array('foo', 'bar'), false); => true // Remove a credential $user->removeCredential('foo'); echo $user->hasCredential('foo'); => false // Remove all credentials (useful in the logout process) $user->clearCredentials(); echo $user->hasCredential('bar'); => false } }
If a user has the foo credential, that user will be able to access the actions for which the security.yml requires that credential. Credentials can also be used to display only authorized content in a template, as shown in Listing 6-25.
Listing 6-25 - Dealing with User Credentials in a Template
<ul> <li><?php echo link_to('section1', 'content/section1') ?></li> <li><?php echo link_to('section2', 'content/section2') ?></li> <?php if ($sf_user->hasCredential('section3')): ?> <li><?php echo link_to('section3', 'content/section3') ?></li> <?php endif; ?> </ul>
As for the authenticated status, credentials are often given to users during the login process. This is why the sfUser object is often extended to add login and logout methods, in order to set the security status of users in a central place.
TIP
Among the symfony plug-ins, the sfGuardPlugin (http://trac.symfony-project.org/wiki/sfGuardPlugin) extends the session class to make login and logout easy. Refer to Chapter 17 for more information.
The YAML syntax used in the security.yml file allows you to restrict access to users having a combination of credentials, using either AND-type or OR-type associations. With such a combination, you can build a complex workflow and user privilege management system--for instance, a content management system (CMS) back-office accessible only to users with the admin credential, where articles can be edited only by users with the editor credential and published only by the ones with the publisher credential. Listing 6-26 shows this example.
Listing 6-26 - Credentials Combination Syntax
editArticle: credentials: [ admin, editor ] # admin AND editor publishArticle: credentials: [ admin, publisher ] # admin AND publisher userManagement: credentials: [[ admin, superuser ]] # admin OR superuser
Each time you add a new level of square brackets, the logic swaps between AND and OR. So you can create very complex credential combinations, such as this:
credentials: [[root, [supplier, [owner, quasiowner]], accounts]]
# root OR (supplier AND (owner OR quasiowner)) OR accounts