fix conflicts.
[SMMID.git] / lib / SMMID / Controller / REST / User.pm
blob399d1e06daf5e142cc4cc6b6ced15f675282a484
2 package SMMID::Controller::REST::User;
4 use Moose;
5 use utf8;
6 use Unicode::Normalize;
7 use IO::File;
8 use Data::Dumper;
9 use HTML::Entities;
10 use SMMID::Login;
11 #use JSON::XS;
13 BEGIN { extends 'Catalyst::Controller::REST' };
15 __PACKAGE__->config(
16 default => 'application/json',
17 stash_key => 'rest',
18 map => { 'application/json' => 'JSON' },
22 sub clean {
23 my $self = shift;
24 my $str = shift;
26 # remove script tags
27 $str =~ s/\<script\>//gi;
28 $str =~ s/\<\/script\>//gi;
30 return $str;
33 sub login : Path('/rest/user/login') Args(0) {
34 my $self = shift;
35 my $c = shift;
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." };
65 return;
67 elsif (exists($login_info->{error})) {
68 $c->stash->{rest} = { error => $login_info->{error} };
69 return;
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." };
73 return;
75 else {
76 $c->stash->{rest} = {
77 message => "Login successful",
78 goto_url => $goto_url
83 sub logout :Path('/rest/user/logout') Args(0) {
84 my $self = shift;
85 my $c = shift;
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});
95 $c->user(undef);
96 $c->logout();
97 $c->stash->{rest} = { message => "User successfully logged out." };
100 sub has_login : Path('/rest/user/has_login') Args(0) {
101 my $self = shift;
102 my $c = shift;
104 if ($c->user()) {
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() };
108 else {
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) {
116 my $self = shift;
117 my $c = shift;
119 my $error="";
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};
124 return;
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";}
148 if ($error){
149 $c->stash->{rest} = {error => $error};
150 return;
153 my $row;
154 $row = {
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()',
166 my $new_dbuser;
168 eval {
169 my $new = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->new($row);
170 $new->insert();
171 $new_dbuser = $new->dbuser_id();
174 if ($@) {
175 $c->stash->{rest} = { error => "Sorry, an error occurred storing the user ($@)" };
176 } else {
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) {
184 my $self = shift;
185 my $c = shift;
187 if (! $c->user() ) {
188 $c->stash->{rest} = { error => "You must be logged in to use this page." };
189 return;
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.";
200 print STDERR $error;
201 $c->stash->{rest} = { error => $error };
202 return;
205 chomp($args->{current_password});
206 if (! $person->verify_password($args->{current_password})) {
207 my $error = "Your current password does not match SGN records.";
208 print STDERR $error;
209 $c->stash->{rest} = { error => "$error" };
210 return;
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.";
224 print STDERR $error;
225 $c->stash->{rest} = { error => $error };
226 return;
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." };
234 return;
237 $person->set_username($new_username);
238 $person->store();
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." };
247 return;
249 #format check
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>." };
253 return;
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." };
258 return;
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." };
272 return;
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." };
277 return;
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);
284 $person->store();
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
308 \"$username\".
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
315 Thank you.
316 Sol Genomics Network
317 END_HEREDOC
319 CXGN::Contact::send_email($subject, $body, $private_email);
322 sub reset_password :Path('/rest/user/reset_password') Args(0) {
323 my $self = shift;
324 my $c = shift;
326 my $email = $c->req->param('password_reset_email');
328 my @person_ids = CXGN::People::Login->get_login_by_email($c->dbc->dbh(), $email);
330 if (!@person_ids) {
331 $c->stash->{rest} = { error => "The provided email ($email) is not associated with any account." };
332 return;
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." };
339 my @reset_links;
340 my @reset_tokens;
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) {
360 my $self = shift;
361 my $c = shift;
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" };
369 $c->detach();
372 if ($confirm_password ne $new_password){
373 $c->stash->{rest} = { error => "Please enter the same password in the confirm password field!" };
374 $c->detach();
377 eval {
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("");
384 if ($@) {
385 $c->stash->{rest} = { error => $@ };
387 else {
388 $c->stash->{rest} = { message => "The password was successfully updated." };
393 sub send_reset_email_message {
394 my $self = shift;
395 my $c = shift;
396 my $pid = shift;
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:
415 $reset_link
417 Thank you.
419 Your friends at $main_url
421 END_HEREDOC
423 CXGN::Contact::send_email($subject, $body, $private_email);
426 sub tempname {
427 my $self = shift;
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 );
432 $rand_string = "";
433 foreach (@bytes) {
434 $_ %= 62;
435 if ( $_ < 26 ) {
436 $rand_string .= chr( 65 + $_ );
438 elsif ( $_ < 52 ) {
439 $rand_string .= chr( 97 + ( $_ - 26 ) );
441 else {
442 $rand_string .= chr( 48 + ( $_ - 52 ) );
445 return $rand_string;
448 sub get_login_button_html :Path('/rest/user/login_button_html') Args(0) {
449 my $self = shift;
450 my $c = shift;
452 # my $logout = $c->req->param("logout");
454 select(STDERR);
455 $|=1;
457 my $html = "";
461 # if ($logout eq "yes") {
462 # print STDERR "generating login button for logout...\n";
463 # $html = <<HTML;
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>
468 # </a>
469 # </div>
470 # </li>
471 # HTML
473 # $c->stash->{rest} = { html => $html };
474 # return;
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 };
483 return;
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 };
495 return;
498 if ( $c->user() ) {
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">
511 $welcome_sign
512 </a>
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>
517 </div>
518 </li>
519 </ul>
520 </div>
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>
523 </button>
525 </nav>
530 $html = $display_name;
533 print STDERR "GENERATED HTML = $html\n";
534 $c->stash->{rest} = { html => $html };
535 return;
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) {
551 my $self = shift;
552 my $c = shift;
554 if (!$c->user()) {
555 $c->stash->{rest} = { error => "Need to be logged in to use feature." };
556 return;
559 if (!$c->user()->check_roles("curator")) {
560 $c->stash->{rest} = { error => "You don't have the privileges to use this feature" };
561 return;
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);
577 if ($username) {
578 my @fail=();
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
584 ername.";}
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.";}
594 if(@fail)
596 my $fail_str="";
597 foreach(@fail)
599 $fail_str .= "<li>$_</li>\n"
601 $c->stash->{rest} = { error => $fail_str };
602 return;
607 eval {
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();
623 if ($@) {
624 $c->stash->{rest} = { html => "An error occurred. $@" };
626 else {
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){
632 my $self = shift;
633 my $c = shift;
635 if (!$c->user()) {
636 $c->stash->{rest} = { error => "Sorry, you need to be logged in." };
637 return;
640 my $dbuser_id = shift;
642 $c->stash->{dbuser_id} = $dbuser_id;
645 sub profile :Chained('user') :PathPart('profile') Args(0){
646 my $self = shift;
647 my $c = shift;
649 if (!$c->user()) {
650 $c->stash->{rest} = { error => "Sorry, you need to be logged in to view user profiles." };
651 return;
654 my $rs = $c->model("SMIDDB")->resultset("SMIDDB::Result::Dbuser")->find( {dbuser_id => $c->stash->{dbuser_id}} );
656 if (!$rs){
657 $c->stash->{rest} = {error => "Sorry, this user does not exist."};
658 } else {
659 my $user_type;
660 if ($rs->user_type() eq "curator"){$user_type = "Curator";}
661 else {$user_type = "Standard User";}
663 my $data;
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){
678 my $self = shift;
679 my $c = shift;
681 if (!$c->user()) {
682 $c->stash->{rest} = { error => "Sorry, you need to be logged in to view user profiles." };
683 return;
686 my $rs = $c->model("SMIDDB")->resultset("SMIDDB::Result::Compound")->search( {dbuser_id => $c->stash->{dbuser_id}} );
687 my @data;
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){
698 my $self = shift;
699 my $c = shift;
701 if (!$c->user()) {
702 $c->stash->{rest} = { error => "Sorry, you need to be logged in to view user profiles." };
703 return;
706 my $rs = $c->model("SMIDDB")->resultset("SMIDDB::Result::Experiment")->search( {'me.dbuser_id' => $c->stash->{dbuser_id} }, {join => 'compound'} );
707 my @data;
709 while (my $r = $rs->next()){
711 next if (!$self->has_view_permission($c, $r->compound()));
713 my $experiment_type;
714 if ($r->experiment_type() eq "hplc_ms"){
715 $experiment_type = "HPLC-MS";
716 } else {
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) {
727 my $self = shift;
728 my $c = shift;
730 my $error = "";
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." };
736 return;
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. ";}
753 if ($error) {
754 $c->stash->{rest} = { error => $error };
755 return;
758 my $data;
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;
766 eval{
767 $row->update($data);
768 print STDERR "Updated user profile.\n";
771 if ($@) {
772 $c->stash->{rest} = {success => 0};
773 } else {
774 $c->stash->{rest} = {success => 1};
779 sub change_password :Chained('user') :PathPart('change_password') Args(0) {
781 my $self = shift;
782 my $c = shift;
784 my $error = "";
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." };
792 return;
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. ";}
805 if ($error) {
806 $c->stash->{rest} = { error => $error };
807 return;
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);
814 if ($@) {
815 $c->stash->{rest} = {success => 0};
816 } else {
817 $c->stash->{rest} = {success => 1};
821 sub has_view_permission {
822 my $self = shift;
823 my $c = shift;
824 my $smid = shift;
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;}
832 return 1;