2 package SGN
::Controller
::AJAX
::User
;
8 BEGIN { extends
'Catalyst::Controller::REST' };
11 default => 'application/json',
13 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
17 sub new_account
:Path
('/ajax/user/new') Args
(0) {
21 if ($c->conf->{is_mirror
}) {
22 $c->stash->{template
} = '/system_message.mas';
23 $c->stash->{message
} = "This site is a mirror site and does not support adding users. Please go to the main site to create an account.";
28 my ($first_name, $last_name, $username, $password, $confirm_password, $email_address, $organization)
29 = $c->req->param(qw(first_name last_name username password confirm_password email_address organization));
33 # check password properties...
36 if (length($username) < 7) {
37 push @fail, "Username is too short. Username must be 7 or more characters";
39 # does user already exist?
41 my $existing_login = CXGN
::People
::Login
-> get_login
($c->dbc()->dbh(), $username);
43 if ($existing_login->get_username()) {
44 push @fail, "Username \"$username\" is already in use. Please pick a different username.";
48 if (length($password) < 7) {
49 push @fail, "Password is too short. Password must be 7 or more characters";
51 if ("$password" ne "$confirm_password") {
52 push @fail, "Password and confirm password do not match.";
56 push @fail, "'Organization' is required.'";
59 if ($password eq $username) {
60 push @fail, "Password must not be the same as your username.";
62 if ($email_address !~ m/[^\@]+\@[^\@]+/) {
63 push @fail, "Email address is invalid.";
66 push @fail,"You must enter a first name or initial.";
69 push @fail,"You must enter a last name.";
73 $c->stash->{rest
} = { error
=> "Account creation failed for the following reason(s): ".(join ", ", @fail) };
80 my $confirm_code = $self->tempname();
81 my $new_user = CXGN
::People
::Login
->new($c->dbc->dbh());
82 $new_user -> set_username
($username);
83 $new_user -> set_password
($password);
84 $new_user -> set_pending_email
($email_address);
85 $new_user -> set_confirm_code
($confirm_code);
86 $new_user -> set_disabled
('unconfirmed account');
87 $new_user -> set_organization
($organization);
90 #this is being added because the person object still uses two different objects, despite the fact that we've merged the tables
91 my $person_id=$new_user->get_sp_person_id();
92 my $new_person=CXGN
::People
::Person
->new($self->dbc->dbh(),$person_id);
93 $new_person->set_first_name($first_name);
94 $new_person->set_last_name($last_name);
97 my $host = $c->req()->hostname();
98 my $subject="[SGN] Email Address Confirmation Request";
99 my $body=<<END_HEREDOC;
101 Please do *NOT* reply to this message. The return address is not valid.
102 Use the <a href="/contact/form">contact form</a> instead.
104 This message is sent to confirm the email address for community user
107 Please click (or cut and paste into your browser) the following link to
108 confirm your account and email address:
110 https://$host/solpeople/account-confirm.pl?username=$username&confirm=$confirm_code
117 CXGN::Contact::send_email($subject,$body,$email_address);
118 $c->stash->{rest} = { message => qq | <table summary="" width="80%" align="center">
119 <tr><td><p>Account was created with username \"$username\". To continue, you must confirm that SGN staff can reach you via email address \"$email_address\". An email has been sent with a URL to confirm this address. Please check your email for this message and use the link to confirm your email address.</p></td></tr>
120 <tr><td><br /></td></tr>
126 sub change_account_info_action :Path('/ajax/user/update') Args(0) {
131 $c->stash->{rest} = { error => "You must be logged in to use this page." };
135 my $person = new CXGN::People::Login($c->dbc->dbh(), $c->user->get_sp_person_id());
137 # my ($current_password, $change_username, $change_password, $change_email) = $c->req->param({qw(current_password change_username change_password change_email)});
139 my $args = $c->req->params();
141 if (!$args->{change_password
} && ! $args->{change_username
} && !$args->{change_email
}) {
142 my $error = "No actions were requested. Please select which fields you would like to update by checking the appropriate checkbox(es) on the form and entering your new information.";
144 $c->stash->{rest
} = { error
=> $error };
148 print STDERR
"Person = ".$person->get_username()."\n";
149 chomp($args->{current_password
});
150 if (! $person->verify_password($args->{current_password
})) {
151 my $error = "Your current password does not match SGN records.";
153 $c->stash->{rest
} = { error
=> "$error" };
157 # Check for error conditions in all changes, before making any of them.
158 # Otherwise, we could end up making some changes and then failing on later
159 # ones. The user would then push the back button and their information may
160 # be different now but they will probably assume no changes were made. This
161 # is most troublesome if the current password changes.
163 if ($args->{change_username
}) {
164 #unless change_username is set, new_username won't be in the args hash because of the prestore test
165 my $new_username = $args->{new_username
};
166 if(length($new_username) < 7) {
167 my $error = "Username must be at least 7 characters long.";
169 $c->stash->{rest
} = { error
=> $error };
173 my $other_user = CXGN
::People
::Login
->get_login($c->dbc->dbh(), $new_username);
174 if (defined $other_user->get_sp_person_id() &&
175 ($person -> get_sp_person_id
() != $other_user->get_sp_person_id())) {
176 print STDERR
"Username alread in use.\n";
177 $c->stash->{rest
} = { error
=> "Username \"$new_username\" is already in use. Please select a different username." };
181 print STDERR
"Saving new username args->{username} to the database...\n";
182 $person->set_username($new_username);
186 if ($args->{change_password
}) {
187 #unless change_password is set, new_password won't be in the args hash because of the prestore test
188 my ($new_password, $confirm_password) = ($args->{new_password
}, $args->{confirm_password
});
189 if(length($args->{new_password
}) < 7) {
190 print STDERR
"Password too short\n";
191 $c->stash->{rest
} = { error
=> "Passwords must be at least 7 characters long. Please try again." };
195 if($args->{new_password
} !~ /^[a-zA-Z0-9~!@#$^&*_.=:;<>?]+$/) {
196 print STDERR
"Illegal characters in password\n";
197 $c->stash->{rest
} = { error
=> "An error occurred. Please use your browser's back button to try again.. The Password can't contain spaces or these symbols: <u><b>` ( ) [ ] { } - + ' \" / \\ , |</b></u>." };
200 if($args->{new_password
} ne $args->{confirm_password
}) {
201 print STDERR
"Password don't match.\n";
202 $c->stash->{rest
} = { error
=> "New password entries do not match. You must enter your new password twice to verify accuracy." };
206 print STDERR
"Saving new password '$args->{new_password}' to the database\n";
207 $person->update_password($args->{new_password
});
210 my $user_private_email = $c->user->get_private_email();
211 if($args->{change_email
}) {
212 #unless change_email is set, private_email won't be in the args hash because of the prestore test
213 my ($private_email, $confirm_email) = ($args->{private_email
}, $args->{confirm_email
});
214 if($private_email !~ m/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+$/) {
215 print STDERR
"Invalid email address\n";
216 $c->stash->{rest
} = { error
=> "An error occurred. Please use your browser's back button to try again. The E-mail address \"$private_email\" does not appear to be a valid e-mail address." };
219 if($private_email ne $confirm_email) {
220 print STDERR
"Emails don't match\n";
221 $c->stash->{rest
} = { error
=> "An error occurred. Please use your browser's back button to try again. New e-mail address entries do not match. You must enter your new e-mail address twice to verify accuracy." };
225 print STDERR
"Saving private email '$private_email' to the database\n";
226 $person->set_private_email($private_email);
227 my $confirm_code = $self->tempname();
228 $person->set_confirm_code($confirm_code);
231 $user_private_email = $private_email;
233 $self->send_confirmation_email($args->{username
}, $user_private_email, $confirm_code, $c->req->hostname());
237 $c->stash->{rest
} = { message
=> "Update successful" };
241 sub send_confirmation_email
{
242 my ($self, $username, $private_email, $confirm_code, $host) = @_;
243 my $subject = "[SGN] E-mail Address Confirmation Request";
244 my $body = <<END_HEREDOC;
245 Please do *NOT* reply to this message. The return address is not valid.
246 Use <a href="/contact/form">the contact form</a> instead.
248 This message is sent to confirm the private e-mail address for community user
251 Please click (or cut and paste into your browser) the following link to
252 confirm your account and e-mail address:
254 http://$host/user/confirm?username=$username&confirm=$confirm_code
260 CXGN::Contact::send_email($subject, $body, $private_email);
263 sub reset_password :Path('/ajax/user/reset_password') Args(0) {
267 my $email = $c->req->param('password_reset_email');
269 my @person_ids = CXGN::People::Login->get_login_by_email($c->dbc->dbh(), $email);
271 print STDERR Dumper(\@person_ids);
273 $c->stash->{rest} = { error => "The provided email ($email) is not associated with any account." };
277 if (@person_ids > 1) {
278 $c->stash->{rest} = { message => "The provided email ($email) is associated with multiple accounts. An email is sent for each account. Please notify the database team using the contact form to consolidate the accounts." };
282 foreach my $pid (@person_ids) {
283 print STDERR "Now processing person with id $pid\n";
284 my $email_reset_token = $self->tempname();
285 $reset_link = $c->req->hostname()."/user/reset_password_form?token=$email_reset_token";
286 my $person = CXGN::People::Login->new( $c->dbc->dbh(), $pid);
287 $person->update_confirm_code($email_reset_token);
288 print STDERR "Sending reset link $reset_link\n";
289 $self->send_reset_email_message($c, $pid, $email, $reset_link);
292 $c->stash->{rest} = { message => "Reset link sent. Please check your email and click on the link." };
295 sub process_reset_password_form :Path('/user/process_reset_password') Args(0) {
299 my $token = $c->req->param("token");
300 my $new_password = $c->req->param("");
303 my $sp_person_id = CXGN::People::Login->get_login_by_token($c->dbc->dbh, $token);
309 sub send_reset_email_message {
313 my $private_email = shift;
314 my $reset_link = shift;
316 my $subject = "[SGN] E-mail Address Confirmation Request";
319 my $body = <<END_HEREDOC
;
321 Please
do *NOT
* reply to this message
.
322 Use
<a href
="/contact/form">the contact form
</a
> to contact us instead
.
324 Your password can be
reset using the following
link:
326 Please click
(or cut
and paste into your browser
) the following
link to
327 confirm your account
and e
-mail address
:
335 CXGN
::Contact
::send_email
($subject, $body, $private_email);
340 my $rand_string = "";
341 my $dev_urandom = new IO
::File
"</dev/urandom" || print STDERR
"Can't open /dev/urandom";
342 $dev_urandom->read( $rand_string, 16 );
343 my @bytes = unpack( "C16", $rand_string );
348 $rand_string .= chr( 65 + $_ );
351 $rand_string .= chr( 97 + ( $_ - 26 ) );
354 $rand_string .= chr( 48 + ( $_ - 52 ) );