FAQ
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

Search Discussions

  • Hernan Lopes at Jan 11, 2011 at 4:18 pm
    I dont know about the book,

    but this manual sure works and my opinion is its better than any book,
    (find the authorization/authentication and compare what you missed)

    the url should be
    http://search.cpan.org/~zarquon/Catalyst-Manual-5.8005/lib/Catalyst/Manual/Tutorial/01_Intro.pod

    att,

    Hernan

    On Tue, Jan 11, 2011 at 2:09 PM, 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
    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive:
    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20110111/4b4e294c/attachment.htm
  • Mike Raynham at Jan 11, 2011 at 5:18 pm

    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') );

    }
    }

    ###
  • Hernan Lopes at Jan 11, 2011 at 6:06 pm
    Or try this application which implements authentication example with perl
    catalyst from scratch.
    You can test it, its just a couple steps.. hope it helps.
    i wrote it sometime ago but i have not tested yet.

    1. create a database
    2. create tables:

    CREATE TABLE users
    (
    id serial NOT NULL,
    nome text,
    sobrenome text,
    is_deleted integer DEFAULT 0,
    endereco text,
    created date DEFAULT now(),
    username text,
    "password" text,
    telefone text,
    email character varying(255),
    CONSTRAINT users_pkey PRIMARY KEY (id)
    );

    CREATE TABLE roles
    (
    id integer NOT NULL,
    "role" text,
    CONSTRAINT role_pkey PRIMARY KEY (id)
    );


    CREATE TABLE users_to_roles
    (
    user_id integer NOT NULL,
    role_id integer NOT NULL,
    CONSTRAINT users_to_roles_pkey PRIMARY KEY (user_id, role_id),
    CONSTRAINT users_to_roles_role_id_fkey FOREIGN KEY (role_id)
    REFERENCES roles (id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT users_to_roles_user_id_fkey FOREIGN KEY (user_id)
    REFERENCES users (id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
    );

    2.1 add some data onto db:

    insert into roles (id, role) values (1, 'admin');
    insert into roles (id, role) values (2, 'gerente');
    insert into roles (id, role) values (3, 'banidos');
    insert into roles (id, role) values (4, 'funcionario');
    insert into roles (id, role) values (5, 'secretaria');

    insert into users (nome, sobrenome, is_deleted, endereco, username,
    password, email) values ('joe', 'silva', '0', '-', 'joe', 'silva', '
    joe@silva.net');
    insert into users (nome, sobrenome, is_deleted, endereco, username,
    password, email) values ('maria', 'gomes', '0', '-', 'maria', 'gomes', '
    mariagomes@hotmail.com');
    insert into users (nome, sobrenome, is_deleted, endereco, username,
    password, email) values ('admin', 'admin', '0', '-', 'admin', 'admin', '
    admin@admins.com');


    insert into users_to_roles ( role_id, user_id ) values (1, 3);
    insert into users_to_roles ( role_id, user_id ) values (2, 1);
    insert into users_to_roles ( role_id, user_id ) values (2, 2);

    3. create a default catalyst app

    catalyst.pl Example::Catalyst::Auth
    cd Example-Catalyst-Auth/

    4. create TT view

    script/example_catalyst_auth_create.pl view TT

    5. open TT.pm file to edit

    vim lib/Example/Catalyst/Auth/View/TT.pm

    6. insert the following into your TT.pm

    package Example::Catalyst::Auth::View::TT;
    use warnings;
    use strict;
    use base 'Catalyst::View::TT';

    __PACKAGE__->config(
    # Set to 1 for detailed timer stats in your HTML as comments
    TIMER => 0,
    # This is your wrapper template located in the 'root/src'
    WRAPPER => 'wrapper.tt2',
    # Change default TT extension
    TEMPLATE_EXTENSION => '.tt2',
    # Set the location for TT files
    INCLUDE_PATH => [
    Example::Catalyst::Auth->path_to( 'root', ),
    ],
    );

    __PACKAGE__->meta->make_immutable;

    1;


    7. now open the main ap config

    vim lib/Example/Catalyst/Auth.pm

    8. and insert inside your __PACKAGE__->config() :

    default_view => 'TT',
    ENCODING => 'utf-8',

    8.1 and also declare these inside your use Catalyst qw//:

    Unicode

    StackTrace
    Authentication
    Authorization::Roles

    8.2 and insert the Auth configuration also.. on that same file:

    __PACKAGE__->config->{'Plugin::Authentication'} = {
    default => {
    class => 'SimpleDB',
    # user_model => 'DBICSchemamodel::Users',
    user_model => 'DBICSchemamodel::User',
    password_type => 'clear',
    user_role_user_field => 'user_id',
    user_role_role_field => 'role_id',
    },
    };

    8.3 and also insert the Store config

    __PACKAGE__->config->{'Plugin::Cache'}{backend} = { #DEFAULT backend
    store => "FastMmap",
    class => "Cache::FastMmap",
    storage => "/tmp/cache",
    expires => 3600,
    };






    8. create the wrapper:

    vim root/wrapper.tt2

    9. and insert this content:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    </head>
    <body>
    [%content%]
    </body>
    </html>

    10. now lets modify our Root controller.
    We should create one index page (And test the view we setup is working)
    We should create one hidden page, which will show only when logged in.

    vim lib/Example/Catalyst/Auth/Controller/Root.pm

    10.1 declare use HTML::FormHandler

    use HTML::FormHandler;

    11. delete index action and add the following:

    sub auto :Private {
    my ($self, $c) =@_;

    if ( $c->action eq $c->controller('root')->action_for('login')
    $c->action eq $c->controller('root')->action_for('index')
    ) {
    return 1;
    }

    # If a user doesn't exist, force login
    if (
    !$c->user_exists
    or (
    (
    !$c->check_user_roles('admin')
    and !$c->check_user_roles('gerente')
    and !$c->check_user_roles('funcionario')
    )
    )
    )
    {
    # Redirect the user to the login page
    $c->forward('login');
    # Return 0 to cancel 'post-auto' processing and prevent use of
    application
    return 0;
    }

    # User found, so return 1 to continue with processing after this 'auto'
    return 1;
    }

    sub index :Path :Args(0) {
    my ( $self, $c ) = @_;
    $c->stash(template => \'Welcome please <a href="/login">login</a>'); #or
    i could use: template => 'index.tt2', and create that file inside myapp/root
    }

    sub hidden_page :Path('/hidden_page') :Args(0) {
    my ( $self, $c ) = @_;
    $c->stash( template => \'CONTEÚDO ESCONDIDO' );
    }

    sub login : Path('/login') : Args(0) {
    my ( $self, $c ) = @_;

    my $form = HTML::FormHandler->new({
    field_list => [
    username => {
    type => 'Text',
    label => 'Login',
    required => 1,
    required_message => 'Campo Requerido',
    },
    password => {
    type => 'Password',
    label => 'Password',
    required => 1,
    required_message => 'Campo Requerido',
    },
    submit => {
    type => 'Submit',
    value => 'Login',
    },
    ],
    });
    $c->stash( template => \$form->render);

    # Get the username and password from form
    my $username = $c->request->params->{username} || undef;
    my $password = $c->request->params->{password} || undef;

    # If the username and password values were found in form
    if ( defined($username) && defined($password) ) {

    # Attempt to log the user in
    if (
    $c->authenticate(
    {
    username => $username,
    password => $password
    }
    )
    )
    {

    $c->forward('hidden_page');

    return;
    }
    else {

    # Set an error message
    $c->stash->{error_msg} =
    "Login desconhecido. Verifique seu login e senha e tente novamente. ";
    }
    }

    # If either of above don't work out, send to the login page
    $c->detach('index') if ($c->user_exists);
    }




    sub logout : Path('/logout') : Args(0) {
    my ( $self, $c ) = @_;

    # Clear the user's state
    $c->logout;

    # Send the user to the starting point
    $c->response->redirect( $c->uri_for('/') );
    }









    12. now create your schema:

    script/example_catalyst_auth_create.pl model DBICSchemamodel DBIC::Schema
    Example::Catalyst::Auth::DBSchema create=static dbi:Pg:dbname=test_auth
    dblogin password

    13. add many_to_many relationships to model User

    vim lib/Example/Catalyst/Auth/DBSchema/Result/User.pm

    14. insert before make_immutable or 1

    __PACKAGE__->many_to_many('roles', 'users_to_roles' => 'role');

    15. add many_to_many relationships to model Role

    vim lib/Example/Catalyst/Auth/DBSchema/Result/Role.pm

    14. insert before make_immutable or 1

    __PACKAGE__->many_to_many('users', 'users_to_roles' => 'user');







    att,
    Hernan

    On Tue, Jan 11, 2011 at 3:18 PM, Mike Raynham wrote:
    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: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive:
    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20110111/2be0b04a/attachment.htm
  • Ben Lavery at Jan 11, 2011 at 6:20 pm
    Hernan, Steve, and Mike, many thanks for your replies.

    I shall look at your replies in more detail tomorrow (I might get to look at it this evening, depends how much work is on this night shift).

    From what I have looked at now though I think your replies will help me a lot. I really appreciate your help :)

    Many thanks once again,
    Ben
  • Steve at Jan 11, 2011 at 5:18 pm
    Ben,

    I understand how frustrating it is to get started, having done so myself
    fairly recently.

    That said, I don't know what help you want. It appears that you may be
    trying to implement the authentication to the application 'DBAuthTest',
    but your application, (which I downloaded and ran) has no facility for
    loggin in a user. There are no login templates, no actions for logging
    in, etc. Furthermore, the authentication plugin is missing.

    I would suggest continuing on in the book through Chapter eight
    (SneakyCat), as this application does authentication and authorization.
    It may provide you the 'missing bits' you need to customize the app from
    Ch. 6.

    P.S. I noticed that the application has yesterday's date on it. Is
    there any chance you uploaded an old version???

    Steve
    Steve Schafer
    Matsch Systems
    Phone: 616-477-9629
    Mobile: 616-304-9440
    Email: steve@matsch.com
    Web: http://www.matsch.com/

    On 1/11/2011 11:09 AM, 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
    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedJan 11, '11 at 4:09p
activeJan 11, '11 at 6:20p
posts6
users4
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2021 Grokbase