PageRenderTime 37ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Foorum/Controller/Profile.pm

http://foorum.googlecode.com/
Perl | 381 lines | 293 code | 60 blank | 28 comment | 32 complexity | 3a9507397795d6afa0671e02c91589c6 MD5 | raw file
  1. package Foorum::Controller::Profile;
  2. use strict;
  3. use warnings;
  4. our $VERSION = '1.000005';
  5. use base 'Catalyst::Controller';
  6. use Foorum::XUtils qw/theschwartz/;
  7. use Digest ();
  8. use Locale::Country::Multilingual;
  9. use vars qw/$lcm/;
  10. $lcm = Locale::Country::Multilingual->new();
  11. sub edit : Local {
  12. my ( $self, $c ) = @_;
  13. return $c->res->redirect('/login') unless ( $c->user_exists );
  14. $c->stash->{template} = 'user/profile/edit.html';
  15. # get all countries code
  16. $lcm->set_lang( $c->stash->{lang} );
  17. my @codes = $lcm->all_country_codes();
  18. my %countries;
  19. foreach (@codes) {
  20. $countries{$_} = $lcm->code2country($_);
  21. }
  22. $c->stash->{countries} = \%countries;
  23. unless ( $c->req->method eq 'POST' ) {
  24. my $birthday = $c->user->{details}->{birthday};
  25. if ( $birthday
  26. and $birthday
  27. and $birthday =~ /^(\d+)\-(\d+)\-(\d+)$/ ) {
  28. $c->stash(
  29. { year => $1,
  30. month => $2,
  31. day => $3,
  32. }
  33. );
  34. }
  35. $c->stash->{user_details} = $c->user->{details};
  36. return;
  37. }
  38. my $birthday
  39. = $c->req->param('year') . '-'
  40. . $c->req->param('month') . '-'
  41. . $c->req->param('day');
  42. my ( @extra_valid, @extra_insert );
  43. if ( length($birthday) > 2 ) { # is not --
  44. @extra_valid
  45. = ( { birthday => [ 'year', 'month', 'day' ] } => ['DATE'] );
  46. @extra_insert = ( birthday => $birthday );
  47. }
  48. # be compatible with Yahoo! ID and email
  49. foreach my $param ( 'gtalk', 'yahoo', 'skype' ) {
  50. if ( $c->req->param($param) =~ /^(\w+)\@/ ) {
  51. $c->req->param( $param, $1 ); # only need the username before @
  52. }
  53. }
  54. $c->form(
  55. gender => [ [ 'REGEX', qr/^(M|F)?$/ ] ],
  56. lang => [ [ 'REGEX', qr/^\w{2}$/ ] ],
  57. @extra_valid,
  58. homepage => ['HTTP_URL'],
  59. nickname => [ qw/NOT_BLANK/, [qw/LENGTH 4 20/] ],
  60. 'qq' => [ [ 'REGEX', qr/^\d{6,14}$/ ] ],
  61. msn => [ qw/EMAIL_LOOSE/, [qw/LENGTH 5 64/] ],
  62. gtalk => [ [ 'REGEX', qr/^\w{2,64}$/ ] ],
  63. yahoo => [ [ 'REGEX', qr/^\w{2,64}$/ ] ],
  64. skype => [ [ 'REGEX', qr/^\w{2,64}$/ ] ],
  65. country => [ [ 'REGEX', qr/^\w{2}$/ ] ],
  66. );
  67. return if ( $c->form->has_error );
  68. # validate country
  69. unless ( $lcm->code2country( $c->req->param('country') ) ) {
  70. $c->req->param( 'country', '' );
  71. }
  72. $c->model('DBIC::User')->update_user(
  73. $c->user,
  74. { nickname => $c->req->param('nickname') || $c->user->username,
  75. gender => $c->req->param('gender') || 'NA',
  76. lang => $c->req->param('lang') || $c->config->{default_lang},
  77. country => $c->req->param('country') || '',
  78. }
  79. );
  80. $c->model('DBIC::UserDetails')->update_or_create(
  81. { user_id => $c->user->user_id,
  82. homepage => $c->req->param('homepage') || '',
  83. 'qq' => $c->req->param('qq') || '',
  84. msn => $c->req->param('msn') || '',
  85. gtalk => $c->req->param('gtalk') || '',
  86. yahoo => $c->req->param('yahoo') || '',
  87. skype => $c->req->param('skype') || '',
  88. @extra_insert,
  89. }
  90. );
  91. # clear user cache too
  92. $c->model('DBIC::User')->delete_cache_by_user( $c->user );
  93. $c->res->redirect( '/u/' . $c->user->username );
  94. }
  95. sub change_password : Local {
  96. my ( $self, $c, $username, $security_code ) = @_;
  97. my $password = $c->req->param('password');
  98. $c->stash->{template} = 'user/profile/change_password.html';
  99. my $user;
  100. # the user input old password
  101. # or the user click from forget_password email
  102. # CAN change password
  103. my $can_change_password = 0;
  104. if ( $username and $security_code ) {
  105. # check if that's mataches.
  106. $user = $c->model('User')->get( { username => $username } );
  107. if ($user) {
  108. my $security_code2 = $c->model('DBIC::SecurityCode')
  109. ->get( 'forget_password', $user->{user_id} );
  110. if ( $security_code2 and $security_code2 eq $security_code ) {
  111. $can_change_password = 1;
  112. $c->stash->{use_security_code} = 1;
  113. }
  114. }
  115. $c->stash->{user} = $user;
  116. }
  117. unless ($can_change_password) {
  118. return $c->res->redirect('/login') unless ( $c->user_exists );
  119. $user = $c->user;
  120. $c->stash->{user} = $user;
  121. # check the password typed in is correct
  122. if ($password) {
  123. my $d = Digest->new(
  124. $c->config->{authentication}->{password_hash_type} );
  125. $d->add($password);
  126. my $computed = $d->digest;
  127. if ( $computed ne $c->user->{password} ) {
  128. $c->set_invalid_form( password => 'WRONG_PASSWORD' );
  129. $c->stash->{user} = $user;
  130. return;
  131. }
  132. $can_change_password = 1;
  133. }
  134. }
  135. return unless ($can_change_password);
  136. # execute validation.
  137. $c->form(
  138. new_password => [ qw/NOT_BLANK/, [qw/LENGTH 6 20/] ],
  139. { passwords => [ 'new_password', 'confirm_password' ] } =>
  140. ['DUPLICATION'],
  141. );
  142. return if ( $c->form->has_error );
  143. # encrypted the new password
  144. my $new_password = $c->req->param('new_password');
  145. my $d = Digest->new( $c->config->{authentication}->{password_hash_type} );
  146. $d->reset;
  147. $d->add($new_password);
  148. my $new_computed = $d->digest;
  149. $c->model('DBIC::User')
  150. ->update_user( $user, { password => $new_computed } );
  151. # delete so that can't use again
  152. if ( $c->stash->{use_security_code} ) {
  153. $c->model('DBIC::SecurityCode')
  154. ->remove( 'forget_password', $user->{user_id} );
  155. }
  156. $c->detach(
  157. '/print_message',
  158. [ { msg => 'Reset Password OK',
  159. url => '/profile/edit',
  160. stay_in_page => 1,
  161. }
  162. ]
  163. );
  164. }
  165. sub forget_password : Local {
  166. my ( $self, $c ) = @_;
  167. $c->stash->{template} = 'user/profile/forget_password.html';
  168. return unless ( $c->req->method eq 'POST' );
  169. my $username = $c->req->param('username');
  170. my $email = $c->req->param('email');
  171. my $user;
  172. if ($username) {
  173. $user = $c->model('DBIC::User')->get( { username => $username } );
  174. return $c->stash->{ERROR_NOT_SUCH_USER} = 1 unless ($user);
  175. $email = $user->{email};
  176. } elsif ($email) {
  177. $user = $c->model('DBIC::User')->get( { email => $email } );
  178. return $c->stash->{ERROR_NOT_SUCH_EMAIL} = 1 unless ($user);
  179. $username = $user->{username};
  180. } else {
  181. return;
  182. }
  183. # create a security code
  184. # URL contains the security_code can change his password later
  185. my $security_code = $c->model('DBIC::SecurityCode')
  186. ->get_or_create( 'forget_password', $user->{user_id} );
  187. # send email
  188. $c->model('DBIC::ScheduledEmail')->create_email(
  189. { template => 'forget_password',
  190. to => $email,
  191. lang => $c->stash->{lang},
  192. stash => {
  193. username => $username,
  194. security_code => $security_code,
  195. IP => $c->req->address,
  196. }
  197. }
  198. );
  199. $c->detach(
  200. '/print_message',
  201. [ { msg =>
  202. 'The instruction to rest your password is sent to your email, please have a check',
  203. url => '/',
  204. stay_in_page => 1,
  205. }
  206. ]
  207. );
  208. }
  209. sub change_email : Local {
  210. my ( $self, $c ) = @_;
  211. return $c->res->redirect('/login') unless ( $c->user_exists );
  212. $c->stash->{template} = 'user/profile/change_email.html';
  213. return unless ( $c->req->method eq 'POST' );
  214. # check the password typed in is correct
  215. my $password = $c->req->param('password');
  216. my $d = Digest->new( $c->config->{authentication}->{password_hash_type} );
  217. $d->add($password);
  218. my $computed = $d->digest;
  219. if ( $computed ne $c->user->{password} ) {
  220. $c->set_invalid_form( password => 'WRONG_PASSWORD' );
  221. return;
  222. }
  223. # validation
  224. my $email = $c->req->param('email');
  225. if ( $email eq $c->user->email ) {
  226. return $c->set_invalid_form( email => 'EMAIL_DUPLICATION' );
  227. }
  228. my $err = $c->model('DBIC::User')->validate_email($email);
  229. if ($err) {
  230. return $c->set_invalid_form( email => $err );
  231. }
  232. $c->model('DBIC::User')->update_user( $c->user, { email => $email } );
  233. $c->res->redirect('/profile/edit');
  234. }
  235. sub change_username : Local {
  236. my ( $self, $c ) = @_;
  237. return $c->res->redirect('/login') unless ( $c->user_exists );
  238. $c->stash->{template} = 'user/profile/change_username.html';
  239. return unless ( $c->req->method eq 'POST' );
  240. # check the password typed in is correct
  241. my $password = $c->req->param('password');
  242. my $d = Digest->new( $c->config->{authentication}->{password_hash_type} );
  243. $d->add($password);
  244. my $computed = $d->digest;
  245. if ( $computed ne $c->user->{password} ) {
  246. $c->set_invalid_form( password => 'WRONG_PASSWORD' );
  247. return;
  248. }
  249. # execute validation.
  250. $c->form(
  251. new_username => [qw/NOT_BLANK/],
  252. { usernames => [ 'new_username', 'confirm_username' ] } =>
  253. ['DUPLICATION'],
  254. );
  255. return if ( $c->form->has_error );
  256. my $new_username = $c->req->param('new_username');
  257. my $err = $c->model('DBIC::User')->validate_username($new_username);
  258. if ($err) {
  259. $c->set_invalid_form( new_username => $err );
  260. return;
  261. }
  262. $c->model('DBIC::User')
  263. ->update_user( $c->user, { username => $new_username, } );
  264. $c->session->{__user} = $new_username;
  265. $c->res->redirect("/u/$new_username");
  266. }
  267. sub profile_photo : Local {
  268. my ( $self, $c ) = @_;
  269. return $c->res->redirect('/login') unless ( $c->user_exists );
  270. $c->stash->{template} = 'user/profile/profile_photo.html';
  271. return unless ( $c->req->method eq 'POST' );
  272. my $new_upload = $c->req->upload('upload');
  273. my $old_upload_id
  274. = ( $c->user->{profile_photo}->{type} eq 'upload' )
  275. ? $c->user->{profile_photo}->{value}
  276. : 0;
  277. my $new_upload_id = $old_upload_id;
  278. if ( ( $c->req->param('attachment_action') eq 'delete' ) or $new_upload )
  279. {
  280. # delete old upload
  281. if ($old_upload_id) {
  282. $c->model('DBIC::Upload')
  283. ->remove_by_upload( $c->user->{profile_photo}->{upload} );
  284. $new_upload_id = 0;
  285. }
  286. # add new upload
  287. if ($new_upload) {
  288. $new_upload_id = $c->model('DBIC::Upload')
  289. ->add_file( $new_upload, { user_id => $c->user->user_id } );
  290. unless ( $new_upload_id =~ /^\d+$/ ) {
  291. return $c->set_invalid_form( upload => $new_upload_id );
  292. }
  293. my $client = theschwartz();
  294. $client->insert(
  295. 'Foorum::TheSchwartz::Worker::ResizeProfilePhoto',
  296. $new_upload_id );
  297. }
  298. }
  299. $c->model('DBIC')->resultset('UserProfilePhoto')
  300. ->search( { user_id => $c->user->{user_id} } )->delete;
  301. $c->model('DBIC')->resultset('UserProfilePhoto')->create(
  302. { user_id => $c->user->{user_id},
  303. type => 'upload',
  304. value => $new_upload_id,
  305. width => 0,
  306. height => 0,
  307. time => time(),
  308. }
  309. );
  310. $c->model('DBIC::User')->delete_cache_by_user( $c->user );
  311. $c->res->redirect( '/u/' . $c->user->{username} );
  312. }
  313. 1;
  314. __END__
  315. =pod
  316. =head1 AUTHOR
  317. Fayland Lam <fayland at gmail.com>
  318. =cut