package Foorum::Controller::Profile;
use strict;
use warnings;
our $VERSION = '1.001000';
use parent 'Catalyst::Controller';
use Foorum::XUtils qw/theschwartz/;
use Digest ();
use Locale::Country::Multilingual;
use vars qw/$lcm/;
$lcm = Locale::Country::Multilingual->new();
sub edit : Local {
my ( $self, $c ) = @_;
return $c->res->redirect('/login') unless ( $c->user_exists );
$c->stash->{template} = 'user/profile/edit.html';
# get all countries code
$lcm->set_lang( $c->stash->{lang} );
my @codes = $lcm->all_country_codes();
my %countries;
foreach (@codes) {
$countries{$_} = $lcm->code2country($_);
}
$c->stash->{countries} = \%countries;
unless ( $c->req->method eq 'POST' ) {
my $birthday = $c->user->{details}->{birthday};
if ( $birthday
and $birthday
and $birthday =~ /^(\d+)\-(\d+)\-(\d+)$/ ) {
$c->stash(
{ year => $1,
month => $2,
day => $3,
}
);
}
$c->stash->{user_details} = $c->user->{details};
return;
}
my $birthday
= $c->req->param('year') . '-'
. $c->req->param('month') . '-'
. $c->req->param('day');
my ( @extra_valid, @extra_insert );
if ( length($birthday) > 2 ) { # is not --
@extra_valid
= ( { birthday => [ 'year', 'month', 'day' ] } => ['DATE'] );
@extra_insert = ( birthday => $birthday );
}
# be compatible with Yahoo! ID and email
foreach my $param ( 'gtalk', 'yahoo', 'skype' ) {
if ( $c->req->param($param) =~ /^(\w+)\@/ ) {
$c->req->param( $param, $1 ); # only need the username before @
}
}
$c->form(
gender => [ [ 'REGEX', qr/^(M|F)?$/ ] ],
lang => [ [ 'REGEX', qr/^\w{2}$/ ] ],
@extra_valid,
homepage => ['HTTP_URL'],
nickname => [ qw/NOT_BLANK/, [qw/LENGTH 4 20/] ],
'qq' => [ [ 'REGEX', qr/^\d{6,14}$/ ] ],
msn => [ qw/EMAIL_LOOSE/, [qw/LENGTH 5 64/] ],
gtalk => [ [ 'REGEX', qr/^\w{2,64}$/ ] ],
yahoo => [ [ 'REGEX', qr/^\w{2,64}$/ ] ],
skype => [ [ 'REGEX', qr/^\w{2,64}$/ ] ],
country => [ [ 'REGEX', qr/^\w{2}$/ ] ],
);
return if ( $c->form->has_error );
# validate country
unless ( $lcm->code2country( $c->req->param('country') ) ) {
$c->req->param( 'country', '' );
}
$c->model('DBIC::User')->update_user(
$c->user,
{ nickname => $c->req->param('nickname') || $c->user->username,
gender => $c->req->param('gender') || 'NA',
lang => $c->req->param('lang') || $c->config->{default_lang},
country => $c->req->param('country') || '',
}
);
$c->model('DBIC::UserDetails')->update_or_create(
{ user_id => $c->user->user_id,
homepage => $c->req->param('homepage') || '',
'qq' => $c->req->param('qq') || '',
msn => $c->req->param('msn') || '',
gtalk => $c->req->param('gtalk') || '',
yahoo => $c->req->param('yahoo') || '',
skype => $c->req->param('skype') || '',
@extra_insert,
}
);
# clear user cache too
$c->model('DBIC::User')->delete_cache_by_user( $c->user );
$c->res->redirect( '/u/' . $c->user->username );
}
sub change_password : Local {
my ( $self, $c, $username, $security_code ) = @_;
my $password = $c->req->param('password');
$c->stash->{template} = 'user/profile/change_password.html';
my $user;
# the user input old password
# or the user click from forget_password email
# CAN change password
my $can_change_password = 0;
if ( $username and $security_code ) {
# check if that's mataches.
$user = $c->model('DBIC::User')->get( { username => $username } );
if ($user) {
my $security_code2 = $c->model('DBIC::SecurityCode')
->get( 'forget_password', $user->{user_id} );
if ( $security_code2 and $security_code2 eq $security_code ) {
$can_change_password = 1;
$c->stash->{use_security_code} = 1;
}
}
$c->stash->{user} = $user;
}
unless ($can_change_password) {
return $c->res->redirect('/login') unless ( $c->user_exists );
$user = $c->user;
$c->stash->{user} = $user;
# check the password typed in is correct
if ($password) {
my $d = Digest->new(
$c->config->{authentication}->{password_hash_type} );
$d->add($password);
my $computed = $d->digest;
if ( $computed ne $c->user->{password} ) {
$c->set_invalid_form( password => 'WRONG_PASSWORD' );
$c->stash->{user} = $user;
return;
}
$can_change_password = 1;
}
}
return unless ($can_change_password);
# execute validation.
$c->form(
new_password => [ qw/NOT_BLANK/, [qw/LENGTH 6 20/] ],
{ passwords => [ 'new_password', 'confirm_password' ] } =>
['DUPLICATION'],
);
return if ( $c->form->has_error );
# encrypted the new password
my $new_password = $c->req->param('new_password');
my $d = Digest->new( $c->config->{authentication}->{password_hash_type} );
$d->reset;
$d->add($new_password);
my $new_computed = $d->digest;
$c->model('DBIC::User')
->update_user( $user, { password => $new_computed } );
# delete so that can't use again
if ( $c->stash->{use_security_code} ) {
$c->model('DBIC::SecurityCode')
->remove( 'forget_password', $user->{user_id} );
}
$c->res->redirect('/profile/edit?st=101');
}
sub forget_password : Local {
my ( $self, $c ) = @_;
$c->stash->{template} = 'user/profile/forget_password.html';
return unless ( $c->req->method eq 'POST' );
my $username = $c->req->param('username');
my $email = $c->req->param('email');
my $user;
if ($username) {
$user = $c->model('DBIC::User')->get( { username => $username } );
return $c->stash->{ERROR_NOT_SUCH_USER} = 1 unless ($user);
$email = $user->{email};
} elsif ($email) {
$user = $c->model('DBIC::User')->get( { email => $email } );
return $c->stash->{ERROR_NOT_SUCH_EMAIL} = 1 unless ($user);
$username = $user->{username};
} else {
return;
}
# create a security code
# URL contains the security_code can change his password later
my $security_code = $c->model('DBIC::SecurityCode')
->get_or_create( 'forget_password', $user->{user_id} );
# send email
$c->model('DBIC::ScheduledEmail')->create_email(
{ template => 'forget_password',
to => $email,
lang => $c->stash->{lang},
stash => {
username => $username,
security_code => $security_code,
IP => $c->req->address,
}
}
);
$c->res->redirect('/?st=102');
}
sub change_email : Local {
my ( $self, $c ) = @_;
return $c->res->redirect('/login') unless ( $c->user_exists );
$c->stash->{template} = 'user/profile/change_email.html';
return unless ( $c->req->method eq 'POST' );
# check the password typed in is correct
my $password = $c->req->param('password');
my $d = Digest->new( $c->config->{authentication}->{password_hash_type} );
$d->add($password);
my $computed = $d->digest;
if ( $computed ne $c->user->{password} ) {
$c->set_invalid_form( password => 'WRONG_PASSWORD' );
return;
}
# validation
my $email = $c->req->param('email');
if ( $email eq $c->user->email ) {
return $c->set_invalid_form( email => 'EMAIL_DUPLICATION' );
}
my $err = $c->model('DBIC::User')->validate_email($email);
if ($err) {
return $c->set_invalid_form( email => $err );
}
$c->model('DBIC::User')->update_user( $c->user, { email => $email } );
$c->res->redirect('/profile/edit');
}
sub change_username : Local {
my ( $self, $c ) = @_;
return $c->res->redirect('/login') unless ( $c->user_exists );
$c->stash->{template} = 'user/profile/change_username.html';
return unless ( $c->req->method eq 'POST' );
# check the password typed in is correct
my $password = $c->req->param('password');
my $d = Digest->new( $c->config->{authentication}->{password_hash_type} );
$d->add($password);
my $computed = $d->digest;
if ( $computed ne $c->user->{password} ) {
$c->set_invalid_form( password => 'WRONG_PASSWORD' );
return;
}
# execute validation.
$c->form(
new_username => [qw/NOT_BLANK/],
{ usernames => [ 'new_username', 'confirm_username' ] } =>
['DUPLICATION'],
);
return if ( $c->form->has_error );
my $new_username = $c->req->param('new_username');
my $err = $c->model('DBIC::User')->validate_username($new_username);
if ($err) {
$c->set_invalid_form( new_username => $err );
return;
}
$c->model('DBIC::User')
->update_user( $c->user, { username => $new_username, } );
$c->session->{__user} = $new_username;
$c->res->redirect("/u/$new_username");
}
sub profile_photo : Local {
my ( $self, $c ) = @_;
return $c->res->redirect('/login') unless ( $c->user_exists );
$c->stash->{template} = 'user/profile/profile_photo.html';
return unless ( $c->req->method eq 'POST' );
my $new_upload = $c->req->upload('upload');
my $old_upload_id
= ( $c->user->{profile_photo}->{type} eq 'upload' )
? $c->user->{profile_photo}->{value}
: 0;
my $new_upload_id = $old_upload_id;
if ( ( $c->req->param('attachment_action') eq 'delete' ) or $new_upload )
{
# delete old upload
if ($old_upload_id) {
$c->model('DBIC::Upload')
->remove_by_upload( $c->user->{profile_photo}->{upload} );
$new_upload_id = 0;
}
# add new upload
if ($new_upload) {
$new_upload_id = $c->model('DBIC::Upload')
->add_file( $new_upload, { user_id => $c->user->user_id } );
unless ( $new_upload_id =~ /^\d+$/ ) {
return $c->set_invalid_form( upload => $new_upload_id );
}
my $client = theschwartz();
$client->insert(
'Foorum::TheSchwartz::Worker::ResizeProfilePhoto',
$new_upload_id );
}
}
$c->model('DBIC')->resultset('UserProfilePhoto')
->search( { user_id => $c->user->{user_id} } )->delete;
$c->model('DBIC')->resultset('UserProfilePhoto')->create(
{ user_id => $c->user->{user_id},
type => 'upload',
value => $new_upload_id,
width => 0,
height => 0,
time => time(),
}
);
$c->model('DBIC::User')->delete_cache_by_user( $c->user );
$c->res->redirect( '/u/' . $c->user->{username} );
}
1;
__END__
=pod
=head1 AUTHOR
Fayland Lam <fayland at gmail.com>
=cut