@@ -26,7 +26,19 @@ def localSetUp(self):
2626 # reset the `covidcast_meta_cache` table (it should always have one row)
2727 self ._db ._cursor .execute ('update covidcast_meta_cache set timestamp = 0, epidata = "[]"' )
2828
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 ):
3042 # make the request
3143 if is_compatibility :
3244 url = BASE_URL_OLD
@@ -37,7 +49,7 @@ def _fetch(self, endpoint="/", is_compatibility=False, **params):
3749 params .setdefault ("data_source" , params .get ("source" ))
3850 else :
3951 url = f"{ BASE_URL } { endpoint } "
40- response = requests .get (url , params = params , auth = AUTH )
52+ response = requests .get (url , params = params , auth = auth )
4153 response .raise_for_status ()
4254 return response .json ()
4355
@@ -67,6 +79,28 @@ def test_basic(self):
6779 out = self ._fetch ("/" , signal = first .signal_pair (), geo = first .geo_pair (), time = "day:*" )
6880 self .assertEqual (len (out ["epidata" ]), len (rows ))
6981
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+
70104 def test_compatibility (self ):
71105 """Request at the /api.php endpoint."""
72106 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):
271305 out = self ._fetch ("/meta" , signal = f"{ first .source } :X" )
272306 self .assertEqual (len (out ), 0 )
273307
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+
274337 def test_coverage (self ):
275338 """Request a signal from the /coverage endpoint."""
276339
0 commit comments