package Catalyst::Authentication::Store::Jifty::DBI::User;
use strict;
use warnings;
use Carp;
use base qw( Catalyst::Authentication::User );
use Scalar::Util qw( blessed );
BEGIN { __PACKAGE__->mk_accessors(qw( config _user _roles )); }
sub new {
my ($class, $config, $c) = @_;
my $user_class = $config->{user_class}
or croak "user_class is missing";
$user_class =~ s/Collection$//;
$config->{record_class} ||= $user_class;
$config->{collection_class} ||= $user_class.'Collection';
my $self = bless {
config => $config,
_roles => undef,
_user => undef,
}, $class;
}
sub load {
my ($self, $auth_info, $c) = @_;
my $jdbi_conf = {};
if ( exists $auth_info->{jifty_dbi} ) {
$jdbi_conf = $auth_info->{jifty_dbi};
}
my $collection;
if ( $jdbi_conf->{collection} ) {
$collection = $jdbi_conf->{collection};
}
elsif ( my $args = $jdbi_conf->{limit_args} ) {
$collection = $c->model( $self->config->{collection_class} );
if ( ref $args eq 'HASH' ) {
$args = [ $args ];
}
foreach my $arg ( @{ $args } ) {
$collection->limit( %{ $arg } );
}
}
else {
$collection = $c->model( $self->config->{collection_class} );
foreach my $column ( keys %{ $auth_info } ) {
next unless defined $auth_info->{$column};
next if blessed $auth_info->{$column}; # relationship
$collection->limit(
column => $column,
value => $auth_info->{$column},
);
}
}
return unless $collection;
my $user = $collection->first;
$self->_user( $user ) if blessed $user;
return $self->get_object ? $self : undef;
}
sub supported_features {
my $self = shift;
return {
session => 1,
roles => 1,
};
}
sub roles {
my $self = shift;
if ( ref $self->_roles eq 'ARRAY' ) {
return @{ $self->_roles };
}
my @roles;
if ( $self->config->{role_column} ) {
my $role_data = $self->get( $self->config->{role_column} );
if ( $role_data ) {
@roles = split /[ ,\|]+/, $role_data;
}
$self->_roles( \@roles );
return @roles;
}
elsif ( ref $self->config->{role_relation} eq 'ARRAY' ) {
my @columns = @{ $self->config->{role_relation} };
if ( @columns == 3 ) {
my ($roles_column, $link_column, $role_column) = @columns;
eval {
my $collection = $self->_user->$roles_column;
while ( my $record = $collection->next ) {
push @roles, $record->$link_column->$role_column;
}
$self->_roles( \@roles );
};
croak "illegal role_relation configuration: $@" if $@;
return @roles;
}
}
croak "illegal role configuration";
}
sub for_session {
my $self = shift;
my %user_data = $self->_user->as_hash;
return \%user_data;
}
sub from_session {
my ($self, $frozen_user, $c) = @_;
if ( $self->config->{use_userdata_from_session} ) {
my $user = $c->model( $self->config->{record_class} );
$user->load_from_hash( %{ $frozen_user } );
$self->_user( $user );
return $self;
}
else {
return $self->load( $frozen_user, $c );
}
}
sub get {
my ($self, $field) = @_;
return $self->_user ? $self->_user->_value( $field ) : undef;
}
sub get_object {
my ($self, $force) = @_;
$self->_user;
}
sub obj {
my ($self, $force) = @_;
$self->get_object( $force );
}
sub auto_create {
my ($self, $auth_info, $c) = @_;
my $user = $c->model( $self->config->{record_class} );
$user->create( %{ $auth_info } );
$self->_user( $user );
return $self;
}
sub auto_update {
my ($self, $auth_info, $c) = @_;
my $user = $self->_user;
$user->_handle->begin_transaction;
eval {
foreach my $column ( keys %{ $auth_info } ) {
next unless defined $auth_info->{$column};
next if blessed $auth_info->{$column}; # relationship
$user->_set( column => $column, value => $auth_info->{$column} );
}
};
$@ ? $user->_handle->rollback : $user->_handle->commit;
}
sub AUTOLOAD {
my $self = shift;
my ($method) = (our $AUTOLOAD =~ /([^:]+)$/);
return if $method eq 'DESTROY';
$self->_user->$method(@_);
}
1;
__END__
=head1 NAME
Catalyst::Authentication::Store::Jifty::DBI::User
=head1 DESCRIPTION
Used internally to do the actual tasks to retrieve/store information.
=head1 METHODS
=head2 new
creates an object.
=head2 load
retrieves a user from storage with the provided information.
=head2 supported_features
shows the supported features, currently Roles and Session.
=head2 roles
returns an array of roles associated with the user.
=head2 from_session
restores the user from a hash reference from the session
=head2 for_session
returns a hash reference of the user data to store.
=head2 get
returns the value of the given column.
=head2 get_object, obj
returns the user object.
=head2 auto_create
creates a user automatically from the auth_info.
=head2 auto_update
updates the user automatically from the auth_info.
=head1 SEE ALSO
L<Catalyst::Plugin::Authentication>,
L<Catalyst::Authentication::Store::DBIx::Class>
=head1 AUTHOR
Kenichi Ishigaki, E<lt>ishigaki@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2008 by Kenichi Ishigaki.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut