On 11/01/11 16:09, Ben Lavery wrote:
Dear all,

After installing Catalyst on an OpenIndiana virtual machine, I've been working 
through the Definitive Guide to Catalyst for the last few weeks and have been 
impressed with how smoothly most of it has gone.

I have, however, become unstuck at Chapter 6.  The book explains how to create 
an application that uses some simple CRUD with user and role data, and uses 
authentication to prevent users updating other user's data.
I have a working application that allows one to create and read user data, but 
I can't figure out how to apply the authentication.  The book says:
"When using the Authentication plug-in, as we showed in Chapter 3..."

I've gone back to Chapter 3 and followed the steps, but I'm not sure where I am supposed to 
put the "$c->authenticate".
If I place it in DBAuthTest::Controller::Root in a subroutine called "auto", 
every page on the site needs me to log in, but no matter what I put in the username and 
password fields it says that the data is invalid.
As such I have no idea where I have gone wrong, after Googling I can't find 
similar problems, or people who have had similar problems or implemented a 
similar system in a similar way.
I have looked at the source code provided on the publisher's site, but it 
doesn't include code for the whole chapter, and indeed seems to stop given code 
a page or two previous to where I am now...

I have uploaded a copy of my application to 
http://hashbang0.com/personal/DBAuthTest.tar.bz2 (~46K) which I hope help 
demonstrate where I am currently.

Many thanks for your time, I appreciate any help you can give,

Ben Lavery

The authentication section of the online tutorial, as suggested by Hernan Lopes, is definitely worth reading. However, what follows may get you started. The following approach doesn't deal with roles or permission levels - it just tests if a user is logged in or not.

The following code is just to give you an idea of how it would work. I've just grabbed bits of code from various places and stuck them together, so please don't expect to be able to just copy and paste it into your code :-)

In your secure controller actions, you need to check if a user is logged in:

In DBAuthTest::Controller::AuthUsers...

###

sub add : Chained('base'): PathPart('add'): Args(0) {
    my ($self, $c) = @_;

    # Detach to the no_user action if a user is not logged in.
    $c->detach( '/no_user' ) unless $c->user_exists;

    # Do secure stuff here...
}

###

Then in DBAuthTest::Controller::Root...

###

sub no_user :Chained('/') :PathPart :Args(0) {
    my ($self, $c) = @_;
        
    # The user is not logged in.

    # Remember the failed action so that we can redirect to it
    # after login.
    $c->session->{action_private_path} = $c->action->private_path;

    # Put a message in the flash so that we can display it on the
    # login page.
    $c->flash(
        error_msg =>
            'To perform the requested action, you must be logged in.'
    );

    # Redirect to a login page.
    $c->response->redirect(
        $c->uri_for_action( '/login' )
    );
}

###

You then need a suitable controller to handle authentication:

###

package DBAuthTest::Controller::Login;

sub login :Chained('base') :PathPart('login') :Args(0) {
    my ( $self, $c ) = @_;

    # Get username and password from somewhere...
    my $username = $c->request->params->{username};
    my $password = $c->request->params->{password};

    # Do something here if username and password have
    # not been supplied.
        
    unless ( $c->authenticate( {
        username => $username,
        password => $password
    } ) ) {

        # Stash an error message.
        $c->stash(
            error_msg => 'Incorrect username, password, or both',
        );

        # Handle invalid credentials.

        return;
    }

    if( $c->session->{action_private_path} ) {

        # Redirect to the previously unauthorised action.
        $c->response->redirect(
            $c->uri_for_action( $c->session->{action_private_path} )
        );

        delete $c->session->{action_private_path};

    } else {

        # Redirect to a default page.
        $c->response->redirect( $c->uri_for_action('/index') );

    }
}

###


_______________________________________________
List: [email protected]
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/

Reply via email to