++ed by:

1 non-PAUSE user.

David J. Oswald
and 1 contributors


Class::User::DBI::Domains - A Domains class.


Version 0.10


Through a DBIx::Connector object, this module models a "Domains" class, used for Roles Based Access Control.

    # Set up a connection using DBIx::Connector:
    # MySQL database settings:

    my $conn = DBIx::Connector->new(
        'dbi:mysql:database=cudbi_tests, 'testing_user', 'testers_pass',
            RaiseError => 1,
            AutoCommit => 1,

    # Now we can play with Class::User::DBI::Domains

    # Set up a 'domains' table in the database.
    Class::User::DBI::Roles->configure_db( $conn );
    my $d = Class::User::DBI::Domains->new( $conn );

        [ 'portland',    'Portland, Oregon location'       ],
        [ 'los angeles', 'Los Angeles, California location' ],

    print "Domain exists." if $p->exists_domain( 'Los Angeles' );

    my @domains = $p->fetch_domains;
    foreach my $domain ( @domains ) {
        my( $name, $description ) = @{$domain};
        print "$name => $description\n";

    print "Description for 'Portland' domain: ", 
          $d->get_domain_description( 'Portland' );
    $d->set_domain_description( 'Portland', 'Portland, Maine location' );
    $d->delete_domains( 'Portland' ); # Pass a list for multiple deletes.


This is a maintenance class facilitating the creation, deletion, and testing of domains that are compatible with Class::User::DBI::UserDomains.

With Class::User::DBI each user may have multiple domains (handled by Class::User::DBI::UserDomains, and testable through either that module or Class::User::DBI). An example of how a domain might be used: User 'john' has the "downtown" domain. 'karen' has the east-side domain. 'nancy' is a manager responsible for both downtown and the east-side, so nancy has both domains.

Domains are completely independent of roles and privileges. They allow for a separate layer of granularity for access control. The layer may be used for location based access control, jurisdiction/stewardship access control... whatever. It's just another set of constraints that can operate independently of roles and privileges.

A common usage is to configure a database table, and then add a few locations (domains) along with their descriptions. Next add one or more locations (or domains) to a user's domain set through Class::User::DBI::UserDomains. Finally, test your Class::User::DBI object to see if the user owned by a given object belongs to a given domain.

Think of domains as a locality. In the context of Class::User::DBI, a user may have a role which has privileges. And those privileges may be used within any of the user's domains or localities. That a "west coast" domain user who has the "sales" role might gain access only to "west coast" sales figures, while the user with an "east coast" domain who also has a "sales" role (with all the same privileges) may only gain access to east coast sales figures. Of course the domain(s) are just flags or attributes, similar to roles and privileges, but independent of the roles/privileges structure. What you do with these attributes is up to you. I like to use them to represent literal locations where a user my exercise the privileges granted by his role.


Nothing is exported. There are many object methods, and three class methods, described in the next section.


new (The constructor -- Class method.)

    my $domain_obj = Class::User::DBI::Domains->new( $connector );

Creates a domain object that can be manipulated to set and get roles from the database's 'cud_domains' table. Pass a DBIx::Connector object as a parameter. Throws an exception if it doesn't get a valid DBIx::Connector.

configure_db (Class method)

    Class::User::DBI::Domains->configure_db( $connector );

This is a class method. Pass a valid DBIx::Connector as a parameter. Builds a minimal database table in support of the Class::User::DBI::Domains class.

The table created will be cud_domains.


    $d->add_domains( [ 'Salt Lake City', 'Salt Lake City, Utah' ], ... );

Add one or more domains. Each domain must be bundled along with its description in an array ref. Pass an AoA for multiple domains, or just an aref for a single domain/description pair.

It will drop requests to add domains that already exist.

Returns a count of domains added, which may be less than the number passed if one already existed.


    $d->delete_domains( 'Portland', 'Los Angeles' ); # Closed two locations.

Deletes from the database all domains specified. Return value is the number of domains actually deleted, which may be less than the number of domains requested if any of the requested domains didn't exist in the database to begin with.


    print "Domain exists." if $d->exists_domain( 'Portland' );

Returns true if a given domain exists, and false if not.


    foreach my $domain ( $d->fetch_domains ) {
        print "$domain->[0] = $domain->[1]\n";

Returns an array of array refs. Each array ref contains the domain's name and its description as the first and second elements, respectively.

An empty list means there are no domains defined.


    my $description = $d->get_domain_description( 'Portland' );

Returns the description for a given domain. Throws an exception if the domain doesn't exist, so be sure to test with $r->exists_domain( 'Portland' ) first.


    $d->set_domain_description( 'Portland', 'Portland, Oregon again now.' );

Sets a new description for a given domain. If the domain doesn't exist in the database, if not enough parameters are passed, or if any of the params are undef, an exception will be thrown. To update a domain by giving it a blank description, pass an empty string as the description.


The dependencies for this module are the same as for Class::User::DBI, from this same distribution. Refer to the documentation in that module for a full description.


Please refer to the configure_db() class method for this module for a simple means of creating the table that supports this class.

All SQL for this distribution is contained in the Class::User::DBI::DB module.


If you find that your particular database engine is not playing nicely with the test suite from this module, it may be necessary to provide the database login credentials for a test database using the same engine that your application will actually be using. You may do this by setting $ENV{CUDBI_TEST_DSN}, $ENV{CUDBI_TEST_DATABASE}, $ENV{CUDBI_TEST_USER}, and $ENV{CUDBI_TEST_PASS}.

Currently the test suite tests against a SQLite database since it's such a lightweight dependency for the testing. The author also uses this module with several MySQL databases. As you're configuring your database, providing its credentials to the tests and running the test scripts will offer really good diagnostics if some aspect of your database tables proves to be at odds with what this module needs.


This module has only been tested on MySQL and SQLite database engines. If you are successful in using it with other engines, please send me an email detailing any additional configuration changes you had to make so that I can document the compatibility, and improve the documentation for the configuration process.



David Oswald, <davido at cpan.org>


Please report any bugs or feature requests to bug-class-user-dbi at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Class-User-DBI. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Class::User::DBI::Domains

You can also look for information at:



Copyright 2012 David Oswald.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.