finalising default and index :Private expurgation
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / Authentication.pod
index 3990f74..66225d8 100644 (file)
@@ -125,8 +125,8 @@ Although we could manually edit the DBIC schema information to include
 the new tables added in the previous step, let's use the C<create=static>
 option on the DBIC model helper to do most of the work for us:
 
-    $ script/myapp_create.pl model MyAppDB DBIC::Schema MyApp::Schema::MyAppDB create=static dbi:SQLite:myapp.db
-    $ ls lib/MyApp/Schema/MyAppDB
+    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=static dbi:SQLite:myapp.db
+    $ ls lib/MyApp/Schema
     Authors.pm  BookAuthors.pm  Books.pm  Roles.pm  UserRoles.pm  Users.pm
 
 Notice how the helper has added three new table-specific result source 
@@ -142,7 +142,7 @@ relationship information to the three new result source files.  Edit
 each of these files and add the following information between the C<# 
 DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment and the closing C<1;>:
 
-C<lib/MyApp/Schema/MyAppDB/Users.pm>:
+C<lib/MyApp/Schema/Users.pm>:
 
     #
     # Set relationships:
@@ -153,7 +153,7 @@ C<lib/MyApp/Schema/MyAppDB/Users.pm>:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *foreign* table
-    __PACKAGE__->has_many(map_user_role => 'MyApp::Schema::MyAppDB::UserRoles', 'user_id');
+    __PACKAGE__->has_many(map_user_role => 'MyApp::Schema::UserRoles', 'user_id');
     
     # many_to_many():
     #   args:
@@ -164,7 +164,7 @@ C<lib/MyApp/Schema/MyAppDB/Users.pm>:
     __PACKAGE__->many_to_many(roles => 'map_user_role', 'role');
 
 
-C<lib/MyApp/Schema/MyAppDB/Roles.pm>:
+C<lib/MyApp/Schema/Roles.pm>:
 
     #
     # Set relationships:
@@ -175,10 +175,10 @@ C<lib/MyApp/Schema/MyAppDB/Roles.pm>:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *foreign* table
-    __PACKAGE__->has_many(map_user_role => 'MyApp::Schema::MyAppDB::UserRoles', 'role_id');
+    __PACKAGE__->has_many(map_user_role => 'MyApp::Schema::UserRoles', 'role_id');
 
 
-C<lib/MyApp/Schema/MyAppDB/UserRoles.pm>:
+C<lib/MyApp/Schema/UserRoles.pm>:
 
     #
     # Set relationships:
@@ -189,14 +189,14 @@ C<lib/MyApp/Schema/MyAppDB/UserRoles.pm>:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
-    __PACKAGE__->belongs_to(user => 'MyApp::Schema::MyAppDB::Users', 'user_id');
+    __PACKAGE__->belongs_to(user => 'MyApp::Schema::Users', 'user_id');
     
     # belongs_to():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
-    __PACKAGE__->belongs_to(role => 'MyApp::Schema::MyAppDB::Roles', 'role_id');
+    __PACKAGE__->belongs_to(role => 'MyApp::Schema::Roles', 'role_id');
 
 
 The code for these three sets of updates is obviously very similar to 
@@ -204,9 +204,9 @@ the edits we made to the C<Books>, C<Authors>, and C<BookAuthors>
 classes created in Part 3.
 
 Note that we do not need to make any change to the 
-C<lib/MyApp/Schema/MyAppDB.pm> schema file.  It simple tells DBIC to 
+C<lib/MyApp/Schema.pm> schema file.  It simple tells DBIC to 
 load all of the result source files it finds in below the 
-C<lib/MyApp/Schema/MyAppDB> directory, so it will automatically pick 
+C<lib/MyApp/Schema> directory, so it will automatically pick 
 up our new table information.
 
 
@@ -227,13 +227,13 @@ Look for the three new model objects in the startup debug output:
     +-------------------------------------------------------------------+----------+
     | MyApp::Controller::Books                                          | instance |
     | MyApp::Controller::Root                                           | instance |
-    | MyApp::Model::MyAppDB                                             | instance |
-    | MyApp::Model::MyAppDB::Author                                     | class    |
-    | MyApp::Model::MyAppDB::Books                                      | class    |
-    | MyApp::Model::MyAppDB::BookAuthors                                | class    |
-    | MyApp::Model::MyAppDB::Roles                                      | class    |
-    | MyApp::Model::MyAppDB::Users                                      | class    |
-    | MyApp::Model::MyAppDB::UserRoles                                  | class    |
+    | MyApp::Model::DB                                                  | instance |
+    | MyApp::Model::DB::Author                                          | class    |
+    | MyApp::Model::DB::Books                                           | class    |
+    | MyApp::Model::DB::BookAuthors                                     | class    |
+    | MyApp::Model::DB::Roles                                           | class    |
+    | MyApp::Model::DB::Users                                           | class    |
+    | MyApp::Model::DB::UserRoles                                       | class    |
     | MyApp::View::TT                                                   | instance |
     '-------------------------------------------------------------------+----------'
     ...
@@ -325,19 +325,19 @@ C<myapp.conf> file and update it to match:
                     # Use DBIC to retrieve username, password & role information
                     class DBIx::Class
                     # This is the model object created by Catalyst::Model::DBIC 
-                    # from your schema (you created 'MyAppDB::User' but as the 
-                    # Catalyst startup debug messages show, it was loaded as 
-                    # 'MyApp::Model::MyAppDB::Users').
+                    # from your schema (you created 'MyApp::Schema::User' but as
+                    # the Catalyst startup debug messages show, it was loaded as 
+                    # 'MyApp::Model::DB::Users').
                     # NOTE: Omit 'MyApp::Model' here just as you would when using 
-                    # '$c->model("MyAppDB::Users)'
-                    user_class MyAppDB::Users
+                    # '$c->model("DB::Users)'
+                    user_class DB::Users
                     # This is the name of the field in your 'users' table that 
                     # contains the user's name
                     id_field username
                 </store>
             </dbic>
-          </realms>
-        </authentication>
+        </realms>
+    </authentication>
 
 Inline comments in the code above explain how each field is being used.
 
@@ -352,14 +352,16 @@ Use the Catalyst create script to create two stub controller files:
     $ script/myapp_create.pl controller Login
     $ script/myapp_create.pl controller Logout
 
-B<NOTE>: You could easily use a single controller here.  For example,
+B<NOTE:> You could easily use a single controller here.  For example,
 you could have a C<User> controller with both C<login> and C<logout>
 actions.  Remember, Catalyst is designed to be very flexible, and leaves
 such matters up to you, the designer and programmer.
 
-Then open C<lib/MyApp/Controller/Login.pm>, locate the C<sub index : 
-Private> method (this was automatically inserted by the helpers when we 
-created the Login controller above), and delete this line:
+Then open C<lib/MyApp/Controller/Login.pm>, locate the C<sub index 
+:Path :Args(0)> method (or C<sub index : Private> if you are using an 
+older version of Catalyst) that was automatically inserted by the 
+helpers when we created the Login controller above, and delete this 
+line:
 
     $c->response->body('Matched MyApp::Controller::Login in Login.');
 
@@ -371,7 +373,7 @@ Then update it to match:
     
     =cut
     
-    sub index : Private {
+    sub index :Path :Args(0) {
         my ($self, $c) = @_;
     
         # Get the username and password from form
@@ -403,22 +405,21 @@ will stay at the login page but receive an error message.  If the
 C<username> and C<password> values are not present in the form, the 
 user will be taken to the empty login form.
 
-Note that we could have used something like C<sub default :Private>; 
-however, the use of C<default> actions is discouraged because it does
-not receive path args as with other actions.  The recommended practice 
-is to only use C<default> in C<MyApp::Controller::Root>.
-
-Another option would be to use something like 
-C<sub base :Path :Args(0) {...}> (where the C<...> refers to the login 
-code shown in C<sub index : Private> above). We are using C<sub base 
-:Path :Args(0) {...}> here to specifically match the URL C</login>. 
-C<Path> actions (aka, "literal actions") create URI matches relative to 
-the namespace of the controller where they are defined.  Although 
-C<Path> supports arguments that allow relative and absolute paths to be 
-defined, here we use an empty C<Path> definition to match on just the 
-name of the controller itself.  The method name, C<base>, is arbitrary. 
-We make the match even more specific with the C<:Args(0)> action 
-modifier -- this forces the match on I<only> C</login>, not 
+Note that we could have used something like C<sub default :Path>,
+however partly for historical reasons, and partly for code clarity it
+is generally recommended only to use C<default> in
+C<MyApp::Controller::Root>, and then mainly to generate the 404 not
+found page for the application.
+
+Instead, we are using C<sub base :Path :Args(0) {...}> here to 
+specifically match the URL C</login>. C<Path> actions (aka, "literal 
+actions") create URI matches relative to the namespace of the 
+controller where they are defined.  Although C<Path> supports 
+arguments that allow relative and absolute paths to be defined, here 
+we use an empty C<Path> definition to match on just the name of the 
+controller itself.  The method name, C<index>, is arbitrary. We make 
+the match even more specific with the C<:Args(0)> action modifier --
+this forces the match on I<only> C</login>, not 
 C</login/somethingelse>.
 
 Next, update the corresponding method in 
@@ -430,7 +431,7 @@ C<lib/MyApp/Controller/Logout.pm> to match:
     
     =cut
     
-    sub index : Private {
+    sub index :Path :Args(0) {
         my ($self, $c) = @_;
     
         # Clear the user's state
@@ -617,17 +618,13 @@ running) and restart it:
 
     $ script/myapp_server.pl
 
-B<IMPORTANT NOTE>: If you happen to be using Internet Explorer, you may
-need to use the command C<script/myapp_server.pl -k> to enable the
-keepalive feature in the development server.  Otherwise, the HTTP
-redirect on successful login may not work correctly with IE (it seems to
-work without -k if you are running the web browser and development
-server on the same machine).  If you are using browser a browser other
-than IE, it should work either way.  If you want to make keepalive the
-default, you can edit C<script/myapp_server.pl> and change the
-initialization value for C<$keepalive> to C<1>.  (You will need to do
-this every time you create a new Catalyst application or rebuild the
-C<myapp_server.pl> script.)
+B<IMPORTANT NOTE:> If you are having issues with authentication on 
+Internet Explorer, be sure to check the system clocks on both your 
+server and client machines.  Internet Explorer is very picky about 
+timestamps for cookies.  Note that you can quickly sync an Ubuntu
+system with the following command:
+
+    sudo ntpdate ntp.ubuntu.com
 
 Now trying going to L<http://localhost:3000/books/list> and you should
 be redirected to the login page, hitting Shift+Reload if necessary (the
@@ -684,6 +681,11 @@ dirty" way to do this:
     e727d1464ae12436e899a726da5b2f11d8381b26
     $
 
+B<Note:> If you are following along in Ubuntu, you will need to install 
+C<Digest::SHA> with the following command to run the example code above:
+
+    sudo apt-get install libdigest-sha-perl
+
 B<Note:> You should probably modify this code for production use to
 not read the password from the command line.  By having the script
 prompt for the cleartext password, it avoids having the password linger
@@ -716,10 +718,9 @@ algorithms are supported.  See C<Digest> for more information.
 =head2 Enable SHA-1 Hash Passwords in
 C<Catalyst::Plugin::Authentication::Store::DBIC>
 
-Edit C<myapp.yml> and update it to match (the C<password_type> and
+Edit C<myapp.conf> and update it to match (the C<password_type> and
 C<password_hash_type> are new, everything else is the same):
 
-    ---
     name MyApp
     <authentication>
         default_realm dbic
@@ -739,24 +740,24 @@ C<password_hash_type> are new, everything else is the same):
                     password_type  hashed
                     # Use the SHA-1 hashing algorithm
                     password_hash_type SHA-1
-                 </credential>
+                </credential>
                 <store>
                     # Use DBIC to retrieve username, password & role information
                     class DBIx::Class
                     # This is the model object created by Catalyst::Model::DBIC 
-                    # from your schema (you created 'MyAppDB::User' but as the 
-                    # Catalyst startup debug messages show, it was loaded as 
-                    # 'MyApp::Model::MyAppDB::Users').
+                    # from your schema (you created 'MyApp::Schema::User' but as
+                    # the Catalyst startup debug messages show, it was loaded as 
+                    # 'MyApp::Model::DB::Users').
                     # NOTE: Omit 'MyApp::Model' here just as you would when using 
-                    # '$c->model("MyAppDB::Users)'
-                    user_class MyAppDB::Users
+                    # '$c->model("DB::Users)'
+                    user_class DB::Users
                     # This is the name of the field in your 'users' table that 
                     # contains the user's name
                     id_field username
-                 </store>
-              </dbic>
-           </realms>
-         </authentication>
+                </store>
+            </dbic>
+        </realms>
+    </authentication>
 
 =head2 Try Out the Hashed Passwords
 
@@ -797,7 +798,7 @@ has changed):
         my ($self, $c, $id) = @_;
     
         # Search for the book and then delete it
-        $c->model('MyAppDB::Books')->search({id => $id})->delete_all;
+        $c->model('DB::Books')->search({id => $id})->delete_all;
     
         # Use 'flash' to save information across requests until it's read
         $c->flash->{status_msg} = "Book deleted";
@@ -853,10 +854,11 @@ C<__PACKAGE__-E<gt>config> setting to something like:
             session => {flash_to_stash => 1}
         );
 
-B<or> add the following to C<myapp.yml>:
+B<or> add the following to C<myapp.conf>:
 
-    session:
-        flash_to_stash: 1
+    <session>
+        flash_to_stash   1
+    </session>
 
 The C<__PACKAGE__-E<gt>config> option is probably preferable here 
 since it's not something you will want to change at runtime without it