41
41
from jormungandr .exceptions import ApiNotFound , RegionNotFound , DeadSocketException , InvalidArguments
42
42
from jormungandr import authentication , cache , app
43
43
from jormungandr .instance import Instance
44
- from jormungandr .utils import can_connect_to_database
45
44
import gevent
46
45
import os
47
46
@@ -154,7 +153,7 @@ def initialization(self):
154
153
def _clear_cache (self ):
155
154
logging .getLogger (__name__ ).info ('clear cache' )
156
155
try :
157
- cache .delete_memoized (self ._all_keys_of_id )
156
+ cache .delete_memoized (self ._exists_id_in_instance )
158
157
except :
159
158
# if there is an error with cache, flask want to access to the app, this will fail at startup
160
159
# with a "working outside of application context"
@@ -219,21 +218,19 @@ def stop(self):
219
218
if not self .thread_event .is_set ():
220
219
self .thread_event .set ()
221
220
222
- def _filter_authorized_instances (self , instances , api ):
223
- if not instances :
224
- return []
225
- # get_user is cached hence access to database only once when cache expires.
226
- user = authentication .get_user (token = authentication .get_token ())
227
- # has_access returns true if can_connect_to_database = false when cache expires for each coverage
228
- valid_instances = [
229
- i for i in instances if authentication .has_access (i .name , abort = False , user = user , api = api )
221
+ def _get_authorized_instances (self , user , api ):
222
+ authorized_instances = [
223
+ i
224
+ for name , i in self .instances .items ()
225
+ if authentication .has_access (name , abort = False , user = user , api = api )
230
226
]
231
- if not valid_instances :
227
+
228
+ if not authorized_instances :
232
229
context = 'User has no access to any instance'
233
230
authentication .abort_request (user , context )
234
- return valid_instances
231
+ return authorized_instances
235
232
236
- def _find_coverage_by_object_id (self , object_id ):
233
+ def _find_coverage_by_object_id_in_instances (self , instances , object_id ):
237
234
if object_id .count (";" ) == 1 or object_id [:6 ] == "coord:" :
238
235
if object_id .count (";" ) == 1 :
239
236
lon , lat = object_id .split (";" )
@@ -244,32 +241,33 @@ def _find_coverage_by_object_id(self, object_id):
244
241
flat = float (lat )
245
242
except :
246
243
raise InvalidArguments (object_id )
247
- return self ._all_keys_of_coord (flon , flat )
248
- return self ._all_keys_of_id (object_id )
244
+ return self ._all_keys_of_coord_in_instances (instances , flon , flat )
249
245
250
- @cache .memoize (app .config [str ('CACHE_CONFIGURATION' )].get (str ('TIMEOUT_PTOBJECTS' ), None ))
251
- def _all_keys_of_id (self , object_id ):
252
- instances = []
253
- futures = {}
254
- for name , instance in self .instances .items ():
255
- futures [name ] = gevent .spawn (instance .has_id , object_id )
256
- for name , future in futures .items ():
257
- if future .get ():
258
- instances .append (name )
246
+ return self ._all_keys_of_id_in_instances (instances , object_id )
259
247
260
- if not instances :
248
+ def _all_keys_of_id_in_instances (self , instances , object_id ):
249
+ valid_instances = []
250
+ for instance in instances :
251
+ if self ._exists_id_in_instance (instance , object_id ):
252
+ valid_instances .append (instance )
253
+ if not valid_instances :
261
254
raise RegionNotFound (object_id = object_id )
262
- return instances
263
255
264
- def _all_keys_of_coord (self , lon , lat ):
256
+ return valid_instances
257
+
258
+ @cache .memoize (app .config [str ('CACHE_CONFIGURATION' )].get (str ('TIMEOUT_PTOBJECTS' ), None ))
259
+ def _exists_id_in_instance (self , instance , object_id ):
260
+ return instance .has_id (object_id )
261
+
262
+ def _all_keys_of_coord_in_instances (self , instances , lon , lat ):
265
263
p = geometry .Point (lon , lat )
266
- instances = [i . name for i in self . instances . values () if i .has_point (p )]
264
+ valid_instances = [i for i in instances if i .has_point (p )]
267
265
logging .getLogger (__name__ ).debug (
268
- "all_keys_of_coord (self, {}, {}) returns {}" .format (lon , lat , instances )
266
+ "_all_keys_of_coord_in_instances (self, {}, {}) returns {}" .format (lon , lat , instances )
269
267
)
270
- if not instances :
268
+ if not valid_instances :
271
269
raise RegionNotFound (lon = lon , lat = lat )
272
- return instances
270
+ return valid_instances
273
271
274
272
def get_region (self , region_str = None , lon = None , lat = None , object_id = None , api = 'ALL' ):
275
273
return self .get_regions (region_str , lon , lat , object_id , api , only_one = True )
@@ -284,27 +282,34 @@ def get_regions(self, region_str=None, lon=None, lat=None, object_id=None, api='
284
282
return [i .name for i in valid_instances ]
285
283
286
284
def get_instances (self , name = None , lon = None , lat = None , object_id = None , api = 'ALL' ):
287
- available_instances = []
285
+ if name and name not in self .instances :
286
+ raise RegionNotFound (region = name )
287
+
288
+ # Request without token or bad token makes a request exception and exits with a message
289
+ # get_user is cached hence access to database only once when cache expires.
290
+ user = authentication .get_user (token = authentication .get_token ())
291
+
292
+ # fetch all the authorized instances (free + private) using cached function has_access()
293
+ authorized_instances = self ._get_authorized_instances (user , api )
294
+ if not authorized_instances :
295
+ # user doesn't have access to any of the instances
296
+ context = 'User has no access to any instance'
297
+ authentication .abort_request (user = user , context = context )
298
+
299
+ # Filter instances among instances in authorized_instances
288
300
if name :
289
- if name in self .instances :
290
- available_instances = [self .instances [name ]]
301
+ valid_instances = [i for i in authorized_instances if i .name == name ]
291
302
elif lon and lat :
292
- available_instances = [
293
- self .instances [k ] for k in self ._all_keys_of_coord (lon , lat ) if k in self .instances
294
- ]
303
+ valid_instances = self ._all_keys_of_coord_in_instances (authorized_instances , lon , lat )
295
304
elif object_id :
296
- instance_keys = self ._find_coverage_by_object_id (object_id )
297
- if instance_keys is None :
298
- available_instances = []
299
- else :
300
- available_instances = [self .instances [k ] for k in instance_keys if k in self .instances ]
305
+ valid_instances = self ._find_coverage_by_object_id_in_instances (authorized_instances , object_id )
301
306
else :
302
- available_instances = list ( self . instances . values ())
303
- valid_instances = self . _filter_authorized_instances ( available_instances , api )
304
- if available_instances and not valid_instances :
307
+ valid_instances = authorized_instances
308
+
309
+ if not valid_instances :
305
310
# user doesn't have access to any of the instances
306
- context = ' User does not have access to any of the instances'
307
- authentication .abort_request (user = authentication . get_user ( None ) , context = context )
311
+ context = " User has no access to any instance or instance doesn't exist"
312
+ authentication .abort_request (user = user , context = context )
308
313
else :
309
314
return valid_instances
310
315
0 commit comments