Пример #1
0
    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'])
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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)
Пример #6
0
    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)
Пример #7
0
    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
Пример #8
0
    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)
Пример #9
0
    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'])
Пример #10
0
    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)
Пример #11
0
    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'])
Пример #12
0
    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)
Пример #13
0
    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)
Пример #14
0
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)
Пример #15
0
 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())
Пример #16
0
    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)