def test_oauth2callback_path_succeeds_for_existing_user(self): google_api.httplib2.Http = MockHttp # Create dummy user now = datetime.now() user = User(profile_slug='dummy_user', google_id='12345', created_at=now, last_login_at=now, modified_at=now) user.put() num_users = User.all().count() response = main.app.get_response('/auth/oauth2callback?code=abc123') # Ensure existing user record has been updated with info from Google (data/user_info.json) user = User.get_by_google_id('12345') self.assertEqual(num_users, User.all().count()) self.assertEqual(user.google_birthday, '0000-01-01') self.assertEqual(user.google_email, '*****@*****.**') self.assertEqual(user.google_gender, 'male') self.assertEqual(user.google_locale, 'en-GB') self.assertEqual(user.google_name, 'Dummy User') self.assertEqual(user.google_picture_url, 'https://lh3.googleusercontent.com/photo.jpg') # Ensure correct response self.assertEqual(response.status_int, 302) self.assertTrue('Location' in response.headers) self.assertTrue('http://localhost/' in response.headers['Location'])
def delete(self, data_source_id, data_view_id): try: current_user = User.get_by_google_id(self.session['current_user']) data_source = DataSource.get_by_id(int(data_source_id)) data_view = DataView.get_by_id(int(data_view_id)) if data_source is None: raise ValueError("No Data Source exists with id %s" % data_source_id) if not data_source.user.key() == current_user.key(): raise ValueError("Data Source with id %s does not belong to user '%s'" % (data_source_id, current_user.profile_slug)) if data_view is None: raise ValueError("No Data View exists with id %s" % data_source_id) if not data_view.data_source.key() == data_source.key(): raise ValueError("Data View with id %s does not belong to Data Source with id %s" % (data_view_id, data_source_id)) data_view.delete() self.response.write('{"response":"success","body":"Data View deleted"}') except ValueError as e: log_api_error(self, e) self.response.write('{"response":"error","body":"%s"}' % e) self.response.set_status(404) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem deleting data source"}') self.response.set_status(500)
def get(self, data_source_id, data_view_id): try: current_user = User.get_by_google_id(self.session['current_user']) data_source = DataSource.get_by_id(int(data_source_id)) data_view = DataView.get_by_id(int(data_view_id)) if data_source is None: raise ValueError("No Data Source exists with id %s" % data_source_id) if not data_source.user.key() == current_user.key(): raise ValueError("Data Source with id %s does not belong to user '%s'" % (data_source_id, current_user.profile_slug)) if data_view is None: raise ValueError("No Data View exists with id %s" % data_source_id) if not data_view.data_source.key() == data_source.key(): raise ValueError("Data View with id %s does not belong to Data Source with id %s" % (data_view_id, data_source_id)) self.response.write('{"response":"success","body":%s}' % json.dumps(data_view.to_dict(default_template=True), ensure_ascii=False)) except ValueError as e: log_api_error(self, e) self.response.write('{"response":"error","body":"%s"}' % e) self.response.set_status(404) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem fetching data source"}') self.response.set_status(500)
def post(self, data_source_id, data_view_id): try: current_user = User.get_by_google_id(self.session['current_user']) data_source = DataSource.get_by_id(int(data_source_id)) data_view = DataView.get_by_id(int(data_view_id)) payload = json.loads(self.request.POST["payload"]) if data_source is None: raise ValueError("No Data Source exists with id %s" % data_source_id) if not data_source.user.key() == current_user.key(): raise ValueError("Data Source with id %s does not belong to user '%s'" % (data_source_id, current_user.profile_slug)) if data_view is None: raise ValueError("No Data View exists with id %s" % data_source_id) if not data_view.data_source.key() == data_source.key(): raise ValueError("Data View with id %s does not belong to Data Source with id %s" % (data_view_id, data_source_id)) if "template" in payload.keys(): data_view.template = payload['template'] data_view.modified_at = DT.now() data_view.put() self.response.write('{"response":"success","body":%s}' % json.dumps(data_view.to_dict(), ensure_ascii=False)) except ValueError as e: log_api_error(self, e) self.response.write('{"response":"error","body":"%s"}' % e) self.response.set_status(404) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem updating data source"}') self.response.set_status(500)
def post(self, data_source_id): try: payload = json.loads(self.request.POST["payload"]) current_user = User.get_by_google_id(self.session['current_user']) data_source = DataSource.get_by_id(int(data_source_id)) if data_source is None: raise ValueError("No Data Source exists with id %s" % data_source_id) if not data_source.user.key() == current_user.key(): raise ValueError("Data Source with id %s does not belong to user '%s'" % (data_source_id, current_user.profile_slug)) if "description" in payload.keys(): data_source.description = payload['description'] if "licence" in payload.keys(): data_source.licence = payload['licence'] if "slug" in payload.keys(): data_source.slug = payload['slug'] if "tags" in payload.keys(): data_source.tags = payload['tags'] if "tbl_stars" in payload.keys(): data_source.tbl_stars = int(payload['tbl_stars']) if "title" in payload.keys(): data_source.title = payload['title'] data_source.modified_at = DT.now() data_source.put() self.response.write('{"response":"success","body":%s}' % json.dumps(data_source.to_dict(), ensure_ascii=False)) except ValueError as e: log_api_error(self, e) self.response.write('{"response":"error","body":"%s"}' % e) self.response.set_status(404) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem updating data source"}') self.response.set_status(500)
def get(self, data_source_id): try: current_user = User.get_by_google_id(self.session['current_user']) data_source = DataSource.get_by_id(int(data_source_id)) if data_source is None: raise ValueError("No Data Source exists with id %s" % data_source_id) if not data_source.user.key() == current_user.key(): raise ValueError("Data Source with id %s does not belong to user '%s'" % (data_source_id, current_user.profile_slug)) data_views = data_source.fetch_data_views() response = { 'total_results': len(data_views), 'data_views': [ds.to_dict() for ds in data_views] } self.response.write('{"response":"success","body":%s}' % json.dumps(response, ensure_ascii=False)) except ValueError as e: log_api_error(self, e) self.response.write('{"response":"error","body":"%s"}' % e) self.response.set_status(404) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem fetching data sources"}') self.response.set_status(500)
def current_user(self, user=None): if user: self.session['current_user'] = user.google_id if 'current_user' in self.session: return User.get_by_google_id(self.session['current_user']) else: return None
def get(self): try: # NB we have to decode "credentials" as it is stored as a string in the DB current_user = User.get_by_google_id(self.session['current_user']).to_dict() current_user["credentials"] = json.loads(current_user["credentials"]) self.response.write('{"response":"success","body":%s}' % json.dumps(current_user, ensure_ascii=False)) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem fetching user profile"}') self.response.set_status(500)
def setUp(self): self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() # Get headers for making authenticated requests google_api.httplib2.Http = MockHttp response = main.app.get_response('/auth/oauth2callback?code=dummy_code') self.auth_headers = {'Cookie': response.headers['Set-Cookie']} # Get the authenticated user response = main.app.get_response('/api/0/user', headers=self.auth_headers) self.current_user = User.get_by_google_id(json.loads(response.body)['body']['google_id'])
def get(self): try: current_user = User.get_by_google_id(self.session['current_user']) data_sources = current_user.fetch_data_sources() response = { 'total_results': len(data_sources), 'data_sources': [ds.to_dict() for ds in data_sources] } self.response.write('{"response":"success","body":%s}' % json.dumps(response, ensure_ascii=False)) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem fetching data sources"}') self.response.set_status(500)
def test_oauth2callback_path_succeeds_for_new_user(self): google_api.httplib2.Http = MockHttp num_users = User.all().count() response = main.app.get_response('/auth/oauth2callback?code=abc123') # Ensure new user record has been created with info from Google (data/user_info.json) user = User.get_by_google_id('12345') self.assertEqual(num_users+1, User.all().count()) self.assertEqual(user.google_birthday, '0000-01-01') self.assertEqual(user.google_email, '*****@*****.**') self.assertEqual(user.google_gender, 'male') self.assertEqual(user.google_locale, 'en-GB') self.assertEqual(user.google_name, 'Dummy User') self.assertEqual(user.google_picture_url, 'https://lh3.googleusercontent.com/photo.jpg') # Ensure correct response self.assertEqual(response.status_int, 302) self.assertTrue('Location' in response.headers) self.assertTrue('http://localhost/' in response.headers['Location'])
def post(self): try: data = json.loads(self.request.POST["payload"]) user = User.get_by_google_id(self.session['current_user']) if None == user: self.response.write('{"response":"error","body":"Unknown User"}') self.response.set_status(500) return if "profile_name" in data.keys(): user.profile_name = data["profile_name"] if "profile_email" in data.keys(): user.profile_email = data["profile_email"] if "profile_description" in data.keys(): user.profile_description = data["profile_description"] if "profile_web_address" in data.keys(): user.profile_web_address = data["profile_web_address"] # TODO allow editing profile slug - must check for collisions - issue#46 user.modified_at = DT.now() user.put() self.response.write('{"response":"success","body":%s}' % json.dumps(user.to_dict(), ensure_ascii=False)) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem updating profile"}') self.response.set_status(500)
def post(self): try: current_user = User.get_by_google_id(self.session['current_user']) payload = json.loads(self.request.POST["payload"]) data_source = DataSource( google_spreadsheet = payload['key'], google_worksheet = payload['id'], title = payload['title'], slug = slug.create(payload['title']), created_at = DT.now(), modified_at = DT.now()) data_source.user = current_user.key() data_source.put() self.response.write('{"response":"success","body":%s}' % json.dumps(data_source.to_dict(), ensure_ascii=False)) except slug.SlugError as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem creating slug for data source"}') self.response.set_status(500) except Exception as e: log_api_error(self, e) self.response.write('{"response":"error","body":"Unknown problem creating data source"}') self.response.set_status(500)
def log_api_error(obj,error): current_user = User.get_by_google_id(obj.session['current_user']) msg_info = (obj.request.method, obj.request.path_url, obj.request.POST.items(), error, error.__class__, current_user.profile_slug) logging.error("%s %s %s 500 '%s' %s [%s]" % msg_info)
def test_user_method_get_by_google_id(self): user = self.make_user() self.assertEqual(user.key(), User.get_by_google_id(dummy.user['google_id']).key())
def get(self): code = self.request.GET.get('code') logging.debug("Auth Code: %s" % code) logging.debug("Session (at start): %s" % self.session) if None == code: # TODO Display cancelled login page issue#27 return self.response.write('No authentication code returned') try: flow = google_api.oauth2_flow() auth = flow.step2_exchange(code) now = datetime.now() # Get Google user info google_user = google_api.user_info(auth.to_json()) # Attempt to fetch user record from DB with matching google_id user = User.get_by_google_id(google_user.get('id')) # Create user if none exists if user == None: profile_slug = slug.create(google_user['email'].split('@')[0]) user = User( google_id = google_user.get('id'), profile_name = google_user.get('name'), profile_slug = profile_slug, created_at = now, modified_at = now, last_login_at = now) # We expect a refresh token, so store it issue#22 user.credentials = auth.to_json() # TODO The following may be causing occasional invalid grant errors issue#22 # logging.debug("User Refresh Token: %s" % user.refresh_token()) # # Do nothing if we have a refresh token # if user.refresh_token(): # logging.debug("User has existing Refresh Token") # pass # # Store refresh token if we can # elif None == user.refresh_token() and auth.refresh_token: # logging.debug("Storing Refresh Token for User") # user.credentials = auth.to_json() # # Go get a refresh token if we need one # else: # logging.debug("Fetching Refresh Token") # logging.debug("Redirect to: /auth/login?approval_prompt") # return self.redirect('/auth/login?approval_prompt') # Update user account # https://github.com/opendatapress/open_data_press/issues/5#issuecomment-23477495 user.google_birthday = google_user.get('birthday') user.google_email = google_user.get('email') user.google_gender = google_user.get('gender') user.google_locale = google_user.get('locale') user.google_name = google_user.get('name') user.google_picture_url = google_user.get('picture', '/img/default_avatar_%s.png' % random.randrange(1,8)) user.last_login_at = now user.put() # Create session logging.debug("Creating session for user: %s" % user.google_id) self.current_user(user) # Redirect to provided url if set if 'redirect_url' in self.session.keys(): url = str(self.session['redirect_url']) del self.session['redirect_url'] return self.redirect(url) # Redirect to dashboard instead logging.debug("Session (at end): %s" % self.session) logging.debug("Redirect to: /dashboard") self.redirect('/dashboard') except Exception as e: error_500(self.request, self.response, e)