]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm
2fdcaded5720fb563110c105f9965278cc6da885
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / AppUtils.pm
1 package OpenILS::Application::AppUtils;
2 use strict; use warnings;
3 use base qw/OpenSRF::Application/;
4 use OpenSRF::Utils::Cache;
5 use OpenSRF::EX qw(:try);
6 use OpenILS::Perm;
7 use OpenSRF::Utils::Logger;
8 my $logger = "OpenSRF::Utils::Logger";
9
10
11 my $cache_client = "OpenSRF::Utils::Cache";
12
13 # ---------------------------------------------------------------------------
14 # Pile of utilty methods used accross applications.
15 # ---------------------------------------------------------------------------
16
17
18 # ---------------------------------------------------------------------------
19 # on sucess, returns the created session, on failure throws ERROR exception
20 # ---------------------------------------------------------------------------
21 sub start_db_session {
22
23         my $self = shift;
24         my $session = OpenSRF::AppSession->connect( "open-ils.storage" );
25         my $trans_req = $session->request( "open-ils.storage.transaction.begin" );
26
27         my $trans_resp = $trans_req->recv();
28         if(ref($trans_resp) and UNIVERSAL::isa($trans_resp,"Error")) { throw $trans_resp; }
29         if( ! $trans_resp->content() ) {
30                 throw OpenSRF::ERROR 
31                         ("Unable to Begin Transaction with database" );
32         }
33         $trans_req->finish();
34         return $session;
35 }
36
37
38 # returns undef if user has all of the perms provided
39 # returns the first failed perm on failure
40 sub check_user_perms {
41         my($self, $user_id, $org_id, @perm_types ) = @_;
42
43         $logger->debug("Checking perms with user : $user_id , org: $org_id, @perm_types");
44
45         throw OpenSRF::EX::ERROR ("Invalid call to check_user_perms()")
46                 unless( defined($user_id) and defined($org_id) and @perm_types); 
47
48         my $session = OpenSRF::AppSession->create("open-ils.storage");
49         for my $type (@perm_types) {
50                 my $req = $session->request(
51                         "open-ils.storage.permission.user_has_perm", 
52                         $user_id, $type, $org_id );
53                 my $resp = $req->gather(1);
54                 if(!$resp) { 
55                         $session->disconnect();
56                         return $type; 
57                 }
58         }
59
60         $session->disconnect();
61         return undef;
62 }
63
64 # checks the list of user perms.  The first one that fails returns a new
65 # OpenILS::Perm object of that type.  Returns undef if all perms are allowed
66 sub check_perms {
67         my( $self, $user_id, $org_id, @perm_types ) = @_;
68         my $t = $self->check_user_perms( $user_id, $org_id, @perm_types );
69         return OpenILS::Event->new('PERM_FAILURE', ilsperm => $t, ilspermloc => $org_id ) if $t;
70         return undef;
71 }
72
73
74
75 # ---------------------------------------------------------------------------
76 # commits and destroys the session
77 # ---------------------------------------------------------------------------
78 sub commit_db_session {
79         my( $self, $session ) = @_;
80
81         my $req = $session->request( "open-ils.storage.transaction.commit" );
82         my $resp = $req->recv();
83
84         if(!$resp) {
85                 throw OpenSRF::EX::ERROR ("Unable to commit db session");
86         }
87
88         if(UNIVERSAL::isa($resp,"Error")) { 
89                 throw $resp ($resp->stringify); 
90         }
91
92         if(!$resp->content) {
93                 throw OpenSRF::EX::ERROR ("Unable to commit db session");
94         }
95
96         $session->finish();
97         $session->disconnect();
98         $session->kill_me();
99 }
100
101 sub rollback_db_session {
102         my( $self, $session ) = @_;
103
104         my $req = $session->request("open-ils.storage.transaction.rollback");
105         my $resp = $req->recv();
106         if(UNIVERSAL::isa($resp,"Error")) { throw $resp;  }
107
108         $session->finish();
109         $session->disconnect();
110         $session->kill_me();
111 }
112
113 # ---------------------------------------------------------------------------
114 # Checks to see if a user is logged in.  Returns the user record on success,
115 # throws an exception on error.
116 # ---------------------------------------------------------------------------
117 sub check_ses {
118         my( $self, $session ) = @_;
119         my $user;
120         my $evt;
121         try {
122                 $user = $self->check_user_session($session);
123         } catch Error with {
124                 $evt = OpenILS::Event->new('NO_SESSION');
125         };
126
127         return ( $user, $evt );
128 }
129
130 sub check_user_session {
131
132         my( $self, $user_session ) = @_;
133
134         my $session = OpenSRF::AppSession->create( "open-ils.auth" );
135         my $request = $session->request("open-ils.auth.session.retrieve", $user_session );
136         my $response = $request->recv();
137
138         if(!$response) {
139                 throw OpenSRF::EX::User 
140                         ("Error communication with storage server");
141         }
142
143         if( ref($response) eq 'HASH' ) {
144                 if(defined($response->{ilsevent}) and $response->{ilsevent} ne '0' ) {
145                         throw OpenSRF::EX::ERROR 
146                                 ("Session [$user_session] cannot be authenticated" );
147                 }
148         }
149
150
151         if(ref($response) and $response->isa("OpenSRF::EX")) {
152                 throw $response ($response->stringify);
153         }
154
155         my $user = $response->content;
156         if(!$user) {
157                 throw OpenSRF::EX::ERROR ("Session [$user_session] cannot be authenticated" );
158         }
159
160         $session->disconnect();
161         $session->kill_me();
162
163         return $user;
164 }
165
166 # generic simple request returning a scalar value
167 sub simplereq {
168         my($self, $service, $method, @params) = @_;
169         return $self->simple_scalar_request($service, $method, @params);
170 }
171
172
173 sub simple_scalar_request {
174         my($self, $service, $method, @params) = @_;
175
176         my $session = OpenSRF::AppSession->create( $service );
177         my $request = $session->request( $method, @params );
178         my $response = $request->recv(30);
179
180         $request->wait_complete;
181
182         if(!$request->complete) {
183                 throw OpenSRF::EX::ERROR ("Call to $service for method $method with params @params" . 
184                                 "\n did not complete successfully");
185         }
186
187         if(!$response) {
188                 warn "No response from $service for method $method with params @params";
189         }
190
191         if(UNIVERSAL::isa($response,"Error")) {
192                 throw $response ("Call to $service for method $method with params @params" . 
193                                 "\n failed with exception: " . $response->stringify );
194         }
195
196
197         $request->finish();
198         $session->finish();
199         $session->disconnect();
200
201         my $value;
202
203         if($response) { $value = $response->content; }
204         else { $value = undef; }
205
206         return $value;
207 }
208
209
210
211
212
213 my $tree                                                = undef;
214 my $orglist                                     = undef;
215 my $org_typelist                        = undef;
216 my $org_typelist_hash   = {};
217
218 sub get_org_tree {
219
220         my $self = shift;
221         if($tree) { return $tree; }
222
223         # see if it's in the cache
224         $tree = $cache_client->new()->get_cache('_orgtree');
225         if($tree) { return $tree; }
226
227         if(!$orglist) {
228                 warn "Retrieving Org Tree\n";
229                 $orglist = $self->simple_scalar_request( 
230                         "open-ils.storage", 
231                         "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
232         }
233
234         if( ! $org_typelist ) {
235                 warn "Retrieving org types\n";
236                 $org_typelist = $self->simple_scalar_request( 
237                         "open-ils.storage", 
238                         "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
239                 $self->build_org_type($org_typelist);
240         }
241
242         $tree = $self->build_org_tree($orglist,1);
243         $cache_client->new()->put_cache('_orgtree', $tree);
244         return $tree;
245
246 }
247
248 my $slimtree = undef;
249 sub get_slim_org_tree {
250
251         my $self = shift;
252         if($slimtree) { return $slimtree; }
253
254         # see if it's in the cache
255         $slimtree = $cache_client->new()->get_cache('slimorgtree');
256         if($slimtree) { return $slimtree; }
257
258         if(!$orglist) {
259                 warn "Retrieving Org Tree\n";
260                 $orglist = $self->simple_scalar_request( 
261                         "open-ils.storage", 
262                         "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
263         }
264
265         $slimtree = $self->build_org_tree($orglist);
266         $cache_client->new->put_cache('slimorgtree', $slimtree);
267         return $slimtree;
268
269 }
270
271
272 sub build_org_type { 
273         my($self, $org_typelist)  = @_;
274         for my $type (@$org_typelist) {
275                 $org_typelist_hash->{$type->id()} = $type;
276         }
277 }
278
279
280
281 sub build_org_tree {
282
283         my( $self, $orglist, $add_types ) = @_;
284
285         return $orglist unless ( 
286                         ref($orglist) and @$orglist > 1 );
287
288         my @list = sort { 
289                 $a->ou_type <=> $b->ou_type ||
290                 $a->name cmp $b->name } @$orglist;
291
292         for my $org (@list) {
293
294                 next unless ($org);
295
296                 if(!ref($org->ou_type()) and $add_types) {
297                         $org->ou_type( $org_typelist_hash->{$org->ou_type()});
298                 }
299
300                 next unless (defined($org->parent_ou));
301
302                 my ($parent) = grep { $_->id == $org->parent_ou } @list;
303                 next unless $parent;
304                 $parent->children([]) unless defined($parent->children); 
305                 push( @{$parent->children}, $org );
306         }
307
308         return $list[0];
309
310 }
311
312 sub fetch_user {
313         my $self = shift;
314         my $id = shift;
315         return $self->simple_scalar_request(
316                 'open-ils.storage',
317                 'open-ils.storage.direct.actor.user.retrieve', $id );
318 }
319
320
321
322 # handy tool to handle the ever-recurring situation of someone requesting 
323 # something on someone else's behalf (think staff member creating something for a user)
324 # returns ($requestor, $targetuser_id, $event );
325 # $event may be a PERM_FAILURE event or a NO_SESSION event
326 # $targetuser == $staffuser->id when $targetuser is undefined.
327 sub handle_requestor {
328         my( $self, $authtoken, $targetuser, @permissions ) = @_;
329
330         my( $requestor, $evt ) = $self->check_ses($authtoken);
331         return (undef, undef, $evt) if $evt;
332
333         $targetuser = $requestor->id unless defined $targetuser;
334         my $userobj = $requestor; 
335         $userobj = $self->fetch_user($targetuser) 
336                 unless $targetuser eq $requestor->id;
337
338         if(!$userobj) {} # XXX Friendly exception
339
340         my $perm;
341
342         #everyone is allowed to view their own data
343         if( $targetuser ne $requestor->id ) {
344                 $perm = $self->check_perms( 
345                         $requestor->id, $userobj->home_ou, @permissions );
346         }
347
348         return ($requestor, $targetuser, $perm);
349 }
350
351
352
353
354
355
356 1;