diff --git a/MANIFEST b/MANIFEST
index f2cb08b..355f650 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -51,6 +51,7 @@ lib/Ark/Plugin/Authentication.pm
lib/Ark/Plugin/Authentication/Backend.pm
lib/Ark/Plugin/Authentication/Credential/OpenID.pm
lib/Ark/Plugin/Authentication/Credential/Password.pm
+lib/Ark/Plugin/Authentication/Store/Data/Model.pm
lib/Ark/Plugin/Authentication/Store/DBIx/Class.pm
lib/Ark/Plugin/Authentication/Store/Minimal.pm
lib/Ark/Plugin/Authentication/Store/Model.pm
@@ -95,7 +96,7 @@ t/path_to/lib/TestApp.pm
t/plugin_authentication.t
t/plugin_authentication_cred_password.t
t/plugin_authentication_store_datamodel.t
-t/plugin_authentication_store_datamodelfast.t
+t/plugin_authentication_store_datamodelbykey.t
t/plugin_authentication_store_dbixclass.t
t/plugin_authentication_store_model.t
t/plugin_core.t
diff --git a/lib/Ark/Plugin/Authentication/Store/Data/Model.pm b/lib/Ark/Plugin/Authentication/Store/Data/Model.pm
index fe5fde2..2db90c6 100644
--- a/lib/Ark/Plugin/Authentication/Store/Data/Model.pm
+++ b/lib/Ark/Plugin/Authentication/Store/Data/Model.pm
@@ -1,7 +1,7 @@
package Ark::Plugin::Authentication::Store::Data::Model;
use Ark::Plugin 'Auth';
-our $VERSION = '0.01_00';
+our $VERSION = '0.04_00';
has 'data_model_model' => (
is => 'rw',
@@ -9,7 +9,7 @@ has 'data_model_model' => (
lazy => 1,
default => sub {
my $self = shift;
- $self->class_config->{model} || 'Data::Model';
+ $self->class_config->{model} || 'DataModel';
},
);
@@ -33,6 +33,16 @@ has 'data_model_user_field' => (
},
);
+has 'data_model_by_key' => (
+ is => 'rw',
+ isa => 'Bool',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ $self->class_config->{by_key} || 0;
+ },
+);
+
around 'find_user' => sub {
my $prev = shift->(@_);
return $prev if $prev;
@@ -45,15 +55,18 @@ around 'find_user' => sub {
if ($model->can('find_user')) {
$user = $model->find_user($id, $info);
}
+ elsif ($self->data_model_by_key) {
+ $user = $model->lookup( $self->data_model_target => $id );
+ }
else {
- my $iterator = $model->get( $self->data_model_target => {
+ my @users = $model->get( $self->data_model_target => {
where => [
$self->data_model_user_field => $id,
],
limit => 1,
} );
- return unless $iterator;
- $user = $iterator->next;
+ return unless @users;
+ $user = $users[0];
}
if ($user) {
@@ -85,20 +98,29 @@ around 'from_session' => sub {
obj_builder => sub {
my $model = $self->app->model( $self->data_model_model );
- $model->get(
- $self->data_model_target => {
- where => [
- $self->data_model_user_field =>
- $user->{hash}{ $self->data_model_user_field },
- ],
- limit => 1,
- }
- )->next;
+ if ($self->data_model_by_key) {
+ return $model->lookup(
+ $self->data_model_target =>
+ $user->{hash}{ $self->data_model_user_field }
+ );
+ }
+ else {
+ return ( $model->get(
+ $self->data_model_target => {
+ where => [
+ $self->data_model_user_field =>
+ $user->{hash}{ $self->data_model_user_field },
+ ],
+ limit => 1,
+ }
+ ) )[0];
+ }
},
);
};
1;
+__END__
=head1 NAME
@@ -107,41 +129,41 @@ Ark::Plugin::Authentication::Store::Data::Model - Ark plugin for storing auth vi
=head1 VERSION
-0.01_00
+0.04_00
=head1 SYNOPSIS
-=head2 Application root
+=head2 Application class
package MyApp::Web;
use Ark;
use_plugins qw(
- Session
- Session::State::Cookie
- Session::Store::Memory
-
Authentication
Authentication::Credential::Password
Authentication::Store::Data::Model
+
+ Session
+ Session::State::Cookie
+ Session::Store::Memory
);
# optional: as your pleasure...
- conf 'Plugin::Authentication::Store::Data::Model' => {
- model => 'Foobar', # *A
- target => 'user', # *B (same as default)
- user_field => 'name', # *C (default is 'username')
- };
conf 'Plugin::Authentication::Credential::Password' => {
- user_field => 'name', # *C (default is 'username')
- password_field => 'password', # *D (same as default)
- password_type => 'clear', # (same as default)
+ user_field => 'name', # *A (default is 'username')
+ password_field => 'password', # *B (same as default)
+ password_type => 'clear', # (same as default)
+ };
+ conf 'Plugin::Authentication::Store::Data::Model' => {
+ model => 'Foobar', # *C (default is 'DataModel')
+ target => 'user', # *D (same as default)
+ user_field => 'name', # *A (default is 'username')
};
1;
-=head2 Autentication controller
+=head2 Autentication controller class
package MyApp::Web::Controller::Authentication;
use Ark 'Controller';
@@ -153,36 +175,27 @@ Ark::Plugin::Authentication::Store::Data::Model - Ark plugin for storing auth vi
sub login :Path('login') {
my ($self, $c) = @_;
- $c->detach(
- $c->req->method ne 'POST' ? 'require_authentication'
- : $c->authenticate($c->req->params) ? 'authorized'
- # alternate: $c->authenticate({id => $id, pw => $pw}), etc.
- : 'unauthorized'
- );
- }
- sub require_authentication :Private {
- my ($self, $c) = @_;
-
- $c->view('MT')->template('authorization/form');
- }
- sub authorized :Private {
- my ($self, $c) = @_;
-
- $c->stash->{message} = 'Welcome, ' . $c->user->obj->name . '!!';
- $c->view('MT')->template('home');
- }
- sub unauthorized :Private {
- my ($self, $c) = @_;
-
- $c->stash->{message} = 'Invalid username or password';
- $c->view('MT')->template('authorization/form');
+ if ($c->req->method eq 'POST') {
+ # e.g. $c->authenticate({name => $username, password => $password})
+ if (my $user = $c->authenticate($c->req->params) {
+ $c->stash->{message} = 'Welcome, ' . $user->obj->name . '!!';
+ $c->view('MT')->template('home');
+ }
+ else {
+ $c->stash->{message} = 'Invalid username or password';
+ $c->view('MT')->template('authorization/form');
+ }
+ }
+ else {
+ $c->view('MT')->template('authorization/form'); # require login
+ }
}
1;
-=head2 Authentication model
+=head2 Authentication model class
- package MyApp::Web::Model::Foobar; # *A
+ package MyApp::Web::Model::Foobar; # *C
use Ark 'Model::Adaptor';
__PACKAGE__->config(
@@ -191,12 +204,12 @@ Ark::Plugin::Authentication::Store::Data::Model - Ark plugin for storing auth vi
1;
-=head2 Table schema of user table
+=head2 Table schema class of user table
package MyApp::Schema::Table::User; # *E
use base qw(Data::Model);
- use Data::Model::Schema sugar => 'myapp'; # *F
use Data::Model::Driver::DBI;
+ use Data::Model::Schema sugar => 'myapp'; # *F
use MyApp::Schema::Column::User; # *G
my $dbfile = '/foo/bar.db';
@@ -205,12 +218,12 @@ Ark::Plugin::Authentication::Store::Data::Model - Ark plugin for storing auth vi
);
base_driver($driver);
- install_model 'user' => schema { # *B
+ install_model 'user' => schema { # *D
key 'id';
- column 'user.id';
- column 'user.name'; # *C
+ column 'user.id' => { auto_increment => 1 };
+ column 'user.name'; # *A
unique 'name';
- column 'user.password'; # *D
+ column 'user.password'; # *B
# ...
};
@@ -220,8 +233,10 @@ Ark::Plugin::Authentication::Store::Data::Model - Ark plugin for storing auth vi
sub find_user {
my ($self, $id, $info) = @_;
- my @users = $self->get( user => { # *B
- name => lc $id, # ignore case
+ my @users = $self->get( user => { # *D
+ where => [
+ name => lc $id, # ignore case
+ ],
# you can use $info for any more conditions!
} );
@@ -229,34 +244,33 @@ Ark::Plugin::Authentication::Store::Data::Model - Ark plugin for storing auth vi
return $users[0]; # found
}
-=head2 Column schema of user table
+ 1;
+
+=head2 Column schema class of user table
package MyApp::Schema::Column::User; # *G
use Data::Model::Schema sugar => 'myapp'; # *F
column_sugar 'user.id'
- => int => {
+ => integer => {
require => 1,
unsigned => 1,
};
- column_sugar 'user.name' => # *C
- varchar => {
- require => 1,
- size => 16,
+ column_sugar 'user.name' # *A
+ => text => {
+ require => 1,
};
- column_sugar 'user.password' => # *D
- varchar => {
- require => 1,
- size => 16,
+ column_sugar 'user.password' # *B
+ => text => {
+ require => 1,
};
- # ... (common.last_updated_datetime, user.last_login_datetime, etc.)
+ # ... (common.last_updated_datetime, user.last_accessed_datetime, etc.)
1;
-=head2 /root/authorization/form.mt
-
- [%=r $self->render('inc/header') %]
+=head2 Authentication template file
+
- [%=r $self->render('inc/footer') %]
-
=head1 DESCRIPTION
This module is a plugin for L; to store authentication informations
for any data by L.
-=head2 Finding user
+=head2 How to find an user
-Default behavior of finding user is below:
+Default behavior of finding an user is below:
=over 4
-=item 1. Constructs C.
-You can change the class-name into other one
+=item 1
+
+Constructs a model object of class named C.
+You can change the class name into other one
by C function (see L).
-Most people will have the class delegete all method to
-L's model.
+Most people make the model class delegete all methods to
+L's model by
+L.
+
+=item 2
-=item 2. Finds row by C column from C model.
-You can change these column name and model name into other ones
+Finds user's row by the column (field) named C, from the model
+named C.
+You can change these column (field) name and model name into other ones
by C function (see L).
-You can also define C method for L's model
-(in that case, this plugin use the method instead of plugin's procedure).
+You can also implement C method for L's
+model (in that case, this plugin use the method instead of plugin's procedure).
+
+=item 3
+
+Returns L
+object as C<< $user >> to application controller, when user is authorized
+by any C plugin.
+This will enable you to get L object
+by C<< $user->obj >> method.
-=item 3. Returns L object as C<< $user >>.
-You can get L object to call
-C<< $user->obj >> method.
+=item 4
-=item 4. Retrieves L object as C<< $c->user >> over session,
-as your pleasure (under C<< use_plugins qw(Session) >>).
-You can get L object to call
-C<< $c->user->obj >> method.
+Retrieves L object as C<< $c->user >> to application
+controller over a session, when you use C<< use_plugins qw(Session) >>.
+You can get L object
+by C<< $c->user->obj >> method.
=back
+=head2 How to find an user by key column (key field)
-=head1 SEE ALSO
+The plugin can find user's row by index
+(so that means that the plugin use method C<< $model->lookup >>).
+This will enable you to find user's row mostly faster about several dozen
+persent (see L).
-=over 4
+When you define a B column (key field) at schema...
-=item L
+ install_model 'user' => schema {
+ key 'id'; # define "id" column as key
+ column 'user.id' => { auto_increment => 1 };
+ column 'user.name';
+ unique 'name';
+ column 'user.password';
+ # ...
+ };
-This plugin looks-up a row B. Maybe fast!
+...and specify that C flag is true;
+
+ conf 'Plugin::Authentication::Credential::Password' => {
+ user_field => 'id', # key column
+ password_field => 'password',
+ password_type => 'clear',
+ };
+ conf 'Plugin::Authentication::Store::Data::Model' => {
+ model => 'Foobar',
+ target => 'user',
+ user_field => 'id', # key column
+ by_key => 1, # turn on!
+ };
+
+you can have the plugin use the key column.
+
+
+
+
+=head1 SEE ALSO
+
+=over 4
=item L
This plugin looks-up a row from L's model.
-=item L
+=item L
This plugin verifies password with user's row object.
@@ -336,10 +403,11 @@ This plugin verifies password with user's row object.
=over 4
-=item MURASE Daisuke ("typester")
+=item Daisuke Murase ("typester")
The author of L.
+I stolen almost every codes from this plugin.
=back
@@ -348,7 +416,7 @@ Ark::Plugin::Authentication::Store::DBIx::Class>.
=over 4
-=item MORIYA Masaki ("Gardejo")
+=item MORIYA Masaki ("gardejo")
C<< >>,
L
@@ -358,7 +426,7 @@ L
=head1 LICENCE AND COPYRIGHT
-Copyright (c) 2009 by MORIYA Masaki ("Gardejo"),
+Copyright (c) 2009 by MORIYA Masaki ("gardejo"),
L.
This library is free software;
diff --git a/lib/Ark/Plugin/Authentication/Store/Data/Model/Fast.pm b/lib/Ark/Plugin/Authentication/Store/Data/Model/Fast.pm
deleted file mode 100644
index fcc520a..0000000
--- a/lib/Ark/Plugin/Authentication/Store/Data/Model/Fast.pm
+++ /dev/null
@@ -1,243 +0,0 @@
-package Ark::Plugin::Authentication::Store::Data::Model::Fast;
-use Ark::Plugin 'Auth';
-
-our $VERSION = '0.01_00';
-
-has 'data_model_model' => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub {
- my $self = shift;
- $self->class_config->{model} || 'Data::Model::Fast';
- },
-);
-
-has 'data_model_target' => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub {
- my $self = shift;
- $self->class_config->{target} || 'user';
- },
-);
-
-has 'data_model_user_field' => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub {
- my $self = shift;
- $self->class_config->{user_field} || 'username';
- },
-);
-
-around 'find_user' => sub {
- my $prev = shift->(@_);
- return $prev if $prev;
-
- my ($self, $id, $info) = @_;
-
- my $model = $self->app->model( $self->data_model_model );
-
- my $user;
- if ($model->can('find_user')) {
- $user = $model->find_user($id, $info);
- }
- else {
- $user = $model->lookup( $self->data_model_target => $id );
- }
-
- if ($user) {
- $self->ensure_class_loaded('Ark::Plugin::Authentication::User');
-
- return Ark::Plugin::Authentication::User->new(
- store => 'Data::Model::Fast',
- obj => $user,
- hash => $user->get_columns,
- );
- }
-
- return;
-};
-
-around 'from_session' => sub {
- my $prev = shift->(@_);
- return $prev if $prev;
-
- my ($self, $user) = @_;
-
- return unless $user->{store} eq 'Data::Model::Fast';
-
- $self->ensure_class_loaded('Ark::Plugin::Authentication::User');
-
- Ark::Plugin::Authentication::User->new(
- store => 'Data::Model::Fast',
- hash => $user->{hash},
- obj_builder => sub {
- my $model = $self->app->model( $self->data_model_model );
-
- $model->lookup(
- $self->data_model_target =>
- $user->{hash}{ $self->data_model_user_field }
- );
- },
- );
-};
-
-1;
-
-=head1 NAME
-
-Ark::Plugin::Authentication::Store::Data::Model::Fast - Ark plugin for storing auth via Data::Model
-
-
-=head1 VERSION
-
-0.01_00
-
-
-=head1 SYNOPSIS
-
-=head2 Application root
-
- package MyApp::Web;
- use Ark;
-
- use_plugins qw(
- Session
- Session::State::Cookie
- Session::Store::Memory
-
- Authentication
- Authentication::Credential::Password
- Authentication::Store::Data::Model::Fast
- );
-
- # as your pleasure...
- conf 'Plugin::Authentication::Store::Data::Model::Fast' => {
- model => 'Foobar', # *A
- target => 'user', # *B (same as default)
- user_field => 'id', # *C (default is 'username')
- };
- conf 'Plugin::Authentication::Credential::Password' => {
- user_field => 'id', # *C (default is 'username')
- password_field => 'password', # *D (same as default)
- password_type => 'clear', # (same as default)
- };
-
- 1;
-
-=head2 Autentication controller
-
-See L.
-
-=head2 Authentication model
-
-See L.
-
-=head2 Table schema of user table
-
-See L.
-
-=head2 Column schema of user table
-
-See L.
-
-=head2 /root/authorization/form.mt
-
- [%=r $self->render('inc/header') %]
-
-
-
- [%=r $self->render('inc/footer') %]
-
-
-
-=head1 DESCRIPTION
-
-This module is a plugin for L; to store authentication informations
-for any data by L.
-
-=head2 Finding user
-
-See L.
-
-In addition, this C plugin finds user's row
-on condition that user-name's field must be defined as key.
-See L
-for further details.
-
-
-=head1 SEE ALSO
-
-=over 4
-
-=item L
-
-This class looks-up a row without key (by C<< $model->get >>).
-
-=item L
-
-This plugin looks-up a row from L's model.
-
-=item L
-
-This plugin verifies password with user's row object.
-
-=back
-
-
-=head1 ACKNOWLEDGEMENTS
-
-=over 4
-
-=item MURASE Daisuke ("typester")
-
-The author of L.
-
-=back
-
-
-=head1 AUTHOR
-
-=over 4
-
-=item MORIYA Masaki ("Gardejo")
-
-C<< >>,
-L
-
-=back
-
-
-=head1 LICENCE AND COPYRIGHT
-
-Copyright (c) 2009 by MORIYA Masaki ("Gardejo"),
-L.
-
-This library is free software;
-you can redistribute it and/or modify it under the same terms as Perl itself.
-See L and L.
diff --git a/t/plugin_authentication_store_datamodel.t b/t/plugin_authentication_store_datamodel.t
index d396834..e5dff26 100644
--- a/t/plugin_authentication_store_datamodel.t
+++ b/t/plugin_authentication_store_datamodel.t
@@ -4,33 +4,10 @@ use File::Temp;
eval "use Data::Model";
plan skip_all => 'Data::Model required to run this test' if $@;
-my $db = "testdatabase_datamodel";
+my $db = "testdatabase_datamodel";
+my $dsn = "dbi:SQLite:dbname=$db";
END { unlink $db }
-{
- # create Database
- my $dbh = DBI->connect("dbi:SQLite:dbname=$db")
- or die DBI->errstr;
-
- $dbh->do(<<'...');
-CREATE TABLE user (
- id INTEGER NOT NULL PRIMARY KEY,
- username TEXT NOT NULL,
- password TEXT NOT NULL
-);
-...
-
- $dbh->do(<<'...');
-INSERT INTO user (username, password) values ('user1', 'pass1');
-...
-
-
- $dbh->do(<<'...');
-INSERT INTO user (username, password) values ('user2', 'pass2');
-...
-
-}
-
{
package T1::Schema::Column;
use Data::Model::Schema sugar => 't1';
@@ -55,17 +32,36 @@ INSERT INTO user (username, password) values ('user2', 'pass2');
use Data::Model::Schema sugar => 't1';
use Data::Model::Driver::DBI;
my $driver = Data::Model::Driver::DBI->new(
- dsn => "dbi:SQLite:dbname=$db",
+ dsn => $dsn,
);
base_driver( $driver );
install_model user => schema {
key 'id';
- column 'user.id';
+ column 'user.id' => { auto_increment => 1 };
column 'user.username';
column 'user.password';
};
+ if (! -f $db) {
+ # create Database
+ my $dbh = DBI->connect($dsn)
+ or die DBI->errstr;
+ foreach my $sql (__PACKAGE__->as_sqls) {
+ $dbh->do($sql);
+ }
+
+ $dbh->do(<<'...');
+INSERT INTO user (username, password) values ('user1', 'pass1');
+...
+
+
+ $dbh->do(<<'...');
+INSERT INTO user (username, password) values ('user2', 'pass2');
+...
+
+ $dbh->disconnect;
+ }
}
{
@@ -82,7 +78,7 @@ INSERT INTO user (username, password) values ('user2', 'pass2');
Authentication::Store::Data::Model
/;
- package T1::Model::Data::Model;
+ package T1::Model::DataModel;
use Ark 'Model::Adaptor';
__PACKAGE__->config(
@@ -118,7 +114,7 @@ plan 'no_plan';
use Ark::Test 'T1',
components => [qw/Controller::Root
- Model::Data::Model
+ Model::DataModel
/],
reuse_connection => 1;
diff --git a/t/plugin_authentication_store_datamodelfast.t b/t/plugin_authentication_store_datamodelbykey.t
similarity index 78%
rename from t/plugin_authentication_store_datamodelfast.t
rename to t/plugin_authentication_store_datamodelbykey.t
index e2f6424..ec7a179 100644
--- a/t/plugin_authentication_store_datamodelfast.t
+++ b/t/plugin_authentication_store_datamodelbykey.t
@@ -4,33 +4,10 @@ use File::Temp;
eval "use Data::Model";
plan skip_all => 'Data::Model required to run this test' if $@;
-my $db = "testdatabase_datamodelfast";
+my $db = "testdatabase_datamodelbykey";
+my $dsn = "dbi:SQLite:dbname=$db";
END { unlink $db }
-{
- # create Database
- my $dbh = DBI->connect("dbi:SQLite:dbname=$db")
- or die DBI->errstr;
-
- $dbh->do(<<'...');
-CREATE TABLE user (
- id INTEGER NOT NULL PRIMARY KEY,
- username TEXT NOT NULL,
- password TEXT NOT NULL
-);
-...
-
- $dbh->do(<<'...');
-INSERT INTO user (id, username, password) values ('1', 'user1', 'pass1');
-...
-
-
- $dbh->do(<<'...');
-INSERT INTO user (id, username, password) values ('2', 'user2', 'pass2');
-...
-
-}
-
{
package T1::Schema::Column;
use Data::Model::Schema sugar => 't1';
@@ -55,17 +32,36 @@ INSERT INTO user (id, username, password) values ('2', 'user2', 'pass2');
use Data::Model::Schema sugar => 't1';
use Data::Model::Driver::DBI;
my $driver = Data::Model::Driver::DBI->new(
- dsn => "dbi:SQLite:dbname=$db",
+ dsn => $dsn,
);
base_driver( $driver );
install_model user => schema {
key 'id';
- column 'user.id';
+ column 'user.id' => { auto_increment => 1 };
column 'user.username';
column 'user.password';
};
+ if (! -f $db) {
+ # create Database
+ my $dbh = DBI->connect($dsn)
+ or die DBI->errstr;
+ foreach my $sql (__PACKAGE__->as_sqls) {
+ $dbh->do($sql);
+ }
+
+ $dbh->do(<<'...');
+INSERT INTO user (id, username, password) values ('1', 'user1', 'pass1');
+...
+
+
+ $dbh->do(<<'...');
+INSERT INTO user (id, username, password) values ('2', 'user2', 'pass2');
+...
+
+ $dbh->disconnect;
+ }
}
{
@@ -79,17 +75,18 @@ INSERT INTO user (id, username, password) values ('2', 'user2', 'pass2');
Authentication
Authentication::Credential::Password
- Authentication::Store::Data::Model::Fast
+ Authentication::Store::Data::Model
/;
- conf 'Plugin::Authentication::Store::Data::Model::Fast' => {
+ conf 'Plugin::Authentication::Store::Data::Model' => {
user_field => 'id',
+ by_key => 1,
};
conf 'Plugin::Authentication::Credential::Password' => {
user_field => 'id',
};
- package T1::Model::Data::Model::Fast;
+ package T1::Model::DataModel;
use Ark 'Model::Adaptor';
__PACKAGE__->config(
@@ -125,7 +122,7 @@ plan 'no_plan';
use Ark::Test 'T1',
components => [qw/Controller::Root
- Model::Data::Model::Fast
+ Model::DataModel
/],
reuse_connection => 1;