1616from StringIO import StringIO as BytesIO
1717
1818from dropbox import (
19+ create_session ,
1920Dropbox ,
2021DropboxOAuth2Flow ,
2122DropboxTeam ,
3940PathRoot ,
4041PathRoot_validator ,
4142)
43+ from dropbox .session import SSLError
4244
4345# Key Types
4446REFRESH_TOKEN_KEY = "REFRESH_TOKEN"
@@ -65,34 +67,43 @@ def _value_from_env_or_die(env_name):
6567sys .exit (1 )
6668return value
6769
70+ _TRUSTED_CERTS_FILE = os .path .join (os .path .dirname (__file__ ),"trusted-certs.crt" )
71+ _EXPIRED_CERTS_FILE = os .path .join (os .path .dirname (__file__ ),"expired-certs.crt" )
72+
73+ # enables testing both with and without a manually-provided CA bundle
74+ @pytest .fixture (params = [None ,_TRUSTED_CERTS_FILE ],ids = ["no-pinning" ,"pinning" ])
75+ def dbx_session (request ):
76+ return create_session (ca_certs = request .param )
77+
6878
6979@pytest .fixture ()
70- def dbx_from_env ():
80+ def dbx_from_env (dbx_session ):
7181oauth2_token = _value_from_env_or_die (format_env_name ())
72- return Dropbox (oauth2_token )
82+ return Dropbox (oauth2_token , session = dbx_session )
7383
7484
7585@pytest .fixture ()
76- def refresh_dbx_from_env ():
86+ def refresh_dbx_from_env (dbx_session ):
7787refresh_token = _value_from_env_or_die (format_env_name (SCOPED_KEY ,USER_KEY ,REFRESH_TOKEN_KEY ))
7888app_key = _value_from_env_or_die (format_env_name (SCOPED_KEY ,USER_KEY ,CLIENT_ID_KEY ))
7989app_secret = _value_from_env_or_die (format_env_name (SCOPED_KEY ,USER_KEY ,CLIENT_SECRET_KEY ))
8090return Dropbox (oauth2_refresh_token = refresh_token ,
81- app_key = app_key ,app_secret = app_secret )
91+ app_key = app_key ,app_secret = app_secret ,
92+ session = dbx_session )
8293
8394
8495@pytest .fixture ()
85- def dbx_team_from_env ():
96+ def dbx_team_from_env (dbx_session ):
8697team_oauth2_token = _value_from_env_or_die (
8798format_env_name (SCOPED_KEY ,TEAM_KEY ,ACCESS_TOKEN_KEY ))
88- return DropboxTeam (team_oauth2_token )
99+ return DropboxTeam (team_oauth2_token , session = dbx_session )
89100
90101
91102@pytest .fixture ()
92- def dbx_app_auth_from_env ():
103+ def dbx_app_auth_from_env (dbx_session ):
93104app_key = _value_from_env_or_die (format_env_name (SCOPED_KEY ,USER_KEY ,CLIENT_ID_KEY ))
94105app_secret = _value_from_env_or_die (format_env_name (SCOPED_KEY ,USER_KEY ,CLIENT_SECRET_KEY ))
95- return Dropbox (app_key = app_key ,app_secret = app_secret )
106+ return Dropbox (app_key = app_key ,app_secret = app_secret , session = dbx_session )
96107
97108
98109@pytest .fixture ()
@@ -110,7 +121,7 @@ def dbx_share_url_from_env():
110121TIMESTAMP = str (datetime .datetime .utcnow ())
111122STATIC_FILE = "/test.txt"
112123
113- @pytest .fixture (scope = 'module' , autouse = True )
124+ @pytest .fixture (scope = 'module' )
114125def pytest_setup ():
115126print ("Setup" )
116127dbx = Dropbox (_value_from_env_or_die (format_env_name ()))
@@ -125,47 +136,14 @@ def pytest_setup():
125136except Exception :
126137print ("File not found" )
127138
128-
129139@pytest .mark .usefixtures (
140+ "pytest_setup" ,
130141"dbx_from_env" ,
131142"refresh_dbx_from_env" ,
132143"dbx_app_auth_from_env" ,
133- "dbx_share_url_from_env"
144+ "dbx_share_url_from_env" ,
134145)
135146class TestDropbox :
136- def test_default_oauth2_urls (self ):
137- flow_obj = DropboxOAuth2Flow ('dummy_app_key' ,'dummy_app_secret' ,
138- 'http://localhost/dummy' ,'dummy_session' ,'dbx-auth-csrf-token' )
139-
140- assert re .match (
141- r'^https://{}/oauth2/authorize\?' .format (re .escape (session .WEB_HOST )),
142- flow_obj ._get_authorize_url ('http://localhost/redirect' ,'state' ,'legacy' ),
143- )
144-
145- assert flow_obj .build_url (
146- '/oauth2/authorize'
147- )== 'https://{}/oauth2/authorize' .format (session .API_HOST )
148-
149- assert flow_obj .build_url (
150- '/oauth2/authorize' ,host = session .WEB_HOST
151- )== 'https://{}/oauth2/authorize' .format (session .WEB_HOST )
152-
153- def test_bad_auth (self ):
154- # Test malformed token
155- malformed_token_dbx = Dropbox (MALFORMED_TOKEN )
156- # TODO: backend is no longer returning `BadInputError`
157- # with pytest.raises(BadInputError,) as cm:
158- # malformed_token_dbx.files_list_folder('')
159- # assert 'token is malformed' in cm.value.message
160- with pytest .raises (AuthError ,):
161- malformed_token_dbx .files_list_folder ('' )
162-
163- # Test reasonable-looking invalid token
164- invalid_token_dbx = Dropbox (INVALID_TOKEN )
165- with pytest .raises (AuthError )as cm :
166- invalid_token_dbx .files_list_folder ('' )
167- assert cm .value .error .is_invalid_access_token ()
168-
169147def test_multi_auth (self ,dbx_from_env ,dbx_app_auth_from_env ,dbx_share_url_from_env ):
170148# Test for user (with oauth token)
171149preview_result ,resp = dbx_from_env .files_get_thumbnail_v2 (
@@ -280,7 +258,10 @@ def test_versioned_route(self, dbx_from_env):
280258# Verify response type is of v2 route
281259assert isinstance (resp ,DeleteResult )
282260
283- @pytest .mark .usefixtures ("dbx_team_from_env" )
261+ @pytest .mark .usefixtures (
262+ "pytest_setup" ,
263+ "dbx_team_from_env" ,
264+ )
284265class TestDropboxTeam :
285266def test_team (self ,dbx_team_from_env ):
286267dbx_team_from_env .team_groups_list ()
@@ -310,3 +291,48 @@ def test_clone_when_team_linked(self, dbx_team_from_env):
310291new_dbxt = dbx_team_from_env .clone ()
311292assert dbx_team_from_env is not new_dbxt
312293assert isinstance (new_dbxt ,dbx_team_from_env .__class__ )
294+
295+ def test_default_oauth2_urls ():
296+ flow_obj = DropboxOAuth2Flow ('dummy_app_key' ,'dummy_app_secret' ,
297+ 'http://localhost/dummy' ,'dummy_session' ,'dbx-auth-csrf-token' )
298+
299+ assert re .match (
300+ r'^https://{}/oauth2/authorize\?' .format (re .escape (session .WEB_HOST )),
301+ flow_obj ._get_authorize_url ('http://localhost/redirect' ,'state' ,'legacy' ),
302+ )
303+
304+ assert flow_obj .build_url (
305+ '/oauth2/authorize'
306+ )== 'https://{}/oauth2/authorize' .format (session .API_HOST )
307+
308+ assert flow_obj .build_url (
309+ '/oauth2/authorize' ,host = session .WEB_HOST
310+ )== 'https://{}/oauth2/authorize' .format (session .WEB_HOST )
311+
312+ def test_bad_auth (dbx_session ):
313+ # Test malformed token
314+ malformed_token_dbx = Dropbox (MALFORMED_TOKEN ,session = dbx_session )
315+ # TODO: backend is no longer returning `BadInputError`
316+ # with pytest.raises(BadInputError,) as cm:
317+ # malformed_token_dbx.files_list_folder('')
318+ # assert 'token is malformed' in cm.value.message
319+ with pytest .raises (AuthError ):
320+ malformed_token_dbx .files_list_folder ('' )
321+
322+ # Test reasonable-looking invalid token
323+ invalid_token_dbx = Dropbox (INVALID_TOKEN ,session = dbx_session )
324+ with pytest .raises (AuthError )as cm :
325+ invalid_token_dbx .files_list_folder ('' )
326+ assert cm .value .error .is_invalid_access_token ()
327+
328+ def test_bad_pins ():
329+ # sanity-check: if we're pinning using expired pins, we should fail w/ an SSL error
330+ _dbx = Dropbox ("dummy_token" ,ca_certs = _EXPIRED_CERTS_FILE )
331+ with pytest .raises (SSLError ,):
332+ _dbx .files_list_folder ('' )
333+
334+ def test_bad_pins_session ():
335+ _session = create_session (ca_certs = _EXPIRED_CERTS_FILE )
336+ _dbx = Dropbox ("dummy_token2" ,session = _session )
337+ with pytest .raises (SSLError ,):
338+ _dbx .files_list_folder ('' )