The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Contentment::Security - Provides the contract for and default implementation of the Contentment security model

DESCRIPTION

The Contentment security model is an application security layer that allows for plugin replacement of the core of the system.

OVERVIEW

This module provides the front-end to the whole system. The real work of determining how security works is handled by the security manager (see Contentment::Security::Manager if you need to create custom security handler).

Basically, each request is assigned a principal (you can think of the principal as an object representing the currrent user) by the security manager. The principal, then, provides access to the profile, the roles, and permissions. The profile contains information about the user's identity and preferences. The principal may be assigned zero or more roles. Each role is a collection of permissions that are conferred to the user holding that role. A permission is simply a name for some permission that can be granted or denied. A principal possesses a union of all the permissions granted by all roles.

Plugins can use this class to check the permissions available to the current principal before performing an action that requires permission. For example, you might only want to let users with the "ModerateComment" permission vote on comments:

  sub vote {
      my $self = shift;
      my $vote = shift;

      # throw an exception if they can't moderate comments
      Contentment->context->security->check_permission(
          'Contentment::Plugin::Moderation::moderate_comment');

      $self->{vote} += $vote;
  }

MODULES

The important pieces of the system are handled in several different modules:

Contentment::Security

This is the front-end to the security system that is used by most modules to determine security permissions and such.

Contentment::Security::Manager

This is the interface that security managers must implement and provides a default implementation.

The default implementation stores the data about users in a local database via the Contentment::Security::Profile::Persistent class. Anonymous users are represented using the Contentment::Security::Profile::Scratch class. It also provides the ability to login and logout using methods named login() and logout().

See that class for more details.

Contentment::Security::Principal

This object is created and returned by the security manager and provides accessors to retrieve profile information, roles, and permissions.

Contentment::Security::Profile

This defines the interface implemented by profiles. It isn't clear that this needs to be a class, so this might just a document on what profiles are expected to do in the future.

Contentment::Security::Profile::Persistent

This is an implementation of the profile interface that stores profile data in the database. It provides a password attribute to store passwords in the database and a roles where the principal's roles are loaded from.

Contentment::Security::Role

The role object is used to associate permissions with principals. There are three special roles defined by the system (which are used by the default security manager, but don't have to be used by any other). The special roles are "Everybody", "Authenticated", and "Anonymous", which are assigned to all principals, authenticated principals, and anonymous principals, respectively.

Contentment::Security::Permission

Permission objects represent individual permissions, which allow an associated principal to perform some operation. There is one special permission defined named "SuperUser". The has_permission() method will always return a true value and check_permission() will never throw an exception for any principal possessing the "SuperUser" permission. Obviously, some care should be exercised when assigning this permission.

At the start of each request, the security manager that has been configured for the system determines which principal to associate with the request. The security system then loads roles associated with the principal and the permissions associated with those roles.

SECURITY FOR PLUGINS

For most developers, all that's really needed is to know which permissions have been granted for the current request. You must register your permissions before using them. Do so with the register_permissions() method:

  sub install {
      my $context  = shift;
      my $security = $context->security;

      $security->register_permissions(
          'Contentment::Plugin::MyPlugin::do_something' => {
              title       => 'Do Something",
              description => "Allow person to do something.",
          },
          'Contentment::Plugin::MyPlugin::say_something' => {
              title       => "Say Something",
              description => "Allow a person to say something.",
          },
          # etc.
      );
  }

To check which permissions have been granted to the current request, just use the check_permission() method:

  sub do_something {
      my $class = shift;
      my $arg   = shift;

      # check to see if the current user can do_something(). If not, this will
      # throw an exception.
      my $context = Contentment->context;
      $context->security->check_permission(
          'Contentment::Plugin::MyPlugin::do_something');

      $class->{do} = "something";
  }

For developers needing more fine-grained control, you can also use the has_permission() method.

Finally, if you need to figure out what the current principal is or access the profile associated with the principal, use the get_principal() method.

  my $principal = $security->get_principal;
  print "User ",$princpal->username," has the following roles:\n";
  for my $role (@{ $princpal->roles }) {
      print " * ",$role->title,"\n";
  }

PLUGINS FOR SECURITY

If you need a specialized security manager, you'll want to see the documentation available in Contentment::Security::Manager.

METHODS

Here is the documentation for each method of Contentment::Security.

@permissions = $security->register_permissions(%perms)

This method registers all the given permissions and returns a list of Contentment::Security::Permission object created (or found) for the permissions registered.

Each permission is keyed by a name which refers to a hash reference containing two keys to strings, "title" and "description", which are used as help information about the permission. Permissions should be named using a namespace your plugin uses to guarantee uniqueness (not to mention clarifying where/how the permission applies).

See "SECURITY FOR PLUGINS" for an example of this method in use.

$test = $security->has_permission($perm)

Returns a true value if the current principal has the permission named $perm or false otherwise.

$security->check_permission($perm)

This method uses has_permission() to determine if the current request has been granted the named permission. If not, an exception is thrown.

$security->check_permissions(@perm)

This method uses has_permission() to determine if the current request has been granted at least one of the named permissions. If not, an exception is thrown.

$principal = $security->get_principal

Returns the principal object associated with the current request.

$principal = $security->lookup_principal($username)

Returns the principal object associated with the given username or undef if no match is found.

CONTEXT

This class adds the following context methods:

$security = $context->security

This method returns the main security object for the application.

$security_manager = $context->security_manager

This method returns the security manager for the application.

HOOK HANDLERS

Contentment::Security::install

Implements the "Contentment::install" hook. It is responsible for installing all of the database objects associated with the Contentment security model and default security manager.

Contentment::Security::upgrade

This is a handler for the "Contentment::upgrade" hook. It is responsible for making sure any changes to the "security_manager" setting is transferred during upgrades.

Contentment::Security::begin

This handles the "Contentment::begin" hook and instantiates the security manager and installs the docs folder into the VFS.

AUTHOR

Andrew Sterling Hanenkamp, <hanenkamp@cpan.org>

COPYRIGHT AND LICENSE

Copyright 2005 Andrew Sterling Hanenkamp. All Rights Reserved.

Contentment is licensed and distributed under the same terms as Perl itself.