def post(self): """Handles POST requests for /worker/snapshot.""" snapshot = model.Snapshot.gql("WHERE __key__ = KEY('Snapshot', :key)", key=int(self.request.get("id"))).get() user = snapshot.user credentials = appengine.StorageByKeyName(model.Credentials, user.user_id(), "credentials").get() if credentials is None or credentials.invalid == True: snapshot.status = "error" snapshot.errorMessage = "Must be logged in to create snapshot." snapshot.put() else: try: http = httplib2.Http() http = credentials.authorize(http) service = discovery.build("tasks", "v1", http) tasklists = service.tasklists() tasklists_list = tasklists.list().execute() parser = apiparse.Parser(model.TaskList, None, snapshot, tasklists.list, model) tasklist_entities = parser.ParseAndStore(tasklists_list) for tasklist in tasklist_entities: tasks = service.tasks() tasks_list = tasks.list(tasklist=tasklist.id, showHidden=True).execute() parser = apiparse.Parser(model.Task, tasklist, snapshot, tasks.list, model, tasklist=tasklist.id, showHidden=True) parser.ParseAndStore(tasks_list) snapshot.status = "completed" snapshot.put() except client.AccessTokenRefreshError, e: snapshot.status = "error" snapshot.errorMessage = "OAuth credentials were revoked." logging.info(e, exc_info=True) snapshot.put() except Exception, e: snapshot.status = "error" snapshot.errorMessage = "Snapshot creation process failed unexpectedly." logging.error(e, exc_info=True) snapshot.put()
def post(self): logging.info(self.request.get("id")) """Handles POST requests for /worker/snapshot.""" snapshot = model.Snapshot.gql("WHERE __key__ = KEY('Snapshot', :key)", key=int(self.request.get("id"))).get() user = snapshot.user credentials = appengine.StorageByKeyName(model.Credentials, user.user_id(), "credentials").get() if credentials is None or credentials.invalid == True: snapshot.status = "error" snapshot.errorMessage = "Must be logged in to create snapshot." snapshot.put() else: try: http = httplib2.Http() http = credentials.authorize(http) service = discovery.build("tasks", "v1", http) tasklist = model.TaskList(parent=snapshot) tasklist.title = self.request.get("name") tasklist.put() if self.request.get("format") == "ics": try: parser = icalparse.Parser(tasklist) tasks_list = parser.ParseAndStore( self.request.get("file")) except Exception, e: snapshot.status = "error" snapshot.errorMessage = "The iCalendar file was malformed." logging.info(e, exc_info=True) snapshot.put() return elif self.request.get("format") == "csv": try: parser = csvparse.Parser(tasklist) tasks_list = parser.ParseAndStore( self.request.get("file")) except Exception, e: snapshot.status = "error" snapshot.errorMessage = "The CSV file was malformed." logging.info(e, exc_info=True) snapshot.put() return
def get(self): """Handles GET requests for /oauth2callback.""" if not self.request.get("code"): self.redirect("/") return user = users.get_current_user() flow = pickle.loads(memcache.get(user.user_id())) if flow: error = False try: credentials = flow.step2_exchange(self.request.params) except client.FlowExchangeError, e: credentials = None error = True appengine.StorageByKeyName(model.Credentials, user.user_id(), "credentials").put(credentials) if error: self.redirect("/?msg=ACCOUNT_ERROR") else: self.redirect(self.request.get("state"))
def _GetCredentials(): user = users.get_current_user() credentials = appengine.StorageByKeyName(model.Credentials, user.user_id(), "credentials").get() # so it turns out that the method that checks if the credentials are okay # doesn't give the correct answer unless you try to refresh it. So we do that # here in order to make sure that the credentials are valid before being # passed to a worker. Obviously if the user revokes the credentials after # this point we will continue to get an error, but we can't stop that. if credentials and not credentials.invalid: try: http = httplib2.Http() http = credentials.authorize(http) service = discovery.build("tasks", "v1", http) tasklists = service.tasklists() tasklists_list = tasklists.list().execute() except: credentials = None return user, credentials
def get_credentials(self): """ Retrieve credentials for the user Returns: result True if we have valid credentials for the user user User object for current user credentials Credentials object for current user. None if no credentials. fail_msg If result==False, message suitabale for displaying to user fail_reason If result==False, cause of the failure. Can be one of "User not logged on" "No credentials" "Invalid credentials" "Credential use error" (Unspecified error when attempting to use credentials) "Credential use HTTP error" (Returned an HTTP error when attempting to use credentials) If no credentials, or credentials are invalid, the calling method can call redirect_for_auth(self, user), which sets the redirect URL back to the calling page. That is, user is redirected to calling page after authorising. """ fn_name = "get_credentials(): " user = None fail_msg = '' fail_reason = '' credentials = None result = False try: user = users.get_current_user() if user is None: # User is not logged in, so there can be no credentials. fail_msg = "User is not logged in" fail_reason = "User not logged on" logging.debug(fn_name + fail_msg) logservice.flush() return False, None, None, fail_msg, fail_reason credentials = appengine.StorageByKeyName(model.Credentials, user.user_id(), "credentials").get() result = False if credentials: if credentials.invalid: # We have credentials, but they are invalid fail_msg = "Invalid credentials for this user" fail_reason = "Invalid credentials" result = False else: #logging.debug(fn_name + "Calling tasklists service to confirm valid credentials") # so it turns out that the method that checks if the credentials are okay # doesn't give the correct answer unless you try to refresh it. So we do that # here in order to make sure that the credentials are valid before being # passed to a worker. Obviously if the user revokes the credentials after # this point we will continue to get an error, but we can't stop that. # Credentials are possibly valid, but need to be confirmed by refreshing # Try multiple times, just in case call to server fails due to external probs (e.g., timeout) # retry_count = settings.NUM_API_TRIES # while retry_count > 0: try: http = httplib2.Http() http = credentials.authorize(http) service = discovery.build("tasks", "v1", http) tasklists_svc = service.tasklists() tasklists_list = tasklists_svc.list().execute() # Successfully used credentials, everything is OK, so break out of while loop fail_msg = '' fail_reason = '' result = True # break except apiclient_errors.HttpError, e: #logging.info(fn_name + "HttpError using credentials: " + get_exception_msg(e)) if e._get_reason().lower() == "daily limit exceeded": fail_reason = "Daily limit exceeded" fail_msg = "HttpError: Daily limit exceeded using credentials." else: fail_reason = "Credential use HTTP error" fail_msg = "Error accessing tasks service: " + e._get_reason( ) result = False credentials = None result = False except Exception, e: #logging.info(fn_name + "Exception using credentials: " + get_exception_msg(e)) fail_reason = "Credential use error" fail_msg = "Exception using credentials: " + get_exception_msg( e) credentials = None result = False
if retry_count <= 2: logging.debug( fn_name + "Sleeping for " + str(settings.FRONTEND_API_RETRY_SLEEP_DURATION) + " seconds before retrying") logservice.flush() time.sleep(settings.FRONTEND_API_RETRY_SLEEP_DURATION) else: logging.exception(fn_name + "Unable to retrieve credentials after " + str(settings.NUM_API_TRIES) + " attempts. Giving up") logservice.flush() appengine.StorageByKeyName(model.Credentials, user.user_id(), "credentials").put(credentials) if error: # TODO: Redirect to retry or invalid_credentials page, with more meaningful message logging.warning( fn_name + "Error retrieving credentials from flow. Redirecting to " + settings.WELCOME_PAGE_URL + "?msg=ACCOUNT_ERROR") logservice.flush() self.redirect(settings.WELCOME_PAGE_URL + "?msg=ACCOUNT_ERROR") logging.debug(fn_name + "<End> (Error retrieving credentials)") logservice.flush() else: # Redirect to the URL stored in the "state" param, when redirect_for_auth was called # This should be the URL that the user was on when authorisation failed logging.debug(fn_name + "Success. Redirecting to " +