The new Authentication tutorial is now available on CPAN. The Authorization tutorial is also on CPAN. Please use that instead of the example below.
The most up-to-date version is always on SVN. Use pod2html from your Perl's bin directory to convert it to HTML.
If you are implementing authentication and authorization in your Catalyst application, you may be having some difficulty recently. Authentication and Authorization is now implemented differently than is shown in the Catalyst::Manual::Tutorial (5.701003). Until related documentation has been updated, I hope that this will help you apply authentication and authorization to your own application.
This is not a full fledged tutorial and I do not presume to have a high level knowledge of all related components. What I am presenting here, however, is what worked for me. For familiarity, I'm basing this example directly on the MyApp tutorial from the Catalyst::Manual documentation. So, if you are familiar with that then the changes here should be clear and easily carried over into your own custom application as needed.
As always, feel free to request additional help in #catalyst, which is where I received the help I needed to implement this myself. My hope is that my presentation here is adequate enough that you will be able to implement this on your own with little stress. Only a few small changes are needed.
In short, the changes consist of the following:
See the brief list of suggested reading material (cpan docs) at the end of this document.
First, if you follow the Authentication tutorial's example, you have a database like the following.
CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT, email_address TEXT, first_name TEXT, last_name TEXT, active INTEGER); CREATE TABLE roles (id INTEGER PRIMARY KEY, role TEXT); CREATE TABLE user_roles (user_id INTEGER, role_id INTEGER, PRIMARY KEY (user_id, role_id));
You do not need to alter anything in your database.
If you've created your DBIx schema according to the same documentation, it should result in the following classes.
package MyAppDB::User; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/PK::Auto Core/); __PACKAGE__->table('users'); __PACKAGE__->add_columns(qw/id username password email_address first_name last_name/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many(map_user_role => 'MyAppDB::UserRole', 'user_id'); 1;
The only thing you will need to change in your User class is to add a second relationship below has_many. This new line will be a many_to_many relationship that says User can have many Roles and they will be identified by the role field in the map_user_roles relation. So, add the following:
__PACKAGE__->many_to_many( roles => 'map_user_role', 'role' );
package MyAppDB::Role; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/PK::Auto Core/); __PACKAGE__->table('roles'); __PACKAGE__->add_columns(qw/id role/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many(map_user_role => 'MyAppDB::UserRole', 'role_id'); 1;
Nothing needs to change in your Role class.
package MyAppDB::UserRole; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/PK::Auto Core/); __PACKAGE__->table('user_roles'); __PACKAGE__->add_columns(qw/user_id role_id/); __PACKAGE__->set_primary_key(qw/user_id role_id/); __PACKAGE__->belongs_to(user => 'MyAppDB::User', 'user_id'); __PACKAGE__->belongs_to(role => 'MyAppDB::Role', 'role_id'); 1;
Nothing needs to be changed in your UserRole class.
Your MyApp.pm should currently include the following:
use Catalyst qw/ . . . Authentication Authentication::Store::DBIC Authentication::Credential::Password Authorization::Roles Authorization::ACL . . . /;
You can change this to read as follows:
use Catalyst qw/ . . . Authentication Authorization::Roles Authorization::ACL . . . /;
If you stored your configuration in YAML (myapp.yml), it probably includes the following:
authentication: dbic: user_class: MyAppDB::User user_field: username password_field: password authorization: dbic: role_class: MyAppDB::Role role_field: role role_rel: map_user_role user_role_user_field: user_id
You'll need to change it to look like the following. Notice that configuration is no longer stored under
authorization->dbic, but that the authorization details are now placed under
authentication->realms->default->store. Also note that some of the fields have changed slightly. (Do not copy and paste the YAML content as proper indentation is crucial).
authentication: realms: default: credential: class: Password password_field: password password_type: clear store: class: DBIx::Class user_class: DB::User id_field: id role_relation: roles role_field: role
In this new YAML configuration...
refers to MyAppDB::User, up above.
The field your user is identified by in your Users table.
The name of the the many_to_many relationship we defined in MyAppDB::User
The name of the field in the Roles table that identifies the text names of your roles (ie 'admin').