1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
7 use Digest::MD5 qw(md5_hex);
9 use OpenSRF::EX qw(:try);
13 use OpenILS::Application::AppUtils;
14 use OpenILS::Utils::Fieldmapper;
15 use OpenILS::Application::Search::Actor;
16 use OpenILS::Utils::ModsParser;
17 use OpenSRF::Utils::Logger;
18 my $logger = "OpenSRF::Utils::Logger";
20 use OpenSRF::Utils::Cache;
23 use OpenILS::Application::Actor::Container;
25 OpenILS::Application::Actor::Container->initialize();
28 my $apputils = "OpenILS::Application::AppUtils";
30 sub _d { warn "Patron:\n" . Dumper(shift()); }
35 my $set_user_settings;
38 __PACKAGE__->register_method(
39 method => "set_user_settings",
40 api_name => "open-ils.actor.patron.settings.update",
42 sub set_user_settings {
43 my( $self, $client, $user_session, $uid, $settings ) = @_;
45 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
47 my( $staff, $user, $evt ) =
48 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
53 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
55 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper($params));
57 return $apputils->simplereq(
59 'open-ils.storage.direct.actor.user_setting.batch.merge', $params );
65 __PACKAGE__->register_method(
66 method => "set_ou_settings",
67 api_name => "open-ils.actor.org_unit.settings.update",
70 my( $self, $client, $user_session, $ouid, $settings ) = @_;
72 my( $staff, $evt ) = $apputils->checkses( $user_session );
74 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
79 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
81 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
83 return $apputils->simplereq(
85 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
89 my $fetch_user_settings;
90 my $fetch_ou_settings;
92 __PACKAGE__->register_method(
93 method => "user_settings",
94 api_name => "open-ils.actor.patron.settings.retrieve",
97 my( $self, $client, $user_session, $uid ) = @_;
99 my( $staff, $user, $evt ) =
100 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
103 $logger->debug("User " . $staff->id . " fetching user $uid\n");
104 my $s = $apputils->simplereq(
106 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
108 return { map { ($_->name,$_->value) } @$s };
113 __PACKAGE__->register_method(
114 method => "ou_settings",
115 api_name => "open-ils.actor.org_unit.settings.retrieve",
118 my( $self, $client, $ouid ) = @_;
120 my $s = $apputils->simplereq(
122 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
124 return { map { ($_->name,$_->value) } @$s };
129 __PACKAGE__->register_method(
130 method => "update_patron",
131 api_name => "open-ils.actor.patron.update",);
134 my( $self, $client, $user_session, $patron ) = @_;
136 my $session = $apputils->start_db_session();
139 #warn $user_session . " " . $patron . "\n";
143 OpenILS::Application::AppUtils->check_user_session(
144 $user_session ); #throws EX on error
146 # XXX does this user have permission to add/create users. Granularity?
147 # $new_patron is the patron in progress. $patron is the original patron
148 # passed in with the method. new_patron will change as the components
149 # of patron are added/updated.
153 if(ref($patron->card)) { $patron->card( $patron->card->id ); }
154 if(ref($patron->billing_address)) { $patron->billing_address( $patron->billing_address->id ); }
155 if(ref($patron->mailing_address)) { $patron->mailing_address( $patron->mailing_address->id ); }
157 # create/update the patron first so we can use his id
158 if($patron->isnew()) {
160 $new_patron = _add_patron($session, _clone_patron($patron), $user_obj);
162 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
163 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
164 $client->respond_complete($new_patron->ex);
168 } else { $new_patron = $patron; }
170 $new_patron = _add_update_addresses($session, $patron, $new_patron, $user_obj);
172 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
173 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
174 $client->respond_complete($new_patron->ex);
178 $new_patron = _add_update_cards($session, $patron, $new_patron, $user_obj);
180 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
181 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
182 $client->respond_complete($new_patron->ex);
186 $new_patron = _add_survey_responses($session, $patron, $new_patron, $user_obj);
187 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
188 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
189 $client->respond_complete($new_patron->ex);
194 # re-update the patron if anything has happened to him during this process
195 if($new_patron->ischanged()) {
196 $new_patron = _update_patron($session, $new_patron, $user_obj);
198 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
199 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
200 $client->respond_complete($new_patron->ex);
205 $session = OpenSRF::AppSession->create("open-ils.storage");
206 $new_patron = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
207 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
208 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
209 $client->respond_complete($new_patron->ex);
213 $new_patron = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
214 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
215 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
216 $client->respond_complete($new_patron->ex);
220 $new_patron = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
221 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
222 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
223 $client->respond_complete($new_patron->ex);
227 $apputils->commit_db_session($session);
229 #warn "Patron Update/Create complete\n";
230 return flesh_user($new_patron->id());
236 __PACKAGE__->register_method(
237 method => "user_retrieve_fleshed_by_id",
238 api_name => "open-ils.actor.user.fleshed.retrieve",);
240 sub user_retrieve_fleshed_by_id {
241 my( $self, $client, $user_session, $user_id ) = @_;
243 my( $requestor, $target, $evt ) = $apputils->
244 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
247 return flesh_user($user_id);
258 $session = OpenSRF::AppSession->create("open-ils.storage");
262 # grab the user with the given id
263 my $ureq = $session->request(
264 "open-ils.storage.direct.actor.user.retrieve", $id);
265 my $user = $ureq->gather(1);
267 if(!$user) { return undef; }
270 my $cards_req = $session->request(
271 "open-ils.storage.direct.actor.card.search.usr.atomic",
273 $user->cards( $cards_req->gather(1) );
275 for my $c(@{$user->cards}) {
276 if($c->id == $user->card || $c->id eq $user->card ) {
277 #warn "Setting my card to " . $c->id . "\n";
282 my $add_req = $session->request(
283 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
285 $user->addresses( $add_req->gather(1) );
287 for my $c(@{$user->addresses}) {
288 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
289 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
292 my $stat_req = $session->request(
293 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
295 $user->stat_cat_entries($stat_req->gather(1));
297 my $standing_penalties_req = $session->request(
298 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
300 $user->standing_penalties($standing_penalties_req->gather(1));
302 if($kill) { $session->disconnect(); }
303 $user->clear_passwd();
309 # clone and clear stuff that would break the database
313 my $new_patron = $patron->clone;
315 # Using the Fieldmapper clone method
316 #my $new_patron = Fieldmapper::actor::user->new();
318 #my $fmap = $Fieldmapper::fieldmap;
319 #no strict; # shallow clone, may be useful in the fieldmapper
321 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
322 # $new_patron->$field( $patron->$field() );
327 $new_patron->clear_billing_address();
328 $new_patron->clear_mailing_address();
329 $new_patron->clear_addresses();
330 $new_patron->clear_card();
331 $new_patron->clear_cards();
332 $new_patron->clear_id();
333 $new_patron->clear_isnew();
334 $new_patron->clear_ischanged();
335 $new_patron->clear_isdeleted();
336 $new_patron->clear_stat_cat_entries();
337 $new_patron->clear_permissions();
338 $new_patron->clear_standing_penalties();
347 my $user_obj = shift;
350 if($apputils->check_user_perms(
351 $user_obj->id, $user_obj->home_ou, "CREATE_USER")) {
352 return OpenILS::Perm->new("CREATE_USER");
355 #warn "Creating new patron\n";
358 my $req = $session->request(
359 "open-ils.storage.direct.actor.user.create",$patron);
360 my $id = $req->gather(1);
362 return OpenILS::EX->new("DUPLICATE_USER_USERNAME");
365 # retrieve the patron from the db to collect defaults
366 my $ureq = $session->request(
367 "open-ils.storage.direct.actor.user.retrieve",
370 #warn "Created new patron with id $id\n";
372 return $ureq->gather(1);
377 my( $session, $patron, $user_obj) = @_;
380 if($patron->id ne $user_obj->id) {
381 if($apputils->check_user_perms(
382 $user_obj->id, $user_obj->home_ou, "UPDATE_USER")) {
383 return OpenILS::Perm->new("UPDATE_USER");
387 #warn "updating patron " . Dumper($patron) . "\n";
389 my $req = $session->request(
390 "open-ils.storage.direct.actor.user.update",$patron );
391 my $status = $req->gather(1);
392 if(!defined($status)) {
393 throw OpenSRF::EX::ERROR
394 ("Unknown error updating patron");
400 sub _add_update_addresses {
403 my $new_patron = shift;
405 my $current_id; # id of the address before creation
407 for my $address (@{$patron->addresses()}) {
409 $address->usr($new_patron->id());
411 if(ref($address) and $address->isnew()) {
412 #warn "Adding new address at street " . $address->street1() . "\n";
414 $current_id = $address->id();
415 $address = _add_address($session,$address);
417 if( $patron->billing_address() and
418 $patron->billing_address() == $current_id ) {
419 $new_patron->billing_address($address->id());
420 $new_patron->ischanged(1);
423 if( $patron->mailing_address() and
424 $patron->mailing_address() == $current_id ) {
425 $new_patron->mailing_address($address->id());
426 $new_patron->ischanged(1);
429 } elsif( ref($address) and $address->ischanged() ) {
430 #warn "Updating address at street " . $address->street1();
431 $address->usr($new_patron->id());
432 _update_address($session,$address);
434 } elsif( ref($address) and $address->isdeleted() ) {
435 #warn "Deleting address at street " . $address->street1();
437 if( $address->id() == $new_patron->mailing_address() ) {
438 $new_patron->clear_mailing_address();
439 _update_patron($session, $new_patron);
442 if( $address->id() == $new_patron->billing_address() ) {
443 $new_patron->clear_billing_address();
444 _update_patron($session, $new_patron);
447 _delete_address($session,$address);
455 # adds an address to the db and returns the address with new id
457 my($session, $address) = @_;
458 $address->clear_id();
461 #warn "Adding Address:\n";
462 #warn Dumper($address);
464 # put the address into the database
465 my $req = $session->request(
466 "open-ils.storage.direct.actor.user_address.create",
470 my $id = $req->gather(1);
472 throw OpenSRF::EX::ERROR
473 ("Unable to create new user address");
476 #warn "Created address with id $id\n";
478 # update all the necessary id's
484 sub _update_address {
485 my( $session, $address ) = @_;
486 my $req = $session->request(
487 "open-ils.storage.direct.actor.user_address.update",
489 my $status = $req->gather(1);
490 if(!defined($status)) {
491 throw OpenSRF::EX::ERROR
492 ("Unknown error updating address");
499 sub _add_update_cards {
503 my $new_patron = shift;
505 my $virtual_id; #id of the card before creation
506 for my $card (@{$patron->cards()}) {
508 $card->usr($new_patron->id());
510 if(ref($card) and $card->isnew()) {
512 $virtual_id = $card->id();
513 $card = _add_card($session,$card);
514 if(UNIVERSAL::isa($card,"OpenILS::EX")) {
518 #if(ref($patron->card)) { $patron->card($patron->card->id); }
519 if($patron->card() == $virtual_id) {
520 $new_patron->card($card->id());
521 $new_patron->ischanged(1);
524 } elsif( ref($card) and $card->ischanged() ) {
525 $card->usr($new_patron->id());
526 _update_card($session, $card);
533 # adds an card to the db and returns the card with new id
535 my( $session, $card ) = @_;
538 #warn "Adding card with barcode " . $card->barcode() . "\n";
539 my $req = $session->request(
540 "open-ils.storage.direct.actor.card.create",
543 my $id = $req->gather(1);
545 return OpenILS::EX->new("DUPLICATE_INVALID_USER_BARCODE");
549 #warn "Created patron card with id $id\n";
555 my( $session, $card ) = @_;
558 my $req = $session->request(
559 "open-ils.storage.direct.actor.card.update",
561 my $status = $req->gather(1);
562 if(!defined($status)) {
563 throw OpenSRF::EX::ERROR
564 ("Unknown error updating card");
572 sub _delete_address {
573 my( $session, $address ) = @_;
575 #warn "Deleting address " . $address->street1() . "\n";
577 my $req = $session->request(
578 "open-ils.storage.direct.actor.user_address.delete",
580 my $status = $req->gather(1);
581 if(!defined($status)) {
582 throw OpenSRF::EX::ERROR
583 ("Unknown error updating address");
585 #warn "Delete address status is $status\n";
590 sub _add_survey_responses {
591 my ($session, $patron, $new_patron) = @_;
593 #warn "updating responses for user " . $new_patron->id . "\n";
595 my $responses = $patron->survey_responses;
599 for my $resp( @$responses ) {
600 $resp->usr($new_patron->id);
603 my $status = $apputils->simple_scalar_request(
605 "open-ils.circ.survey.submit.user_id",
614 sub _create_stat_maps {
616 my($session, $user_session, $patron, $new_patron) = @_;
618 my $maps = $patron->stat_cat_entries();
620 for my $map (@$maps) {
622 next unless($map->isnew() || $map->ischanged());
624 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
626 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
630 $map->target_usr($new_patron->id);
632 #warn "Updating stat entry with method $method and session $user_session and map $map\n";
634 my $req = $session->request($method, $map);
635 my $status = $req->gather(1);
640 throw OpenSRF::EX::ERROR
641 ("Error updating stat map with method $method");
649 sub _create_perm_maps {
651 my($session, $user_session, $patron, $new_patron) = @_;
653 my $maps = $patron->permissions;
655 for my $map (@$maps) {
657 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
658 if ($map->isdeleted()) {
659 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
660 } elsif ($map->isnew()) {
661 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
666 $map->usr($new_patron->id);
668 #warn( "Updating permissions with method $method and session $user_session and map $map" );
669 $logger->debug( "Updating permissions with method $method and session $user_session and map $map" );
671 my $req = $session->request($method, $map);
672 my $status = $req->gather(1);
677 throw OpenSRF::EX::ERROR
678 ("Error updating permission map with method $method");
687 sub _create_standing_penalties {
689 my($session, $user_session, $patron, $new_patron) = @_;
691 my $maps = $patron->standing_penalties;
694 for my $map (@$maps) {
696 if ($map->isdeleted()) {
697 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
698 } elsif ($map->isnew()) {
699 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
705 $map->usr($new_patron->id);
707 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
709 my $req = $session->request($method, $map);
710 my $status = $req->gather(1);
714 throw OpenSRF::EX::ERROR
715 ("Error updating standing penalty with method $method");
725 __PACKAGE__->register_method(
726 method => "search_username",
727 api_name => "open-ils.actor.user.search.username",
730 sub search_username {
731 my($self, $client, $username) = @_;
732 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
734 "open-ils.storage.direct.actor.user.search.usrname.atomic",
742 __PACKAGE__->register_method(
743 method => "user_retrieve_by_barcode",
744 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
746 sub user_retrieve_by_barcode {
747 my($self, $client, $user_session, $barcode) = @_;
749 $logger->debug("Searching for user with barcode $barcode");
750 #my $user_obj = $apputils->check_user_session( $user_session );
751 my ($user_obj, $evt) = $apputils->check_ses($user_session);
754 my $session = OpenSRF::AppSession->create("open-ils.storage");
756 # find the card with the given barcode
757 my $creq = $session->request(
758 "open-ils.storage.direct.actor.card.search.barcode.atomic",
760 my $card = $creq->gather(1);
762 if(!$card || !$card->[0]) {
763 $session->disconnect();
764 return OpenILS::Event->new( 'USER_NOT_FOUND' );
768 my $user = flesh_user($card->usr(), $session);
769 $session->disconnect();
770 if(!$user) { return OpenILS::Event->new( 'USER_NOT_FOUND' ); }
777 __PACKAGE__->register_method(
778 method => "get_user_by_id",
779 api_name => "open-ils.actor.user.retrieve",);
782 my ($self, $client, $user_session, $id) = @_;
784 my $user_obj = $apputils->check_user_session( $user_session );
786 return $apputils->simple_scalar_request(
788 "open-ils.storage.direct.actor.user.retrieve",
794 __PACKAGE__->register_method(
795 method => "get_org_types",
796 api_name => "open-ils.actor.org_types.retrieve",);
800 my($self, $client) = @_;
802 return $org_types if $org_types;
804 $apputils->simple_scalar_request(
806 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
811 __PACKAGE__->register_method(
812 method => "get_user_profiles",
813 api_name => "open-ils.actor.user.profiles.retrieve",
817 sub get_user_profiles {
818 return $user_profiles if $user_profiles;
820 return $user_profiles =
821 $apputils->simple_scalar_request(
823 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
828 __PACKAGE__->register_method(
829 method => "get_user_ident_types",
830 api_name => "open-ils.actor.user.ident_types.retrieve",
833 sub get_user_ident_types {
834 return $ident_types if $ident_types;
835 return $ident_types =
836 $apputils->simple_scalar_request(
838 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
844 __PACKAGE__->register_method(
845 method => "get_org_unit",
846 api_name => "open-ils.actor.org_unit.retrieve",
851 my( $self, $client, $user_session, $org_id ) = @_;
853 if(defined($user_session) && !defined($org_id)) {
855 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
856 if(!defined($org_id)) {
857 $org_id = $user_obj->home_ou;
862 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
864 "open-ils.storage.direct.actor.org_unit.retrieve",
873 __PACKAGE__->register_method(
874 method => "get_org_tree",
875 api_name => "open-ils.actor.org_tree.retrieve",
877 note => "Returns the entire org tree structure",
881 my( $self, $client) = @_;
884 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
886 # see if it's in the cache
887 #warn "Getting ORG Tree\n";
888 my $tree = $cache_client->get_cache('orgtree');
890 #warn "Found orgtree in cache. returning...\n";
894 my $orglist = $apputils->simple_scalar_request(
896 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
899 #warn "found org list\n";
902 $tree = $self->build_org_tree($orglist);
903 $cache_client->put_cache('orgtree', $tree);
909 # turns an org list into an org tree
912 my( $self, $orglist) = @_;
914 return $orglist unless (
915 ref($orglist) and @$orglist > 1 );
918 $a->ou_type <=> $b->ou_type ||
919 $a->name cmp $b->name } @$orglist;
921 for my $org (@list) {
923 next unless ($org and defined($org->parent_ou));
924 my ($parent) = grep { $_->id == $org->parent_ou } @list;
927 $parent->children([]) unless defined($parent->children);
928 push( @{$parent->children}, $org );
936 __PACKAGE__->register_method(
937 method => "get_org_descendants",
938 api_name => "open-ils.actor.org_tree.descendants.retrieve"
941 # depth is optional. org_unit is the id
942 sub get_org_descendants {
943 my( $self, $client, $org_unit, $depth ) = @_;
944 my $orglist = $apputils->simple_scalar_request(
946 "open-ils.storage.actor.org_unit.descendants.atomic",
948 return $self->build_org_tree($orglist);
952 __PACKAGE__->register_method(
953 method => "get_org_ancestors",
954 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
957 # depth is optional. org_unit is the id
958 sub get_org_ancestors {
959 my( $self, $client, $org_unit, $depth ) = @_;
960 my $orglist = $apputils->simple_scalar_request(
962 "open-ils.storage.actor.org_unit.ancestors.atomic",
964 return $self->build_org_tree($orglist);
968 __PACKAGE__->register_method(
969 method => "get_standings",
970 api_name => "open-ils.actor.standings.retrieve"
975 return $user_standings if $user_standings;
976 return $user_standings =
977 $apputils->simple_scalar_request(
979 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
984 __PACKAGE__->register_method(
985 method => "get_my_org_path",
986 api_name => "open-ils.actor.org_unit.full_path.retrieve"
989 sub get_my_org_path {
990 my( $self, $client, $user_session, $org_id ) = @_;
991 my $user_obj = $apputils->check_user_session($user_session);
992 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
994 return $apputils->simple_scalar_request(
996 "open-ils.storage.actor.org_unit.full_path.atomic",
1001 __PACKAGE__->register_method(
1002 method => "patron_adv_search",
1003 api_name => "open-ils.actor.patron.search.advanced" );
1005 sub patron_adv_search {
1006 my( $self, $client, $staff_login, $search_hash ) = @_;
1009 #warn "patron adv with $staff_login and search " .
1010 #Dumper($search_hash) . "\n";
1012 my $session = OpenSRF::AppSession->create("open-ils.storage");
1013 my $req = $session->request(
1014 "open-ils.storage.actor.user.crazy_search", $search_hash);
1016 my $ans = $req->gather(1);
1018 my %hash = map { ($_ =>1) } @$ans;
1019 $ans = [ keys %hash ];
1021 #warn "Returning @$ans\n";
1023 $session->disconnect();
1030 sub _verify_password {
1031 my($user_session, $password) = @_;
1032 my $user_obj = $apputils->check_user_session($user_session);
1034 #grab the user with password
1035 $user_obj = $apputils->simple_scalar_request(
1037 "open-ils.storage.direct.actor.user.retrieve",
1040 if($user_obj->passwd eq $password) {
1048 __PACKAGE__->register_method(
1049 method => "update_password",
1050 api_name => "open-ils.actor.user.password.update");
1052 __PACKAGE__->register_method(
1053 method => "update_password",
1054 api_name => "open-ils.actor.user.username.update");
1056 __PACKAGE__->register_method(
1057 method => "update_password",
1058 api_name => "open-ils.actor.user.email.update");
1060 sub update_password {
1061 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1063 #warn "Updating user with method " .$self->api_name . "\n";
1064 my $user_obj = $apputils->check_user_session($user_session);
1066 if($self->api_name =~ /password/) {
1068 #make sure they know the current password
1069 if(!_verify_password($user_session, md5_hex($current_password))) {
1070 return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
1073 $user_obj->passwd($new_value);
1075 elsif($self->api_name =~ /username/) {
1076 my $users = search_username(undef, undef, $new_value);
1077 if( $users and $users->[0] ) {
1078 return OpenILS::Event->new('USERNAME_EXISTS');
1080 $user_obj->usrname($new_value);
1083 elsif($self->api_name =~ /email/) {
1084 #warn "Updating email to $new_value\n";
1085 $user_obj->email($new_value);
1088 my $session = $apputils->start_db_session();
1089 $user_obj = _update_patron($session, $user_obj, $user_obj);
1090 $apputils->commit_db_session($session);
1092 if($user_obj) { return 1; }
1097 __PACKAGE__->register_method(
1098 method => "check_user_perms",
1099 api_name => "open-ils.actor.user.perm.check",
1100 notes => <<" NOTES");
1101 Takes a login session, user id, an org id, and an array of perm type strings. For each
1102 perm type, if the user does *not* have the given permission it is added
1103 to a list which is returned from the method. If all permissions
1104 are allowed, an empty list is returned
1105 if the logged in user does not match 'user_id', then the logged in user must
1106 have VIEW_PERMISSION priveleges.
1109 sub check_user_perms {
1110 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1112 my( $staff, $evt ) = $apputils->checkses($login_session);
1113 return $evt if $evt;
1115 if($staff->id ne $user_id) {
1116 if( my $evt = $apputils->check_perms(
1117 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1123 for my $perm (@$perm_types) {
1124 if($apputils->check_perms($user_id, $org_id, $perm)) {
1125 push @not_allowed, $perm;
1129 return \@not_allowed
1132 __PACKAGE__->register_method(
1133 method => "check_user_perms2",
1134 api_name => "open-ils.actor.user.perm.check.multi_org",
1136 Checks the permissions on a list of perms and orgs for a user
1137 @param authtoken The login session key
1138 @param user_id The id of the user to check
1139 @param orgs The array of org ids
1140 @param perms The array of permission names
1141 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1142 if the logged in user does not match 'user_id', then the logged in user must
1143 have VIEW_PERMISSION priveleges.
1146 sub check_user_perms2 {
1147 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1149 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1150 $authtoken, $user_id, 'VIEW_PERMISSION' );
1151 return $evt if $evt;
1154 for my $org (@$orgs) {
1155 for my $perm (@$perms) {
1156 if($apputils->check_perms($user_id, $org, $perm)) {
1157 push @not_allowed, [ $org, $perm ];
1162 return \@not_allowed
1166 __PACKAGE__->register_method(
1167 method => 'check_user_perms3',
1168 api_name => 'open-ils.actor.user.perm.highest_org',
1170 Returns the highest org unit id at which a user has a given permission
1171 If the requestor does not match the target user, the requestor must have
1172 'VIEW_PERMISSION' rights at the home org unit of the target user
1173 @param authtoken The login session key
1174 @param userid The id of the user in question
1175 @param perm The permission to check
1176 @return The org unit highest in the org tree within which the user has
1177 the requested permission
1180 sub check_user_perms3 {
1181 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1183 my( $staff, $target, $org, $evt );
1185 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1186 $authtoken, $userid, 'VIEW_PERMISSION' );
1187 return $evt if $evt;
1189 my $tree = $self->get_org_tree();
1190 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1194 sub _find_highest_perm_org {
1195 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1196 my $org = $apputils->find_org($org_tree, $start_org );
1200 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1202 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1208 __PACKAGE__->register_method(
1209 method => 'check_user_perms4',
1210 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1212 Returns the highest org unit id at which a user has a given permission
1213 If the requestor does not match the target user, the requestor must have
1214 'VIEW_PERMISSION' rights at the home org unit of the target user
1215 @param authtoken The login session key
1216 @param userid The id of the user in question
1217 @param perms An array of perm names to check
1218 @return An array of orgId's representing the org unit
1219 highest in the org tree within which the user has the requested permission
1220 The arrah of orgId's has matches the order of the perms array
1223 sub check_user_perms4 {
1224 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1226 my( $staff, $target, $org, $evt );
1228 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1229 $authtoken, $userid, 'VIEW_PERMISSION' );
1230 return $evt if $evt;
1233 return [] unless ref($perms);
1234 my $tree = $self->get_org_tree();
1236 for my $p (@$perms) {
1237 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1245 __PACKAGE__->register_method(
1246 method => "user_fines_summary",
1247 api_name => "open-ils.actor.user.fines.summary",
1248 notes => <<" NOTES");
1249 Returns a short summary of the users total open fines, excluding voided fines
1250 Params are login_session, user_id
1251 Returns a 'mous' object.
1254 sub user_fines_summary {
1255 my( $self, $client, $login_session, $user_id ) = @_;
1257 my $user_obj = $apputils->check_user_session($login_session);
1258 if($user_obj->id ne $user_id) {
1259 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1260 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1264 return $apputils->simple_scalar_request(
1266 "open-ils.storage.direct.money.open_user_summary.search.usr",
1274 __PACKAGE__->register_method(
1275 method => "user_transactions",
1276 api_name => "open-ils.actor.user.transactions",
1277 notes => <<" NOTES");
1278 Returns a list of open user transactions (mbts objects);
1279 Params are login_session, user_id
1280 Optional third parameter is the transactions type. defaults to all
1283 __PACKAGE__->register_method(
1284 method => "user_transactions",
1285 api_name => "open-ils.actor.user.transactions.have_charge",
1286 notes => <<" NOTES");
1287 Returns a list of all open user transactions (mbts objects) that have an initial charge
1288 Params are login_session, user_id
1289 Optional third parameter is the transactions type. defaults to all
1292 __PACKAGE__->register_method(
1293 method => "user_transactions",
1294 api_name => "open-ils.actor.user.transactions.have_balance",
1295 notes => <<" NOTES");
1296 Returns a list of all open user transactions (mbts objects) that have a balance
1297 Params are login_session, user_id
1298 Optional third parameter is the transactions type. defaults to all
1301 __PACKAGE__->register_method(
1302 method => "user_transactions",
1303 api_name => "open-ils.actor.user.transactions.fleshed",
1304 notes => <<" NOTES");
1305 Returns an object/hash of transaction, circ, title where transaction = an open
1306 user transactions (mbts objects), circ is the attached circluation, and title
1307 is the title the circ points to
1308 Params are login_session, user_id
1309 Optional third parameter is the transactions type. defaults to all
1312 __PACKAGE__->register_method(
1313 method => "user_transactions",
1314 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1315 notes => <<" NOTES");
1316 Returns an object/hash of transaction, circ, title where transaction = an open
1317 user transactions that has an initial charge (mbts objects), circ is the
1318 attached circluation, and title is the title the circ points to
1319 Params are login_session, user_id
1320 Optional third parameter is the transactions type. defaults to all
1323 __PACKAGE__->register_method(
1324 method => "user_transactions",
1325 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1326 notes => <<" NOTES");
1327 Returns an object/hash of transaction, circ, title where transaction = an open
1328 user transaction that has a balance (mbts objects), circ is the attached
1329 circluation, and title is the title the circ points to
1330 Params are login_session, user_id
1331 Optional third parameter is the transaction type. defaults to all
1336 sub user_transactions {
1337 my( $self, $client, $login_session, $user_id, $type ) = @_;
1339 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1340 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1341 return $evt if $evt;
1343 my $api = $self->api_name();
1347 if(defined($type)) { @xact = (xact_type => $type);
1349 } else { @xact = (); }
1351 if($api =~ /have_charge/) {
1353 $trans = $apputils->simple_scalar_request(
1355 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1356 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1358 } elsif($api =~ /have_balance/) {
1360 $trans = $apputils->simple_scalar_request(
1362 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1363 { usr => $user_id, balance_owed => { ">" => 0 }, @xact });
1367 $trans = $apputils->simple_scalar_request(
1369 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1370 { usr => $user_id, @xact });
1373 if($api !~ /fleshed/) { return $trans; }
1375 #warn "API: $api\n";
1378 for my $t (@$trans) {
1380 #warn $t->id . "\n";
1382 my $circ = $apputils->simple_scalar_request(
1384 "open-ils.storage.direct.action.circulation.retrieve",
1389 my $title = $apputils->simple_scalar_request(
1391 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1392 $circ->target_copy );
1396 my $u = OpenILS::Utils::ModsParser->new();
1397 $u->start_mods_batch($title->marc());
1398 my $mods = $u->finish_mods_batch();
1400 push @resp, {transaction => $t, circ => $circ, record => $mods };
1410 __PACKAGE__->register_method(
1411 method => "user_perms",
1412 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1414 notes => <<" NOTES");
1415 Returns a list of permissions
1418 my( $self, $client, $authtoken, $user ) = @_;
1420 my( $staff, $evt ) = $apputils->checkses($authtoken);
1421 return $evt if $evt;
1423 $user ||= $staff->id;
1425 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1429 return $apputils->simple_scalar_request(
1431 "open-ils.storage.permission.user_perms.atomic",
1435 __PACKAGE__->register_method(
1436 method => "retrieve_perms",
1437 api_name => "open-ils.actor.permissions.retrieve",
1438 notes => <<" NOTES");
1439 Returns a list of permissions
1441 sub retrieve_perms {
1442 my( $self, $client ) = @_;
1443 return $apputils->simple_scalar_request(
1445 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1448 __PACKAGE__->register_method(
1449 method => "retrieve_groups",
1450 api_name => "open-ils.actor.groups.retrieve",
1451 notes => <<" NOTES");
1452 Returns a list of user groupss
1454 sub retrieve_groups {
1455 my( $self, $client ) = @_;
1456 return $apputils->simple_scalar_request(
1458 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1461 __PACKAGE__->register_method(
1462 method => "retrieve_groups_tree",
1463 api_name => "open-ils.actor.groups.tree.retrieve",
1464 notes => <<" NOTES");
1465 Returns a list of user groups
1467 sub retrieve_groups_tree {
1468 my( $self, $client ) = @_;
1469 my $groups = $apputils->simple_scalar_request(
1471 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1472 return $self->build_group_tree($groups);
1476 # turns an org list into an org tree
1477 sub build_group_tree {
1479 my( $self, $grplist) = @_;
1481 return $grplist unless (
1482 ref($grplist) and @$grplist > 1 );
1484 my @list = sort { $a->name cmp $b->name } @$grplist;
1487 for my $grp (@list) {
1489 if ($grp and !defined($grp->parent)) {
1493 my ($parent) = grep { $_->id == $grp->parent} @list;
1495 $parent->children([]) unless defined($parent->children);
1496 push( @{$parent->children}, $grp );
1504 __PACKAGE__->register_method(
1505 method => "add_user_to_groups",
1506 api_name => "open-ils.actor.user.set_groups",
1507 notes => <<" NOTES");
1508 Adds a user to one or more permission groups
1511 sub add_user_to_groups {
1512 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1514 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1515 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1516 return $evt if $evt;
1518 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1519 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1520 return $evt if $evt;
1522 $apputils->simplereq(
1524 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1526 for my $group (@$groups) {
1527 my $link = Fieldmapper::permission::usr_grp_map->new;
1529 $link->usr($userid);
1531 my $id = $apputils->simplereq(
1533 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1539 __PACKAGE__->register_method(
1540 method => "get_user_perm_groups",
1541 api_name => "open-ils.actor.user.get_groups",
1542 notes => <<" NOTES");
1543 Retrieve a user's permission groups.
1547 sub get_user_perm_groups {
1548 my( $self, $client, $authtoken, $userid ) = @_;
1550 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1551 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1552 return $evt if $evt;
1554 return $apputils->simplereq(
1556 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );