Example #1
0
    def post(self, test):
        """Create a new timeline card for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)

        if service is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        message = self.request.body

        data = json.loads(message)

        body = {}
        body["text"] = data["text"]

        try:
            # Insert timeline card and return as reponse
            result = service.timeline().insert(body=body).execute()
            self.response.status = 200
            self.response.out.write(json.dumps(result))
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
Example #2
0
    def get(self, test):
        """Retrieve submissions for the current user."""
        
        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        if gplus_id is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()

        if user is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        items = []
        submissions = Submission.query(ancestor=user.key).order(-Submission.date).fetch(50)
        for submission in submissions:
            items.append({
              "id": submission.key.id(),
              "colour": submission.colour,
              "url": submission.url,
              "date": submission.date.strftime("%Y-%m-%dT%H:%M:%S.%f")
            })
        
        self.response.out.write(json.dumps({"items": items}))        
Example #3
0
    def post(self, test):
        """Create a new timeline card for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)

        if service is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        message = self.request.body

        data = json.loads(message)

        body = {}
        body["text"] = data["text"]

        try:
            # Insert timeline card and return as reponse
            result = service.timeline().insert(body=body).execute()
            self.response.status = 200
            self.response.out.write(json.dumps(result))
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
Example #4
0
    def post(self):
        """Create a new timeline card for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id)

        if service is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        message = self.request.body

        data = json.loads(message)

        body = {}
        body["text"] = data["text"]
        if "image" in data:
            body["attachments"] = [{"contentType": "image/*", "contentUrl": data["image"]}]
        body["menuItems"] = [{"action": "SHARE"}, {"action": "REPLY"}]

        try:
            # Insert timeline card and return as reponse
            result = service.timeline().insert(body=body).execute()
            self.response.status = 200
            self.response.out.write(json.dumps(result))
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
Example #5
0
    def get(self, test, timelineId, attachmentId):
        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)
        if service is None:
            self.response.content_type = "application/json"
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Invalid credentials."))
            return

        attachment_metadata = service.timeline().attachments().get(
            itemId=timelineId, attachmentId=attachmentId).execute()
        content_type = str(attachment_metadata.get("contentType"))
        content_url = attachment_metadata.get("contentUrl")
        resp, content = service._http.request(content_url)

        if resp.status == 200:
            self.response.content_type = content_type
            self.response.out.write(content)
        else:
            logging.info(resp)
            self.response.content_type = "application/json"
            self.response.status = resp.status
            self.response.out.write(
                utils.createError(resp.status,
                                  "Unable to retrieve attachment."))
Example #6
0
    def post(self):
        """
        Exchange the one-time authorization code for a token and verify user.
        Return a channel token for push notifications on success
        """

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = ("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" % access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's client ID does not match the app's client ID"))
            return

        token = channel.create_channel(result["email"])

        self.session["credentials"] = credentials

        self.response.status = 200
        self.response.out.write(utils.createMessage({"token": token}))
Example #7
0
    def post(self):
        """
            Exchange the one-time authorization code for a token and verify user.

            Return a channel token for push notifications on success
        """

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = ("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" % access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's client ID does not match the app's client ID"))
            return

        token = channel.create_channel(result["email"])

        self.response.status = 200
        self.response.out.write(utils.createMessage({"token": token}))
Example #8
0
    def post(self):
        """Revoke current user's token and reset their session."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")

        # Only disconnect a connected user.
        credentials = get_credentials(gplus_id)
        if credentials is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        # Deregister contacts and subscriptions
        service = get_auth_service(gplus_id)

        result = service.contacts().list().execute()
        logging.info(result)
        if "items" in result:
            for contact in result["items"]:
                del_result = service.contacts().delete(
                    id=contact["id"]).execute()
                logging.info(del_result)

        result = service.subscriptions().list().execute()
        logging.info(result)
        if "items" in result:
            for subscription in result["items"]:
                del_result = service.subscriptions().delete(
                    id=subscription["id"]).execute()
                logging.info(del_result)

        # Execute HTTP GET request to revoke current token.
        access_token = credentials.access_token
        url = "https://accounts.google.com/o/oauth2/revoke?token=%s" % access_token
        h = httplib2.Http()
        result = h.request(url, "GET")[0]

        ndb.Key("User", gplus_id).delete()

        if result["status"] == "200":
            # Reset the user's session.
            self.response.status = 200
            self.response.out.write(
                utils.createMessage("Successfully disconnected user."))
        else:
            # For whatever reason, the given token was invalid.
            self.response.status = 400
            self.response.out.write(
                utils.createError(400,
                                  "Failed to revoke token for given user."))
Example #9
0
    def post(self):
        """Revoke current user's token and reset their session."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")

        # Only disconnect a connected user.
        credentials = get_credentials(gplus_id)
        if credentials is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        # Deregister contacts and subscriptions
        service = get_auth_service(gplus_id)

        result = service.contacts().list().execute()
        logging.info(result)
        if "items" in result:
            for contact in result["items"]:
                del_result = service.contacts().delete(id=contact["id"]).execute()
                logging.info(del_result)

        result = service.subscriptions().list().execute()
        logging.info(result)
        if "items" in result:
            for subscription in result["items"]:
                del_result = service.subscriptions().delete(id=subscription["id"]).execute()
                logging.info(del_result)

        # Execute HTTP GET request to revoke current token.
        access_token = credentials.access_token
        url = "https://accounts.google.com/o/oauth2/revoke?token=%s" % access_token
        h = httplib2.Http()
        result = h.request(url, "GET")[0]

        ndb.Key("User", gplus_id).delete()

        if result["status"] == "200":
            # Reset the user's session.
            self.response.status = 200
            self.response.out.write(utils.createMessage("Successfully disconnected user."))
        else:
            # For whatever reason, the given token was invalid.
            self.response.status = 400
            self.response.out.write(utils.createError(400, "Failed to revoke token for given user."))
Example #10
0
    def post(self, id):

        self.response.content_type = "application/json"

        if self._content is None:
            self.response.status = 400
            self.response.out.write(
                utils.createError(
                    400, "Couldn't decode content or invalid content-type"))

        # Trying to access card to see if user is allowed to
        request = self._service.timeline().get(id=id)
        try:
            card = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        # 2) Insert data into cloud storage
        write_retry_params = gcs.RetryParams(backoff_factor=1.1)
        file_name = str(uuid.uuid4())
        gcs_file = gcs.open(bucket + "/" + file_name,
                            'w',
                            content_type=self._content_type,
                            retry_params=write_retry_params)
        gcs_file.write(self._content)
        gcs_file.close()

        # 3) Update card with attachment info
        if not "attachments" in card:
            card["attachments"] = []

        attachment = {
            "id":
            file_name,
            "contentType":
            self._content_type,
            "contentUrl":
            "%s/upload/mirror/v1/timeline/%s/attachments/%s" %
            (utils.base_url, card["id"], file_name),
            "isProcessing":
            False
        }

        card["attachments"].append(attachment)

        request = self._service.internal().timeline().update(id=card["id"],
                                                             body=card)

        try:
            result = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        self.response.status = 200
        self.response.out.write(json.dumps(result))
Example #11
0
    def put(self, id):

        self.response.content_type = "application/json"

        if self._content is None:
            self.response.status = 400
            self.response.out.write(utils.createError(400, "Couldn't decode content or invalid content-type"))

        # Trying to access card to see if user is allowed to
        request = self._service.timeline().get(id=id)
        try:
            card = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        # 2) Insert data into cloud storage
        write_retry_params = gcs.RetryParams(backoff_factor=1.1)
        file_name = str(uuid.uuid4())
        gcs_file = gcs.open(bucket + "/" + file_name,
                        'w',
                        content_type=self._content_type,
                        retry_params=write_retry_params)
        gcs_file.write(self._content)
        gcs_file.close()

        # 3) Update card with attachment info and new metainfo
        if self._metainfo is None:
            new_card = {}
        else:
            new_card = self._metainfo

        if "attachments" in card:
            new_card["attachments"] = card["attachments"]
        else:
            new_card["attachments"] = []

        attachment = {
            "id": file_name,
            "contentType": self._content_type,
            "contentUrl": "%s/upload/mirror/v1/timeline/%s/attachments/%s" % (utils.base_url, card["id"], file_name),
            "isProcessing": False
        }

        new_card["attachments"].append(attachment)

        request = self._service.internal().timeline().update(id=card["id"], body=new_card)

        try:
            result = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        self.response.status = 200
        self.response.out.write(json.dumps(result))
Example #12
0
    def post(self, id):

        self.response.content_type = "application/json"

        if self._content is None:
            self.response.status = 400
            self.response.out.write(
                utils.createError(
                    400, "Couldn't decode content or invalid content-type"))

        # Trying to access card to see if user is allowed to
        request = self._service.timeline().get(id=id)
        try:
            card = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        # 2) Insert data into blob store
        file_name = files.blobstore.create(mime_type=self._content_type)
        with files.open(file_name, 'a') as f:
            f.write(self._content)
        files.finalize(file_name)
        blob_key = files.blobstore.get_blob_key(file_name)

        # 3) Update card with attachment info
        if not "attachments" in card:
            card["attachments"] = []

        attachment = {
            "id":
            str(blob_key),
            "contentType":
            self._content_type,
            "contentUrl":
            "%s/upload/mirror/v1/timeline/%s/attachments/%s" %
            (utils.base_url, card["id"], str(blob_key)),
            "isProcessing":
            False
        }

        card["attachments"].append(attachment)

        request = self._service.internal().timeline().update(id=card["id"],
                                                             body=card)

        try:
            result = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        self.response.status = 200
        self.response.out.write(json.dumps(result))
Example #13
0
    def process_request(self, request):

        if request.path == '/':
            return None

        if request.path.startswith('/form/login/'):
            return None

        if request.path.startswith('/form/signup/'):
            return None

        if request.path.startswith('/auth/login/'):
            return None

        if request.path.startswith('/auth/signup/'):
            return None

        if request.path.startswith('/all/'):
            return None

        if request.path.startswith('/admin/'):
            return None

        if 'AUTHENTICATION' not in request.COOKIES:
            return createError('Login first.')

        token = request.COOKIES.get('AUTHENTICATION')
        auth = None
        try:
            auth = Auth.objects.get(code=token)
        except:
            return createError('No authentication token.')

        if timezone.now() > auth.expiredTime:
            return createError('Session expired.')

        try:
            currentPerson = Person.objects.get(id=auth.user_id)
        except:
            createError('Person not found.')
        request.META['CURRENT_PERSON'] = currentPerson

        return None
Example #14
0
    def put(self, id):

        self.response.content_type = "application/json"

        if self._content is None:
            self.response.status = 400
            self.response.out.write(utils.createError(400, "Couldn't decode content or invalid content-type"))

        # Trying to access card to see if user is allowed to
        request = self._service.timeline().get(id=id)
        try:
            card = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        # 2) Insert data into blob store
        file_name = files.blobstore.create(mime_type=self._content_type)
        with files.open(file_name, 'a') as f:
            f.write(self._content)
        files.finalize(file_name)
        blob_key = files.blobstore.get_blob_key(file_name)

        # 3) Update card with attachment info and new metainfo
        if self._metainfo is None:
            new_card = {}
        else:
            new_card = self._metainfo

        if "attachments" in card:
            new_card["attachments"] = card["attachments"]
        else:
            new_card["attachments"] = []

        attachment = {
            "id": str(blob_key),
            "contentType": self._content_type,
            "contentUrl": "%s/upload/mirror/v1/timeline/%s/attachments/%s" % (utils.base_url, card["id"], str(blob_key)),
            "isProcessing": False
        }

        new_card["attachments"].append(attachment)

        request = self._service.internal().timeline().update(id=card["id"], body=new_card)

        try:
            result = request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        self.response.status = 200
        self.response.out.write(json.dumps(result))
Example #15
0
    def get(self, timelineId, attachmentId):
        credentials = self.session.get("credentials")
        if credentials is None:
            self.response.content_type = "application/json"
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid credentials."))
            return

        http = httplib2.Http()
        http = credentials.authorize(http)
        http.timeout = 60

        resp, content = http.request("%s/upload/mirror/v1/timeline/%s/attachments/%s" % (utils.base_url, timelineId, attachmentId))
        if resp.status == 200:
            self.response.content_type = resp["content-type"]
            self.response.out.write(content)
        else:
            self.response.content_type = "application/json"
            self.response.status = resp.status
            self.response.out.write(utils.createError(resp.status, "Unable to retrieve attachment."))
Example #16
0
    def get(self):
        """Retrieve timeline cards for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id)

        if service is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return
        try:
            # Retrieve timeline cards and return as reponse
            result = service.timeline().list().execute()
            self.response.status = 200
            self.response.out.write(json.dumps(result))
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
Example #17
0
    def get(self, test):
        """Retrieve submissions for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        if gplus_id is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()

        if user is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        items = []
        submissions = Submission.query(
            ancestor=user.key).order(-Submission.date).fetch(50)
        for submission in submissions:
            items.append({
                "id":
                submission.key.id(),
                "colour":
                submission.colour,
                "url":
                submission.url,
                "date":
                submission.date.strftime("%Y-%m-%dT%H:%M:%S.%f")
            })

        self.response.out.write(json.dumps({"items": items}))
Example #18
0
    def get(self):
        """Retrieve timeline cards for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id)

        if service is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return
        try:
            # Retrieve timeline cards and return as reponse
            result = service.timeline().list().execute()
            self.response.status = 200
            self.response.out.write(json.dumps(result))
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
Example #19
0
    def get(self, test, timelineId, attachmentId):
        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)
        if service is None:
            self.response.content_type = "application/json"
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid credentials."))
            return

        attachment_metadata = service.timeline().attachments().get(
            itemId=timelineId, attachmentId=attachmentId).execute()
        content_type = str(attachment_metadata.get("contentType"))
        content_url = attachment_metadata.get("contentUrl")
        resp, content = service._http.request(content_url)

        if resp.status == 200:
            self.response.content_type = content_type
            self.response.out.write(content)
        else:
            logging.info(resp)
            self.response.content_type = "application/json"
            self.response.status = resp.status
            self.response.out.write(utils.createError(resp.status, "Unable to retrieve attachment."))
Example #20
0
    def get(self, test, submission_id):
        """Remove a Submission for the user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()

        if user.get() is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return
Example #21
0
    def get(self, test, source_id):
        """
        Remove a Source for the user.
        Set Source.active = False if no users are tracking it anymore.
        """

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)

        if service is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return
Example #22
0
    def post(self):
        """Create a new timeline card for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id)

        if service is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        message = self.request.body

        data = json.loads(message)

        body = {}
        body["text"] = data["text"]
        if "image" in data:
            body["attachments"] = [{
                "contentType": "image/*",
                "contentUrl": data["image"]
            }]
        body["menuItems"] = [{"action": "SHARE"}, {"action": "REPLY"}]

        try:
            # Insert timeline card and return as reponse
            result = service.timeline().insert(body=body).execute()
            self.response.status = 200
            self.response.out.write(json.dumps(result))
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
Example #23
0
    def get(self, test, source_id):
        """
        Remove a Source for the user.
        Set Source.active = False if no users are tracking it anymore.
        """

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)

        if service is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return
Example #24
0
    def get(self, test, submission_id):
        """Remove a Submission for the user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()

        if user.get() is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return
Example #25
0
    def post(self, test):
        """Add a new source to be tracker."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)

        if service is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        data = json.loads(self.request.body)

        # TODO
        logging.info(data)
Example #26
0
    def get(self, id, attachment):

        # Trying to access card to see if user is allowed to
        request = self._service.timeline().get(id=id)
        try:
            request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        if not blobstore.get(attachment):
            self.response.content_type = "application/json"
            self.response.status = 404
            self.response.out.write(utils.createError(404, "Attachment not found"))
            return

        self.send_blob(attachment)
Example #27
0
    def post(self, test):
        """Add a new source to be tracker."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        service = get_auth_service(gplus_id, test)

        if service is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        data = json.loads(self.request.body)

        # TODO
        logging.info(data)
Example #28
0
    def get(self, id, attachment):

        # Trying to access card to see if user is allowed to
        request = self._service.timeline().get(id=id)
        try:
            request.execute()
        except HttpError as e:
            self.response.status = e.resp.status
            self.response.out.write(e.content)
            return

        if not blobstore.get(attachment):
            self.response.content_type = "application/json"
            self.response.status = 404
            self.response.out.write(
                utils.createError(404, "Attachment not found"))
            return

        self.send_blob(attachment)
Example #29
0
    def get(self, test):
        """Retrieve currently tracked sources for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()

        if user is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        items = []
        if user.sources is not None:
            for source in user.sources:
                data = source.get()
                items.append(data.id)

        self.response.out.write(json.dumps({"items": items}))
Example #30
0
    def get(self, test):
        """Retrieve currently tracked sources for the current user."""

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()

        if user is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        items = []
        if user.sources is not None:
            for source in user.sources:
                data = source.get()
                items.append(data.id)

        self.response.out.write(json.dumps({"items": items}))
Example #31
0
    def post(self):
        """Exchange the one-time authorization code for a token and
        store the token in the session."""

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = ("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" % access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's client ID does not match the app's client ID"))
            return

        self.session["gplus_id"] = gplus_id
        stored_credentials = get_credentials(gplus_id)
        if stored_credentials is None:
            store_credentials(gplus_id, credentials)

        # Create a new authorized API client
        service = get_auth_service(gplus_id)

        # Re-register contacts just in case new ones have been added
        try:
            # Register contacts
            body = {}
            body["acceptTypes"] = ["image/*"]
            body["id"] = "instaglass_sepia"
            body["displayName"] = "Sepia"
            body["imageUrls"] = ["https://mirror-api.appspot.com/images/sepia.jpg"]
            result = service.contacts().insert(body=body).execute()
            logging.info(result)

            body = {}
            body["acceptTypes"] = ["image/*"]
            body["id"] = "add_a_cat"
            body["displayName"] = "Add a Cat to that"
            body["imageUrls"] = ["https://mirror-api.appspot.com/images/cat.png"]
            result = service.contacts().insert(body=body).execute()
            logging.info(result)

        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
            return

        if stored_credentials is not None:
            self.response.status = 200
            self.response.out.write(utils.createMessage("Current user is already connected."))
            return

        try:
            # Register contacts
            body = {}
            body["acceptTypes"] = ["image/*"]
            body["id"] = "instaglass_sepia"
            body["displayName"] = "Sepia"
            body["imageUrls"] = ["https://mirror-api.appspot.com/images/sepia.jpg"]
            result = service.contacts().insert(body=body).execute()
            logging.info(result)

            # Register subscription
            verifyToken = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(32))
            body = {}
            body["collection"] = "timeline"
            body["operation"] = "UPDATE"
            body["userToken"] = gplus_id
            body["verifyToken"] = verifyToken
            body["callbackUrl"] = utils.base_url + "/timeline_update"
            result = service.subscriptions().insert(body=body).execute()
            logging.info(result)

            # Send welcome message
            body = {}
            body["text"] = "Welcome to Instaglass!"
            body["attachments"] = [{"contentType": "image/jpeg", "contentUrl": "https://mirror-api.appspot.com/images/sepia.jpg"}]
            result = service.timeline().insert(body=body).execute()
            logging.info(result)
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
            return

        # Store the access, refresh token and verify token
        user = ndb.Key("User", gplus_id).get()
        user.verifyToken = verifyToken
        user.put()
        self.response.status = 200
        self.response.out.write(utils.createMessage("Successfully connected user."))
Example #32
0
    def post(self, test):
        """
        Exchange the one-time authorization code for a token and
        store the credentials for later access.

        Setup all contacts and subscriptions necessary for the hosted services.
        """

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = ("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" % access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's client ID does not match the app's client ID"))
            return

        # Store credentials associated with the User ID for later use
        self.session["gplus_id"] = gplus_id
        stored_credentials = get_credentials(gplus_id, test)
        new_user = False
        if stored_credentials is None:
            new_user = True
            store_credentials(gplus_id, test, credentials)

        # handle cases where credentials don't have a refresh token
        credentials = get_credentials(gplus_id, test)

        if credentials.refresh_token is None:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "No Refresh token available, need to reauthenticate"))
            return

        # Create new authorized API clients for the Mirror API and Google+ API
        try:
            service = get_auth_service(gplus_id, test)
            plus_service = get_auth_service(gplus_id, test, "plus", "v1")
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except UnknownApiNameOrVersion:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to initialize client library. Discovery document not found."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to initialize client library. %s" % e))
            return

        # Fetch user information
        try:
            result = plus_service.people().get(userId="me", fields="displayName,image").execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Store some public user information for later user
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()
        user.displayName = result["displayName"]
        user.imageUrl = result["image"]["url"]
        user.put()

        # Fetch user friends and store for later user
        try:
            result = plus_service.people().list(userId="me", collection="visible", maxResults=100, orderBy="best", fields="items/id").execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        friends = []
        if "items" in result:
            for item in result["items"]:
                friends.append(item["id"])

        user.friends = friends
        user.put()

        # Delete all existing contacts, so only the currently implemented ones are available
        try:
            result = service.contacts().list().execute()
            if "items" in result:
                for contact in result["items"]:
                    del_result = service.contacts().delete(id=contact["id"]).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Register contacts defined in the demo services
        contacts = []
        for demo_service in demo_services:
            if hasattr(demo_service, "CONTACTS"):
                contacts.extend(demo_service.CONTACTS)

        for contact in contacts:
            try:
                result = service.contacts().insert(body=contact).execute()
            except AccessTokenRefreshError:
                _disconnect(gplus_id, test)
                self.response.status = 401
                self.response.out.write(utils.createError(401, "Failed to refresh access token."))
                return
            except HttpError as e:
                self.response.status = 500
                self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
                return

        """
        Re-register subscriptions to make sure all of them are available.
        Normally it would be best to use subscriptions.list first to check.
        For the purposes of this demo service all possible subscriptions are made.
        Normally you would only set-up subscriptions for the services you need.
        """

        # Delete all existing subscriptions
        try:
            result = service.subscriptions().list().execute()
            if "items" in result:
                for subscription in result["items"]:
                    del_result = service.subscriptions().delete(id=subscription["id"]).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Generate random verifyToken and store it in User entity
        verifyToken = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(32))
        user.verifyToken = verifyToken
        user.put()

        # Subscribe to all timeline inserts/updates/deletes
        body = {}
        body["collection"] = "timeline"
        body["userToken"] = gplus_id
        body["verifyToken"] = verifyToken
        body["callbackUrl"] = utils.base_url + ("" if test is None else "/test") + "/timeline_update"
        try:
            result = service.subscriptions().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Subscribe to all location updates
        body = {}
        body["collection"] = "locations"
        body["userToken"] = gplus_id
        body["verifyToken"] = verifyToken
        body["callbackUrl"] = utils.base_url + ("" if test is None else "/test") + "/locations_update"
        try:
            result = service.subscriptions().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        if not new_user:
            self.response.status = 200
            self.response.out.write(utils.createMessage("Current user is already connected."))
            return

        # Send welcome messages for new users
        welcomes = []
        for demo_service in demo_services:
            if hasattr(demo_service, "WELCOMES"):
                welcomes.extend(demo_service.WELCOMES)

        for welcome in welcomes:
            try:
                result = service.timeline().insert(body=welcome).execute()
            except AccessTokenRefreshError:
                _disconnect(gplus_id, test)
                self.response.status = 401
                self.response.out.write(utils.createError(401, "Failed to refresh access token."))
                return
            except HttpError as e:
                self.response.status = 500
                self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
                return

        self.response.status = 200
        self.response.out.write(utils.createMessage("Successfully connected user."))
Example #33
0
    def post(self, test):
        """
        Remove contacts and subscriptions registered for the user.
        Revoke current user's token and reset their session.
        Delete User entity from Data store.
        """

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")

        # Only disconnect a connected user.
        credentials = get_credentials(gplus_id, test)
        if credentials is None:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Current user not connected."))
            return

        # Create a new authorized API client
        try:
            service = get_auth_service(gplus_id, test)
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
            return
        except UnknownApiNameOrVersion:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to initialize client library. Discovery document not found."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to initialize client library. %s" % e))
            return

        # De-register contacts
        try:
            result = service.contacts().list().execute()
            if "items" in result:
                for contact in result["items"]:
                    del_result = service.contacts().delete(id=contact["id"]).execute()
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # De-register subscriptions
        try:
            result = service.subscriptions().list().execute()
            if "items" in result:
                for subscription in result["items"]:
                    del_result = service.subscriptions().delete(id=subscription["id"]).execute()
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Execute HTTP GET request to revoke current token.
        access_token = credentials.access_token
        url = "https://accounts.google.com/o/oauth2/revoke?token=%s" % access_token
        h = httplib2.Http()
        try:
            result = h.request(url, "GET")[0]
            if result["status"] == "200":
                # Reset the user's session.
                self.response.status = 200
                self.response.out.write(utils.createMessage("Successfully disconnected user."))
            else:
                # For whatever reason, the given token was invalid.
                self.response.status = 400
                self.response.out.write(utils.createError(400, "Failed to revoke token for given user."))
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Delete User entity from datastore
        if test is not None:
            ndb.Key("TestUser", gplus_id).delete()
        else:
            ndb.Key("User", gplus_id).delete()
Example #34
0
    def post(self):
        """Exchange the one-time authorization code for a token and
        store the token in the session."""

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json',
                                                 scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401,
                                  "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = (
            "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" %
            access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401,
                    "Token's client ID does not match the app's client ID"))
            return

        self.session["gplus_id"] = gplus_id
        stored_credentials = get_credentials(gplus_id)
        if stored_credentials is None:
            store_credentials(gplus_id, credentials)

        # Create a new authorized API client
        service = get_auth_service(gplus_id)

        # Re-register contacts just in case new ones have been added
        try:
            # Register contacts
            body = {}
            body["acceptTypes"] = ["image/*"]
            body["id"] = "instaglass_sepia"
            body["displayName"] = "Sepia"
            body["imageUrls"] = [
                "https://mirror-api.appspot.com/images/sepia.jpg"
            ]
            result = service.contacts().insert(body=body).execute()
            logging.info(result)

            body = {}
            body["acceptTypes"] = ["image/*"]
            body["id"] = "add_a_cat"
            body["displayName"] = "Add a Cat to that"
            body["imageUrls"] = [
                "https://mirror-api.appspot.com/images/cat.png"
            ]
            result = service.contacts().insert(body=body).execute()
            logging.info(result)

        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
            return

        if stored_credentials is not None:
            self.response.status = 200
            self.response.out.write(
                utils.createMessage("Current user is already connected."))
            return

        try:
            # Register contacts
            body = {}
            body["acceptTypes"] = ["image/*"]
            body["id"] = "instaglass_sepia"
            body["displayName"] = "Sepia"
            body["imageUrls"] = [
                "https://mirror-api.appspot.com/images/sepia.jpg"
            ]
            result = service.contacts().insert(body=body).execute()
            logging.info(result)

            # Register subscription
            verifyToken = ''.join(
                random.choice(string.ascii_letters + string.digits)
                for x in range(32))
            body = {}
            body["collection"] = "timeline"
            body["operation"] = "UPDATE"
            body["userToken"] = gplus_id
            body["verifyToken"] = verifyToken
            body["callbackUrl"] = utils.base_url + "/timeline_update"
            result = service.subscriptions().insert(body=body).execute()
            logging.info(result)

            # Send welcome message
            body = {}
            body["text"] = "Welcome to Instaglass!"
            body["attachments"] = [{
                "contentType":
                "image/jpeg",
                "contentUrl":
                "https://mirror-api.appspot.com/images/sepia.jpg"
            }]
            result = service.timeline().insert(body=body).execute()
            logging.info(result)
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
            return

        # Store the access, refresh token and verify token
        user = ndb.Key("User", gplus_id).get()
        user.verifyToken = verifyToken
        user.put()
        self.response.status = 200
        self.response.out.write(
            utils.createMessage("Successfully connected user."))
Example #35
0
    def post(self, test):
        """
        Exchange the one-time authorization code for a token and
        store the credentials for later access.

        Setup all contacts and subscriptions necessary for the hosted services.
        """

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json',
                                                 scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401,
                                  "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = (
            "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" %
            access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401,
                    "Token's client ID does not match the app's client ID"))
            return

        # Store credentials associated with the User ID for later use
        self.session["gplus_id"] = gplus_id
        stored_credentials = get_credentials(gplus_id, test)
        new_user = False
        if stored_credentials is None:
            new_user = True
            store_credentials(gplus_id, test, credentials)

        # handle cases where credentials don't have a refresh token
        credentials = get_credentials(gplus_id, test)

        if credentials.refresh_token is None:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401, "No Refresh token available, need to reauthenticate"))
            return

        # Create new authorized API clients for the Mirror API and Google+ API
        try:
            service = get_auth_service(gplus_id, test)
            plus_service = get_auth_service(gplus_id, test, "plus", "v1")
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except UnknownApiNameOrVersion:
            self.response.status = 500
            self.response.out.write(
                utils.createError(
                    500,
                    "Failed to initialize client library. Discovery document not found."
                ))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(
                    500, "Failed to initialize client library. %s" % e))
            return

        # Fetch user information
        try:
            result = plus_service.people().get(
                userId="me", fields="displayName,image").execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Store some public user information for later user
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()
        user.displayName = result["displayName"]
        user.imageUrl = result["image"]["url"]
        user.put()
        """
        Re-register subscriptions and contacts to make sure all of them are available.
        """

        # Delete all existing subscriptions
        try:
            result = service.subscriptions().list().execute()
            if "items" in result:
                for subscription in result["items"]:
                    service.subscriptions().delete(
                        id=subscription["id"]).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Generate random verifyToken and store it in User entity
        if user.verifyToken is None:
            verifyToken = ''.join(
                random.choice(string.ascii_letters + string.digits)
                for x in range(32))
            user.verifyToken = verifyToken
            user.put()
        else:
            verifyToken = user.verifyToken

        # Contact for receiving submissions
        contact_id = "colours_of_the_world"
        existing = True
        try:
            result = service.contacts().get(id=contact_id).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            if e.resp.status == 404:
                existing = False
            else:
                self.response.status = 500
                self.response.out.write(
                    utils.createError(500,
                                      "Failed to execute request. %s" % e))
                return

        body = {}
        body["acceptTypes"] = "image/*"
        body["id"] = contact_id
        body["displayName"] = "Colours of the World"
        body["imageUrls"] = [utils.base_url + "/images/card.png"]

        try:
            if existing:
                result = service.contacts().update(id=contact_id,
                                                   body=body).execute()
            else:
                result = service.contacts().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Subscribe to all timeline inserts/updates/deletes
        body = {}
        body["collection"] = "timeline"
        body["userToken"] = gplus_id
        body["verifyToken"] = verifyToken
        body["callbackUrl"] = utils.base_url + ("" if test is None else
                                                "/test") + "/timeline_update"
        try:
            result = service.subscriptions().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        if not new_user:
            self.response.status = 200
            self.response.out.write(
                utils.createMessage("Current user is already connected."))
            return

        # Send welcome messages for new users
        welcome = {
            "html":
            ("<article>"
             "  <img src=\"" + utils.base_url +
             "/images/card.png\" width=\"100%\" height=\"100%\">"
             "  <div class=\"photo-overlay\"></div>"
             "  <section>"
             "    <p class=\"text-large\">Welcome to Colours of the World!</p>"
             "    <p class=\"text-small\">Your first task will be sent to you soon</p>"
             "  </section>"
             "</article>")
        }

        try:
            result = service.timeline().insert(body=welcome).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Create a new task for the user
        taskqueue.add(url="/tasks/createtask",
                      countdown=10,
                      params={
                          "user": gplus_id,
                          "test": test
                      },
                      method="POST")

        self.response.status = 200
        self.response.out.write(
            utils.createMessage("Successfully connected user."))
Example #36
0
    def post(self, test):
        """
        Remove subscriptions registered for the user.
        Revoke current user's token and reset their session.
        Delete User entity from Data store.
        """

        self.response.content_type = "application/json"

        gplus_id = self.session.get("gplus_id")

        # Only disconnect a connected user.
        credentials = get_credentials(gplus_id, test)
        if credentials is None:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Current user not connected."))
            return

        # Create a new authorized API client
        try:
            service = get_auth_service(gplus_id, test)
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
            return
        except UnknownApiNameOrVersion:
            self.response.status = 500
            self.response.out.write(
                utils.createError(
                    500,
                    "Failed to initialize client library. Discovery document not found."
                ))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(
                    500, "Failed to initialize client library. %s" % e))
            return

        # De-register contacts
        try:
            result = service.contacts().list().execute()
            if "items" in result:
                for contact in result["items"]:
                    service.contacts().delete(id=contact["id"]).execute()
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # De-register subscriptions
        try:
            result = service.subscriptions().list().execute()
            if "items" in result:
                for subscription in result["items"]:
                    service.subscriptions().delete(
                        id=subscription["id"]).execute()
        except AccessTokenRefreshError:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Execute HTTP GET request to revoke current token.
        access_token = credentials.access_token
        url = "https://accounts.google.com/o/oauth2/revoke?token=%s" % access_token
        h = httplib2.Http()
        try:
            result = h.request(url, "GET")[0]
            if result["status"] == "200":
                # Reset the user's session.
                self.response.status = 200
                self.response.out.write(
                    utils.createMessage("Successfully disconnected user."))
            else:
                # For whatever reason, the given token was invalid.
                self.response.status = 400
                self.response.out.write(
                    utils.createError(
                        400, "Failed to revoke token for given user."))
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Delete User entity from datastore
        if test is not None:
            ndb.Key("TestUser", gplus_id).delete()
        else:
            ndb.Key("User", gplus_id).delete()
Example #37
0
    def post(self, test):
        """
        Exchange the one-time authorization code for a token and
        store the credentials for later access.

        Setup all contacts and subscriptions necessary for the hosted services.
        """

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json',
                                                 scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(
                utils.createError(401,
                                  "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = (
            "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" %
            access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401,
                    "Token's client ID does not match the app's client ID"))
            return

        # Store credentials associated with the User ID for later use
        self.session["gplus_id"] = gplus_id
        stored_credentials = get_credentials(gplus_id, test)
        new_user = False
        if stored_credentials is None:
            new_user = True
            store_credentials(gplus_id, test, credentials)

        # handle cases where credentials don't have a refresh token
        credentials = get_credentials(gplus_id, test)

        if credentials.refresh_token is None:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(
                    401, "No Refresh token available, need to reauthenticate"))
            return

        # Create new authorized API clients for the Mirror API and Google+ API
        try:
            service = get_auth_service(gplus_id, test)
            plus_service = get_auth_service(gplus_id, test, "plus", "v1")
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except UnknownApiNameOrVersion:
            self.response.status = 500
            self.response.out.write(
                utils.createError(
                    500,
                    "Failed to initialize client library. Discovery document not found."
                ))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(
                    500, "Failed to initialize client library. %s" % e))
            return

        # Fetch user information
        try:
            result = plus_service.people().get(
                userId="me", fields="displayName,image").execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Store some public user information for later user
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()
        user.displayName = result["displayName"]
        user.imageUrl = result["image"]["url"]
        user.put()
        """
        Re-register subscriptions to make sure all of them are available.
        Normally it would be best to use subscriptions.list first to check.
        For the purposes of this demo service all possible subscriptions are made.
        Normally you would only set-up subscriptions for the services you need.
        """

        # Delete all existing subscriptions
        try:
            result = service.subscriptions().list().execute()
            if "items" in result:
                for subscription in result["items"]:
                    service.subscriptions().delete(
                        id=subscription["id"]).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Generate random verifyToken and store it in User entity
        verifyToken = ''.join(
            random.choice(string.ascii_letters + string.digits)
            for x in range(32))
        user.verifyToken = verifyToken
        user.put()

        # Subscribe to all timeline inserts/updates/deletes
        body = {}
        body["collection"] = "timeline"
        body["userToken"] = gplus_id
        body["verifyToken"] = verifyToken
        body["callbackUrl"] = utils.base_url + ("" if test is None else
                                                "/test") + "/timeline_update"
        try:
            result = service.subscriptions().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(
                utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(
                utils.createError(500, "Failed to execute request. %s" % e))
            return

        if not new_user:
            self.response.status = 200
            self.response.out.write(
                utils.createMessage("Current user is already connected."))
            return

        # Send welcome messages for new users
        welcomes = []
        #for demo_service in demo_services:
        #    if hasattr(demo_service, "WELCOMES"):
        #        welcomes.extend(demo_service.WELCOMES)

        for welcome in welcomes:
            try:
                result = service.timeline().insert(body=welcome).execute()
            except AccessTokenRefreshError:
                _disconnect(gplus_id, test)
                self.response.status = 401
                self.response.out.write(
                    utils.createError(401, "Failed to refresh access token."))
                return
            except HttpError as e:
                self.response.status = 500
                self.response.out.write(
                    utils.createError(500,
                                      "Failed to execute request. %s" % e))
                return

        self.response.status = 200
        self.response.out.write(
            utils.createMessage("Successfully connected user."))
Example #38
0
    def post(self, test):
        """
        Exchange the one-time authorization code for a token and
        store the credentials for later access.

        Setup all contacts and subscriptions necessary for the hosted services.
        """

        self.response.content_type = "application/json"

        state = self.request.get("state")
        gplus_id = self.request.get("gplus_id")
        code = self.request.body

        if state != self.session.get("state"):
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Invalid state parameter"))
            return

        try:
            oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
            oauth_flow.redirect_uri = 'postmessage'
            credentials = oauth_flow.step2_exchange(code)
        except FlowExchangeError:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to upgrade the authorization code."))
            return

        # Check that the access token is valid.
        access_token = credentials.access_token
        url = ("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s" % access_token)
        h = httplib2.Http()
        result = json.loads(h.request(url, 'GET')[1])

        # If there was an error in the access token info, abort.
        if result.get("error") is not None:
            self.response.status = 500
            self.response.out.write(json.dumps(result.get("error")))
            return

        # Verify that the access token is used for the intended user.
        if result["user_id"] != gplus_id:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's user ID doesn't match given user ID."))
            return

        # Verify that the access token is valid for this app.
        if result['issued_to'] != utils.CLIENT_ID:
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Token's client ID does not match the app's client ID"))
            return

        # Store credentials associated with the User ID for later use
        self.session["gplus_id"] = gplus_id
        stored_credentials = get_credentials(gplus_id, test)
        new_user = False
        if stored_credentials is None:
            new_user = True
            store_credentials(gplus_id, test, credentials)

        # handle cases where credentials don't have a refresh token
        credentials = get_credentials(gplus_id, test)

        if credentials.refresh_token is None:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "No Refresh token available, need to reauthenticate"))
            return

        # Create new authorized API clients for the Mirror API and Google+ API
        try:
            service = get_auth_service(gplus_id, test)
            plus_service = get_auth_service(gplus_id, test, "plus", "v1")
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except UnknownApiNameOrVersion:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to initialize client library. Discovery document not found."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to initialize client library. %s" % e))
            return

        # Fetch user information
        try:
            result = plus_service.people().get(userId="me", fields="displayName,image").execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Store some public user information for later user
        if test is not None:
            user = ndb.Key("TestUser", gplus_id).get()
        else:
            user = ndb.Key("User", gplus_id).get()
        user.displayName = result["displayName"]
        user.imageUrl = result["image"]["url"]
        user.put()

        """
        Re-register subscriptions and contacts to make sure all of them are available.
        """

        # Delete all existing subscriptions
        try:
            result = service.subscriptions().list().execute()
            if "items" in result:
                for subscription in result["items"]:
                    service.subscriptions().delete(id=subscription["id"]).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Generate random verifyToken and store it in User entity
        if user.verifyToken is None:
            verifyToken = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(32))
            user.verifyToken = verifyToken
            user.put()
        else:
            verifyToken = user.verifyToken

        # Contact for receiving submissions
        contact_id = "colours_of_the_world"
        existing = True
        try:
            result = service.contacts().get(id=contact_id).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            if e.resp.status == 404:
                existing = False
            else:
                self.response.status = 500
                self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
                return
        
        body =  {}
        body["acceptTypes"] = "image/*"
        body["id"] = contact_id
        body["displayName"] = "Colours of the World"
        body["imageUrls"] = [utils.base_url + "/images/card.png"]
        
        try:
            if existing:
                result = service.contacts().update(id=contact_id, body=body).execute()
            else:
                result = service.contacts().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Subscribe to all timeline inserts/updates/deletes
        body = {}
        body["collection"] = "timeline"
        body["userToken"] = gplus_id
        body["verifyToken"] = verifyToken
        body["callbackUrl"] = utils.base_url + ("" if test is None else "/test") + "/timeline_update"
        try:
            result = service.subscriptions().insert(body=body).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        if not new_user:
            self.response.status = 200
            self.response.out.write(utils.createMessage("Current user is already connected."))
            return


        # Send welcome messages for new users
        welcome = {
            "html": ("<article>"
                     "  <img src=\"" + utils.base_url + "/images/card.png\" width=\"100%\" height=\"100%\">"
                     "  <div class=\"photo-overlay\"></div>"
                     "  <section>"
                     "    <p class=\"text-large\">Welcome to Colours of the World!</p>"
                     "    <p class=\"text-small\">Your first task will be sent to you soon</p>"
                     "  </section>"
                     "</article>")
        }

        try:
            result = service.timeline().insert(body=welcome).execute()
        except AccessTokenRefreshError:
            _disconnect(gplus_id, test)
            self.response.status = 401
            self.response.out.write(utils.createError(401, "Failed to refresh access token."))
            return
        except HttpError as e:
            self.response.status = 500
            self.response.out.write(utils.createError(500, "Failed to execute request. %s" % e))
            return

        # Create a new task for the user
        taskqueue.add(url="/tasks/createtask", countdown=10,
                      params={"user": gplus_id, "test": test},
                      method="POST")

        self.response.status = 200
        self.response.out.write(utils.createMessage("Successfully connected user."))