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;
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 = $apputils->check_user_session( $user_session );
750 my ($user_obj, $evt) = $apputils->check_ses($user_session);
753 my $session = OpenSRF::AppSession->create("open-ils.storage");
755 # find the card with the given barcode
756 my $creq = $session->request(
757 "open-ils.storage.direct.actor.card.search.barcode.atomic",
759 my $card = $creq->gather(1);
761 if(!$card || !$card->[0]) {
762 $session->disconnect();
763 return OpenILS::Event->new( 'USER_NOT_FOUND' );
767 my $user = flesh_user($card->usr(), $session);
768 $session->disconnect();
769 if(!$user) { return OpenILS::Event->new( 'USER_NOT_FOUND' ); }
776 __PACKAGE__->register_method(
777 method => "get_user_by_id",
778 api_name => "open-ils.actor.user.retrieve",);
781 my ($self, $client, $user_session, $id) = @_;
783 my $user_obj = $apputils->check_user_session( $user_session );
785 return $apputils->simple_scalar_request(
787 "open-ils.storage.direct.actor.user.retrieve",
793 __PACKAGE__->register_method(
794 method => "get_org_types",
795 api_name => "open-ils.actor.org_types.retrieve",);
799 my($self, $client) = @_;
801 return $org_types if $org_types;
803 $apputils->simple_scalar_request(
805 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
810 __PACKAGE__->register_method(
811 method => "get_user_profiles",
812 api_name => "open-ils.actor.user.profiles.retrieve",
816 sub get_user_profiles {
817 return $user_profiles if $user_profiles;
819 return $user_profiles =
820 $apputils->simple_scalar_request(
822 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
827 __PACKAGE__->register_method(
828 method => "get_user_ident_types",
829 api_name => "open-ils.actor.user.ident_types.retrieve",
832 sub get_user_ident_types {
833 return $ident_types if $ident_types;
834 return $ident_types =
835 $apputils->simple_scalar_request(
837 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
843 __PACKAGE__->register_method(
844 method => "get_org_unit",
845 api_name => "open-ils.actor.org_unit.retrieve",
850 my( $self, $client, $user_session, $org_id ) = @_;
852 if(defined($user_session) && !defined($org_id)) {
854 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
855 if(!defined($org_id)) {
856 $org_id = $user_obj->home_ou;
861 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
863 "open-ils.storage.direct.actor.org_unit.retrieve",
872 __PACKAGE__->register_method(
873 method => "get_org_tree",
874 api_name => "open-ils.actor.org_tree.retrieve",
876 note => "Returns the entire org tree structure",
880 my( $self, $client) = @_;
883 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
885 # see if it's in the cache
886 #warn "Getting ORG Tree\n";
887 my $tree = $cache_client->get_cache('orgtree');
889 #warn "Found orgtree in cache. returning...\n";
893 my $orglist = $apputils->simple_scalar_request(
895 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
898 #warn "found org list\n";
901 $tree = $self->build_org_tree($orglist);
902 $cache_client->put_cache('orgtree', $tree);
908 # turns an org list into an org tree
911 my( $self, $orglist) = @_;
913 return $orglist unless (
914 ref($orglist) and @$orglist > 1 );
917 $a->ou_type <=> $b->ou_type ||
918 $a->name cmp $b->name } @$orglist;
920 for my $org (@list) {
922 next unless ($org and defined($org->parent_ou));
923 my ($parent) = grep { $_->id == $org->parent_ou } @list;
926 $parent->children([]) unless defined($parent->children);
927 push( @{$parent->children}, $org );
935 __PACKAGE__->register_method(
936 method => "get_org_descendants",
937 api_name => "open-ils.actor.org_tree.descendants.retrieve"
940 # depth is optional. org_unit is the id
941 sub get_org_descendants {
942 my( $self, $client, $org_unit, $depth ) = @_;
943 my $orglist = $apputils->simple_scalar_request(
945 "open-ils.storage.actor.org_unit.descendants.atomic",
947 return $self->build_org_tree($orglist);
951 __PACKAGE__->register_method(
952 method => "get_org_ancestors",
953 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
956 # depth is optional. org_unit is the id
957 sub get_org_ancestors {
958 my( $self, $client, $org_unit, $depth ) = @_;
959 my $orglist = $apputils->simple_scalar_request(
961 "open-ils.storage.actor.org_unit.ancestors.atomic",
963 return $self->build_org_tree($orglist);
967 __PACKAGE__->register_method(
968 method => "get_standings",
969 api_name => "open-ils.actor.standings.retrieve"
974 return $user_standings if $user_standings;
975 return $user_standings =
976 $apputils->simple_scalar_request(
978 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
983 __PACKAGE__->register_method(
984 method => "get_my_org_path",
985 api_name => "open-ils.actor.org_unit.full_path.retrieve"
988 sub get_my_org_path {
989 my( $self, $client, $user_session, $org_id ) = @_;
990 my $user_obj = $apputils->check_user_session($user_session);
991 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
993 return $apputils->simple_scalar_request(
995 "open-ils.storage.actor.org_unit.full_path.atomic",
1000 __PACKAGE__->register_method(
1001 method => "patron_adv_search",
1002 api_name => "open-ils.actor.patron.search.advanced" );
1004 sub patron_adv_search {
1005 my( $self, $client, $staff_login, $search_hash ) = @_;
1008 #warn "patron adv with $staff_login and search " .
1009 #Dumper($search_hash) . "\n";
1011 my $session = OpenSRF::AppSession->create("open-ils.storage");
1012 my $req = $session->request(
1013 "open-ils.storage.actor.user.crazy_search", $search_hash);
1015 my $ans = $req->gather(1);
1017 my %hash = map { ($_ =>1) } @$ans;
1018 $ans = [ keys %hash ];
1020 #warn "Returning @$ans\n";
1022 $session->disconnect();
1029 sub _verify_password {
1030 my($user_session, $password) = @_;
1031 my $user_obj = $apputils->check_user_session($user_session);
1033 #grab the user with password
1034 $user_obj = $apputils->simple_scalar_request(
1036 "open-ils.storage.direct.actor.user.retrieve",
1039 if($user_obj->passwd eq $password) {
1047 __PACKAGE__->register_method(
1048 method => "update_password",
1049 api_name => "open-ils.actor.user.password.update");
1051 __PACKAGE__->register_method(
1052 method => "update_password",
1053 api_name => "open-ils.actor.user.username.update");
1055 __PACKAGE__->register_method(
1056 method => "update_password",
1057 api_name => "open-ils.actor.user.email.update");
1059 sub update_password {
1060 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1062 #warn "Updating user with method " .$self->api_name . "\n";
1063 my $user_obj = $apputils->check_user_session($user_session);
1065 if($self->api_name =~ /password/) {
1067 #make sure they know the current password
1068 if(!_verify_password($user_session, md5_hex($current_password))) {
1069 return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
1072 $user_obj->passwd($new_value);
1074 elsif($self->api_name =~ /username/) {
1075 my $users = search_username(undef, undef, $new_value);
1076 if( $users and $users->[0] ) {
1077 return OpenILS::Event->new('USERNAME_EXISTS');
1079 $user_obj->usrname($new_value);
1082 elsif($self->api_name =~ /email/) {
1083 #warn "Updating email to $new_value\n";
1084 $user_obj->email($new_value);
1087 my $session = $apputils->start_db_session();
1088 $user_obj = _update_patron($session, $user_obj, $user_obj);
1089 $apputils->commit_db_session($session);
1091 if($user_obj) { return 1; }
1096 __PACKAGE__->register_method(
1097 method => "check_user_perms",
1098 api_name => "open-ils.actor.user.perm.check",
1099 notes => <<" NOTES");
1100 Takes a login session, user id, an org id, and an array of perm type strings. For each
1101 perm type, if the user does *not* have the given permission it is added
1102 to a list which is returned from the method. If all permissions
1103 are allowed, an empty list is returned
1104 if the logged in user does not match 'user_id', then the logged in user must
1105 have VIEW_PERMISSION priveleges.
1108 sub check_user_perms {
1109 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1111 my( $staff, $evt ) = $apputils->checkses($login_session);
1112 return $evt if $evt;
1114 if($staff->id ne $user_id) {
1115 if( my $evt = $apputils->check_perms(
1116 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1122 for my $perm (@$perm_types) {
1123 if($apputils->check_perms($user_id, $org_id, $perm)) {
1124 push @not_allowed, $perm;
1128 return \@not_allowed
1131 __PACKAGE__->register_method(
1132 method => "check_user_perms2",
1133 api_name => "open-ils.actor.user.perm.check.multi_org",
1135 Checks the permissions on a list of perms and orgs for a user
1136 @param authtoken The login session key
1137 @param user_id The id of the user to check
1138 @param orgs The array of org ids
1139 @param perms The array of permission names
1140 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1141 if the logged in user does not match 'user_id', then the logged in user must
1142 have VIEW_PERMISSION priveleges.
1145 sub check_user_perms2 {
1146 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1148 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1149 $authtoken, $user_id, 'VIEW_PERMISSION' );
1150 return $evt if $evt;
1153 for my $org (@$orgs) {
1154 for my $perm (@$perms) {
1155 if($apputils->check_perms($user_id, $org, $perm)) {
1156 push @not_allowed, [ $org, $perm ];
1161 return \@not_allowed
1165 __PACKAGE__->register_method(
1166 method => 'check_user_perms3',
1167 api_name => 'open-ils.actor.user.perm.highest_org',
1169 Returns the highest org unit id at which a user has a given permission
1170 If the requestor does not match the target user, the requestor must have
1171 'VIEW_PERMISSION' rights at the home org unit of the target user
1172 @param authtoken The login session key
1173 @param userid The id of the user in question
1174 @param perm The permission to check
1175 @return The org unit highest in the org tree within which the user has
1176 the requested permission
1179 sub check_user_perms3 {
1180 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1182 my( $staff, $target, $org, $evt );
1184 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1185 $authtoken, $userid, 'VIEW_PERMISSION' );
1186 return $evt if $evt;
1188 my $tree = $self->get_org_tree();
1189 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1193 sub _find_highest_perm_org {
1194 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1195 my $org = $apputils->find_org($org_tree, $start_org );
1199 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1201 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1207 __PACKAGE__->register_method(
1208 method => 'check_user_perms4',
1209 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1211 Returns the highest org unit id at which a user has a given permission
1212 If the requestor does not match the target user, the requestor must have
1213 'VIEW_PERMISSION' rights at the home org unit of the target user
1214 @param authtoken The login session key
1215 @param userid The id of the user in question
1216 @param perms An array of perm names to check
1217 @return An array of orgId's representing the org unit
1218 highest in the org tree within which the user has the requested permission
1219 The arrah of orgId's has matches the order of the perms array
1222 sub check_user_perms4 {
1223 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1225 my( $staff, $target, $org, $evt );
1227 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1228 $authtoken, $userid, 'VIEW_PERMISSION' );
1229 return $evt if $evt;
1232 return [] unless ref($perms);
1233 my $tree = $self->get_org_tree();
1235 for my $p (@$perms) {
1236 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1244 __PACKAGE__->register_method(
1245 method => "user_fines_summary",
1246 api_name => "open-ils.actor.user.fines.summary",
1247 notes => <<" NOTES");
1248 Returns a short summary of the users total open fines, excluding voided fines
1249 Params are login_session, user_id
1250 Returns a 'mous' object.
1253 sub user_fines_summary {
1254 my( $self, $client, $login_session, $user_id ) = @_;
1256 my $user_obj = $apputils->check_user_session($login_session);
1257 if($user_obj->id ne $user_id) {
1258 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1259 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1263 return $apputils->simple_scalar_request(
1265 "open-ils.storage.direct.money.open_user_summary.search.usr",
1273 __PACKAGE__->register_method(
1274 method => "user_transactions",
1275 api_name => "open-ils.actor.user.transactions",
1276 notes => <<" NOTES");
1277 Returns a list of open user transactions (mbts objects);
1278 Params are login_session, user_id
1279 Optional third parameter is the transactions type. defaults to all
1282 __PACKAGE__->register_method(
1283 method => "user_transactions",
1284 api_name => "open-ils.actor.user.transactions.have_charge",
1285 notes => <<" NOTES");
1286 Returns a list of all open user transactions (mbts objects) that have an initial charge
1287 Params are login_session, user_id
1288 Optional third parameter is the transactions type. defaults to all
1291 __PACKAGE__->register_method(
1292 method => "user_transactions",
1293 api_name => "open-ils.actor.user.transactions.have_balance",
1294 notes => <<" NOTES");
1295 Returns a list of all open user transactions (mbts objects) that have a balance
1296 Params are login_session, user_id
1297 Optional third parameter is the transactions type. defaults to all
1300 __PACKAGE__->register_method(
1301 method => "user_transactions",
1302 api_name => "open-ils.actor.user.transactions.fleshed",
1303 notes => <<" NOTES");
1304 Returns an object/hash of transaction, circ, title where transaction = an open
1305 user transactions (mbts objects), circ is the attached circluation, and title
1306 is the title the circ points to
1307 Params are login_session, user_id
1308 Optional third parameter is the transactions type. defaults to all
1311 __PACKAGE__->register_method(
1312 method => "user_transactions",
1313 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1314 notes => <<" NOTES");
1315 Returns an object/hash of transaction, circ, title where transaction = an open
1316 user transactions that has an initial charge (mbts objects), circ is the
1317 attached circluation, and title is the title the circ points to
1318 Params are login_session, user_id
1319 Optional third parameter is the transactions type. defaults to all
1322 __PACKAGE__->register_method(
1323 method => "user_transactions",
1324 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1325 notes => <<" NOTES");
1326 Returns an object/hash of transaction, circ, title where transaction = an open
1327 user transaction that has a balance (mbts objects), circ is the attached
1328 circluation, and title is the title the circ points to
1329 Params are login_session, user_id
1330 Optional third parameter is the transaction type. defaults to all
1335 sub user_transactions {
1336 my( $self, $client, $login_session, $user_id, $type ) = @_;
1338 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1339 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1340 return $evt if $evt;
1342 my $api = $self->api_name();
1346 if(defined($type)) { @xact = (xact_type => $type);
1348 } else { @xact = (); }
1350 if($api =~ /have_charge/) {
1352 $trans = $apputils->simple_scalar_request(
1354 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1355 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1357 } elsif($api =~ /have_balance/) {
1359 $trans = $apputils->simple_scalar_request(
1361 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1362 { usr => $user_id, balance_owed => { ">" => 0 }, @xact });
1366 $trans = $apputils->simple_scalar_request(
1368 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1369 { usr => $user_id, @xact });
1372 if($api !~ /fleshed/) { return $trans; }
1374 #warn "API: $api\n";
1377 for my $t (@$trans) {
1379 #warn $t->id . "\n";
1381 my $circ = $apputils->simple_scalar_request(
1383 "open-ils.storage.direct.action.circulation.retrieve",
1388 my $title = $apputils->simple_scalar_request(
1390 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1391 $circ->target_copy );
1395 my $u = OpenILS::Utils::ModsParser->new();
1396 $u->start_mods_batch($title->marc());
1397 my $mods = $u->finish_mods_batch();
1399 push @resp, {transaction => $t, circ => $circ, record => $mods };
1409 __PACKAGE__->register_method(
1410 method => "user_perms",
1411 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1413 notes => <<" NOTES");
1414 Returns a list of permissions
1417 my( $self, $client, $authtoken, $user ) = @_;
1419 my( $staff, $evt ) = $apputils->checkses($authtoken);
1420 return $evt if $evt;
1422 $user ||= $staff->id;
1424 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1428 return $apputils->simple_scalar_request(
1430 "open-ils.storage.permission.user_perms.atomic",
1434 __PACKAGE__->register_method(
1435 method => "retrieve_perms",
1436 api_name => "open-ils.actor.permissions.retrieve",
1437 notes => <<" NOTES");
1438 Returns a list of permissions
1440 sub retrieve_perms {
1441 my( $self, $client ) = @_;
1442 return $apputils->simple_scalar_request(
1444 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1447 __PACKAGE__->register_method(
1448 method => "retrieve_groups",
1449 api_name => "open-ils.actor.groups.retrieve",
1450 notes => <<" NOTES");
1451 Returns a list of user groupss
1453 sub retrieve_groups {
1454 my( $self, $client ) = @_;
1455 return $apputils->simple_scalar_request(
1457 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1460 __PACKAGE__->register_method(
1461 method => "retrieve_groups_tree",
1462 api_name => "open-ils.actor.groups.tree.retrieve",
1463 notes => <<" NOTES");
1464 Returns a list of user groups
1466 sub retrieve_groups_tree {
1467 my( $self, $client ) = @_;
1468 my $groups = $apputils->simple_scalar_request(
1470 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1471 return $self->build_group_tree($groups);
1475 # turns an org list into an org tree
1476 sub build_group_tree {
1478 my( $self, $grplist) = @_;
1480 return $grplist unless (
1481 ref($grplist) and @$grplist > 1 );
1483 my @list = sort { $a->name cmp $b->name } @$grplist;
1486 for my $grp (@list) {
1488 if ($grp and !defined($grp->parent)) {
1492 my ($parent) = grep { $_->id == $grp->parent} @list;
1494 $parent->children([]) unless defined($parent->children);
1495 push( @{$parent->children}, $grp );
1503 __PACKAGE__->register_method(
1504 method => "add_user_to_groups",
1505 api_name => "open-ils.actor.user.set_groups",
1506 notes => <<" NOTES");
1507 Adds a user to one or more permission groups
1510 sub add_user_to_groups {
1511 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1513 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1514 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1515 return $evt if $evt;
1517 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1518 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1519 return $evt if $evt;
1521 $apputils->simplereq(
1523 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1525 for my $group (@$groups) {
1526 my $link = Fieldmapper::permission::usr_grp_map->new;
1528 $link->usr($userid);
1530 my $id = $apputils->simplereq(
1532 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1538 __PACKAGE__->register_method(
1539 method => "get_user_perm_groups",
1540 api_name => "open-ils.actor.user.get_groups",
1541 notes => <<" NOTES");
1542 Retrieve a user's permission groups.
1546 sub get_user_perm_groups {
1547 my( $self, $client, $authtoken, $userid ) = @_;
1549 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1550 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1551 return $evt if $evt;
1553 return $apputils->simplereq(
1555 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );