def test_auth_cookie_caches_calls_to_plotly(self): app = dash.Dash() app.scripts.config.serve_locally = True auth = PlotlyAuth(app, 'private-cookie-test', 'private', 'http://localhost:5000') app.layout = html.Div() creator = users['creator']['oauth_token'] with mock.patch('dash_auth.plotly_auth.check_view_access', wraps=plotly_auth.check_view_access) as wrapped: self.check_endpoints(auth, app, creator) res = self.check_endpoints(auth, app, creator) n_endpoints = (len(endpoints['protected']['get']) + len(endpoints['unprotected']['get'])) self.assertEqual(wrapped.call_count, n_endpoints * 2) access_granted_cookie = get_cookie(res, PlotlyAuth.AUTH_COOKIE_NAME) self.check_endpoints(auth, app, creator, ({ 'name': PlotlyAuth.AUTH_COOKIE_NAME, 'value': access_granted_cookie }, )) self.assertEqual(wrapped.call_count, n_endpoints * 2) # Regenerate tokens with a shorter expiration # User's won't actually do this in practice, we're # just doing it to shorten up the expiration from 5 min # to 10 seconds auth.config['permissions_cache_expiry'] = 10 auth.create_access_codes() res = self.check_endpoints(auth, app, creator) self.assertEqual(wrapped.call_count, n_endpoints * 3) # Using the same auth cookie should prevent an # additional access call access_granted_cookie = get_cookie(res, PlotlyAuth.AUTH_COOKIE_NAME) self.check_endpoints(auth, app, creator, ({ 'name': PlotlyAuth.AUTH_COOKIE_NAME, 'value': access_granted_cookie }, )) self.assertEqual(wrapped.call_count, (n_endpoints * 3)) # But after the expiration time (10 seconds), another call to # plotly should be made time.sleep(10) self.check_endpoints(auth, app, creator) self.assertEqual(wrapped.call_count, (n_endpoints * 4))
def test_permissions_can_change(self): app_name = 'private-flip-flop-app-test' app_url = 'http://localhost:5000' app = dash.Dash() app.scripts.config.serve_locally = True auth = PlotlyAuth(app, app_name, 'private', app_url) app.layout = html.Div() auth.config['permissions_cache_expiry'] = 30 auth.create_access_codes() viewer_token = users['viewer']['oauth_token'] with mock.patch('dash_auth.plotly_auth.check_view_access', wraps=plotly_auth.check_view_access) as \ wrapped: n_endpoints = (len(endpoints['protected']['get']) + len(endpoints['unprotected']['get'])) # sanity check the endpoints when the app is private self.check_endpoints(auth, app, viewer_token) self.assertEqual(wrapped.call_count, n_endpoints) # make app public dash_auth.plotly_auth.create_or_overwrite_dash_app( app_name, 'public', app_url) res = self.check_endpoints(auth, app, viewer_token, all_200=True) self.assertEqual(wrapped.call_count, n_endpoints * 2) # The last access granted response contained a cookie that grants # the user access for 30 seconds (5 minutes by default) # without making an API call to plotly. # Include this cookie in the response and verify that it grants # the user access up until the expiration date access_granted_cookie = get_cookie(res, PlotlyAuth.AUTH_COOKIE_NAME) self.assertEqual(access_granted_cookie, auth._access_codes['access_granted']) plotly_auth.create_or_overwrite_dash_app(app_name, 'private', app_url) # Even though the app is private, the viewer will still get 200s access_cookie = ({ 'name': PlotlyAuth.AUTH_COOKIE_NAME, 'value': access_granted_cookie }, ) self.check_endpoints(auth, app, viewer_token, access_cookie, all_200=True) self.assertEqual(wrapped.call_count, n_endpoints * 2) # But after 30 seconds, the auth token will expire, # and the user will be denied access time.sleep(5) self.check_endpoints(auth, app, viewer_token, access_cookie, all_200=True) self.assertEqual(wrapped.call_count, n_endpoints * 2) time.sleep(26) self.check_endpoints(auth, app, viewer_token, access_cookie) self.assertEqual(wrapped.call_count, n_endpoints * 3)