[cgiapp] Re: CAP:Authentication with an enum credential

Mark Rajcok mrajcok at gmail.com
Sun Apr 26 16:30:09 EDT 2009


On Mon, Apr 20, 2009 at 9:13 PM, Mark Rajcok <mrajcok at gmail.com> wrote:

> On Wed, Apr 15, 2009 at 9:15 AM, Mark Stosberg <mark at summersault.com>wrote:
>
>> On Tue, 14 Apr 2009 01:06:38 -0400
>> Mark Rajcok <mrajcok at gmail.com> wrote:
>>
>> > I'm using CAP:Authentication and I have a u_state field in my Users
>> table.
>> > The u_state field is a MySQL enum, and can be set to created, active,
>> > restricted, or disabled.
>> >
>> > I'm trying to figure out how I can display a "Sorry, your account has
>> been
>> > disabled" error page if a user with u_state=disabled tries to log in.
>> >
>> > I looked at (and tried using) custom filters with CAP:Authentication,
>> but
>> > something like the following isn't supported syntax-wise:
>> >    CONSTRAINTS => {  'stateFilter:u_state' =>
>>  "(created,active,restricted)"
>> > }
>> >
>> > Any suggestions?
>>
>> I think you are right, Mark. I think you may need to write your own driver
>> for
>> this.
>>
>> You can copy the DBI driver and modify it, or write one from scratch,
>> which has
>> the possibility of being simpler and less abstracted because it is
>> designed
>> just for your case.
>>
>> You could also ask Cees if he's interested in  patch for "enum()" support
>> in
>> CGI::Application::Plugin::Authentication.
>>
>>  Mark
>>
>
> Not exactly efficient (because I make another query of the database for
> every successful login), but here's what I'm doing for now:
>
> Added a callback to $self->authen->config(
>         POST_LOGIN_CALLBACK => \&_post_login,
>
> sub _post_login {  # we only get here if we authenticated
>     my $self = shift;
>     my $sql = 'select count(*) from user where u_username = ? and u_state =
> "disabled"';
>     if($self->dbh->selectrow_arrayref($sql, undef,
> $self->authen->username)->[0]) {
>         $self->authen->logout;
>         my $page = $self->custom_error(
>                 type=>'forbidden', msg=>'Your account has been disabled.');
>         print $self->query->header, $page;
>         exit  # prevent any other/normal CAP processing
>     }
>     # else the callback returns and the user is logged in
> }
>
> custom_error() is essentially and error run mode that I wrote.
>
> In essence, I'm using CAP::Authentication for normal username+password
> authentication, then I have this additional method to check the account
> state.
>

The above works when the user logs in.  It does not work if the user does
not log in -- i.e., if the user comes back to the website using a session
cookie.

To handle both cases, I removed POST_LOGIN_CALLBACK  and added a
cgiapp_prerun() method.  If the page requires authentication, then I check
the account state.

#------------------------------------------------------------------------------
sub cgiapp_prerun {                    # overrides
    my $self = shift;
    $self->_check_account_state if
$self->authen->is_protected_runmode($self->get_current_runmode())
}
#------------------------------------------------------------------------------
sub _check_account_state {
    my $self = shift;
    my $sql = 'select count(*) from user where u_username = ? and u_state =
"disabled"';
    if($self->dbh->selectrow_arrayref($sql,undef,
$self->authen->username)->[0]) {
        $self->authen->logout;
        my $page = $self->custom_error(type=>'forbidden', msg=>'Your account
has been disabled.');
        print $self->query->header, $page;
        exit
    }
}


More information about the cgiapp mailing list