X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Manual.git;a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FTutorial%2FAppendices.pod;h=4004312d419fe2ad477e6970e31b8db554c40050;hp=eca683080124890614f8fb0257c2808bda172dc9;hb=3b1fa91be1d89d2297aa9e8e83462344d9cd9820;hpb=d712b8268991d1d97723bda87975411c4f74263d diff --git a/lib/Catalyst/Manual/Tutorial/Appendices.pod b/lib/Catalyst/Manual/Tutorial/Appendices.pod index eca6830..4004312 100644 --- a/lib/Catalyst/Manual/Tutorial/Appendices.pod +++ b/lib/Catalyst/Manual/Tutorial/Appendices.pod @@ -1,11 +1,11 @@ =head1 NAME -Catalyst::Manual::Tutorial::Appendices - Catalyst Tutorial - Part 9: Appendices +Catalyst::Manual::Tutorial::Appendices - Catalyst Tutorial - Chapter 10: Appendices =head1 OVERVIEW -This is B of the Catalyst tutorial. +This is B for the Catalyst tutorial. L @@ -21,30 +21,34 @@ L =item 3 -L +L =item 4 -L +L =item 5 -L +L =item 6 -L +L =item 7 -L +L =item 8 -L +L =item 9 +L + +=item 10 + B =back @@ -52,7 +56,7 @@ B =head1 DESCRIPTION -This part of the tutorial provides supporting information relevant to +This chapter of the tutorial provides supporting information relevant to the Catalyst tutorial. @@ -71,28 +75,28 @@ regex patterns). I: =over 4 -=item * +=item * ":0,$s/^ " Removes four leading spaces from the entire file (from the first line, C<0>, to the last line, C<$>). -=item * +=item * "%s/^ " A shortcut for the previous item (C<%> specifies the entire file; so this removes four leading spaces from every line). -=item * +=item * ":.,$s/^ " Removes the first four spaces from the line the cursor is on at the time the regex command is executed (".") to the last line of the file. -=item * +=item * ":.,44s/^ " @@ -103,8 +107,8 @@ Removes four leading space from the current line through line 44 =head2 "Un-indenting" with Emacs -Although there author has not used emacs for many years (apologies to -the emacs fans out there), here is a quick hint to get you started. To +Although the author has not used Emacs for many years (apologies to +the Emacs fans out there), here is a quick hint to get you started. To replace the leading spaces of every line in a file, use: M-x replace-regexp @@ -112,22 +116,31 @@ replace the leading spaces of every line in a file, use: with: All of that will occur on the single line at the bottom of your screen. -Note that "" represents the return key/enter. Also, there are +Note that "" represents the return key/enter. Also, there are four spaces after the "^" on the "Replace regexp:" line and no spaces entered on the last line. You can limit the replacement operation by selecting text first (depending -on your version of emacs, you can either use the mouse or experiment with -commands such as C to set the mark at the cursor location and +on your version of Emacs, you can either use the mouse or experiment with +commands such as C to set the mark at the cursor location and C> and C> to set the mark at the beginning and end of the file respectively. +Also, Stefan Kangas sent in the following tip about an alternate +approach using the command C to redo the indentation +for the currently selected region (adhering to indent rules in the +current major mode). You can run the command by typing M-x indent- +region or pressing the default keybinding C-M-\ in cperl-mode. +Additional details can be found here: + +L + -=head1 APPENDIX 2: USING MYSQL AND POSTGRESQL +=head1 APPENDIX 2: USING POSTGRESQL AND MYSQL The main database used in this tutorial is the very simple yet powerful SQLite. This section provides information that can be used to "convert" -the tutorial to use MySQL and PostgreSQL. However, note that part of +the tutorial to use PostgreSQL and MySQL. However, note that part of the beauty of the MVC architecture is that very little database-specific code is spread throughout the system (at least when MVC is "done right"). Consequently, converting from one database to another is @@ -140,16 +153,375 @@ section are not designed to take maximum advantage of the various features in each database for issues such as referential integrity and field types/constraints. + +=head2 PostgreSQL + +Use the following steps to adapt the tutorial to PostgreSQL. Thanks +to Caelum (Rafael Kitover) for assistance with the most recent +updates, and Louis Moore, Marcello Romani and Tom Lanyon for help with +earlier versions. + +=over 4 + +=item * + +Chapter 3: More Catalyst Basics + +=over 4 + +=item * + +Install the PostgreSQL server and client and DBD::Pg: + +If you are following along in Debian 5, you can quickly install these +items via this command: + + sudo aptitude install postgresql libdbd-pg-perl libdatetime-format-pg-perl + +To configure the permissions, you can open +C and change this line (near the +bottom): + + # "local" is for Unix domain socket connections only + local all all ident sameuser + +to: + + # "local" is for Unix domain socket connections only + local all all trust + +And then restart PostgreSQL: + + sudo /etc/init.d/postgresql-8.3 restart + + +=item * + +Create the database and a user for the database (note that we are +using "EcatalystE" to represent the hidden password of +"catalyst"): + + $ sudo -u postgres createuser -P catappuser + Enter password for new role: + Enter it again: + Shall the new role be a superuser? (y/n) n + Shall the new role be allowed to create databases? (y/n) n + Shall the new role be allowed to create more new roles? (y/n) n + CREATE ROLE + $ sudo -u postgres createdb -O catappuser catappdb + CREATE DATABASE + +=item * + +Create the C<.sql> file and load the data: + +=over 4 + +=item * + +Open the C in your editor and enter: + + -- + -- Drops just in case you are reloading + --- + DROP TABLE IF EXISTS books CASCADE; + DROP TABLE IF EXISTS authors CASCADE; + DROP TABLE IF EXISTS book_authors CASCADE; + DROP TABLE IF EXISTS users CASCADE; + DROP TABLE IF EXISTS roles CASCADE; + DROP TABLE IF EXISTS user_roles CASCADE; + + -- + -- Create a very simple database to hold book and author information + -- + CREATE TABLE books ( + id SERIAL PRIMARY KEY, + title TEXT , + rating INTEGER, + -- Manually add these later + -- created TIMESTAMP NOT NULL DEFAULT now(), + -- updated TIMESTAMP + ); + + CREATE TABLE authors ( + id SERIAL PRIMARY KEY, + first_name TEXT, + last_name TEXT + ); + + -- 'book_authors' is a many-to-many join table between books & authors + CREATE TABLE book_authors ( + book_id INTEGER REFERENCES books(id) ON DELETE CASCADE ON UPDATE CASCADE, + author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY (book_id, author_id) + ); + + --- + --- Load some sample data + --- + INSERT INTO books (title, rating) VALUES ('CCSP SNRS Exam Certification Guide', 5); + INSERT INTO books (title, rating) VALUES ('TCP/IP Illustrated, Volume 1', 5); + INSERT INTO books (title, rating) VALUES ('Internetworking with TCP/IP Vol.1', 4); + INSERT INTO books (title, rating) VALUES ('Perl Cookbook', 5); + INSERT INTO books (title, rating) VALUES ('Designing with Web Standards', 5); + INSERT INTO authors (first_name, last_name) VALUES ('Greg', 'Bastien'); + INSERT INTO authors (first_name, last_name) VALUES ('Sara', 'Nasseh'); + INSERT INTO authors (first_name, last_name) VALUES ('Christian', 'Degu'); + INSERT INTO authors (first_name, last_name) VALUES ('Richard', 'Stevens'); + INSERT INTO authors (first_name, last_name) VALUES ('Douglas', 'Comer'); + INSERT INTO authors (first_name, last_name) VALUES ('Tom', 'Christiansen'); + INSERT INTO authors (first_name, last_name) VALUES ('Nathan', 'Torkington'); + INSERT INTO authors (first_name, last_name) VALUES ('Jeffrey', 'Zeldman'); + INSERT INTO book_authors VALUES (1, 1); + INSERT INTO book_authors VALUES (1, 2); + INSERT INTO book_authors VALUES (1, 3); + INSERT INTO book_authors VALUES (2, 4); + INSERT INTO book_authors VALUES (3, 5); + INSERT INTO book_authors VALUES (4, 6); + INSERT INTO book_authors VALUES (4, 7); + INSERT INTO book_authors VALUES (5, 8); + +=item * + +Load the data: + + $ psql -U catappuser -W catappdb -f myapp01_psql.sql + Password for user catappuser: + psql:myapp01_psql.sql:8: NOTICE: CREATE TABLE will create implicit sequence "books_id_seq" for serial column "books.id" + psql:myapp01_psql.sql:8: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "books_pkey" for table "books" + CREATE TABLE + psql:myapp01_psql.sql:15: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "book_authors_pkey" for table "book_authors" + CREATE TABLE + psql:myapp01_psql.sql:21: NOTICE: CREATE TABLE will create implicit sequence "authors_id_seq" for serial column "authors.id" + psql:myapp01_psql.sql:21: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "authors_pkey" for table "authors" + CREATE TABLE + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + ... + +=item * + +Make sure the data loaded correctly: + + $ psql -U catappuser -W catappdb + Password for user catappuser: + Welcome to psql 8.3.7, the PostgreSQL interactive terminal. + + Type: \copyright for distribution terms + \h for help with SQL commands + \? for help with psql commands + \g or terminate with semicolon to execute query + \q to quit + + catappdb=> \dt + List of relations + Schema | Name | Type | Owner + --------+--------------+-------+------------ + public | authors | table | catappuser + public | book_authors | table | catappuser + public | books | table | catappuser + (3 rows) + + catappdb=> select * from books; + id | title | rating + ----+------------------------------------+-------- + 1 | CCSP SNRS Exam Certification Guide | 5 + 2 | TCP/IP Illustrated, Volume 1 | 5 + 3 | Internetworking with TCP/IP Vol.1 | 4 + 4 | Perl Cookbook | 5 + 5 | Designing with Web Standards | 5 + (5 rows) + + catappdb=> + +=back + +=item * + +After the steps where you: + + edit lib/MyApp.pm + + create lib/MyAppDB.pm + + create lib/MyAppDB/Book.pm + + create lib/MyAppDB/Author.pm + + create lib/MyAppDB/BookAuthor.pm + + +=item * + +Generate the model using the Catalyst "_create.pl" script: + + $ rm lib/MyApp/Model/DB.pm # Delete just in case already there + $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \ + create=static components=TimeStamp,EncodedColumn \ + 'dbi:Pg:dbname=catappdb' 'catappuser' 'catalyst' '{ AutoCommit => 1 }' + +=back + +=item * + +Chapter 4: Basic CRUD + +Add Datetime Columns to Our Existing Books Table + + $ psql -U catappuser -W catappdb + ... + catappdb=> ALTER TABLE books ADD created TIMESTAMP NOT NULL DEFAULT now(); + ALTER TABLE + catappdb=> ALTER TABLE books ADD updated TIMESTAMP; + ALTER TABLE + catappdb=> \q + +Re-generate the model using the Catalyst "_create.pl" script: + + $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \ + create=static components=TimeStamp,EncodedColumn \ + 'dbi:Pg:dbname=catappdb' 'catappuser' 'catalyst' '{ AutoCommit => 1 }' + + +=item * + +Chapter 5: Authentication + +=over 4 + +=item * + +Create the C<.sql> file for the user/roles data: + +Open C in your editor and enter: + + -- + -- Add users and roles tables, along with a many-to-many join table + -- + + CREATE TABLE users ( + id SERIAL PRIMARY KEY, + username TEXT, + password TEXT, + email_address TEXT, + first_name TEXT, + last_name TEXT, + active INTEGER + ); + + CREATE TABLE roles ( + id SERIAL PRIMARY KEY, + role TEXT + ); + + CREATE TABLE user_roles ( + user_id INTEGER REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE, + role_id INTEGER REFERENCES roles(id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY (user_id, role_id) + ); + + -- + -- Load up some initial test data + -- + INSERT INTO users (username, password, email_address, first_name, last_name, active) + VALUES ('test01', 'mypass', 't01@na.com', 'Joe', 'Blow', 1); + INSERT INTO users (username, password, email_address, first_name, last_name, active) + VALUES ('test02', 'mypass', 't02@na.com', 'Jane', 'Doe', 1); + INSERT INTO users (username, password, email_address, first_name, last_name, active) + VALUES ('test03', 'mypass', 't03@na.com', 'No', 'Go', 0); + INSERT INTO roles (role) VALUES ('user'); + INSERT INTO roles (role) VALUES ('admin'); + INSERT INTO user_roles VALUES (1, 1); + INSERT INTO user_roles VALUES (1, 2); + INSERT INTO user_roles VALUES (2, 1); + INSERT INTO user_roles VALUES (3, 1); + +=item * + +Load the data: + + $ psql -U catappuser -W catappdb -f myapp02_psql.sql + Password for user catappuser: + psql:myapp02_psql.sql:13: NOTICE: CREATE TABLE will create implicit sequence "users_id_seq" for serial column "users.id" + psql:myapp02_psql.sql:13: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "users_pkey" for table "users" + CREATE TABLE + psql:myapp02_psql.sql:18: NOTICE: CREATE TABLE will create implicit sequence "roles_id_seq" for serial column "roles.id" + psql:myapp02_psql.sql:18: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "roles_pkey" for table "roles" + CREATE TABLE + psql:myapp02_psql.sql:24: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "user_roles_pkey" for table "user_roles" + CREATE TABLE + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + INSERT 0 1 + +Confirm with: + + $ psql -U catappuser -W catappdb -c "select * from users" + Password for user catappuser: + id | username | password | email_address | first_name | last_name | active + ----+----------+----------+---------------+------------+-----------+-------- + 1 | test01 | mypass | t01@na.com | Joe | Blow | 1 + 2 | test02 | mypass | t02@na.com | Jane | Doe | 1 + 3 | test03 | mypass | t03@na.com | No | Go | 0 + (3 rows) + + +=item * + +Modify C to match the following (the only difference +is the C line): + + #!/usr/bin/perl + + use strict; + use warnings; + + use MyApp::Schema; + + my $schema = MyApp::Schema->connect('dbi:Pg:dbname=catappdb', 'catappuser', 'catalyst'); + + my @users = $schema->resultset('Users')->all; + + foreach my $user (@users) { + $user->password('mypass'); + $user->update; + } + +Run the C as per the "normal" flow of the +tutorial: + + $ perl -Ilib set_hashed_passwords.pl + +You can verify that it worked with this command: + + $ psql -U catappuser -W catappdb -c "select * from users" + + +=back + +=back + + =head2 MySQL -Use the following steps to adapt the tutorial to MySQL. Thanks to Jim +B This section is out of data with the rest of the tutorial. +Consider using SQLite or PostgreSQL since they are current. + +Use the following steps to adapt the tutorial to MySQL. Thanks to Jim Howard for the help. =over 4 =item * -Part 2: Catalyst Basics +Chapter 3: Catalyst Basics =over 4 @@ -169,7 +541,7 @@ The Perl C module =back -For CentOS users (see +For CentOS users (see L), you can use the following commands to install the software and start the MySQL daemon: @@ -317,7 +689,8 @@ Delete the existing model: Regenerate the model using the Catalyst "_create.pl" script: - script/myapp_create.pl model MyAppDB DBIC::Schema MyAppDB dbi:mysql:myapp 'tutorial' '' '{ AutoCommit => 1 }' + script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \ + dbi:mysql:myapp '_username_here_' '_password_here_' '{ AutoCommit => 1 }' =back @@ -325,7 +698,7 @@ Regenerate the model using the Catalyst "_create.pl" script: =item * -Part 4: Authentication +Chapter 5: Authentication =over 4 @@ -398,68 +771,6 @@ Load the user/roles data: =back -=head2 PostgreSQL - -B -- Please see the latest version of this document for possible updates: -L - - -=head1 APPENDIX 3: IMPROVED HASHING SCRIPT - -Here is an improved SHA-1 hashing script from Gavin Henry that does -not expose the passwords to "capture" on the command line. - - #!/usr/bin/perl -w - #=============================================================================== - # - # FILE: enc_pass.pl - # - # USAGE: ./enc_pass.pl - # - # DESCRIPTION: Encrypt a Password using SHA-1 - # - # OPTIONS: --- - # REQUIREMENTS: --- - # BUGS: --- - # NOTES: --- - # AUTHOR: Gavin Henry (GH), - # COMPANY: Suretec Systems Ltd. - # VERSION: 1.0 - # CREATED: 26/06/2006 - # REVISION: --- - # COPYRIGHT: http://search.cpan.org/dist/perl/pod/perlgpl.pod - #=============================================================================== - - use strict; - use warnings; - use Digest::SHA1; - use Term::ReadKey; - - sub get_pass { - ReadMode 'noecho'; - chomp( my $pw = ReadLine 0 ); - ReadMode 'normal'; - return $pw; - } - - print "Enter the password to be encrypted: "; - my $pass = get_pass(); - - print "\nConfirm the password: "; - my $verify = get_pass(); - - if ( $pass eq $verify ) { - my $sha1_enc = Digest::SHA1->new; - $sha1_enc->add($pass); - - print "\nYour encrypted password is: " - . $sha1_enc->hexdigest . "\n" - . "Paste this into your SQL INSERT/COPY Data.\n"; - } - else { - print "\nPasswords do not match!\n"; - } - =head1 AUTHOR @@ -467,7 +778,7 @@ Kennedy Clark, C Please report any errors, issues or suggestions to the author. The most recent version of the Catalyst Tutorial can be found at -L. +L. -Copyright 2006, Kennedy Clark, under Creative Commons License -(L). +Copyright 2006-2008, Kennedy Clark, under Creative Commons License +(L).