Forgot to add Ubuntu quick time sync command to prev commit
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / Authentication.pod
index fa577d3..7e002a8 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 |
     '-------------------------------------------------------------------+----------'
     ...
@@ -287,55 +287,63 @@ backed session store).
 
 Although C<__PACKAGE__-E<gt>config(name =E<gt> 'value');> is still 
 supported, newer Catalyst applications tend to place all configuration 
-information in C<myapp.yml> and automatically load this information 
+information in C<myapp.conf> and automatically load this information 
 into C<MyApp-E<gt>config> using the 
-L<ConfigLoader|Catalyst::Plugin::ConfigLoader> plugin.  Here, we need 
-to load several parameters that tell 
+L<ConfigLoader|Catalyst::Plugin::ConfigLoader> plugin.  
+
+First, as noted in Part 3 of the tutorial, Catalyst has recently 
+switched from a default config file format of YAML to 
+C<Config::General> (an apache-like format).  In case you are using
+a version of Catalyst earlier than v5.7014, delete the C<myapp.yml>
+file and simply follow the directions below to create a new
+C<myapp.conf> file.
+
+Here, we need to load several parameters that tell 
 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> 
 where to locate information in your database.  To do this, edit the 
-C<myapp.yml> YAML and update it to match:
-
-    ---
-    name: MyApp
-    authentication:
-        default_realm: dbic
-        realms:
-            dbic:
-                credential:
+C<myapp.conf> file and update it to match:
+
+    name MyApp
+    <authentication>
+        default_realm dbic
+        <realms>
+            <dbic>
+                <credential>
                     # Note this first definition would be the same as setting
                     # __PACKAGE__->config->{authentication}->{realms}->{dbic}
                     #     ->{credential} = 'Password' in lib/MyApp.pm 
-                    # (IOW, each hash key becomes a "name:" in the YAML file).
                     #
                     # Specify that we are going to do password-based auth
-                    class:          Password
+                    class Password
                     # This is the name of the field in the users table with the
                     # password stored in it
-                    password_field: password
+                    password_field password
                     # We are using an unencrypted password now
-                    password_type:  clear
-                store:
+                    password_type clear
+                </credential>
+                <store>
                     # Use DBIC to retrieve username, password & role information
-                    class:          DBIx::Class
+                    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
+                    id_field username
+                </store>
+            </dbic>
+        </realms>
+    </authentication>
 
 Inline comments in the code above explain how each field is being used.
 
-B<TIP>: Although YAML uses a very simple and easy-to-ready format, it 
-does require the use of a consistent level of indenting.  Be sure you 
-line up everything on a given 'level' with the same number of indents. 
-Also, be sure B<not> to use C<tab> characters (YAML does not support 
-them because they are handled inconsistently across editors).
-
+Note that you can use many other config file formats with catalyst.
+See L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
+for details.
 
 =head2 Add Login and Logout Controllers
 
@@ -344,7 +352,7 @@ 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.
@@ -609,17 +617,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
@@ -676,6 +680,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
@@ -708,44 +717,46 @@ 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
-        realms:
-            dbic:
-                credential:
+    name MyApp
+    <authentication>
+        default_realm dbic
+        <realms>
+            <dbic>
+                <credential>
                     # Note this first definition would be the same as setting
                     # __PACKAGE__->config->{authentication}->{realms}->{dbic}
                     #     ->{credential} = 'Password' in lib/MyApp.pm 
-                    # (IOW, each hash key becomes a "name:" in the YAML file).
                     #
                     # Specify that we are going to do password-based auth
-                    class:          Password
+                    class Password
                     # This is the name of the field in the users table with the
                     # password stored in it
-                    password_field: password
+                    password_field password
                     # Switch to more secure hashed passwords
-                    password_type:  hashed
+                    password_type  hashed
                     # Use the SHA-1 hashing algorithm
-                    password_hash_type: SHA-1
-                store:
+                    password_hash_type SHA-1
+                </credential>
+                <store>
                     # Use DBIC to retrieve username, password & role information
-                    class:          DBIx::Class
+                    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
-
+                    id_field username
+                </store>
+            </dbic>
+        </realms>
+    </authentication>
 
 =head2 Try Out the Hashed Passwords
 
@@ -786,7 +797,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";
@@ -842,10 +853,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