--- /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://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Runtime/5.80/trunk/lib/Roadmap.pod>
+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://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Runtime/5.80/trunk/TODO>
+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:
found, and automatically call the actions it finds that match the
circumstances of the request.
-The URL (for example http://localhost.3000/foo/bar) consists of two
+The URL (for example http://localhost:3000/foo/bar) consists of two
parts, the base, describing how to connect to the server
(http://localhost:3000/ in this example) and the path, which the
server uses to decide what to return (foo/bar). Please note that the
=head2 Try the Delete Feature
-One you save the Books controller, the server should automatically restart.
+Once you save the Books controller, the server should automatically restart.
The C<delete> method should now appear in the "Loaded Chained actions" section
of the startup debug output:
Result Class, it keeps the code inside our TT template nice and clean
(remember, we want the templates to be as close to pure HTML markup as
possible). Obviously, this capability becomes even more useful as you
-use to to remove even more complicated row-specific logic from your
+use it to remove even more complicated row-specific logic from your
templates!
is now self-documenting and readable enough that you could probably get
by with no comments at all. All of the "complex" work is being done in
our Result Class methods (and, because we have broken the code into
-nice, modular chucks, the Result Class code is hardly something you
+nice, modular chunks, the Result Class code is hardly something you
would call complex).
As we saw in this section, always strive to keep your view AND
role TEXT
);
CREATE TABLE user_role (
- user_id INTEGER REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ user_id INTEGER REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
role_id INTEGER REFERENCES role(id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (user_id, role_id)
);
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 *