[Catalyst] Extending C::Plugin::Authentication::Store::DBIC for
additional constraints
Ashvin Kumar
ashvin at affinitycircles.com
Mon Mar 26 09:28:36 GMT 2007
Doran L. Barton wrote:
>Not long ago, Fernan Aguero proclaimed...
>
>
>>Certainly not what you were asking (subclassing
>>store::dbic), but ...
>>
>>
>>sub login : Local {
>> my ( $self, $c ) = @_;
>>
>> my $username = $c->req->params->{username} || "";
>> my $password = $c->req->params->{password} || "";
>>
>> my $model = $c->model('Users');
>>
>> if ( $username && $password ) {
>>
>> # attempt to login
>> if ( $c->login( $username, $password ) ) {
>>
>> # now we check site_id
>> $ok = $model->search(
>> { username => $username,
>> password => $password,
>> site_id => $site_id } )->count();
>>
>> $c->logout unless $ok > 0;
>>
>> }
>>
>>
>
>This is an interesting strategy. The only thing I question is the
>$c->login() call because the username field is not unique (there could be
>more than one 'johndoe' in the table).
>
>After I posted my original question, I started wondering about
>concatenating the username and site_id together. I have a feeling this
>won't fly well inside DBIx::Class, but in theory if I declare the user
>field to be "username || '#' || site_id" and call the login() using
>$username . '#' . $c->stash->{'site_id'}, the resulting SELECT in sql would
>find the unique row. Of course, that all falls apart in the ORM, most
>likely.
>
>
We had a similar requirement, and came to a slightly different solution
than proposed by Fernan. Instead of authenticating on username/password,
we authenticated based on user_id/password where user_id is the primary
key and guaranteed to be unique.
In the login subroutine, we pulled the user object based on the username
param and the site_id, and then called $c->login with the user object's
id and the password param. In code-speak:
In our setup:
__PACKAGE__->config->{ authentication }{ dbic } = {
user_class => 'MyModel::users'
user_field => 'id', # guaranteed to be unique
password_field => 'password',
};
Our login function:
sub login : Local {
my ( $self, $c ) = @_;
my $username = $c->req->params->{ username } || '';
my $password = $c->req->params->{ password } || '';
my $site_id = $c->req->params->{ site_id };
if ( $username && $password ) {
my $user_obj = $c->model( 'MyModel::users' )->search(
{
username => $username,
site_id => $site_id,
}
)->first;
if ( $user_obj && $c->login( $user_obj->id, $password ) ) {
# user's logged in...
}
}
}
This process takes an extra query since the authentication class does
it's own query as well, but it solves the problem. I hope that helps.
Ashvin
More information about the Catalyst
mailing list