X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Manual.git;a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FCookbook.pod;h=8b450c57f184806c0688ad84a4911c6b20db3ff4;hp=d6da3c8935013b26f78a10af51f41c7d9dd193c1;hb=e2728084ad684d622fbc47f14097b28cff1f2021;hpb=b1a08fe19fd4ce1cd7756727319d08156b1e563f diff --git a/lib/Catalyst/Manual/Cookbook.pod b/lib/Catalyst/Manual/Cookbook.pod index d6da3c8..8b450c5 100644 --- a/lib/Catalyst/Manual/Cookbook.pod +++ b/lib/Catalyst/Manual/Cookbook.pod @@ -11,7 +11,7 @@ Yummy code like your mum used to bake! =head1 Basics These recipes cover some basic stuff that is worth knowing for -catalyst developers. +Catalyst developers. =head2 Delivering a Custom Error Page @@ -127,7 +127,7 @@ reference. package MyApp::Controller::Foo; use Moose; use namespace::autoclean; - BEGIN { extends 'Catalyst::Controller'; + BEGIN { extends 'Catalyst::Controller' }; ## Write data into the session sub add_item : Local { @@ -212,7 +212,7 @@ See also L. =head1 Skipping your VCS's directories -Catalyst uses Module::Pluggable to load Models, Views and Controllers. +Catalyst uses Module::Pluggable to load Models, Views, and Controllers. Module::Pluggable will scan through all directories and load modules it finds. Sometimes you might want to skip some of these directories, for example when your version control system makes a subdirectory with @@ -221,7 +221,7 @@ Catalyst skips subversion and CVS directories already, there are other source control systems. Here is the configuration you need to add their directories to the list to skip. -You can make catalyst skip these directories using the Catalyst config: +You can make Catalyst skip these directories using the Catalyst config: # Configure the application __PACKAGE__->config( @@ -234,7 +234,7 @@ and other options. =head1 Users and Access Control -Most multiuser, and some single user web applications require that +Most multiuser, and some single-user web applications require that users identify themselves, and the application is often required to define those roles. The recipes below describe some ways of doing this. @@ -243,7 +243,7 @@ this. This is extensively covered in other documentation; see in particular L and the Authentication chapter -of the Tutorial at L. +of the Tutorial at L. =head2 Pass-through login (and other actions) @@ -262,27 +262,6 @@ like so: } } -=head2 FIXME - -To restrict access to any action, you can use the C method: - - sub restricted : Local { - my ( $self, $c ) = @_; - - $c->detach("unauthorized") - unless $c->check_user_roles( "admin" ); - - # do something restricted here - } - -You can also use the C method. This just gives an -error if the current user does not have one of the required roles: - - sub also_restricted : Global { - my ( $self, $c ) = @_; - $c->assert_user_roles( qw/ user admin / ); - } - =head2 Authentication/Authorization This is done in several steps: @@ -299,7 +278,7 @@ verification>. =item Authorization Making sure the user only accesses functions you want them to -access. This is done by checking the verified users data against your +access. This is done by checking the verified user's data against your internal list of groups, or allowed persons for the current page. =back @@ -326,17 +305,17 @@ Examples: A Storage backend contains the actual data representing the users. It is queried by the credential verifiers. Updating the store is not done -within this system, you will need to do it yourself. +within this system; you will need to do it yourself. Examples: - DBIC - Storage using a database. + DBIC - Storage using a database via DBIx::Class. Minimal - Storage using a simple hash (for testing). =head3 User objects A User object is created by either the storage backend or the -credential verifier, and filled with the retrieved user information. +credential verifier, and is filled with the retrieved user information. Examples: @@ -345,7 +324,7 @@ Examples: =head3 ACL authorization ACL stands for Access Control List. The ACL plugin allows you to -regulate access on a path by path basis, by listing which users, or +regulate access on a path-by-path basis, by listing which users, or roles, have access to which paths. =head3 Roles authorization @@ -362,35 +341,50 @@ pass it these values. =head3 Checking roles -Role checking is done by using the C<< $c->check_user_roles >> method, -this will check using the currently logged in user (via C<< $c->user +Role checking is done by using the C<< $c->check_user_roles >> method. +This will check using the currently logged-in user (via C<< $c->user >>). You pass it the name of a role to check, and it returns true if the user is a member. =head3 EXAMPLE - package MyApp; - use Moose; - use namespace::autoclean; - extends qw/Catalyst/; - use Catalyst qw/Authentication - Authorization::Roles/; - - __PACKAGE__->config( - 'Plugin::Authentication' => { - default => { - credential => { - class => 'Htpasswd', - # FIXME - }, - store => { - class => 'Null', - }, - }, - }, - ); - - sub login : Local { + package MyApp; + use Moose; + use namespace::autoclean; + extends qw/Catalyst/; + use Catalyst qw/ + Authentication + Authorization::Roles + /; + + __PACKAGE__->config( + authentication => { + default_realm => 'test', + realms => { + test => { + credential => { + class => 'Password', + password_field => 'password', + password_type => 'self_check', + }, + store => { + class => 'Htpasswd', + file => 'htpasswd', + }, + }, + }, + }, + ); + + package MyApp::Controller::Root; + use Moose; + use namespace::autoclean; + + BEGIN { extends 'Catalyst::Controller' } + + __PACKAGE__->config(namespace => ''); + + sub login : Local { my ($self, $c) = @_; if ( my $user = $c->req->param("user") @@ -418,11 +412,11 @@ the user is a member. =head3 Using authentication in a testing environment -Ideally, to write tests for authentication/authorization code one -would first set up a test database with known data, then use +Ideally, to write tests for authentication/authorization code one would +first set up a test database with known data, then use L to simulate a user logging -in. Unfortunately the former can be rather awkward, which is why it's -a good thing that the authentication framework is so flexible. +in. Unfortunately this can be rather awkward, which is why it's a good +thing that the authentication framework is so flexible. Instead of using a test database, one can simply change the authentication store to something a bit easier to deal with in a @@ -430,33 +424,23 @@ testing environment. Additionally, this has the advantage of not modifying one's database, which can be problematic if one forgets to use the testing instead of production database. -e.g., - - # FIXME - Out of date - use Catalyst::Plugin::Authentication::Store::Minimal::Backend; - - # Sets up the user `test_user' with password `test_pass' - MyApp->default_auth_store( - Catalyst::Plugin::Authentication::Store::Minimal::Backend->new({ - test_user => { password => 'test_pass' }, - }) - ); - -Now, your test code can call C<$c->login('test_user', 'test_pass')> and -successfully login, without messing with the database at all. +Alternatively, if you want to authenticate real users, but not have to +worry about their passwords, you can use +L to force all users to +authenticate with a global password. =head3 More information -L has a longer explanation. +L has a longer explanation. =head2 Authorization =head3 Introduction Authorization is the step that comes after -authentication. Authentication establishes that the user agent is -really representing the user we think it's representing, and then -authorization determines what this user is allowed to do. +authentication. Authentication establishes that the user agent is really +representing the user we think it's representing, and then authorization +determines what this user is allowed to do. =head3 Role Based Access Control @@ -477,7 +461,7 @@ With this action, anyone can just come into the moose cage and feed the moose, which is a very dangerous thing. We need to restrict this action, so that only a qualified moose feeder can perform that action. -The Authorization::Roles plugin let's us perform role based access +The Authorization::Roles plugin lets us perform role based access control checks. Let's load it: use parent qw/Catalyst/; @@ -525,7 +509,7 @@ administration). Checking for roles all the time can be tedious and error prone. -The Authorization::ACL plugin let's us declare where we'd like checks +The Authorization::ACL plugin lets us declare where we'd like checks to be done automatically for us. For example, we may want to completely block out anyone who isn't a @@ -576,7 +560,7 @@ If this action does not exist, an error will be thrown, which you can clean up in your C private action instead. Also, it's important to note that if you restrict access to "/" then -C, C, etc will also be restricted. +C, C, etc. will also be restricted. MyApp->acl_allow_root_internals; @@ -597,11 +581,14 @@ can be used outside of Catalyst, e.g. in a cron job). It's trivial to write a simple component in Catalyst that slurps in an outside Model: package MyApp::Model::DB; + use base qw/Catalyst::Model::DBIC::Schema/; + __PACKAGE__->config( schema_class => 'Some::DBIC::Schema', connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}]; ); + 1; and that's it! Now C is part of your @@ -614,9 +601,9 @@ See L. =head2 Create accessors to preload static data once per server instance When you have data that you want to load just once from the model at -server load instead of for each request, use mk_group_accessors to +startup, instead of for each request, use mk_group_accessors to create accessors and tie them to resultsets in your package that -inherits from DBIx::Class::Schema +inherits from DBIx::Class::Schema: package My::Schema; use base qw/DBIx::Class::Schema/; @@ -640,12 +627,12 @@ inherits from DBIx::Class::Schema and now in the controller, you can now access any of these without a per-request fetch: - $c->stash->{something} = $c->model('My::Schema')->schema->ACCESSORNAMEn; + $c->stash->{something} = $c->model('My::Schema')->schema->ACCESSORNAME; =head2 XMLRPC -Unlike SOAP, XMLRPC is a very simple (and imo elegant) web-services +Unlike SOAP, XMLRPC is a very simple (and elegant) web-services protocol, exchanging small XML messages like these: Request: @@ -748,7 +735,7 @@ enforce a specific one. =head1 Views Views pertain to the display of your application. As with models, -catalyst is uncommonly flexible. The recipes below are just a start. +Catalyst is uncommonly flexible. The recipes below are just a start. =head2 Catalyst::View::TT @@ -758,8 +745,8 @@ display your data; you can choose to generate HTML, PDF files, or plain text if you wanted. Most Catalyst applications use a template system to generate their HTML, -and though there are several template systems available, Template -Toolkit is probably the most popular. +and though there are several template systems available, +L