1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
5 $Data::Dumper::Indent = 0;
8 use Digest::MD5 qw(md5_hex);
10 use OpenSRF::EX qw(:try);
14 use OpenILS::Application::AppUtils;
15 use OpenILS::Utils::Fieldmapper;
16 use OpenILS::Application::Search::Actor;
17 use OpenILS::Utils::ModsParser;
18 use OpenSRF::Utils::Logger qw/$logger/;
20 use OpenSRF::Utils::Cache;
23 use OpenILS::Application::Actor::Container;
25 OpenILS::Application::Actor::Container->initialize();
28 my $apputils = "OpenILS::Application::AppUtils";
31 sub _d { warn "Patron:\n" . Dumper(shift()); }
36 my $set_user_settings;
39 __PACKAGE__->register_method(
40 method => "set_user_settings",
41 api_name => "open-ils.actor.patron.settings.update",
43 sub set_user_settings {
44 my( $self, $client, $user_session, $uid, $settings ) = @_;
46 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
48 my( $staff, $user, $evt ) =
49 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
54 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
56 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper($params));
58 return $apputils->simplereq(
60 'open-ils.storage.direct.actor.user_setting.batch.merge', $params );
66 __PACKAGE__->register_method(
67 method => "set_ou_settings",
68 api_name => "open-ils.actor.org_unit.settings.update",
71 my( $self, $client, $user_session, $ouid, $settings ) = @_;
73 my( $staff, $evt ) = $apputils->checkses( $user_session );
75 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
80 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
82 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
84 return $apputils->simplereq(
86 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
90 my $fetch_user_settings;
91 my $fetch_ou_settings;
93 __PACKAGE__->register_method(
94 method => "user_settings",
95 api_name => "open-ils.actor.patron.settings.retrieve",
98 my( $self, $client, $user_session, $uid ) = @_;
100 my( $staff, $user, $evt ) =
101 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
104 $logger->debug("User " . $staff->id . " fetching user $uid\n");
105 my $s = $apputils->simplereq(
107 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
109 return { map { ($_->name,$_->value) } @$s };
114 __PACKAGE__->register_method(
115 method => "ou_settings",
116 api_name => "open-ils.actor.org_unit.settings.retrieve",
119 my( $self, $client, $ouid ) = @_;
121 my $s = $apputils->simplereq(
123 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
125 return { map { ($_->name,$_->value) } @$s };
130 __PACKAGE__->register_method(
131 method => "update_patron",
132 api_name => "open-ils.actor.patron.update",);
135 my( $self, $client, $user_session, $patron ) = @_;
137 my $session = $apputils->start_db_session();
140 $logger->debug("Updating Patron: " . Dumper($patron));
142 #warn $user_session . " " . $patron . "\n";
146 OpenILS::Application::AppUtils->check_user_session(
147 $user_session ); #throws EX on error
149 # XXX does this user have permission to add/create users. Granularity?
150 # $new_patron is the patron in progress. $patron is the original patron
151 # passed in with the method. new_patron will change as the components
152 # of patron are added/updated.
156 if(ref($patron->card)) { $patron->card( $patron->card->id ); }
157 if(ref($patron->billing_address)) { $patron->billing_address( $patron->billing_address->id ); }
158 if(ref($patron->mailing_address)) { $patron->mailing_address( $patron->mailing_address->id ); }
160 # create/update the patron first so we can use his id
161 if($patron->isnew()) {
163 $new_patron = _add_patron($session, _clone_patron($patron), $user_obj);
165 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
166 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
167 $client->respond_complete($new_patron->ex);
171 } else { $new_patron = $patron; }
173 $new_patron = _add_update_addresses($session, $patron, $new_patron, $user_obj);
175 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
176 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
177 $client->respond_complete($new_patron->ex);
181 $new_patron = _add_update_cards($session, $patron, $new_patron, $user_obj);
183 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
184 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
185 $client->respond_complete($new_patron->ex);
189 $new_patron = _add_survey_responses($session, $patron, $new_patron, $user_obj);
190 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
191 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
192 $client->respond_complete($new_patron->ex);
197 # re-update the patron if anything has happened to him during this process
198 if($new_patron->ischanged()) {
199 $new_patron = _update_patron($session, $new_patron, $user_obj);
201 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
202 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
203 $client->respond_complete($new_patron->ex);
208 $session = OpenSRF::AppSession->create("open-ils.storage");
209 $new_patron = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
210 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
211 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
212 $client->respond_complete($new_patron->ex);
216 $new_patron = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
217 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
218 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
219 $client->respond_complete($new_patron->ex);
223 $new_patron = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
224 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") ||
225 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
226 $client->respond_complete($new_patron->ex);
230 $apputils->commit_db_session($session);
232 #warn "Patron Update/Create complete\n";
233 return flesh_user($new_patron->id());
239 __PACKAGE__->register_method(
240 method => "user_retrieve_fleshed_by_id",
241 api_name => "open-ils.actor.user.fleshed.retrieve",);
243 sub user_retrieve_fleshed_by_id {
244 my( $self, $client, $user_session, $user_id ) = @_;
246 my( $requestor, $target, $evt ) = $apputils->
247 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
250 return flesh_user($user_id);
261 $session = OpenSRF::AppSession->create("open-ils.storage");
265 # grab the user with the given id
266 my $ureq = $session->request(
267 "open-ils.storage.direct.actor.user.retrieve", $id);
268 my $user = $ureq->gather(1);
270 if(!$user) { return undef; }
273 my $cards_req = $session->request(
274 "open-ils.storage.direct.actor.card.search.usr.atomic",
276 $user->cards( $cards_req->gather(1) );
278 for my $c(@{$user->cards}) {
279 if($c->id == $user->card || $c->id eq $user->card ) {
280 #warn "Setting my card to " . $c->id . "\n";
285 my $add_req = $session->request(
286 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
288 $user->addresses( $add_req->gather(1) );
290 for my $c(@{$user->addresses}) {
291 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
292 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
295 my $stat_req = $session->request(
296 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
298 $user->stat_cat_entries($stat_req->gather(1));
300 my $standing_penalties_req = $session->request(
301 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
303 $user->standing_penalties($standing_penalties_req->gather(1));
305 if($kill) { $session->disconnect(); }
306 $user->clear_passwd();
312 # clone and clear stuff that would break the database
316 my $new_patron = $patron->clone;
318 # Using the Fieldmapper clone method
319 #my $new_patron = Fieldmapper::actor::user->new();
321 #my $fmap = $Fieldmapper::fieldmap;
322 #no strict; # shallow clone, may be useful in the fieldmapper
324 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
325 # $new_patron->$field( $patron->$field() );
330 $new_patron->clear_billing_address();
331 $new_patron->clear_mailing_address();
332 $new_patron->clear_addresses();
333 $new_patron->clear_card();
334 $new_patron->clear_cards();
335 $new_patron->clear_id();
336 $new_patron->clear_isnew();
337 $new_patron->clear_ischanged();
338 $new_patron->clear_isdeleted();
339 $new_patron->clear_stat_cat_entries();
340 $new_patron->clear_permissions();
341 $new_patron->clear_standing_penalties();
350 my $user_obj = shift;
353 if($apputils->check_user_perms(
354 $user_obj->id, $user_obj->home_ou, "CREATE_USER")) {
355 return OpenILS::Perm->new("CREATE_USER");
358 #warn "Creating new patron\n";
361 my $req = $session->request(
362 "open-ils.storage.direct.actor.user.create",$patron);
363 my $id = $req->gather(1);
365 return OpenILS::EX->new("DUPLICATE_USER_USERNAME");
368 # retrieve the patron from the db to collect defaults
369 my $ureq = $session->request(
370 "open-ils.storage.direct.actor.user.retrieve",
373 #warn "Created new patron with id $id\n";
375 return $ureq->gather(1);
380 my( $session, $patron, $user_obj) = @_;
383 if($patron->id ne $user_obj->id) {
384 if($apputils->check_user_perms(
385 $user_obj->id, $user_obj->home_ou, "UPDATE_USER")) {
386 return OpenILS::Perm->new("UPDATE_USER");
390 #warn "updating patron " . Dumper($patron) . "\n";
392 my $req = $session->request(
393 "open-ils.storage.direct.actor.user.update",$patron );
394 my $status = $req->gather(1);
395 if(!defined($status)) {
396 throw OpenSRF::EX::ERROR
397 ("Unknown error updating patron");
403 sub _add_update_addresses {
406 my $new_patron = shift;
408 my $current_id; # id of the address before creation
410 for my $address (@{$patron->addresses()}) {
412 $address->usr($new_patron->id());
414 if(ref($address) and $address->isnew()) {
415 #warn "Adding new address at street " . $address->street1() . "\n";
417 $current_id = $address->id();
418 $address = _add_address($session,$address);
420 if( $patron->billing_address() and
421 $patron->billing_address() == $current_id ) {
422 $new_patron->billing_address($address->id());
423 $new_patron->ischanged(1);
426 if( $patron->mailing_address() and
427 $patron->mailing_address() == $current_id ) {
428 $new_patron->mailing_address($address->id());
429 $new_patron->ischanged(1);
432 } elsif( ref($address) and $address->ischanged() ) {
433 #warn "Updating address at street " . $address->street1();
434 $address->usr($new_patron->id());
435 _update_address($session,$address);
437 } elsif( ref($address) and $address->isdeleted() ) {
438 #warn "Deleting address at street " . $address->street1();
440 if( $address->id() == $new_patron->mailing_address() ) {
441 $new_patron->clear_mailing_address();
442 _update_patron($session, $new_patron);
445 if( $address->id() == $new_patron->billing_address() ) {
446 $new_patron->clear_billing_address();
447 _update_patron($session, $new_patron);
450 _delete_address($session,$address);
458 # adds an address to the db and returns the address with new id
460 my($session, $address) = @_;
461 $address->clear_id();
464 #warn "Adding Address:\n";
465 #warn Dumper($address);
467 # put the address into the database
468 my $req = $session->request(
469 "open-ils.storage.direct.actor.user_address.create",
473 my $id = $req->gather(1);
475 throw OpenSRF::EX::ERROR
476 ("Unable to create new user address");
479 #warn "Created address with id $id\n";
481 # update all the necessary id's
487 sub _update_address {
488 my( $session, $address ) = @_;
489 my $req = $session->request(
490 "open-ils.storage.direct.actor.user_address.update",
492 my $status = $req->gather(1);
493 if(!defined($status)) {
494 throw OpenSRF::EX::ERROR
495 ("Unknown error updating address");
502 sub _add_update_cards {
506 my $new_patron = shift;
508 my $virtual_id; #id of the card before creation
509 for my $card (@{$patron->cards()}) {
511 $card->usr($new_patron->id());
513 if(ref($card) and $card->isnew()) {
515 $virtual_id = $card->id();
516 $card = _add_card($session,$card);
517 if(UNIVERSAL::isa($card,"OpenILS::EX")) {
521 #if(ref($patron->card)) { $patron->card($patron->card->id); }
522 if($patron->card() == $virtual_id) {
523 $new_patron->card($card->id());
524 $new_patron->ischanged(1);
527 } elsif( ref($card) and $card->ischanged() ) {
528 $card->usr($new_patron->id());
529 _update_card($session, $card);
536 # adds an card to the db and returns the card with new id
538 my( $session, $card ) = @_;
541 #warn "Adding card with barcode " . $card->barcode() . "\n";
542 my $req = $session->request(
543 "open-ils.storage.direct.actor.card.create",
546 my $id = $req->gather(1);
548 return OpenILS::EX->new("DUPLICATE_INVALID_USER_BARCODE");
552 #warn "Created patron card with id $id\n";
558 my( $session, $card ) = @_;
561 my $req = $session->request(
562 "open-ils.storage.direct.actor.card.update",
564 my $status = $req->gather(1);
565 if(!defined($status)) {
566 throw OpenSRF::EX::ERROR
567 ("Unknown error updating card");
575 sub _delete_address {
576 my( $session, $address ) = @_;
578 #warn "Deleting address " . $address->street1() . "\n";
580 my $req = $session->request(
581 "open-ils.storage.direct.actor.user_address.delete",
583 my $status = $req->gather(1);
584 if(!defined($status)) {
585 throw OpenSRF::EX::ERROR
586 ("Unknown error updating address");
588 #warn "Delete address status is $status\n";
593 sub _add_survey_responses {
594 my ($session, $patron, $new_patron) = @_;
596 #warn "updating responses for user " . $new_patron->id . "\n";
598 my $responses = $patron->survey_responses;
602 for my $resp( @$responses ) {
603 $resp->usr($new_patron->id);
606 my $status = $apputils->simple_scalar_request(
608 "open-ils.circ.survey.submit.user_id",
617 sub _create_stat_maps {
619 my($session, $user_session, $patron, $new_patron) = @_;
621 my $maps = $patron->stat_cat_entries();
623 for my $map (@$maps) {
625 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
626 if ($map->isdeleted()) {
627 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
628 } elsif ($map->isnew()) {
629 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
634 $map->target_usr($new_patron->id);
636 #warn "Updating stat entry with method $method and session $user_session and map $map\n";
638 my $req = $session->request($method, $map);
639 my $status = $req->gather(1);
641 #if(!$map->ischanged && !$status) {
642 # throw OpenSRF::EX::ERROR
643 # ("Error handling stat_cat map with method $method");
650 sub _create_perm_maps {
652 my($session, $user_session, $patron, $new_patron) = @_;
654 my $maps = $patron->permissions;
656 for my $map (@$maps) {
658 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
659 if ($map->isdeleted()) {
660 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
661 } elsif ($map->isnew()) {
662 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
667 $map->usr($new_patron->id);
669 #warn( "Updating permissions with method $method and session $user_session and map $map" );
670 $logger->debug( "Updating permissions with method $method and session $user_session and map $map" );
672 my $req = $session->request($method, $map);
673 my $status = $req->gather(1);
675 if($map->isnew and !$status) {
676 throw OpenSRF::EX::ERROR
677 ("Error creating permission map with method $method");
686 sub _create_standing_penalties {
688 my($session, $user_session, $patron, $new_patron) = @_;
690 my $maps = $patron->standing_penalties;
693 for my $map (@$maps) {
695 if ($map->isdeleted()) {
696 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
697 } elsif ($map->isnew()) {
698 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
704 $map->usr($new_patron->id);
706 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
708 my $req = $session->request($method, $map);
709 my $status = $req->gather(1);
713 throw OpenSRF::EX::ERROR
714 ("Error updating standing penalty with method $method");
724 __PACKAGE__->register_method(
725 method => "search_username",
726 api_name => "open-ils.actor.user.search.username",
729 sub search_username {
730 my($self, $client, $username) = @_;
731 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
733 "open-ils.storage.direct.actor.user.search.usrname.atomic",
741 __PACKAGE__->register_method(
742 method => "user_retrieve_by_barcode",
743 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
745 sub user_retrieve_by_barcode {
746 my($self, $client, $user_session, $barcode) = @_;
748 $logger->debug("Searching for user with barcode $barcode");
749 my ($user_obj, $evt) = $apputils->checkses($user_session);
752 my $session = OpenSRF::AppSession->create("open-ils.storage");
754 # find the card with the given barcode
755 my $creq = $session->request(
756 "open-ils.storage.direct.actor.card.search.barcode.atomic",
758 my $card = $creq->gather(1);
760 if(!$card || !$card->[0]) {
761 $session->disconnect();
762 return OpenILS::Event->new( 'USER_NOT_FOUND' );
766 my $user = flesh_user($card->usr(), $session);
767 $session->disconnect();
768 if(!$user) { return OpenILS::Event->new( 'USER_NOT_FOUND' ); }
775 __PACKAGE__->register_method(
776 method => "get_user_by_id",
777 api_name => "open-ils.actor.user.retrieve",);
780 my ($self, $client, $user_session, $id) = @_;
782 my $user_obj = $apputils->check_user_session( $user_session );
784 return $apputils->simple_scalar_request(
786 "open-ils.storage.direct.actor.user.retrieve",
792 __PACKAGE__->register_method(
793 method => "get_org_types",
794 api_name => "open-ils.actor.org_types.retrieve",);
798 my($self, $client) = @_;
800 return $org_types if $org_types;
802 $apputils->simple_scalar_request(
804 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
809 __PACKAGE__->register_method(
810 method => "get_user_profiles",
811 api_name => "open-ils.actor.user.profiles.retrieve",
815 sub get_user_profiles {
816 return $user_profiles if $user_profiles;
818 return $user_profiles =
819 $apputils->simple_scalar_request(
821 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
826 __PACKAGE__->register_method(
827 method => "get_user_ident_types",
828 api_name => "open-ils.actor.user.ident_types.retrieve",
831 sub get_user_ident_types {
832 return $ident_types if $ident_types;
833 return $ident_types =
834 $apputils->simple_scalar_request(
836 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
842 __PACKAGE__->register_method(
843 method => "get_org_unit",
844 api_name => "open-ils.actor.org_unit.retrieve",
849 my( $self, $client, $user_session, $org_id ) = @_;
851 if(defined($user_session) && !defined($org_id)) {
853 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
854 if(!defined($org_id)) {
855 $org_id = $user_obj->home_ou;
860 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
862 "open-ils.storage.direct.actor.org_unit.retrieve",
871 __PACKAGE__->register_method(
872 method => "get_org_tree",
873 api_name => "open-ils.actor.org_tree.retrieve",
875 note => "Returns the entire org tree structure",
879 my( $self, $client) = @_;
882 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
884 # see if it's in the cache
885 #warn "Getting ORG Tree\n";
886 my $tree = $cache_client->get_cache('orgtree');
888 #warn "Found orgtree in cache. returning...\n";
892 my $orglist = $apputils->simple_scalar_request(
894 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
897 #warn "found org list\n";
900 $tree = $self->build_org_tree($orglist);
901 $cache_client->put_cache('orgtree', $tree);
907 # turns an org list into an org tree
910 my( $self, $orglist) = @_;
912 return $orglist unless (
913 ref($orglist) and @$orglist > 1 );
916 $a->ou_type <=> $b->ou_type ||
917 $a->name cmp $b->name } @$orglist;
919 for my $org (@list) {
921 next unless ($org and defined($org->parent_ou));
922 my ($parent) = grep { $_->id == $org->parent_ou } @list;
925 $parent->children([]) unless defined($parent->children);
926 push( @{$parent->children}, $org );
934 __PACKAGE__->register_method(
935 method => "get_org_descendants",
936 api_name => "open-ils.actor.org_tree.descendants.retrieve"
939 # depth is optional. org_unit is the id
940 sub get_org_descendants {
941 my( $self, $client, $org_unit, $depth ) = @_;
942 my $orglist = $apputils->simple_scalar_request(
944 "open-ils.storage.actor.org_unit.descendants.atomic",
946 return $self->build_org_tree($orglist);
950 __PACKAGE__->register_method(
951 method => "get_org_ancestors",
952 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
955 # depth is optional. org_unit is the id
956 sub get_org_ancestors {
957 my( $self, $client, $org_unit, $depth ) = @_;
958 my $orglist = $apputils->simple_scalar_request(
960 "open-ils.storage.actor.org_unit.ancestors.atomic",
962 return $self->build_org_tree($orglist);
966 __PACKAGE__->register_method(
967 method => "get_standings",
968 api_name => "open-ils.actor.standings.retrieve"
973 return $user_standings if $user_standings;
974 return $user_standings =
975 $apputils->simple_scalar_request(
977 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
982 __PACKAGE__->register_method(
983 method => "get_my_org_path",
984 api_name => "open-ils.actor.org_unit.full_path.retrieve"
987 sub get_my_org_path {
988 my( $self, $client, $user_session, $org_id ) = @_;
989 my $user_obj = $apputils->check_user_session($user_session);
990 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
992 return $apputils->simple_scalar_request(
994 "open-ils.storage.actor.org_unit.full_path.atomic",
999 __PACKAGE__->register_method(
1000 method => "patron_adv_search",
1001 api_name => "open-ils.actor.patron.search.advanced" );
1003 sub patron_adv_search {
1004 my( $self, $client, $staff_login, $search_hash ) = @_;
1006 #warn "patron adv with $staff_login and search " .
1007 #Dumper($search_hash) . "\n";
1009 my $session = OpenSRF::AppSession->create("open-ils.storage");
1010 my $req = $session->request(
1011 "open-ils.storage.actor.user.crazy_search", $search_hash);
1013 my $ans = $req->gather(1);
1015 my %hash = map { ($_ =>1) } @$ans;
1016 $ans = [ keys %hash ];
1018 #warn "Returning @$ans\n";
1020 $session->disconnect();
1027 sub _verify_password {
1028 my($user_session, $password) = @_;
1029 my $user_obj = $apputils->check_user_session($user_session);
1031 #grab the user with password
1032 $user_obj = $apputils->simple_scalar_request(
1034 "open-ils.storage.direct.actor.user.retrieve",
1037 if($user_obj->passwd eq $password) {
1045 __PACKAGE__->register_method(
1046 method => "update_password",
1047 api_name => "open-ils.actor.user.password.update");
1049 __PACKAGE__->register_method(
1050 method => "update_password",
1051 api_name => "open-ils.actor.user.username.update");
1053 __PACKAGE__->register_method(
1054 method => "update_password",
1055 api_name => "open-ils.actor.user.email.update");
1057 sub update_password {
1058 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1060 #warn "Updating user with method " .$self->api_name . "\n";
1061 my $user_obj = $apputils->check_user_session($user_session);
1063 if($self->api_name =~ /password/) {
1065 #make sure they know the current password
1066 if(!_verify_password($user_session, md5_hex($current_password))) {
1067 return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
1070 $user_obj->passwd($new_value);
1072 elsif($self->api_name =~ /username/) {
1073 my $users = search_username(undef, undef, $new_value);
1074 if( $users and $users->[0] ) {
1075 return OpenILS::Event->new('USERNAME_EXISTS');
1077 $user_obj->usrname($new_value);
1080 elsif($self->api_name =~ /email/) {
1081 #warn "Updating email to $new_value\n";
1082 $user_obj->email($new_value);
1085 my $session = $apputils->start_db_session();
1086 $user_obj = _update_patron($session, $user_obj, $user_obj);
1087 $apputils->commit_db_session($session);
1089 if($user_obj) { return 1; }
1094 __PACKAGE__->register_method(
1095 method => "check_user_perms",
1096 api_name => "open-ils.actor.user.perm.check",
1097 notes => <<" NOTES");
1098 Takes a login session, user id, an org id, and an array of perm type strings. For each
1099 perm type, if the user does *not* have the given permission it is added
1100 to a list which is returned from the method. If all permissions
1101 are allowed, an empty list is returned
1102 if the logged in user does not match 'user_id', then the logged in user must
1103 have VIEW_PERMISSION priveleges.
1106 sub check_user_perms {
1107 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1109 my( $staff, $evt ) = $apputils->checkses($login_session);
1110 return $evt if $evt;
1112 if($staff->id ne $user_id) {
1113 if( my $evt = $apputils->check_perms(
1114 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1120 for my $perm (@$perm_types) {
1121 if($apputils->check_perms($user_id, $org_id, $perm)) {
1122 push @not_allowed, $perm;
1126 return \@not_allowed
1129 __PACKAGE__->register_method(
1130 method => "check_user_perms2",
1131 api_name => "open-ils.actor.user.perm.check.multi_org",
1133 Checks the permissions on a list of perms and orgs for a user
1134 @param authtoken The login session key
1135 @param user_id The id of the user to check
1136 @param orgs The array of org ids
1137 @param perms The array of permission names
1138 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1139 if the logged in user does not match 'user_id', then the logged in user must
1140 have VIEW_PERMISSION priveleges.
1143 sub check_user_perms2 {
1144 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1146 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1147 $authtoken, $user_id, 'VIEW_PERMISSION' );
1148 return $evt if $evt;
1151 for my $org (@$orgs) {
1152 for my $perm (@$perms) {
1153 if($apputils->check_perms($user_id, $org, $perm)) {
1154 push @not_allowed, [ $org, $perm ];
1159 return \@not_allowed
1163 __PACKAGE__->register_method(
1164 method => 'check_user_perms3',
1165 api_name => 'open-ils.actor.user.perm.highest_org',
1167 Returns the highest org unit id at which a user has a given permission
1168 If the requestor does not match the target user, the requestor must have
1169 'VIEW_PERMISSION' rights at the home org unit of the target user
1170 @param authtoken The login session key
1171 @param userid The id of the user in question
1172 @param perm The permission to check
1173 @return The org unit highest in the org tree within which the user has
1174 the requested permission
1177 sub check_user_perms3 {
1178 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1180 my( $staff, $target, $org, $evt );
1182 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1183 $authtoken, $userid, 'VIEW_PERMISSION' );
1184 return $evt if $evt;
1186 my $tree = $self->get_org_tree();
1187 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1191 sub _find_highest_perm_org {
1192 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1193 my $org = $apputils->find_org($org_tree, $start_org );
1197 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1199 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1205 __PACKAGE__->register_method(
1206 method => 'check_user_perms4',
1207 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1209 Returns the highest org unit id at which a user has a given permission
1210 If the requestor does not match the target user, the requestor must have
1211 'VIEW_PERMISSION' rights at the home org unit of the target user
1212 @param authtoken The login session key
1213 @param userid The id of the user in question
1214 @param perms An array of perm names to check
1215 @return An array of orgId's representing the org unit
1216 highest in the org tree within which the user has the requested permission
1217 The arrah of orgId's has matches the order of the perms array
1220 sub check_user_perms4 {
1221 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1223 my( $staff, $target, $org, $evt );
1225 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1226 $authtoken, $userid, 'VIEW_PERMISSION' );
1227 return $evt if $evt;
1230 return [] unless ref($perms);
1231 my $tree = $self->get_org_tree();
1233 for my $p (@$perms) {
1234 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1242 __PACKAGE__->register_method(
1243 method => "user_fines_summary",
1244 api_name => "open-ils.actor.user.fines.summary",
1245 notes => <<" NOTES");
1246 Returns a short summary of the users total open fines, excluding voided fines
1247 Params are login_session, user_id
1248 Returns a 'mous' object.
1251 sub user_fines_summary {
1252 my( $self, $client, $login_session, $user_id ) = @_;
1254 my $user_obj = $apputils->check_user_session($login_session);
1255 if($user_obj->id ne $user_id) {
1256 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1257 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1261 return $apputils->simple_scalar_request(
1263 "open-ils.storage.direct.money.open_user_summary.search.usr",
1271 __PACKAGE__->register_method(
1272 method => "user_transactions",
1273 api_name => "open-ils.actor.user.transactions",
1274 notes => <<" NOTES");
1275 Returns a list of open user transactions (mbts objects);
1276 Params are login_session, user_id
1277 Optional third parameter is the transactions type. defaults to all
1280 __PACKAGE__->register_method(
1281 method => "user_transactions",
1282 api_name => "open-ils.actor.user.transactions.have_charge",
1283 notes => <<" NOTES");
1284 Returns a list of all open user transactions (mbts objects) that have an initial charge
1285 Params are login_session, user_id
1286 Optional third parameter is the transactions type. defaults to all
1289 __PACKAGE__->register_method(
1290 method => "user_transactions",
1291 api_name => "open-ils.actor.user.transactions.have_balance",
1292 notes => <<" NOTES");
1293 Returns a list of all open user transactions (mbts objects) that have a balance
1294 Params are login_session, user_id
1295 Optional third parameter is the transactions type. defaults to all
1298 __PACKAGE__->register_method(
1299 method => "user_transactions",
1300 api_name => "open-ils.actor.user.transactions.fleshed",
1301 notes => <<" NOTES");
1302 Returns an object/hash of transaction, circ, title where transaction = an open
1303 user transactions (mbts objects), circ is the attached circluation, and title
1304 is the title the circ points to
1305 Params are login_session, user_id
1306 Optional third parameter is the transactions type. defaults to all
1309 __PACKAGE__->register_method(
1310 method => "user_transactions",
1311 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1312 notes => <<" NOTES");
1313 Returns an object/hash of transaction, circ, title where transaction = an open
1314 user transactions that has an initial charge (mbts objects), circ is the
1315 attached circluation, and title is the title the circ points to
1316 Params are login_session, user_id
1317 Optional third parameter is the transactions type. defaults to all
1320 __PACKAGE__->register_method(
1321 method => "user_transactions",
1322 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1323 notes => <<" NOTES");
1324 Returns an object/hash of transaction, circ, title where transaction = an open
1325 user transaction that has a balance (mbts objects), circ is the attached
1326 circluation, and title is the title the circ points to
1327 Params are login_session, user_id
1328 Optional third parameter is the transaction type. defaults to all
1333 sub user_transactions {
1334 my( $self, $client, $login_session, $user_id, $type ) = @_;
1336 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1337 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1338 return $evt if $evt;
1340 my $api = $self->api_name();
1344 if(defined($type)) { @xact = (xact_type => $type);
1346 } else { @xact = (); }
1348 if($api =~ /have_charge/) {
1350 $trans = $apputils->simple_scalar_request(
1352 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1353 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1355 } elsif($api =~ /have_balance/) {
1357 $trans = $apputils->simple_scalar_request(
1359 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1360 { usr => $user_id, balance_owed => { ">" => 0 }, @xact });
1364 $trans = $apputils->simple_scalar_request(
1366 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1367 { usr => $user_id, @xact });
1370 if($api !~ /fleshed/) { return $trans; }
1372 #warn "API: $api\n";
1375 for my $t (@$trans) {
1377 #warn $t->id . "\n";
1380 if( $t->xact_type ne 'circulation' ) {
1381 push @resp, {transaction => $t};
1385 my $circ = $apputils->simple_scalar_request(
1387 "open-ils.storage.direct.action.circulation.retrieve",
1392 my $title = $apputils->simple_scalar_request(
1394 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1395 $circ->target_copy );
1399 my $u = OpenILS::Utils::ModsParser->new();
1400 $u->start_mods_batch($title->marc());
1401 my $mods = $u->finish_mods_batch();
1403 push @resp, {transaction => $t, circ => $circ, record => $mods };
1413 __PACKAGE__->register_method(
1414 method => "user_perms",
1415 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1417 notes => <<" NOTES");
1418 Returns a list of permissions
1421 my( $self, $client, $authtoken, $user ) = @_;
1423 my( $staff, $evt ) = $apputils->checkses($authtoken);
1424 return $evt if $evt;
1426 $user ||= $staff->id;
1428 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1432 return $apputils->simple_scalar_request(
1434 "open-ils.storage.permission.user_perms.atomic",
1438 __PACKAGE__->register_method(
1439 method => "retrieve_perms",
1440 api_name => "open-ils.actor.permissions.retrieve",
1441 notes => <<" NOTES");
1442 Returns a list of permissions
1444 sub retrieve_perms {
1445 my( $self, $client ) = @_;
1446 return $apputils->simple_scalar_request(
1448 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1451 __PACKAGE__->register_method(
1452 method => "retrieve_groups",
1453 api_name => "open-ils.actor.groups.retrieve",
1454 notes => <<" NOTES");
1455 Returns a list of user groupss
1457 sub retrieve_groups {
1458 my( $self, $client ) = @_;
1459 return $apputils->simple_scalar_request(
1461 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1464 __PACKAGE__->register_method(
1465 method => "retrieve_groups_tree",
1466 api_name => "open-ils.actor.groups.tree.retrieve",
1467 notes => <<" NOTES");
1468 Returns a list of user groups
1470 sub retrieve_groups_tree {
1471 my( $self, $client ) = @_;
1472 my $groups = $apputils->simple_scalar_request(
1474 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1475 return $self->build_group_tree($groups);
1479 # turns an org list into an org tree
1480 sub build_group_tree {
1482 my( $self, $grplist) = @_;
1484 return $grplist unless (
1485 ref($grplist) and @$grplist > 1 );
1487 my @list = sort { $a->name cmp $b->name } @$grplist;
1490 for my $grp (@list) {
1492 if ($grp and !defined($grp->parent)) {
1496 my ($parent) = grep { $_->id == $grp->parent} @list;
1498 $parent->children([]) unless defined($parent->children);
1499 push( @{$parent->children}, $grp );
1507 __PACKAGE__->register_method(
1508 method => "add_user_to_groups",
1509 api_name => "open-ils.actor.user.set_groups",
1510 notes => <<" NOTES");
1511 Adds a user to one or more permission groups
1514 sub add_user_to_groups {
1515 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1517 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1518 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1519 return $evt if $evt;
1521 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1522 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1523 return $evt if $evt;
1525 $apputils->simplereq(
1527 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1529 for my $group (@$groups) {
1530 my $link = Fieldmapper::permission::usr_grp_map->new;
1532 $link->usr($userid);
1534 my $id = $apputils->simplereq(
1536 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1542 __PACKAGE__->register_method(
1543 method => "get_user_perm_groups",
1544 api_name => "open-ils.actor.user.get_groups",
1545 notes => <<" NOTES");
1546 Retrieve a user's permission groups.
1550 sub get_user_perm_groups {
1551 my( $self, $client, $authtoken, $userid ) = @_;
1553 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1554 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1555 return $evt if $evt;
1557 return $apputils->simplereq(
1559 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );