Example #1
0
 def checkPOIStatus(self, ipDron, portDron, poi):
     if poi in self.assignedPOIs:
         # TODO
         if self.assignedPOIs[poi][0] == ipDron:
             self.POIsToAssign.append(poi)
         else:
             self.client.send_direct_message(createMessage(ASIGNAR_POI, POI_ALREADY_ASSIGNED, "go back to explore"), ipDron)
Example #2
0
 def execute(self):
     self.bebop.disconnect()
     self.client.send_direct_message(createMessage(FIN, END_MISSION, "end"), self.bebop.ip, self.bebop.port)
     for i in self.poisVigilarTimeoutDict:
         self.poisVigilarTimeoutDict[i].cancel()
     for i in self.poisVigilarCriticoTimeoutDict:
         self.poisVigilarCriticoTimeoutDict[i].cancel()
     self.logStats.endExecution()
     return None
 def execute(self):
     self.client.send_message(
         createMessage(
             GENERAL, MISSION_ABORTED,
             dict({
                 "ip": self.bebop.ip,
                 "poi": self.bebop.poi_position
             }), self.idMessage))
     return None
Example #4
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 #5
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 #6
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."))
 def execute(self):
     result = []
     for key in self.poisVigilar:
         if convertTupleToString(key) in self.assignedPOIs and self.client.check_connection(self.assignedPOIs[convertTupleToString(key)]["ip"]) == 0:
             self.client.send_message(createMessage(ASIGNAR_POI, MISSION_OK, key))
             self.poisVigilar.remove(key)
             timer2 = threading.Timer(TIME_BETWEEN_POI_PING, self.checkMissionStatus, (key,))
             timer2.start()
         else:
             self.nextState = ASIGNAR_POI
             result.append(key)
     for key in self.poisCritico:
         if convertTupleToString(key) in self.assignedPOIs and self.client.check_connection(self.assignedPOIs[convertTupleToString(key)]["ip"]) == 0:
             self.client.send_message(createMessage(ASIGNAR_POI, MISSION_OK, key))
             self.poisCritico.remove(key)
             timer2 = threading.Timer(TIME_BETWEEN_POI_PING, self.checkMissionStatus, (key,))
             timer2.start()
         else:
             self.nextState = ASIGNAR_POI
             result.append(key)
     minPoi = getClosestPOI(self.bebop.current_position, result)
     if minPoi is None:
         return None
     return {"poi": minPoi, "type": POI_CRITICO}
Example #8
0
    def execute(self):
        client1 = client()
        timer = Timer(SYNC_WAIT, self.wakeUp)
        timer.start()
        self.syncLock.acquire()
        client1.search_friends(self.bebop.ip)
        if not self.awoken:
            message = createMessage(INICIO, SYNC, 'wake up!')
            client1.send_message(message)
        for i in range(len(POI_POSITIONS)):
            new_timer = Timer(POI_TIMERS[i], self.setTimerFunc, (POI_POSITIONS[i],))
            new_timer.start()
            self.poiVigilarTimeoutDict[convertTupleToString(POI_POSITIONS[i])] = new_timer

        return client1
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 execute(self):
     if not self.timeout:
         if len(self.client.check_friends()) != 0:
             self.client.send_message(
                 createMessage(
                     GENERAL, UPDATE_MAP,
                     utils.convertTupleToString(
                         self.bebop.current_position)))
         elif not self.isAlone:
             self.nextState = DESPLAZARSE_SIN_CONEXION
             return self.client
         if self.bebop.poi_position is not None:
             if self.bebop.poi_position in self.poisCritico:
                 self.nextState = POI_CRITICO
             else:
                 self.nextState = POI_VIGILAR
             return self.bebop.poi_position
         isChequearMisionResult = self.isChequearMision()
         if isChequearMisionResult is not None:
             return isChequearMisionResult
         else:
             return self.isAsignarPOI()
     return None
Example #11
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 #12
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 #13
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 #14
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."))
 def execute(self):
     self.bebop.updateSearchMap(self.bebop.current_position)
     self.client.send_message(createMessage(GENERAL, UPDATE_MAP, utils.convertTupleToString(self.bebop.current_position)))
     return None
Example #16
0
    def execute(self):
        if self.isAlone:
            self.result = self.poiType
            self.bebop.poi_position = self.poi
            self.assignedPOIs[self.poi] = self.bebop.ip
        else:
            if len(self.poiAlreadyAssigned
                   ) > 0 and self.previousState == CANCELAR_MISION:
                return None

            if len(self.availableDistances) > 0 or len(
                    self.availableResults) > 0:
                # im late to the party
                return None

            connected_drones = self.client.check_friends()
            distance = cartesianDistance(self.poi, self.bebop.current_position)
            available_battery = self.bebop.getBatteryPercentage()
            ipPort = dict({"ip": self.bebop.ip, "port": self.bebop.port})
            if available_battery - (distance /
                                    DISTANCE_ENERGY_RATIO) > LOW_BATTERY:
                message = createMessage(ASIGNAR_POI, AVAILABLE, ipPort)
                self.availableDrones.append(ipPort)
                for ipPort in connected_drones:
                    # antes estaba send_message
                    self.client.send_direct_message(message, ipPort["ip"],
                                                    ipPort["port"])
            else:
                message = createMessage(
                    ASIGNAR_POI, UNAVAILABLE,
                    concatIpPort(self.bebop.ip, self.bebop.port))
                for ipPort in connected_drones:
                    # antes estaba send_message
                    self.client.send_direct_message(message, ipPort["ip"],
                                                    ipPort["port"])
                return None

            timer1 = threading.Timer(WAIT_TIME, self.messageWaitTimeout)
            timer1.start()

            conditionMet = False
            while not conditionMet and not self.timeout:
                self.messageWait.acquire()
                if self.blockHandleMessage.locked():
                    self.blockHandleMessage.release()
                self.messageMutex.acquire()
                conditionMet = len(self.availableDrones) + len(
                    self.unavailableDrones) - 1 >= len(connected_drones)
                self.messageMutex.release()

            self.timeout = False
            timer1.cancel()
            availableDronesNumber = len(self.availableDrones)
            distanceDict = dict({
                "distance": distance,
                "ip": self.bebop.ip,
                "port": self.bebop.port
            })
            message2 = createMessage(ASIGNAR_POI, DISTANCE, distanceDict)
            self.messageMutex.acquire()
            # for ip in self.availableDrones:
            #     if ip != self.bebop.ip:
            self.client.send_message(message2)
            self.messageMutex.release()
            timer2 = threading.Timer(SYNC_ASIGNARPOI_MSG,
                                     self.messageWaitTimeout)
            timer2.start()
            conditionMet = False
            self.availableDistances.append(distanceDict)
            while not conditionMet and not self.timeout:
                self.messageWait.acquire()
                if self.blockHandleMessage.locked():
                    self.blockHandleMessage.release()
                self.messageMutex.acquire()
                conditionMet = len(
                    self.availableDistances) >= availableDronesNumber
                self.messageMutex.release()
            self.timeout = False
            timer2.cancel()
            minDistance = distance
            minIp = self.bebop.ip
            minPort = self.bebop.port

            self.messageMutex.acquire()
            minimoEncontrado = dict({"ip": minIp, "port": minPort})
            for elem in self.availableDistances:
                if elem["distance"] < minDistance:
                    minDistance = elem["distance"]
                    minIp = elem["ip"]
                    minPort = elem["port"]
                elif elem["distance"] == minDistance:
                    if self.isLower(elem, minimoEncontrado):
                        minDistance = elem["distance"]
                        minIp = elem["ip"]
                        minPort = elem["port"]
                        minimoEncontrado = dict({"ip": minIp, "port": minPort})
            # minimoEncontrado = dict({"ip": minIp, "port": minPort})
            message3 = createMessage(ASIGNAR_POI, RESULT, minimoEncontrado)
            for ipPort in self.availableDrones:
                if ipPort["ip"] != self.bebop.ip or ipPort[
                        "port"] != self.bebop.port:
                    self.client.send_direct_message(message3, ipPort["ip"],
                                                    ipPort["port"])
            self.messageMutex.release()
            timer3 = threading.Timer(SYNC_ASIGNARPOI_MSG,
                                     self.messageWaitTimeout)
            timer3.start()
            conditionMet = False
            self.availableResults.append(minimoEncontrado)
            while not conditionMet and not self.timeout:
                self.messageWait.acquire()
                if self.blockHandleMessage.locked():
                    self.blockHandleMessage.release()
                self.messageMutex.acquire()
                conditionMet = len(self.availableResults) >= len(
                    self.availableDrones)
                self.messageMutex.release()
            self.timeout = False
            timer3.cancel()

            concensus = ''
            concensusValue = 0
            self.messageMutex.acquire()
            for ipPort in self.availableDrones:
                count = 0
                for elem in self.availableResults:
                    if elem == ipPort["ip"]:
                        count += 1
                if count > concensusValue:
                    concensusValue = count
                    concensus = ipPort
                elif count == concensusValue:
                    if self.isLower(ipPort, concensus):
                        concensusValue = count
                        concensus = ipPort
            self.messageMutex.release()
            if concensus["ip"] == self.bebop.ip and concensus[
                    "port"] == self.bebop.port:
                self.result = self.poiType
                self.bebop.poi_position = self.poi
                message4 = createMessage(GENERAL, POI_ASSIGNED,
                                         convertTupleToString(self.poi))
                self.client.send_message(message4)
            timer2 = threading.Timer(TIME_BETWEEN_POI_PING,
                                     self.checkMissionStatus, (self.poi, ))
            timer2.start()
            self.assignedPOIs[convertTupleToString(self.poi)] = concensus
        return self.poi
Example #17
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 #18
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 #19
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 #20
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."))