예제 #1
0
def notebook_authenticate(cmd_args, force=False, silent=True):
    """ Similiar to authenticate but prints student emails after
    all calls and uses a different way to get codes. If SILENT is True,
    it will suppress the error message and redirect to FORCE=True
    """
    server = server_url(cmd_args)
    network.check_ssl()
    access_token = None
    if not force:
        try:
            access_token = refresh_local_token(server)
        except OAuthException as e:
            # Account for Invalid Grant Error During make_token_post
            if not silent:
                raise e
            return notebook_authenticate(cmd_args, force=True, silent=False)

    if not access_token:
        access_token = perform_oauth(get_code_via_terminal,
                                     cmd_args,
                                     copy_msg=NOTEBOOK_COPY_MESSAGE,
                                     paste_msg=NOTEBOOK_PASTE_MESSAGE)

    # Always display email
    email = display_student_email(cmd_args, access_token)
    if email is None and not force:
        return notebook_authenticate(cmd_args, force=True)  # Token has expired
    elif email is None:
        # Did not get a valid token even after a fresh login
        log.warning('Could not get login email. You may have been logged out. '
                    ' Try logging in again.')
    return access_token
예제 #2
0
def notebook_authenticate(cmd_args, force=False):
    """ Similiar to authenticate but prints student emails after
    all calls and uses a different way to get codes.
    """
    server = server_url(cmd_args)
    network.check_ssl()
    access_token = None
    if not force:
        access_token = refresh_local_token(server)

    if not access_token:
        access_token = perform_oauth(
            get_code_via_terminal,
            cmd_args,
            copy_msg=NOTEBOOK_COPY_MESSAGE,
            paste_msg=NOTEBOOK_PASTE_MESSAGE)

    # Always display email
    email = display_student_email(cmd_args, access_token)
    if email is None and not force:
        return notebook_authenticate(cmd_args, force=True)  # Token has expired
    elif email is None:
        # Did not get a valid token even after a fresh login
        log.warning('Could not get login email. You may have been logged out. '
                    ' Try logging in again.')
    return access_token
예제 #3
0
def authenticate(cmd_args, endpoint='', force=False, nointeract=False):
    """Returns an OAuth token that can be passed to the server for
    identification. If FORCE is False, it will attempt to use a cached token
    or refresh the OAuth token. If NOINTERACT is true, it will return None
    rather than prompting the user.
    """
    server = server_url(cmd_args)
    network.check_ssl()
    access_token = None

    try:
        assert not force
        access_token = refresh_local_token(server)
    except Exception:
        if nointeract:
            return access_token
        print('Performing authentication')
        access_token = perform_oauth(get_code, cmd_args, endpoint)
        email = display_student_email(cmd_args, access_token)
        if not email:
            log.warning('Could not get login email. Try logging in again.')

    log.debug('Authenticated with access token={}'.format(access_token))

    return access_token
예제 #4
0
def authenticate(cmd_args, endpoint='', force=False):
    """Returns an OAuth token that can be passed to the server for
    identification. If FORCE is False, it will attempt to use a cached token
    or refresh the OAuth token.
    """
    server = server_url(cmd_args)
    network.check_ssl()
    access_token = None
    if not force:
        access_token = refresh_local_token(server)

    if not access_token:
        print('Performing authentication')
        access_token = perform_oauth(get_code, cmd_args, endpoint)
        email = display_student_email(cmd_args, access_token)
        if not email:
            log.warning('Could not get login email. Try logging in again.')

    return access_token
예제 #5
0
    def run(self, messages, nointeract=False):
        if not self.assignment.endpoint:
            log.info('No assignment endpoint, skipping backup')
            return

        if self.args.local:
            print_warning("Cannot backup when running ok with --local.")
            return

        if not self.args.insecure:
            network.check_ssl()

        if self.args.revise:
            action = 'revision'
        elif self.args.submit:
            action = 'submission'
        else:
            action = 'backup'

        message_list = self.load_unsent_messages()

        access_token = self.assignment.authenticate(nointeract=nointeract)
        log.info('Authenticated with access token')
        log.info('Sending unsent messages')

        if not access_token:
            print_error(
                "Not authenticated. Cannot send {} to server".format(action))
            self.dump_unsent_messages(message_list)
            return

        # Messages from the current backup to send first
        is_send_first = self.args.submit or self.args.revise
        subm_messages = [messages] if is_send_first else []

        if is_send_first:
            response = self.send_all_messages(access_token,
                                              subm_messages,
                                              current=True)
            if message_list:
                self.send_all_messages(access_token,
                                       message_list,
                                       current=False)
        else:
            message_list.append(messages)
            response = self.send_all_messages(access_token,
                                              message_list,
                                              current=False)

        base_url = self.assignment.server_url + '/{}/{}/{}'

        if isinstance(response, dict):
            print_success('{action} successful for user: {email}'.format(
                action=action.title(), email=response['data']['email']))

            submission_type = 'submissions' if self.args.submit else 'backups'
            url = base_url.format(response['data']['assignment'],
                                  submission_type, response['data']['key'])

            if self.args.submit or self.args.backup:
                print_success('URL: {0}'.format(url))

            if self.args.backup:
                print('NOTE: this is only a backup. '
                      'To submit your assignment, use:\n'
                      '\tpython3 ok --submit')

        self.dump_unsent_messages(message_list + subm_messages)
        print()
예제 #6
0
    def send_all_messages(self, access_token, message_list, current=False):
        if not self.args.insecure:
            ssl = network.check_ssl()
        else:
            ssl = None

        if current and self.args.revise:
            action = "Revise"
        elif current and self.args.submit:
            action = "Submit"
        else:
            action = "Backup"

        num_messages = len(message_list)
        send_all = self.args.submit or self.args.backup
        retries = self.RETRY_LIMIT

        if send_all:
            timeout = None
            stop_time = datetime.datetime.max
            retries = self.RETRY_LIMIT * 2
        else:
            timeout = self.SHORT_TIMEOUT
            stop_time = datetime.datetime.now() + datetime.timedelta(
                seconds=timeout)
            log.info('Setting timeout to %d seconds', timeout)

        first_response = None
        error_msg = ''
        log.info("Sending {0} messages".format(num_messages))

        while retries > 0 and message_list and datetime.datetime.now(
        ) < stop_time:
            log.info('Sending messages...%d left', len(message_list))

            print('{action}... {percent}% complete'.format(
                action=action,
                percent=100 -
                round(len(message_list) * 100 / num_messages, 2)),
                  end='\r')

            # message_list is assumed to be ordered in chronological order.
            # We want to send the most recent message first, and send older
            # messages after.
            message = message_list[-1]

            try:
                response = self.send_messages(access_token, message, timeout,
                                              current)
            except requests.exceptions.Timeout as ex:
                log.warning("HTTP request timeout: %s", str(ex))
                retries -= 1
                error_msg = 'Connection timed out after {} seconds. '.format(timeout) + \
                            'Please check your network connection.'
            except (requests.exceptions.RequestException,
                    requests.exceptions.BaseHTTPError) as ex:
                log.warning('%s: %s', ex.__class__.__name__, str(ex))
                retries -= 1
                if getattr(ex, 'response', None) is None:
                    error_msg = 'Please check your network connection.'
                    continue
                try:
                    response_json = ex.response.json()
                except ValueError as ex:
                    log.warning("Invalid JSON Response", exc_info=True)
                    retries -= 1
                    error_msg = 'The server did not provide a valid response. Try again soon.'
                    continue

                log.warning('%s error message: %s', ex.__class__.__name__,
                            response_json['message'])

                if ex.response.status_code == 401:  # UNAUTHORIZED (technically authorization != authentication, but oh well)
                    raise exceptions.AuthenticationException(
                        response_json.get(
                            'message'))  # raise this for the caller
                elif ex.response.status_code == 403 and 'download_link' in response_json[
                        'data']:
                    retries = 0
                    error_msg = 'Aborting because OK may need to be updated.'
                else:
                    retries -= 1
                    error_msg = response_json['message']
            except Exception as ex:
                if ssl and isinstance(ex, ssl.CertificateError):
                    retries = 0
                    log.warning("SSL Error: %s", str(ex))
                    error_msg = 'SSL Verification Error: {}\n'.format(ex) + \
                                'Please check your network connection and SSL configuration.'
                else:
                    retries -= 1
                    log.warning(error_msg, exc_info=True)
                    error_msg = "Unknown Error: {}".format(ex)
            else:
                if not first_response:
                    first_response = response
                message_list.pop()

        if current and error_msg:
            print()  # Preserve progress bar.
            print_error('Could not', action.lower() + ':', error_msg)
        elif not message_list:
            print('{action}... 100% complete'.format(action=action))
            due_date = self.get_due_date(access_token, timeout)
            if due_date is not None and action != "Revise":
                now = datetime.datetime.now(tz=datetime.timezone.utc)
                time_to_deadline = due_date - now
                if time_to_deadline < datetime.timedelta(0):
                    print_error(
                        "{action} past deadline by".format(action=action),
                        display_timedelta(-time_to_deadline))
                elif time_to_deadline < datetime.timedelta(hours=10):
                    print_warning("Assignment is due in",
                                  display_timedelta(time_to_deadline))
            return first_response
        elif not send_all:
            # Do not display any error messages if --backup or --submit are not
            # used.
            print()
        elif not error_msg:
            # No errors occurred, but could not complete request within TIMEOUT.
            print()  # Preserve progress bar.
            print_error('Could not {} within {} seconds.'.format(
                action.lower(), timeout))
        else:
            # If not all messages could be backed up successfully.
            print()  # Preserve progress bar.
            print_error('Could not', action.lower() + ':', error_msg)
예제 #7
0
    def run(self, messages):
        if not self.assignment.endpoint:
            log.info('No assignment endpoint, skipping backup')
            return

        if self.args.local:
            print("Cannot backup when running ok with --local.")
            return

        if not self.args.insecure:
            network.check_ssl()

        if self.args.revise:
            action = 'revision'
        elif self.args.submit:
            action = 'submission'
        else:
            action = 'backup'

        message_list = self.load_unsent_messages()

        access_token = self.assignment.authenticate()
        log.info('Authenticated with access token')
        log.info('Sending unsent messages')

        if not access_token:
            print("Not authenticated. Cannot send {} to server".format(action))
            self.dump_unsent_messages(message_list)
            return

        # Messages from the current backup to send first
        is_send_first = self.args.submit or self.args.revise
        subm_messages = [messages] if is_send_first else []

        if is_send_first:
            response = self.send_all_messages(access_token, subm_messages,
                                              current=True)
            if message_list:
                self.send_all_messages(access_token, message_list,
                                       current=False)
        else:
            message_list.append(messages)
            response = self.send_all_messages(access_token, message_list,
                                              current=False)

        base_url = self.assignment.server_url + '/{}/{}/{}'

        if isinstance(response, dict):
            print('{action} successful for user: {email}'.format(action=action.title(),
                        email=response['data']['email']))

            submission_type = 'submissions' if self.args.submit else 'backups'
            url = base_url.format(response['data']['assignment'],
                                  submission_type,
                                  response['data']['key'])

            if self.args.submit or self.args.backup:
                print('URL: {0}'.format(url))

            if self.args.backup:
                print('NOTE: this is only a backup. '
                      'To submit your assignment, use:\n'
                      '\tpython3 ok --submit')

        self.dump_unsent_messages(message_list + subm_messages)
        print()
예제 #8
0
    def send_all_messages(self, access_token, message_list, current=False):
        if not self.args.insecure:
            ssl = network.check_ssl()
        else:
            ssl = None

        if current and self.args.revise:
            action = "Revise"
        elif current and self.args.submit:
            action = "Submit"
        else:
            action = "Backup"

        num_messages = len(message_list)
        send_all = self.args.submit or self.args.backup
        retries = self.RETRY_LIMIT

        if send_all:
            timeout = None
            stop_time = datetime.datetime.max
            retries = self.RETRY_LIMIT * 2
        else:
            timeout = self.SHORT_TIMEOUT
            stop_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
            log.info('Setting timeout to %d seconds', timeout)

        first_response = None
        error_msg = ''
        log.info("Sending {0} messages".format(num_messages))

        while retries > 0 and message_list and datetime.datetime.now() < stop_time:
            log.info('Sending messages...%d left', len(message_list))

            print('{action}... {percent}% complete'.format(action=action,
                percent=100 - round(len(message_list) * 100 / num_messages, 2)),
                end='\r')

            # message_list is assumed to be ordered in chronological order.
            # We want to send the most recent message first, and send older
            # messages after.
            message = message_list[-1]

            try:
                response = self.send_messages(access_token, message, timeout, current)
            except requests.exceptions.Timeout as ex:
                log.warning("HTTP request timeout: %s", str(ex))
                retries -= 1
                error_msg = 'Connection timed out after {} seconds. '.format(timeout) + \
                            'Please check your network connection.'
            except (requests.exceptions.RequestException, requests.exceptions.BaseHTTPError) as ex:
                log.warning('%s: %s', ex.__class__.__name__, str(ex))
                retries -= 1
                if getattr(ex, 'response', None) is None:
                    error_msg = 'Please check your network connection.'
                    continue
                try:
                    response_json = ex.response.json()
                except ValueError as ex:
                    log.warning("Invalid JSON Response", exc_info=True)
                    retries -= 1
                    error_msg = 'The server did not provide a valid response. Try again soon.'
                    continue

                log.warning('%s error message: %s', ex.__class__.__name__,
                            response_json['message'])

                if ex.response.status_code == 403 and 'download_link' in response_json['data']:
                    retries = 0
                    error_msg = 'Aborting because OK may need to be updated.'
                else:
                    retries -= 1
                    error_msg = response_json['message']
            except Exception as ex:
                if ssl and isinstance(ex, ssl.CertificateError):
                    retries = 0
                    log.warning("SSL Error: %s", str(ex))
                    error_msg = 'SSL Verification Error: {}\n'.format(ex) + \
                                'Please check your network connection and SSL configuration.'
                else:
                    retries -= 1
                    log.warning(error_msg, exc_info=True)
                    error_msg = "Unknown Error: {}".format(ex)
            else:
                if not first_response:
                    first_response = response
                message_list.pop()

        if current and error_msg:
            print()     # Preserve progress bar.
            print('Could not', action.lower() + ':', error_msg)
        elif not message_list:
            print('{action}... 100% complete'.format(action=action))
            return first_response
        elif not send_all:
            # Do not display any error messages if --backup or --submit are not
            # used.
            print()
        elif not error_msg:
            # No errors occurred, but could not complete request within TIMEOUT.
            print()     # Preserve progress bar.
            print('Could not {} within {} seconds.'.format(action.lower(), timeout))
        else:
            # If not all messages could be backed up successfully.
            print()     # Preserve progress bar.
            print('Could not', action.lower() + ':', error_msg)