2 package SMMID
::Controller
::REST
::User
;
6 use Unicode
::Normalize
;
13 BEGIN { extends
'Catalyst::Controller::REST' };
16 default => 'application/json',
18 map => { 'application/json' => 'JSON' },
27 $str =~ s/\<script\>//gi;
28 $str =~ s/\<\/script\>//gi
;
33 sub login
: Path
('/rest/user/login') Args
(0) {
37 my $LOGIN_COOKIE_NAME = $c->config->{login_cookie_name
};
39 my $username = $c->req->param("username");
40 my $password = $c->req->param("password");
41 my $goto_url = $c->req->param("goto_url");
42 my $logout = $c->req->param("logout");
44 my $cookie = $c->req->param($LOGIN_COOKIE_NAME);
46 print STDERR
"Goto URL = $goto_url\n";
48 my $login = SMMID
::Login
->new( { schema
=> $c->model("SMIDDB")->schema() } );
49 my $login_info = $login->login_user($username, $password);
51 my $credentials = SMMID
::Authentication
::Credentials
->new();
52 my ($user_row, $login_info) = $credentials->authenticate($c,'default', { username
=> $username, password
=> $password });
55 if ($login_info->{cookie_string
}) {
57 # set the new cookie. The caller (controller)
58 # will actually need to set the cookie.
60 $c->response->cookies->{$LOGIN_COOKIE_NAME}->{value
} = $login_info->{cookie_string
};
63 if (exists($login_info->{incorrect_password
}) && $login_info->{incorrect_password
} == 1) {
64 $c->stash->{rest
} = { error
=> "Login credentials are incorrect. Please try again." };
67 elsif (exists($login_info->{error
})) {
68 $c->stash->{rest
} = { error
=> $login_info->{error
} };
71 elsif (exists($login_info->{account_disabled
}) && $login_info->{account_disabled
}) {
72 $c->stash->{rest
} = { error
=> "This account has been disabled due to $login_info->{account_disabled}. Please contact the database to fix this problem." };
77 message
=> "Login successful",
83 sub logout
:Path
('/rest/user/logout') Args
(0) {
87 my $LOGIN_COOKIE_NAME = $c->config->{login_cookie_name
};
88 print STDERR
"LOGIN COOKIE NAME = $LOGIN_COOKIE_NAME\n";
90 my $login = SMMID
::Login
->new( { schema
=> $c->model("SMIDDB")->schema() } );
91 my $cookie = $login->logout_user();
92 print STDERR
"LOGOUT: COOKIE = $cookie\n";
93 $c->res->cookies->{$LOGIN_COOKIE_NAME} = undef;
94 delete($c->res->cookies->{$LOGIN_COOKIE_NAME});
97 $c->stash->{rest
} = { message
=> "User successfully logged out." };
100 sub has_login
: Path
('/rest/user/has_login') Args
(0) {
105 print STDERR
"has_login: user present...\n";
106 $c->stash->{rest
} = { user
=> $c->user()->get_object()->dbuser_id(), role
=> $c->user()->get_object()->user_type() };
109 print STDERR
"No user found.\n";
110 $c->stash->{rest
} = { user
=> undef, role
=> undef };
115 sub new_account
:Path
('/rest/user/new') Args
(0) {
121 if (!$c->user() || $c->user()->get_object()->user_type() ne "curator"){
122 $error .= "You must be logged in as a curator to create new accounts.";
123 $c->stash->{rest
} = {error
=> $error};
127 my $first_name = $self->clean($c->req->param("first_name"));
128 my $last_name = $self->clean($c->req->param("last_name"));
129 my $email_address = $self->clean($c->req->param("email_address"));
130 my $organization = $self->clean($c->req->param("organization"));
131 my $username = $self->clean($c->req->param("username"));
132 my $user_type = $self->clean($c->req->param("user_type"));
134 my $already_exists = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->find({username
=> $username});
135 if ($already_exists){$error .= "A user with this username already exists.\n";}
137 if(length($first_name) == 0){$error .= "Need a first name or a first initial.\n";}
138 if(length($last_name) == 0){$error .= "Need a last name.\n";}
139 if(length($email_address) == 0){$error .= "Need an email address.\n";}
140 if(length($username) == 0){$error .= "Need a username. This is often the same as the email.\n";}
142 my $password = $self->clean($c->req->param("password"));
143 my $confirm_password = $self->clean($c->req->param("confirm_password"));
145 if (length($password) < 7){$error .= "Password must be at least 7 characters long.\n";}
146 if ($password ne $confirm_password){$error .= "Please confirm that the password is entered twice.\n";}
149 $c->stash->{rest
} = {error
=> $error};
155 first_name
=> $first_name,
156 last_name
=> $last_name,
157 email
=> $email_address,
158 organization
=> $organization,
159 username
=> $username,
160 user_type
=> $user_type,
161 password
=> "crypt($password, gen_salt('bf'))",
162 creation_date
=> 'now()',
163 last_modified_date
=> 'now()',
169 my $new = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->new($row);
171 $new_dbuser = $new->dbuser_id();
175 $c->stash->{rest
} = { error
=> "Sorry, an error occurred storing the user ($@)" };
177 $c->stash->{rest
} = {success
=> "Successfully stored the new user with id=$new_dbuser"};
183 sub change_account_info_action
:Path
('/rest/user/update') Args
(0) {
188 $c->stash->{rest
} = { error
=> "You must be logged in to use this page." };
192 my $person = new CXGN
::People
::Login
($c->dbc->dbh(), $c->user->get_sp_person_id());
194 # my ($current_password, $change_username, $change_password, $change_email) = $c->req->param({qw(current_password change_username change_password change_email)});
196 my $args = $c->req->params();
198 if (!$args->{change_password
} && ! $args->{change_username
} && !$args->{change_email
}) {
199 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.";
201 $c->stash->{rest
} = { error
=> $error };
205 chomp($args->{current_password
});
206 if (! $person->verify_password($args->{current_password
})) {
207 my $error = "Your current password does not match SGN records.";
209 $c->stash->{rest
} = { error
=> "$error" };
213 # Check for error conditions in all changes, before making any of them.
214 # Otherwise, we could end up making some changes and then failing on later
215 # ones. The user would then push the back button and their information may
216 # be different now but they will probably assume no changes were made. This
217 # is most troublesome if the current password changes.
219 if ($args->{change_username
}) {
220 #unless change_username is set, new_username won't be in the args hash because of the prestore test
221 my $new_username = $args->{new_username
};
222 if(length($new_username) < 7) {
223 my $error = "Username must be at least 7 characters long.";
225 $c->stash->{rest
} = { error
=> $error };
229 my $other_user = CXGN
::People
::Login
->get_login($c->dbc->dbh(), $new_username);
230 if (defined $other_user->get_sp_person_id() &&
231 ($person -> get_sp_person_id
() != $other_user->get_sp_person_id())) {
232 print STDERR
"Username alread in use.\n";
233 $c->stash->{rest
} = { error
=> "Username \"$new_username\" is already in use. Please select a different username." };
237 $person->set_username($new_username);
241 if ($args->{change_password
}) {
242 #unless change_password is set, new_password won't be in the args hash because of the prestore test
243 my ($new_password, $confirm_password) = ($args->{new_password
}, $args->{confirm_password
});
244 if(length($args->{new_password
}) < 7) {
245 print STDERR
"Password too short\n";
246 $c->stash->{rest
} = { error
=> "Passwords must be at least 7 characters long. Please try again." };
250 if($args->{new_password
} !~ /^[a-zA-Z0-9~!@#$^&*_.=:;<>?]+$/) {
251 print STDERR
"Illegal characters in password\n";
252 $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>." };
255 if($args->{new_password
} ne $args->{confirm_password
}) {
256 print STDERR
"Password don't match.\n";
257 $c->stash->{rest
} = { error
=> "New password entries do not match. You must enter your new password twice to verify accuracy." };
261 print STDERR
"Saving new password to the database\n";
262 $person->update_password($args->{new_password
});
265 my $user_private_email = $c->user->get_private_email();
266 if($args->{change_email
}) {
267 #unless change_email is set, private_email won't be in the args hash because of the prestore test
268 my ($private_email, $confirm_email) = ($args->{private_email
}, $args->{confirm_email
});
269 if($private_email !~ m/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+$/) {
270 print STDERR
"Invalid email address\n";
271 $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." };
274 if($private_email ne $confirm_email) {
275 print STDERR
"Emails don't match\n";
276 $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." };
280 print STDERR
"Saving private email '$private_email' to the database\n";
281 $person->set_private_email($private_email);
282 my $confirm_code = $self->tempname();
283 $person->set_confirm_code($confirm_code);
286 $user_private_email = $private_email;
288 $self->send_confirmation_email($args->{username
}, $user_private_email, $confirm_code, $c->config->{main_production_site_url
});
292 $c->stash->{rest
} = { message
=> "Update successful" };
296 sub send_confirmation_email
{
297 my ($self, $username, $private_email, $confirm_code, $host) = @_;
298 my $subject = "[SGN] E-mail Address Confirmation Request";
300 my $body = <<END_HEREDOC;
302 You requested an account on the site $host.
304 Please do *NOT* reply to this message. The return address is not valid.
305 Use the contact form at $host/contact/form instead.
307 This message is sent to confirm the private e-mail address for community user
310 Please click (or cut and paste into your browser) the following link to
311 confirm your account and e-mail address:
313 $host/user/confirm?username=$username&confirm=$confirm_code
319 CXGN::Contact::send_email($subject, $body, $private_email);
322 sub reset_password :Path('/rest/user/reset_password') Args(0) {
326 my $email = $c->req->param('password_reset_email');
328 my @person_ids = CXGN::People::Login->get_login_by_email($c->dbc->dbh(), $email);
331 $c->stash->{rest} = { error => "The provided email ($email) is not associated with any account." };
335 if (@person_ids > 1) {
336 $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." };
341 foreach my $pid (@person_ids) {
342 my $email_reset_token = $self->tempname();
343 my $reset_link = $c->config->{main_production_site_url}."/user/reset_password_form?reset_password_token=$email_reset_token";
344 my $person = CXGN::People::Login->new( $c->dbc->dbh(), $pid);
345 $person->update_confirm_code($email_reset_token);
346 print STDERR "Sending reset link $reset_link\n";
347 $self->send_reset_email_message($c, $pid, $email, $reset_link);
348 push @reset_links, $reset_link;
349 push @reset_tokens, $email_reset_token;
352 $c->stash->{rest} = {
353 message => "Reset link sent. Please check your email and click on the link.",
354 reset_links => \@reset_links,
355 reset_tokens => \@reset_tokens
359 sub process_reset_password_form :Path('/rest/user/process_reset_password') Args(0) {
363 my $token = $c->req->param("token");
364 my $confirm_password = $c->req->param("confirm_password");
365 my $new_password = $c->req->param("new_password");
367 if (length($new_password) < 7) {
368 $c->stash->{rest} = { error => "Password is too short. Password must be 7 or more characters" };
372 if ($confirm_password ne $new_password){
373 $c->stash->{rest} = { error => "Please enter the same password in the confirm password field!" };
378 my $sp_person_id = CXGN::People::Login->get_login_by_token($c->dbc->dbh, $token);
380 my $login = CXGN::People::Login->new($c->dbc->dbh(), $sp_person_id);
381 $login->update_password($new_password);
382 $login->update_confirm_code("");
385 $c->stash->{rest} = { error => $@ };
388 $c->stash->{rest} = { message => "The password was successfully updated." };
393 sub send_reset_email_message {
397 my $private_email = shift;
398 my $reset_link = shift;
400 my $subject = "[SGN] E-mail Address Confirmation Request";
401 my $main_url = $c->config->{main_production_site_url};
403 my $body = <<END_HEREDOC
;
407 you have requested a password
reset on
$main_url.
409 If this request did
not come from you
, please let us know
.
411 To contact us
, please
do NOT reply to this message
; rather
, use the contact form
($main_url/contact/form
) instead
.
413 Your password can be
reset using the following
link, which you can either click
or cut
and paste into your browser
:
419 Your friends at
$main_url
423 CXGN
::Contact
::send_email
($subject, $body, $private_email);
428 my $rand_string = "";
429 my $dev_urandom = new IO
::File
"</dev/urandom" || print STDERR
"Can't open /dev/urandom";
430 $dev_urandom->read( $rand_string, 16 );
431 my @bytes = unpack( "C16", $rand_string );
436 $rand_string .= chr( 65 + $_ );
439 $rand_string .= chr( 97 + ( $_ - 26 ) );
442 $rand_string .= chr( 48 + ( $_ - 52 ) );
448 sub get_login_button_html
:Path
('/rest/user/login_button_html') Args
(0) {
452 # my $logout = $c->req->param("logout");
461 # if ($logout eq "yes") {
462 # print STDERR "generating login button for logout...\n";
464 # <li class="dropdown">
465 # <div class="btn-group" role="group" aria-label="..." style="height:34px; margin: 1px 0px 0px 0px" >
466 # <a href="/user/login">
467 # <button id="logouclass="btn btn-primary" type="button" style="margin: 7px 7px 0px 0px">Login</button>
473 # $c->stash->{rest} = { html => $html };
478 if ( $c->config->{disable_login
} ) {
479 $html = '<div class="btn-group" role="group" aria-label="..." style="height:34px; margin: 1px 0px 0px 0px" > <button class="btn btn-primary disabled" type="button" style="margin: 7px 7px 0px 0px">Login</button> </div>';
482 $c->stash->{rest
} = { html
=> $html };
486 if( $c->config->{'is_mirror'} ) {
487 my $production_site = $c->config->{main_production_site_url
};
489 # if the site is a mirror, gray out the login/logout links
491 print STDERR
"generating login button for mirror site...\n";
492 $html = qq| <a style
="line-height: 1.2; text-decoration: underline; background: none" href
="$production_site" title
="log in on main site">main site
</a
> |;
494 $c->stash->{rest
} = { html
=> $html };
499 print STDERR
"Generate login button for logged in user...\n";
500 my $sp_person_id = $c->user->get_object->dbuser_id();
501 my $username = $c->user->id();
502 my $welcome_sign = "Hi, ".$c->user->get_object()->first_name();
503 my $display_name = qq(
505 <nav
class="navbar navbar-expand-lg navbar-light bg-white">
507 <div
class="collapse navbar-collapse" id
="navbarNavDropdown">
508 <ul
class="navbar-nav">
509 <li
class="nav-item dropdown">
510 <a
class="nav-link dropdown-toggle header_link" style
="color:lightblue;" href
="/browse" id
="navbarDropdownMenuLink" data
-toggle
="dropdown" aria
-haspopup
="true" aria
-expanded
="false">
513 <div
class="dropdown-menu" aria
-labelledby
="navbarDropdownMenuLink">
514 <a
class="dropdown-item" href
="/user/$sp_person_id/profile">Your Profile
</a
>
515 <a
class="dropdown-item"><button id
="navbar_logout" class="btn btn-primary" type
="button" onclick
="logout();" title
="Logout">Logout
</button></a>
521 <button
class="navbar-toggler" type
="button" data
-toggle
="collapse" data
-target
="#navbarNavDropdown" aria
-controls
="navbarNavDropdown" aria
-expanded
="false" aria
-label
="Toggle navigation">
522 <span
class="navbar-toggler-icon"></span
>
530 $html = $display_name;
533 print STDERR
"GENERATED HTML = $html\n";
534 $c->stash->{rest
} = { html
=> $html };
539 ### Generate regular login button
541 print STDERR
"generating regular login button..\n";
542 $html = qq | <button id
="site_login_button" name
="site_login_button" class="btn btn-primary" type
="button">Login
</button
> |;
544 $c->stash->{rest
} = {
545 html
=> $html, logged_in
=> $c->user_exists
550 sub quick_create_user
:Path
('/rest/user/quick_create_account') Args
(0) {
555 $c->stash->{rest
} = { error
=> "Need to be logged in to use feature." };
559 if (!$c->user()->check_roles("curator")) {
560 $c->stash->{rest
} = { error
=> "You don't have the privileges to use this feature" };
563 my $logged_in_person_id = $c->user()->get_sp_person_id();
565 my $logged_in_user=CXGN
::People
::Person
->new($c->dbc->dbh(), $logged_in_person_id);
566 $logged_in_person_id=$logged_in_user->get_sp_person_id();
567 my $logged_in_username=$logged_in_user->get_first_name()." ".$logged_in_user->get_last_name();
568 my $logged_in_user_type=$logged_in_user->get_user_type();
570 my ($username, $password, $confirm_password, $email_address, $new_user_type, $first_name, $last_name) =
571 map { print STDERR
$_." ".$c->req->param($_)."\n"; $c->req->param($_) } qw
| username password confirm_password confirm_email user_type first_name last_name
|;
573 print STDERR
"$username, $password, $confirm_password, $email_address, $new_user_type, $first_name, $last_name\n";
575 my $new_user_login=CXGN
::People
::Login
->new($c->dbc->dbh);
580 if(length($username)<7){push @fail,"Username is too short. Username must be 7 or more characters";}
581 my $existing_login=CXGN
::People
::Login
->get_login($c->dbc->dbh, $username);
583 if($existing_login->get_username()){push @fail,"Username \"$username\" is already in use. Please pick a different us
586 if(length($password)<7){push @fail,"Password is too short. Password must be 7 or more characters";}
588 if("$password" ne "$confirm_password"){push @fail,"Password and confirm password do not match.";}
590 if($password eq $username){push @fail,"Password must not be the same as your username.";}
592 if($new_user_type ne 'user' and $new_user_type ne 'sequencer' and $new_user_type ne 'submitter'){
593 push @fail,"Sorry, but you cannot create user of type \"$new_user_type\" with web interface.";}
599 $fail_str .= "<li>$_</li>\n"
601 $c->stash->{rest
} = { error
=> $fail_str };
608 $new_user_login->set_username(encode_entities
($username));
609 $new_user_login->set_password($password);
610 $new_user_login->set_private_email(encode_entities
($email_address));
611 $new_user_login->set_user_type(encode_entities
($new_user_type));
612 $new_user_login->store();
613 my $new_user_person_id=$new_user_login->get_sp_person_id();
614 my $new_user_person=CXGN
::People
::Person
->new($c->dbc->dbh, $new_user_person_id);
615 $new_user_person->set_first_name(encode_entities
($first_name));
616 $new_user_person->set_last_name(encode_entities
($last_name));
617 ##removed. This was causing problems with creating new accounts for people,
618 ##and then not finding it in the people search.
619 #$new_user_person->set_censor(1);#censor by default, since we are creating this account, not the person whose info might be displayed, and they might not want it to be displayed
620 $new_user_person->store();
624 $c->stash->{rest
} = { html
=> "An error occurred. $@" };
627 $c->stash->{rest
} = { html
=> "<center><h4>Account successfully created for $first_name $last_name</h4><a href=\"/user/admin/quick_create_account\">Create another account" };
631 sub user
:Chained
('/') :PathPart
('rest/user') CaptureArgs
(1){
636 $c->stash->{rest
} = { error
=> "Sorry, you need to be logged in." };
640 my $dbuser_id = shift;
642 $c->stash->{dbuser_id
} = $dbuser_id;
645 sub profile
:Chained
('user') :PathPart
('profile') Args
(0){
650 $c->stash->{rest
} = { error
=> "Sorry, you need to be logged in to view user profiles." };
654 my $rs = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->find( {dbuser_id
=> $c->stash->{dbuser_id
}} );
657 $c->stash->{rest
} = {error
=> "Sorry, this user does not exist."};
660 if ($rs->user_type() eq "curator"){$user_type = "Curator";}
661 else {$user_type = "Standard User";}
664 $data->{first_name
} = $rs->first_name();
665 $data->{last_name
} = $rs->last_name();
666 $data->{full_name
} = $rs->first_name()." ".$rs->last_name();
667 $data->{email_address
} = $rs->email();
668 $data->{username
} = $rs->username();
669 $data->{user_role
} = $user_type;
670 $data->{organization
} = $rs->organization();
672 $c->stash->{rest
} = {data
=> $data};
677 sub authored_smids
:Chained
('user') :PathPart
('authored_smids') Args
(0){
682 $c->stash->{rest
} = { error
=> "Sorry, you need to be logged in to view user profiles." };
686 my $rs = $c->model("SMIDDB")->resultset("SMIDDB::Result::Compound")->search( {dbuser_id
=> $c->stash->{dbuser_id
}} );
688 while (my $r = $rs->next()){
690 next if (!$self->has_view_permission($c, $r));
692 push @data, ["<a href=\"/smid/".$r->compound_id()."\">".$r->smid_id()."</a>", $r->formula(), $r->molecular_weight(), $r->curation_status(), $r->public_status() ];
694 $c->stash->{rest
} = {data
=> \
@data};
697 sub authored_experiments
:Chained
('user') :PathPart
('authored_experiments') Args
(0){
702 $c->stash->{rest
} = { error
=> "Sorry, you need to be logged in to view user profiles." };
706 my $rs = $c->model("SMIDDB")->resultset("SMIDDB::Result::Experiment")->search( {'me.dbuser_id' => $c->stash->{dbuser_id
} }, {join => 'compound'} );
709 while (my $r = $rs->next()){
711 next if (!$self->has_view_permission($c, $r->compound()));
714 if ($r->experiment_type() eq "hplc_ms"){
715 $experiment_type = "HPLC-MS";
717 $experiment_type = "MS/MS";
720 push @data, [$experiment_type, "<a href=\"/smid/".$r->compound_id()."\">".$r->compound()->smid_id()."</a>"];
722 $c->stash->{rest
} = {data
=> \
@data};
725 sub change_profile
:Chained
('user') :PathPart
('change_profile') Args
(0) {
732 my $row = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->find( {dbuser_id
=> $c->stash->{dbuser_id
}} );
734 if (!$c->user() || $c->user()->dbuser_id() != $c->stash->{dbuser_id
}){
735 $c->stash->{rest
} = { error
=> "Sorry, you need to have a valid login to edit user data." };
739 print STDERR
"Found user profile editor...\n";
741 my $first_name = $self->clean($c->req->param("first_name"));
742 my $last_name = $self->clean($c->req->param("last_name"));
743 my $email_address = $self->clean($c->req->param("email_address"));
744 my $organization = $self->clean($c->req->param("organization"));
745 my $username = $self->clean($c->req->param("username"));
747 if (length($first_name) == 0){$error .= "First name may not be blank. ";}
748 if (length($last_name) == 0){$error .= "Last name may not be blank. ";}
749 if (length($email_address) == 0){$error .= "Email may not be blank. ";}
750 if (length($organization) == 0){$error .= "Organization may not be blank. ";}
751 if (length($username) == 0){$error .= "Username may not be blank. ";}
754 $c->stash->{rest
} = { error
=> $error };
759 $data->{first_name
} = $first_name;
760 $data->{last_name
} = $last_name;
761 $data->{email
} = $email_address;
762 $data->{username
} = $username;
763 $data->{organization
} = $organization;
768 print STDERR
"Updated user profile.\n";
772 $c->stash->{rest
} = {success
=> 0};
774 $c->stash->{rest
} = {success
=> 1};
779 sub change_password
:Chained
('user') :PathPart
('change_password') Args
(0) {
786 my $dbuser_id = $c->stash->{dbuser_id
};
788 my $row = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->find( {dbuser_id
=> $dbuser_id} );
790 if (!$c->user() || $c->user()->get_object()->dbuser_id() != $dbuser_id){
791 $c->stash->{rest
} = { error
=> "Sorry, you need to have a valid login to edit user data." };
795 my $old_password = $self->clean($c->req->param("old_password"));
796 my $new_password = $self->clean($c->req->param("new_password"));
797 my $new_password_confirm = $self->clean($c->req->param("new_password_confirm"));
799 my $login = SMMID
::Login
->new( { schema
=> $c->model("SMIDDB")->schema() } );
800 my $current_user = $login->user_from_credentials($c->user()->get_object()->username(), $old_password);
801 if (!$current_user){$error .= "Incorrect password. ";}
802 if (length($new_password) < 7){$error .= "New password must be at least 7 characters long. ";}
803 if ($new_password ne $new_password_confirm){$error .= "Please confirm that the new password is entered twice. ";}
806 $c->stash->{rest
} = { error
=> $error };
811 my $masked_new_password = $login->schema()->storage->dbh()->prepare("UPDATE dbuser SET password=crypt(?, gen_salt('bf')) WHERE dbuser_id=?");
812 $masked_new_password->execute($new_password, $dbuser_id);
815 $c->stash->{rest
} = {success
=> 0};
817 $c->stash->{rest
} = {success
=> 1};
821 sub has_view_permission
{
826 if($smid->public_status() eq "public"){return 1;}
828 if(!$c->user() && $smid->public_status() eq "private"){return 0;}
830 if($smid->public_status() eq "private" && $c->user()->get_object()->dbuser_id() != $smid->dbuser_id() && $c->user()->get_object()->user_type() ne "curator"){return 0;}