@@ -26,7 +26,19 @@ def localSetUp(self):
26
26
# reset the `covidcast_meta_cache` table (it should always have one row)
27
27
self ._db ._cursor .execute ('update covidcast_meta_cache set timestamp = 0, epidata = "[]"' )
28
28
29
- def _fetch (self , endpoint = "/" , is_compatibility = False , ** params ):
29
+ cur = self ._db ._cursor
30
+ # NOTE: we must specify the db schema "epidata" here because the cursor/connection are bound to schema "covid"
31
+ cur .execute ("TRUNCATE TABLE epidata.api_user" )
32
+ cur .execute ("TRUNCATE TABLE epidata.user_role" )
33
+ cur .execute ("TRUNCATE TABLE epidata.user_role_link" )
34
+ cur .execute ("INSERT INTO epidata.api_user (api_key, email) VALUES ('quidel_key', 'quidel_email')" )
35
+ cur .execute ("INSERT INTO epidata.user_role (name) VALUES ('quidel')" )
36
+ cur .execute (
37
+ "INSERT INTO epidata.user_role_link (user_id, role_id) SELECT api_user.id, user_role.id FROM epidata.api_user JOIN epidata.user_role WHERE api_key='quidel_key' and user_role.name='quidel'"
38
+ )
39
+ cur .execute ("INSERT INTO epidata.api_user (api_key, email) VALUES ('key', 'email')" )
40
+
41
+ def _fetch (self , endpoint = "/" , is_compatibility = False , auth = AUTH , ** params ):
30
42
# make the request
31
43
if is_compatibility :
32
44
url = BASE_URL_OLD
@@ -37,7 +49,7 @@ def _fetch(self, endpoint="/", is_compatibility=False, **params):
37
49
params .setdefault ("data_source" , params .get ("source" ))
38
50
else :
39
51
url = f"{ BASE_URL } { endpoint } "
40
- response = requests .get (url , params = params , auth = AUTH )
52
+ response = requests .get (url , params = params , auth = auth )
41
53
response .raise_for_status ()
42
54
return response .json ()
43
55
@@ -67,6 +79,28 @@ def test_basic(self):
67
79
out = self ._fetch ("/" , signal = first .signal_pair (), geo = first .geo_pair (), time = "day:*" )
68
80
self .assertEqual (len (out ["epidata" ]), len (rows ))
69
81
82
+ def test_basic_restricted_source (self ):
83
+ """Request a signal from the / endpoint."""
84
+ rows = [CovidcastTestRow .make_default_row (time_value = 2020_04_01 + i , value = i , source = "quidel" ) for i in range (10 )]
85
+ first = rows [0 ]
86
+ self ._insert_rows (rows )
87
+
88
+ with self .subTest ("validation" ):
89
+ out = self ._fetch ("/" )
90
+ self .assertEqual (out ["result" ], - 1 )
91
+
92
+ with self .subTest ("no_roles" ):
93
+ out = self ._fetch ("/" , signal = first .signal_pair (), geo = first .geo_pair (), time = "day:*" )
94
+ self .assertEqual (len (out ["epidata" ]), 0 )
95
+
96
+ with self .subTest ("no_api_key" ):
97
+ out = self ._fetch ("/" , auth = None , signal = first .signal_pair (), geo = first .geo_pair (), time = "day:*" )
98
+ self .assertEqual (len (out ["epidata" ]), 0 )
99
+
100
+ with self .subTest ("quidel_role" ):
101
+ out = self ._fetch ("/" , auth = ("epidata" , "quidel_key" ), signal = first .signal_pair (), geo = first .geo_pair (), time = "day:*" )
102
+ self .assertEqual (len (out ["epidata" ]), len (rows ))
103
+
70
104
def test_compatibility (self ):
71
105
"""Request at the /api.php endpoint."""
72
106
rows = [CovidcastTestRow .make_default_row (source = "src" , signal = "sig" , time_value = 2020_04_01 + i , value = i ) for i in range (10 )]
@@ -271,6 +305,35 @@ def test_meta(self):
271
305
out = self ._fetch ("/meta" , signal = f"{ first .source } :X" )
272
306
self .assertEqual (len (out ), 0 )
273
307
308
+ def test_meta_restricted (self ):
309
+ """Request 'restricted' signals from the /meta endpoint."""
310
+ # NOTE: this method is nearly identical to ./test_covidcast_meta.py:test_restricted_sources()
311
+ # ...except the self._fetch() methods are different, as is the format of those methods' outputs
312
+ # (the other covidcast_meta endpoint uses APrinter, this one returns its own unadulterated json).
313
+ # additionally, the sample data used here must match entries (that is, named sources and signals)
314
+ # from covidcast_utils.model.data_sources (the `data_sources` variable from file
315
+ # src/server/endpoints/covidcast_utils/model.py, which is created by the _load_data_sources() method
316
+ # and fed by src/server/endpoints/covidcast_utils/db_sources.csv, but also surreptitiously augmened
317
+ # by _load_data_signals() which attaches a list of signals to each source,
318
+ # in turn fed by src/server/endpoints/covidcast_utils/db_signals.csv)
319
+
320
+ # insert data from two different sources, one restricted/protected (quidel), one not
321
+ self ._insert_rows ([
322
+ CovidcastTestRow .make_default_row (source = "quidel" , signal = "raw_pct_negative" ),
323
+ CovidcastTestRow .make_default_row (source = "hhs" , signal = "confirmed_admissions_covid_1d" )
324
+ ])
325
+
326
+ # update metadata cache
327
+ update_cache (args = None )
328
+
329
+ # verify unauthenticated (no api key) or unauthorized (user w/o privilege) only see metadata for one source
330
+ self .assertEqual (len (self ._fetch ("/meta" , auth = None )), 1 )
331
+ self .assertEqual (len (self ._fetch ("/meta" , auth = AUTH )), 1 )
332
+
333
+ # verify authorized user sees metadata for both sources
334
+ qauth = ('epidata' , 'quidel_key' )
335
+ self .assertEqual (len (self ._fetch ("/meta" , auth = qauth )), 2 )
336
+
274
337
def test_coverage (self ):
275
338
"""Request a signal from the /coverage endpoint."""
276
339
0 commit comments