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 next unless($map->isnew() || $map->ischanged());
627 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
629 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
633 $map->target_usr($new_patron->id);
635 #warn "Updating stat entry with method $method and session $user_session and map $map\n";
637 my $req = $session->request($method, $map);
638 my $status = $req->gather(1);
640 if( $map->isnew() and !$status) {
641 throw OpenSRF::EX::ERROR
642 ("Error creating permission 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);
674 if($map->isnew and !$status) {
675 throw OpenSRF::EX::ERROR
676 ("Error creating permission map with method $method");
685 sub _create_standing_penalties {
687 my($session, $user_session, $patron, $new_patron) = @_;
689 my $maps = $patron->standing_penalties;
692 for my $map (@$maps) {
694 if ($map->isdeleted()) {
695 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
696 } elsif ($map->isnew()) {
697 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
703 $map->usr($new_patron->id);
705 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
707 my $req = $session->request($method, $map);
708 my $status = $req->gather(1);
712 throw OpenSRF::EX::ERROR
713 ("Error updating standing penalty with method $method");
723 __PACKAGE__->register_method(
724 method => "search_username",
725 api_name => "open-ils.actor.user.search.username",
728 sub search_username {
729 my($self, $client, $username) = @_;
730 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
732 "open-ils.storage.direct.actor.user.search.usrname.atomic",
740 __PACKAGE__->register_method(
741 method => "user_retrieve_by_barcode",
742 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
744 sub user_retrieve_by_barcode {
745 my($self, $client, $user_session, $barcode) = @_;
747 $logger->debug("Searching for user with barcode $barcode");
748 my ($user_obj, $evt) = $apputils->checkses($user_session);
751 my $session = OpenSRF::AppSession->create("open-ils.storage");
753 # find the card with the given barcode
754 my $creq = $session->request(
755 "open-ils.storage.direct.actor.card.search.barcode.atomic",
757 my $card = $creq->gather(1);
759 if(!$card || !$card->[0]) {
760 $session->disconnect();
761 return OpenILS::Event->new( 'USER_NOT_FOUND' );
765 my $user = flesh_user($card->usr(), $session);
766 $session->disconnect();
767 if(!$user) { return OpenILS::Event->new( 'USER_NOT_FOUND' ); }
774 __PACKAGE__->register_method(
775 method => "get_user_by_id",
776 api_name => "open-ils.actor.user.retrieve",);
779 my ($self, $client, $user_session, $id) = @_;
781 my $user_obj = $apputils->check_user_session( $user_session );
783 return $apputils->simple_scalar_request(
785 "open-ils.storage.direct.actor.user.retrieve",
791 __PACKAGE__->register_method(
792 method => "get_org_types",
793 api_name => "open-ils.actor.org_types.retrieve",);
797 my($self, $client) = @_;
799 return $org_types if $org_types;
801 $apputils->simple_scalar_request(
803 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
808 __PACKAGE__->register_method(
809 method => "get_user_profiles",
810 api_name => "open-ils.actor.user.profiles.retrieve",
814 sub get_user_profiles {
815 return $user_profiles if $user_profiles;
817 return $user_profiles =
818 $apputils->simple_scalar_request(
820 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
825 __PACKAGE__->register_method(
826 method => "get_user_ident_types",
827 api_name => "open-ils.actor.user.ident_types.retrieve",
830 sub get_user_ident_types {
831 return $ident_types if $ident_types;
832 return $ident_types =
833 $apputils->simple_scalar_request(
835 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
841 __PACKAGE__->register_method(
842 method => "get_org_unit",
843 api_name => "open-ils.actor.org_unit.retrieve",
848 my( $self, $client, $user_session, $org_id ) = @_;
850 if(defined($user_session) && !defined($org_id)) {
852 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
853 if(!defined($org_id)) {
854 $org_id = $user_obj->home_ou;
859 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
861 "open-ils.storage.direct.actor.org_unit.retrieve",
870 __PACKAGE__->register_method(
871 method => "get_org_tree",
872 api_name => "open-ils.actor.org_tree.retrieve",
874 note => "Returns the entire org tree structure",
878 my( $self, $client) = @_;
881 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
883 # see if it's in the cache
884 #warn "Getting ORG Tree\n";
885 my $tree = $cache_client->get_cache('orgtree');
887 #warn "Found orgtree in cache. returning...\n";
891 my $orglist = $apputils->simple_scalar_request(
893 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
896 #warn "found org list\n";
899 $tree = $self->build_org_tree($orglist);
900 $cache_client->put_cache('orgtree', $tree);
906 # turns an org list into an org tree
909 my( $self, $orglist) = @_;
911 return $orglist unless (
912 ref($orglist) and @$orglist > 1 );
915 $a->ou_type <=> $b->ou_type ||
916 $a->name cmp $b->name } @$orglist;
918 for my $org (@list) {
920 next unless ($org and defined($org->parent_ou));
921 my ($parent) = grep { $_->id == $org->parent_ou } @list;
924 $parent->children([]) unless defined($parent->children);
925 push( @{$parent->children}, $org );
933 __PACKAGE__->register_method(
934 method => "get_org_descendants",
935 api_name => "open-ils.actor.org_tree.descendants.retrieve"
938 # depth is optional. org_unit is the id
939 sub get_org_descendants {
940 my( $self, $client, $org_unit, $depth ) = @_;
941 my $orglist = $apputils->simple_scalar_request(
943 "open-ils.storage.actor.org_unit.descendants.atomic",
945 return $self->build_org_tree($orglist);
949 __PACKAGE__->register_method(
950 method => "get_org_ancestors",
951 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
954 # depth is optional. org_unit is the id
955 sub get_org_ancestors {
956 my( $self, $client, $org_unit, $depth ) = @_;
957 my $orglist = $apputils->simple_scalar_request(
959 "open-ils.storage.actor.org_unit.ancestors.atomic",
961 return $self->build_org_tree($orglist);
965 __PACKAGE__->register_method(
966 method => "get_standings",
967 api_name => "open-ils.actor.standings.retrieve"
972 return $user_standings if $user_standings;
973 return $user_standings =
974 $apputils->simple_scalar_request(
976 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
981 __PACKAGE__->register_method(
982 method => "get_my_org_path",
983 api_name => "open-ils.actor.org_unit.full_path.retrieve"
986 sub get_my_org_path {
987 my( $self, $client, $user_session, $org_id ) = @_;
988 my $user_obj = $apputils->check_user_session($user_session);
989 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
991 return $apputils->simple_scalar_request(
993 "open-ils.storage.actor.org_unit.full_path.atomic",
998 __PACKAGE__->register_method(
999 method => "patron_adv_search",
1000 api_name => "open-ils.actor.patron.search.advanced" );
1002 sub patron_adv_search {
1003 my( $self, $client, $staff_login, $search_hash ) = @_;
1005 #warn "patron adv with $staff_login and search " .
1006 #Dumper($search_hash) . "\n";
1008 my $session = OpenSRF::AppSession->create("open-ils.storage");
1009 my $req = $session->request(
1010 "open-ils.storage.actor.user.crazy_search", $search_hash);
1012 my $ans = $req->gather(1);
1014 my %hash = map { ($_ =>1) } @$ans;
1015 $ans = [ keys %hash ];
1017 #warn "Returning @$ans\n";
1019 $session->disconnect();
1026 sub _verify_password {
1027 my($user_session, $password) = @_;
1028 my $user_obj = $apputils->check_user_session($user_session);
1030 #grab the user with password
1031 $user_obj = $apputils->simple_scalar_request(
1033 "open-ils.storage.direct.actor.user.retrieve",
1036 if($user_obj->passwd eq $password) {
1044 __PACKAGE__->register_method(
1045 method => "update_password",
1046 api_name => "open-ils.actor.user.password.update");
1048 __PACKAGE__->register_method(
1049 method => "update_password",
1050 api_name => "open-ils.actor.user.username.update");
1052 __PACKAGE__->register_method(
1053 method => "update_password",
1054 api_name => "open-ils.actor.user.email.update");
1056 sub update_password {
1057 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1059 #warn "Updating user with method " .$self->api_name . "\n";
1060 my $user_obj = $apputils->check_user_session($user_session);
1062 if($self->api_name =~ /password/) {
1064 #make sure they know the current password
1065 if(!_verify_password($user_session, md5_hex($current_password))) {
1066 return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
1069 $user_obj->passwd($new_value);
1071 elsif($self->api_name =~ /username/) {
1072 my $users = search_username(undef, undef, $new_value);
1073 if( $users and $users->[0] ) {
1074 return OpenILS::Event->new('USERNAME_EXISTS');
1076 $user_obj->usrname($new_value);
1079 elsif($self->api_name =~ /email/) {
1080 #warn "Updating email to $new_value\n";
1081 $user_obj->email($new_value);
1084 my $session = $apputils->start_db_session();
1085 $user_obj = _update_patron($session, $user_obj, $user_obj);
1086 $apputils->commit_db_session($session);
1088 if($user_obj) { return 1; }
1093 __PACKAGE__->register_method(
1094 method => "check_user_perms",
1095 api_name => "open-ils.actor.user.perm.check",
1096 notes => <<" NOTES");
1097 Takes a login session, user id, an org id, and an array of perm type strings. For each
1098 perm type, if the user does *not* have the given permission it is added
1099 to a list which is returned from the method. If all permissions
1100 are allowed, an empty list is returned
1101 if the logged in user does not match 'user_id', then the logged in user must
1102 have VIEW_PERMISSION priveleges.
1105 sub check_user_perms {
1106 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1108 my( $staff, $evt ) = $apputils->checkses($login_session);
1109 return $evt if $evt;
1111 if($staff->id ne $user_id) {
1112 if( my $evt = $apputils->check_perms(
1113 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1119 for my $perm (@$perm_types) {
1120 if($apputils->check_perms($user_id, $org_id, $perm)) {
1121 push @not_allowed, $perm;
1125 return \@not_allowed
1128 __PACKAGE__->register_method(
1129 method => "check_user_perms2",
1130 api_name => "open-ils.actor.user.perm.check.multi_org",
1132 Checks the permissions on a list of perms and orgs for a user
1133 @param authtoken The login session key
1134 @param user_id The id of the user to check
1135 @param orgs The array of org ids
1136 @param perms The array of permission names
1137 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1138 if the logged in user does not match 'user_id', then the logged in user must
1139 have VIEW_PERMISSION priveleges.
1142 sub check_user_perms2 {
1143 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1145 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1146 $authtoken, $user_id, 'VIEW_PERMISSION' );
1147 return $evt if $evt;
1150 for my $org (@$orgs) {
1151 for my $perm (@$perms) {
1152 if($apputils->check_perms($user_id, $org, $perm)) {
1153 push @not_allowed, [ $org, $perm ];
1158 return \@not_allowed
1162 __PACKAGE__->register_method(
1163 method => 'check_user_perms3',
1164 api_name => 'open-ils.actor.user.perm.highest_org',
1166 Returns the highest org unit id at which a user has a given permission
1167 If the requestor does not match the target user, the requestor must have
1168 'VIEW_PERMISSION' rights at the home org unit of the target user
1169 @param authtoken The login session key
1170 @param userid The id of the user in question
1171 @param perm The permission to check
1172 @return The org unit highest in the org tree within which the user has
1173 the requested permission
1176 sub check_user_perms3 {
1177 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1179 my( $staff, $target, $org, $evt );
1181 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1182 $authtoken, $userid, 'VIEW_PERMISSION' );
1183 return $evt if $evt;
1185 my $tree = $self->get_org_tree();
1186 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1190 sub _find_highest_perm_org {
1191 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1192 my $org = $apputils->find_org($org_tree, $start_org );
1196 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1198 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1204 __PACKAGE__->register_method(
1205 method => 'check_user_perms4',
1206 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1208 Returns the highest org unit id at which a user has a given permission
1209 If the requestor does not match the target user, the requestor must have
1210 'VIEW_PERMISSION' rights at the home org unit of the target user
1211 @param authtoken The login session key
1212 @param userid The id of the user in question
1213 @param perms An array of perm names to check
1214 @return An array of orgId's representing the org unit
1215 highest in the org tree within which the user has the requested permission
1216 The arrah of orgId's has matches the order of the perms array
1219 sub check_user_perms4 {
1220 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1222 my( $staff, $target, $org, $evt );
1224 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1225 $authtoken, $userid, 'VIEW_PERMISSION' );
1226 return $evt if $evt;
1229 return [] unless ref($perms);
1230 my $tree = $self->get_org_tree();
1232 for my $p (@$perms) {
1233 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1241 __PACKAGE__->register_method(
1242 method => "user_fines_summary",
1243 api_name => "open-ils.actor.user.fines.summary",
1244 notes => <<" NOTES");
1245 Returns a short summary of the users total open fines, excluding voided fines
1246 Params are login_session, user_id
1247 Returns a 'mous' object.
1250 sub user_fines_summary {
1251 my( $self, $client, $login_session, $user_id ) = @_;
1253 my $user_obj = $apputils->check_user_session($login_session);
1254 if($user_obj->id ne $user_id) {
1255 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1256 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1260 return $apputils->simple_scalar_request(
1262 "open-ils.storage.direct.money.open_user_summary.search.usr",
1270 __PACKAGE__->register_method(
1271 method => "user_transactions",
1272 api_name => "open-ils.actor.user.transactions",
1273 notes => <<" NOTES");
1274 Returns a list of open user transactions (mbts objects);
1275 Params are login_session, user_id
1276 Optional third parameter is the transactions type. defaults to all
1279 __PACKAGE__->register_method(
1280 method => "user_transactions",
1281 api_name => "open-ils.actor.user.transactions.have_charge",
1282 notes => <<" NOTES");
1283 Returns a list of all open user transactions (mbts objects) that have an initial charge
1284 Params are login_session, user_id
1285 Optional third parameter is the transactions type. defaults to all
1288 __PACKAGE__->register_method(
1289 method => "user_transactions",
1290 api_name => "open-ils.actor.user.transactions.have_balance",
1291 notes => <<" NOTES");
1292 Returns a list of all open user transactions (mbts objects) that have a balance
1293 Params are login_session, user_id
1294 Optional third parameter is the transactions type. defaults to all
1297 __PACKAGE__->register_method(
1298 method => "user_transactions",
1299 api_name => "open-ils.actor.user.transactions.fleshed",
1300 notes => <<" NOTES");
1301 Returns an object/hash of transaction, circ, title where transaction = an open
1302 user transactions (mbts objects), circ is the attached circluation, and title
1303 is the title the circ points to
1304 Params are login_session, user_id
1305 Optional third parameter is the transactions type. defaults to all
1308 __PACKAGE__->register_method(
1309 method => "user_transactions",
1310 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1311 notes => <<" NOTES");
1312 Returns an object/hash of transaction, circ, title where transaction = an open
1313 user transactions that has an initial charge (mbts objects), circ is the
1314 attached circluation, and title is the title the circ points to
1315 Params are login_session, user_id
1316 Optional third parameter is the transactions type. defaults to all
1319 __PACKAGE__->register_method(
1320 method => "user_transactions",
1321 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1322 notes => <<" NOTES");
1323 Returns an object/hash of transaction, circ, title where transaction = an open
1324 user transaction that has a balance (mbts objects), circ is the attached
1325 circluation, and title is the title the circ points to
1326 Params are login_session, user_id
1327 Optional third parameter is the transaction type. defaults to all
1332 sub user_transactions {
1333 my( $self, $client, $login_session, $user_id, $type ) = @_;
1335 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1336 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1337 return $evt if $evt;
1339 my $api = $self->api_name();
1343 if(defined($type)) { @xact = (xact_type => $type);
1345 } else { @xact = (); }
1347 if($api =~ /have_charge/) {
1349 $trans = $apputils->simple_scalar_request(
1351 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1352 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1354 } elsif($api =~ /have_balance/) {
1356 $trans = $apputils->simple_scalar_request(
1358 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1359 { usr => $user_id, balance_owed => { ">" => 0 }, @xact });
1363 $trans = $apputils->simple_scalar_request(
1365 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1366 { usr => $user_id, @xact });
1369 if($api !~ /fleshed/) { return $trans; }
1371 #warn "API: $api\n";
1374 for my $t (@$trans) {
1376 #warn $t->id . "\n";
1379 if( $t->xact_type ne 'circulation' ) {
1380 push @resp, {transaction => $t};
1384 my $circ = $apputils->simple_scalar_request(
1386 "open-ils.storage.direct.action.circulation.retrieve",
1391 my $title = $apputils->simple_scalar_request(
1393 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1394 $circ->target_copy );
1398 my $u = OpenILS::Utils::ModsParser->new();
1399 $u->start_mods_batch($title->marc());
1400 my $mods = $u->finish_mods_batch();
1402 push @resp, {transaction => $t, circ => $circ, record => $mods };
1412 __PACKAGE__->register_method(
1413 method => "user_perms",
1414 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1416 notes => <<" NOTES");
1417 Returns a list of permissions
1420 my( $self, $client, $authtoken, $user ) = @_;
1422 my( $staff, $evt ) = $apputils->checkses($authtoken);
1423 return $evt if $evt;
1425 $user ||= $staff->id;
1427 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1431 return $apputils->simple_scalar_request(
1433 "open-ils.storage.permission.user_perms.atomic",
1437 __PACKAGE__->register_method(
1438 method => "retrieve_perms",
1439 api_name => "open-ils.actor.permissions.retrieve",
1440 notes => <<" NOTES");
1441 Returns a list of permissions
1443 sub retrieve_perms {
1444 my( $self, $client ) = @_;
1445 return $apputils->simple_scalar_request(
1447 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1450 __PACKAGE__->register_method(
1451 method => "retrieve_groups",
1452 api_name => "open-ils.actor.groups.retrieve",
1453 notes => <<" NOTES");
1454 Returns a list of user groupss
1456 sub retrieve_groups {
1457 my( $self, $client ) = @_;
1458 return $apputils->simple_scalar_request(
1460 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1463 __PACKAGE__->register_method(
1464 method => "retrieve_groups_tree",
1465 api_name => "open-ils.actor.groups.tree.retrieve",
1466 notes => <<" NOTES");
1467 Returns a list of user groups
1469 sub retrieve_groups_tree {
1470 my( $self, $client ) = @_;
1471 my $groups = $apputils->simple_scalar_request(
1473 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1474 return $self->build_group_tree($groups);
1478 # turns an org list into an org tree
1479 sub build_group_tree {
1481 my( $self, $grplist) = @_;
1483 return $grplist unless (
1484 ref($grplist) and @$grplist > 1 );
1486 my @list = sort { $a->name cmp $b->name } @$grplist;
1489 for my $grp (@list) {
1491 if ($grp and !defined($grp->parent)) {
1495 my ($parent) = grep { $_->id == $grp->parent} @list;
1497 $parent->children([]) unless defined($parent->children);
1498 push( @{$parent->children}, $grp );
1506 __PACKAGE__->register_method(
1507 method => "add_user_to_groups",
1508 api_name => "open-ils.actor.user.set_groups",
1509 notes => <<" NOTES");
1510 Adds a user to one or more permission groups
1513 sub add_user_to_groups {
1514 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1516 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1517 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1518 return $evt if $evt;
1520 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1521 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1522 return $evt if $evt;
1524 $apputils->simplereq(
1526 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1528 for my $group (@$groups) {
1529 my $link = Fieldmapper::permission::usr_grp_map->new;
1531 $link->usr($userid);
1533 my $id = $apputils->simplereq(
1535 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1541 __PACKAGE__->register_method(
1542 method => "get_user_perm_groups",
1543 api_name => "open-ils.actor.user.get_groups",
1544 notes => <<" NOTES");
1545 Retrieve a user's permission groups.
1549 sub get_user_perm_groups {
1550 my( $self, $client, $authtoken, $userid ) = @_;
1552 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1553 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1554 return $evt if $evt;
1556 return $apputils->simplereq(
1558 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );