From: erickson Date: Fri, 1 Feb 2008 20:12:54 +0000 (+0000) Subject: porting work-org method and perm-check speedup: svn merge -r8571:8573 X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=029e9e4f129cd10d3c3fba84342203a1835c2ed2;p=Evergreen.git porting work-org method and perm-check speedup: svn merge -r8571:8573 git-svn-id: svn://svn.open-ils.org/ILS/branches/acq-experiment@8574 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm index 9330f96af7..604bb4ac35 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm @@ -1246,6 +1246,7 @@ sub update_password { __PACKAGE__->register_method( method => "update_passwd", + authoritative => 1, api_name => "open-ils.actor.user.password.update"); __PACKAGE__->register_method( @@ -1409,6 +1410,99 @@ sub _find_highest_perm_org { return $lastid; } + +__PACKAGE__->register_method( + method => 'check_user_work_perms', + api_name => 'open-ils.actor.user.work_perm.highest_org_set', + authoritative => 1, + signature => { + desc => q/ + Returns a set of org units which represent the highest orgs in + the org tree where the user has the requested permission. The + purpose of this method is to return the smallest set of org units + which represent the full expanse of the user's ability to perform + the requested action. The user whose perms this method should + check is implied by the authtoken. /, + params => [ + {desc => 'authtoken', type => 'string'}, + {desc => 'permission name', type => 'string'} + ], + return => {desc => 'An array of org IDs'} + } +); + +sub check_user_work_perms { + my($self, $conn, $auth, $perm) = @_; + my $e = new_editor(authtoken=>$auth); + return $e->event unless $e->checkauth; + + # first, quickly grab the list of work_ou's for this user + my $work_orgs = $e->json_query({ + select => {puwoum => ['work_ou']}, + from => 'puwoum', + where => {usr => $e->requestor->id}}); + + return [] unless @$work_orgs; + my @work_orgs; + push(@work_orgs, $_->{work_ou}) for @$work_orgs; + + $logger->debug("found work orgs @work_orgs"); + + my @allowed_orgs; + my $org_tree = get_org_tree(); + my $org_types = get_org_types(); + + # use the first work org to determine the highest depth at which + # the user has the requested permission + my $first_org = shift @work_orgs; + my $high_org_id = _find_highest_perm_org($perm, $e->requestor->id, $first_org, $org_tree); + $logger->debug("found highest work org $high_org_id"); + + + return [] if $high_org_id == -1; # not allowed anywhere + push(@allowed_orgs, $high_org_id); + my $high_org = $apputils->find_org($org_tree, $high_org_id); + + # now that we have the highest depth, find the org in the tree relative to + # each work org at that depth. + my ($org_type) = grep { $_->id == $high_org->ou_type } @$org_types; + my $org_depth = $org_type->depth; + for my $org (@work_orgs) { + $logger->debug("work org looking at $org"); + + # retrieve sorted list of ancestors and descendants for this work_ou + my $org_list = $e->json_query({ + select => { + aou => [{ + transform => 'actor.org_unit_full_path', + column => 'id', + result_field => 'id', + params => [$org_depth] + }] + }, + from => 'aou', + where => {id=>$org} + }); + + # go through the list until we find the org at the correct depth + my @org_list; + push(@org_list, $_->{id}) for @$org_list; + for my $sub_org (@org_list) { + $logger->debug("work org looking at sub-org $sub_org"); + my $org_unit = $apputils->find_org($org_tree, $sub_org); + my ($ou_type) = grep { $_->id == $org_unit->ou_type } @$org_types; + if($ou_type->depth >= $org_depth) { + push(@allowed_orgs, $sub_org); + last; + } + } + } + + return \@allowed_orgs; +} + + + __PACKAGE__->register_method( method => 'check_user_perms4', api_name => 'open-ils.actor.user.perm.highest_org.batch', @@ -2708,6 +2802,8 @@ __PACKAGE__->register_method( / ); +# XXX Make me retun undef if no user has the ID + sub usrname_exists { my( $self, $conn, $auth, $usrname ) = @_; my $e = new_editor(authtoken=>$auth); diff --git a/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm b/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm index c5af42014c..bbfc6e06ef 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm @@ -9,7 +9,7 @@ use OpenILS::Utils::ModsParser; use OpenSRF::EX qw(:try); use OpenILS::Event; use Data::Dumper; -use OpenILS::Utils::CStoreEditor; +use OpenILS::Utils::CStoreEditor qw/:funcs/; use OpenILS::Const qw/:const/; # --------------------------------------------------------------------------- @@ -41,16 +41,30 @@ sub start_db_session { return $session; } +my $PERM_QUERY = { + select => { + au => [ { + transform => 'permission.usr_has_perm', + alias => 'has_perm', + column => 'id', + params => [] + } ] + }, + from => 'au', + where => {}, +}; + # returns undef if user has all of the perms provided # returns the first failed perm on failure sub check_user_perms { my($self, $user_id, $org_id, @perm_types ) = @_; $logger->debug("Checking perms with user : $user_id , org: $org_id, @perm_types"); + for my $type (@perm_types) { - return $type unless ($self->storagereq( - "open-ils.storage.permission.user_has_perm", - $user_id, $type, $org_id )); + $PERM_QUERY->{select}->{au}->[0]->{params} = [$type, $org_id]; + $PERM_QUERY->{where}->{id} = $user_id; + return $type unless $self->is_true(new_editor()->json_query($PERM_QUERY)->[0]->{has_perm}); } return undef; }