--- /dev/null
+Catalyst-Manual-*
+MYMETA.yml
+META.yml
+Makefile
+inc/
+blib
+pm_to_blib
+MANIFEST
+Makefile.old
+MANIFEST.bak
+
Revision history for Catalyst-Manual
-5.8005 27 Oct 2010
+5.8007 29 Feb 2011
+ - Tutorial
+ - Switch to use of DBIx::Class::PassphraseColumn for hashed & salted
+ passwords. It's much more flexible than the previously used
+ DBIx::Class::EncodedColumn.
+
+5.8006 29 Feb 2011
+ - Fix metadata to refer to the new git repository
+ - Cookbook
+ - Small fixes and typos
+ - Tutorial
+ - Various typo fixes.
+ - RT #57989: typo
+ - RT #61486: correct instructions for MySQL
+ - RT #62095: prevent XSS
+ - RT #62095: persistent message on /login
+ - RT #63057: typo
+ - RT #64087: typos
+ - RT #64126: Use precise name of licence
+ - RT #64126: typos
+ - RT #67820: fix relationship decleration
+ - Do not recommend FastMmap
+ - DevelopmentProcess
+ - RT #62610: typo
+
+5.8005 27 Oct 2010
- Tutorial:
- Add DATABASE CONFIG SWITCHING USING MULTIPLE CONFIG FILES section
- Critical bugfix on index page.
5.8004 17 Feb 2010
- Tutorial:
- - Add foreign key support for SQLite
+ - Add foreign key support for SQLite
(huge thanks to Caelum for that and other good edits!)
- Add "Quick Start" to Intro (Chapter 1)
- Switch to use of "-r" to auto-restart the dev svr
5.7019 11 Mar 2009
- Tutorial:
- Change from the use of "part" to refer to each .pod file for the
- tutorial in favor of the more intuitive word "chapter." "Part"
- was just to ambiguous (e.g., does "prior part" refer to the prior
+ tutorial in favor of the more intuitive word "chapter." "Part"
+ was just to ambiguous (e.g., does "prior part" refer to the prior
.pod file or the prior section in the current .pod file).
- - Move use of "load_namespaces" for DBIC from BasicCRUD to
+ - Move use of "load_namespaces" for DBIC from BasicCRUD to
MoreCatalystBasics
- Update the "Table of Contents" in Tutorial.pod to match the current
sections
5.7018 8 Mar 2009
- Tutorial:
- - Add a new section to BasicCRUD covering more advanced features of
+ - Add a new section to BasicCRUD covering more advanced features of
DBIC ("EXPLORING THE POWER OF DBIC")
- Convert from Ubuntu to Debian 5 live CD as the recommended way to do
the tutorial (all code and examples updated and tested to match)
- MoreCatalystBasics - Additional clarification about TTSite
(Del Merritt)
- Tutorial::Authorization - Corrects the ACL for "/books/delete"
- - Additional comments
+ - Additional comments
(Del Merritt)
- - Tutorial::AdvancedCRUD::FormFu - suggest how the intrepid user
+ - Tutorial::AdvancedCRUD::FormFu - suggest how the intrepid user
might now proceed, having completed the Tutorial. (Del Merritt)
- Fix typo in Authorization section (RT #42091)
- Fix typo in BasicCRUD (RT #42034)
5.7015 15 Dec 2008
- Tutorial:
- Remove TTSite from Tutorial (thanks to dhoss for the help)
- - Update Tutorial for Ubuntu 8.10 (therefore update to
+ - Update Tutorial for Ubuntu 8.10 (therefore update to
Cat v5.7014, C::Devel v1.07, DBIC v0.08010, etc.)
- - Reorganize MoreCatalystBasics.pod so user is able to run
- the app the first time much earlier and build on it from
+ - Reorganize MoreCatalystBasics.pod so user is able to run
+ the app the first time much earlier and build on it from
there (running the app each time along the way)
- Update URL for latest copy in SVN to match new location of repo
- Other:
- Misc typo fix
- Change use of Class::C3 to MRO::Compat, as rafl tells me
- this is best practice, and gives you native next::method in
+ this is best practice, and gives you native next::method in
5.10. (t0m)
5.7014 04 Nov 2008
- Expurgation of all use of default :Private and index :Private in favour
of default :Path and index :Path :Args(0)
- Expurgation of all yaml as configuration format
- - Major updates to tutorial, thanks hkclark and gerda
+ - Major updates to tutorial, thanks hkclark and gerda
-5.7011 16 May 2008
+5.7011 16 May 2008
- added warnings and poiinters to newer examples in HTML::Widget,
and Authentication parts of the tutorial.
- pod fix (RT #32636)
5.701002 25 Aug 2007
5.701001 17 Aug 2007
- - Changes to mocation of lib/Catalyst/Manual.pod to
+ - Changes to mocation of lib/Catalyst/Manual.pod to
lib/Catalyst/ManualPlaceholder.pm to keep cpan indexer happy.
5.700704 08 Aug 2007
- Updated mailing list addresses to scsys.co.uk domains
-5.700703
- - Cookbook: Updated development server deployment instructions, and
+5.700703
+ - Cookbook: Updated development server deployment instructions, and
included a better description of the POE engine.
5.700702 26 April 2007
\bCVS\b
,v$
\B\.svn\b
+^\.git
# Avoid Makemaker generated and utility files.
\bMakefile$
\bpm_to_blib$
\bblibdirs$
^MANIFEST\.SKIP$
+\bMYMETA.yml$
# Avoid Module::Build generated and utility files.
\bBuild$
use strict;
use warnings;
-our $VERSION = '5.8005';
+our $VERSION = '5.8007';
=head1 NAME
=head2 Discussing proposed bugfixes or improvements
-L<http://dev.catalystframework.org/wiki/#Community> has information about how
+L<http://wiki.catalystframework.org/wiki/#Community> has information about how
to get in touch with the Catalyst "community". In particular, you would
want to discuss a proposed change on the mailing list:
or on IRC:
irc://irc.perl.org/catalyst-dev
- http://dev.catalystframework.org/wiki/livegroups
+ http://wiki.catalystframework.org/wiki/livegroups
Usually, the core team will be more than happy for you to contribute, and
will talk you through how to submit a patch, or get a "commit bit".
=head2 Roadmap for features
The Catalyst Roadmap is kept at
-L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=blob;f=lib/Catalyst/ROADMAP.pod;hb=HEAD>
+L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=blob_plain;f=lib/Catalyst/ROADMAP.pod;hb=master>
=head2 Bug list
The TODO list with known bugs / deficiences is kept at
-L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=blob;f=TODO;hb=HEAD>
+L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=blob_plain;f=TODO;hb=master>
=head1 The Catalyst Core Team
Now http://localhost:3000/hello prints "Hello World!".
-Note that actions with the C< :Global > attribute are equivalent to
+Note that actions with the C< :Local > attribute are equivalent to
using a C<:Path('action_name') > attribute, so our action could be
equivalently:
Although recent versions of SQLite and L<DBIx::Class::Schema::Loader>
automatically handle the C<has_many> and C<belongs_to> relationships,
-C<many_to_many> relationships currently need to be manually inserted.
-To add a C<many_to_many> relationship, first edit
+C<many_to_many> relationship bridges (not technically a relationship)
+currently need to be manually inserted.
+To add a C<many_to_many> relationship bridge, first edit
C<lib/MyApp/Schema/Result/Book.pm> and add the following text below
the C<# You can replace this text...> comment:
# many_to_many():
# args:
- # 1) Name of relationship, DBIC will create accessor with this name
+ # 1) Name of relationship bridge, DBIC will create accessor with this name
# 2) Name of has_many() relationship this many_to_many() is shortcut for
# 3) Name of belongs_to() relationship in model class of has_many() above
# You must already have the has_many() defined to use a many_to_many().
a statement that evaluates to C<true>. This is customarily done with
C<1;> on a line by itself.
-The C<many_to_many> relationship is optional, but it makes it
+The C<many_to_many> relationship bridge is optional, but it makes it
easier to map a book to its collection of authors. Without
it, we would have to "walk" through the C<book_author> table as in
C<$book-E<gt>book_author-E<gt>first-E<gt>author-E<gt>last_name> (we
authors, we have to use C<first> to display a single author).
C<many_to_many> allows us to use the shorter
C<$book-E<gt>author-E<gt>first-E<gt>last_name>. Note that you cannot
-define a C<many_to_many> relationship without also having the
+define a C<many_to_many> relationship bridge without also having the
C<has_many> relationship in place.
Then edit C<lib/MyApp/Schema/Result/Author.pm> and add the reverse
-C<many_to_many> relationship for C<Author> as follows (again, be careful
+C<many_to_many> relationship bridge for C<Author> as follows (again, be careful
to put in above the C<1;> but below the C<# DO NOT MODIFY THIS OR
ANYTHING ABOVE!> comment):
# many_to_many():
# args:
- # 1) Name of relationship, DBIC will create accessor with this name
+ # 1) Name of relationship bridge, DBIC will create accessor with this name
# 2) Name of has_many() relationship this many_to_many() is shortcut for
# 3) Name of belongs_to() relationship in model class of has_many() above
# You must already have the has_many() defined to use a many_to_many().
easy with the Catalyst plugin Catalyst::Plugin:RequireSSL.
-=head2 Re-Run the DBIC::Schema Model Helper to Include DBIx::Class::EncodedColumn
+=head2 Re-Run the DBIC::Schema Model Helper to Include DBIx::Class::PassphraseColumn
Next, we can re-run the model helper to have it include
-L<DBIx::Class::EncodedColumn|DBIx::Class::EncodedColumn> in all of the
-Result Classes it generates for us. Simply use the same command we
-saw in Chapters 3 and 4, but add C<,EncodedColumn> to the C<components>
-argument:
+L<DBIx::Class::PassphraseColumn> in all of the Result Classes it generates for
+us. Simply use the same command we saw in Chapters 3 and 4, but add
+C<,PassphraseColumn> to the C<components> argument:
$ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
- create=static components=TimeStamp,EncodedColumn dbi:SQLite:myapp.db \
+ create=static components=TimeStamp,PassphraseColumn dbi:SQLite:myapp.db \
on_connect_do="PRAGMA foreign_keys = ON"
If you then open one of the Result Classes, you will see that it
-includes EncodedColumn in the C<load_components> line. Take a look at
+includes PassphraseColumn in the C<load_components> line. Take a look at
C<lib/MyApp/Schema/Result/User.pm> since that's the main class where we
want to use hashed and salted passwords:
- __PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp", "EncodedColumn");
+ __PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp", "PassphraseColumn");
-=head2 Modify the "password" Column to Use EncodedColumn
+=head2 Modify the "password" Column to Use PassphraseColumn
Open the file C<lib/MyApp/Schema/Result/User.pm> and enter the following
text below the "# DO NOT MODIFY THIS OR ANYTHING ABOVE!" line but above
the closing "1;":
- # Have the 'password' column use a SHA-1 hash and 10-character salt
- # with hex encoding; Generate the 'check_password" method
+ # Have the 'password' column use a SHA-1 hash and 20-byte salt
+ # with RFC 2307 encoding; Generate the 'check_password" method
__PACKAGE__->add_columns(
'password' => {
- encode_column => 1,
- encode_class => 'Digest',
- encode_args => {salt_length => 10},
- encode_check_method => 'check_password',
+ passphrase => 'rfc2307',
+ passphrase_class => 'SaltedDigest',
+ passphrase_args => {
+ algorithm => 'SHA-1',
+ salt_random => 20.
+ },
+ passphrase_check_method => 'check_password',
},
);
-This redefines the automatically generated definition for the password
-fields at the top of the Result Class file to now use EncodedColumn
-logic (C<encoded_column> is set to 1). C<encode_class> can be set to
-either C<Digest> to use
-L<DBIx::Class::EncodedColumn::Digest|DBIx::Class::EncodedColumn::Digest>,
-or C<Crypt::Eksblowfish::Bcrypt> for
-L<DBIx::Class::EncodedColumn::Crypt::Eksblowfish::Bcrypt|DBIx::Class::EncodedColumn::Crypt::Eksblowfish::Bcrypt>.
-C<encode_args> is then used to customize the type of Digest you
-selected. Here we only specified the size of the salt to use, but
-we could have also modified the hashing algorithm ('SHA-256' is
-the default) and the format to use ('base64' is the default, but
-'hex' and 'binary' are other options). To use these, you could
-change the C<encode_args> to something like:
-
- encode_args => {algorithm => 'SHA-1',
- format => 'hex',
- salt_length => 10},
-
+This redefines the automatically generated definition for the password fields at
+the top of the Result Class file to now use PassphraseColumn logic, storing
+passwords in RFC 2307 format (C<passphrase> is set to C<rfc2307>).
+C<passphrase_class> can be set to the name of any C<Authen::Passphrase::*>
+class, such as C<SaltedDigest> to use L<Authen::Passphrase::SaltedDigest>, or
+C<BlowfishCrypt> to use L<Authen::Passphrase::BlowfishCrypt>.
+C<passphrase_args> is then used to customize the passphrase class you
+selected. Here we specified the digest algorithm to use as C<SHA-1> and the size
+of the salt to use, but we could have also specified any other option the
+selected passphrase class supports.
=head2 Load Hashed Passwords in the Database
$user->update;
}
-EncodedColumn lets us simply call C<$user->check_password($password)>
+PassphraseColumn lets us simply call C<$user->check_password($password)>
to see if the user has supplied the correct password, or, as we show
above, call C<$user->update($new_password)> to update the hashed
password stored for this user.
SELECT me.id, me.username, me.password, me.email_address,
me.first_name, me.last_name, me.active FROM users me:
UPDATE users SET password = ? WHERE ( id = ? ):
- 'oXiyAcGOjowz7ISUhpIm1IrS8AxSZ9r4jNjpX9VnVeQmN6GRtRKTz', '1'
+ '{SSHA}esgz64CpHMo8pMfgIIszP13ft23z/zio04aCwNdm0wc6MDeloMUH4g==', '1'
UPDATE users SET password = ? WHERE ( id = ? ):
- 'PmyEPrkB8EGwvaF/DvJm7LIfxoZARjv8ygFIR7pc1gEA1OfwHGNzs', '2'
+ '{SSHA}FpGhpCJus+Ea9ne4ww8404HH+hJKW/fW+bAv1v6FuRUy2G7I2aoTRQ==', '2'
UPDATE users SET password = ? WHERE ( id = ? ):
- 'h7CS1Fm9UCs4hjcbu2im0HumaHCJUq4Uriac+SQgdUMUfFSoOrz3c', '3'
+ '{SSHA}ZyGlpiHls8qFBSbHr3r5t/iqcZE602XLMbkSVRRNl6rF8imv1abQVg==', '3'
But we can further confirm our actions by dumping the users table:
$ sqlite3 myapp.db "select * from users"
- 1|test01|38d3974fa9e9263099f7bc2574284b2f55473a9bM=fwpX2NR8|t01@na.com|Joe|Blow|1
- 2|test02|6ed8586587e53e0d7509b1cfed5df08feadc68cbMJlnPyPt0I|t02@na.com|Jane|Doe|1
- 3|test03|af929a151340c6aed4d54d7e2651795d1ad2e2f7UW8dHoGv9z|t03@na.com|No|Go|0
+ 1|test01|{SSHA}esgz64CpHMo8pMfgIIszP13ft23z/zio04aCwNdm0wc6MDeloMUH4g==|t01@na.com|Joe|Blow|1
+ 2|test02|{SSHA}FpGhpCJus+Ea9ne4ww8404HH+hJKW/fW+bAv1v6FuRUy2G7I2aoTRQ==|t02@na.com|Jane|Doe|1
+ 3|test03|{SSHA}ZyGlpiHls8qFBSbHr3r5t/iqcZE602XLMbkSVRRNl6rF8imv1abQVg==|t03@na.com|No|Go|0
As you can see, the passwords are much harder to steal from the
database (not only are the hashes stored, but every hash is different
$ 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 \
+ create=static components=TimeStamp,PassphraseColumn \
'dbi:Pg:dbname=catappdb' 'catappuser' 'catalyst' '{ AutoCommit => 1 }'
=back
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 \
+ create=static components=TimeStamp,PassphraseColumn \
'dbi:Pg:dbname=catappdb' 'catappuser' 'catalyst' '{ AutoCommit => 1 }'
Regenerate the model using the Catalyst "_create.pl" script:
script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=static \
- components=TimeStamp,EncodedColumn dbi:mysql:myapp 'tutorial' 'yourpassword' '{ AutoCommit => 1 }'
+ components=TimeStamp,PassphraseColumn dbi:mysql:myapp 'tutorial' 'yourpassword' '{ AutoCommit => 1 }'
=back
--
-- Convert passwords to SHA-1 hashes
--
- UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 1;
- UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 2;
- UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 3;
+ UPDATE users SET password = '{SSHA}esgz64CpHMo8pMfgIIszP13ft23z/zio04aCwNdm0wc6MDeloMUH4g==' WHERE id = 1;
+ UPDATE users SET password = '{SSHA}FpGhpCJus+Ea9ne4ww8404HH+hJKW/fW+bAv1v6FuRUy2G7I2aoTRQ==' WHERE id = 2;
+ UPDATE users SET password = '{SSHA}ZyGlpiHls8qFBSbHr3r5t/iqcZE602XLMbkSVRRNl6rF8imv1abQVg==' WHERE id = 3;
=item *