Exemplo n.º 1
0
    def __init__(self, request, response):  # pylint: disable=super-init-not-called
        # Set self.request, self.response and self.app.
        self.initialize(request, response)

        self.start_time = datetime.datetime.utcnow()

        # Initializes the return dict for the handlers.
        self.values = {}

        # This try-catch block is intended to log cases where getting the
        # request payload errors with ValueError: Invalid boundary in multipart
        # form: b''. This is done to gather sufficient data to help debug the
        # error if it arises in the future.
        try:
            payload_json_string = self.request.get('payload')
        except ValueError as e:
            logging.error('%s: request %s', e, self.request)
            raise e
        # TODO(#13155): Remove the if-else part once all the handlers have had
        # schema validation implemented.
        if payload_json_string:
            self.payload = json.loads(payload_json_string)
        else:
            self.payload = None
        self.iframed = False

        self.user_id = None
        self.username = None
        self.email = None
        self.partially_logged_in = False
        self.user_is_scheduled_for_deletion = False
        self.current_user_is_super_admin = False
        # Once the attribute `normalized_request` is type annotated here, make
        # sure to fix all the subclasses using normalized_request.get() method
        # by removing their type: ignore[union-attr] and using a type cast
        # instead to eliminate the possibility on union types.
        # e.g. ClassroomAccessValidationHandler.
        self.normalized_request = None
        self.normalized_payload = None

        try:
            auth_claims = auth_services.get_auth_claims_from_request(request)
        except auth_domain.StaleAuthSessionError:
            auth_services.destroy_auth_session(self.response)
            self.redirect(user_services.create_login_url(self.request.uri))
            return
        except auth_domain.UserDisabledError:
            auth_services.destroy_auth_session(self.response)
            self.redirect('/logout?redirect_url=%s' %
                          feconf.PENDING_ACCOUNT_DELETION_URL)
            return
        except auth_domain.InvalidAuthSessionError:
            logging.exception('User session is invalid!')
            auth_services.destroy_auth_session(self.response)
            self.redirect(user_services.create_login_url(self.request.uri))
            return
        else:
            self.current_user_is_super_admin = (
                auth_claims is not None and auth_claims.role_is_super_admin)

        if auth_claims:
            auth_id = auth_claims.auth_id
            user_settings = user_services.get_user_settings_by_auth_id(auth_id)
            if user_settings is None:
                # If the user settings are not yet created and the request leads
                # to signup page create a new user settings. Otherwise logout
                # the not-fully registered user.
                email = auth_claims.email
                if 'signup?' in self.request.uri:
                    user_settings = (user_services.create_new_user(
                        auth_id, email))
                else:
                    logging.exception(
                        'Cannot find user %s with email %s on page %s' %
                        (auth_id, email, self.request.uri))
                    auth_services.destroy_auth_session(self.response)
                    return

            self.email = user_settings.email
            self.values['user_email'] = user_settings.email
            self.user_id = user_settings.user_id

            if user_settings.deleted:
                self.user_is_scheduled_for_deletion = user_settings.deleted
            elif (self.REDIRECT_UNFINISHED_SIGNUPS
                  and not user_services.has_fully_registered_account(
                      self.user_id)):
                self.partially_logged_in = True
            else:
                self.username = user_settings.username
                self.values['username'] = self.username
                # In order to avoid too many datastore writes, we do not bother
                # recording a log-in if the current time is sufficiently close
                # to the last log-in time.
                if (user_settings.last_logged_in is None
                        or not utils.are_datetimes_close(
                            datetime.datetime.utcnow(),
                            user_settings.last_logged_in)):
                    user_services.record_user_logged_in(self.user_id)

        self.roles = ([feconf.ROLE_ID_GUEST]
                      if self.user_id is None else user_settings.roles)
        self.user = user_services.get_user_actions_info(self.user_id)

        if not self._is_requested_path_currently_accessible_to_user():
            auth_services.destroy_auth_session(self.response)
            return

        self.values['is_super_admin'] = self.current_user_is_super_admin
Exemplo n.º 2
0
    def __init__(self, request, response):  # pylint: disable=super-init-not-called
        # Set self.request, self.response and self.app.
        self.initialize(request, response)

        self.start_time = datetime.datetime.utcnow()

        # Initializes the return dict for the handlers.
        self.values = {}

        if self.request.get('payload'):
            self.payload = json.loads(self.request.get('payload'))
        else:
            self.payload = None
        self.iframed = False

        self.user_id = None
        self.username = None
        self.email = None
        self.partially_logged_in = False
        self.user_is_scheduled_for_deletion = False
        self.current_user_is_super_admin = False

        try:
            auth_claims = auth_services.get_auth_claims_from_request(request)
        except auth_domain.StaleAuthSessionError:
            auth_services.destroy_auth_session(self.response)
            self.redirect(user_services.create_login_url(self.request.uri))
            return
        except auth_domain.InvalidAuthSessionError:
            logging.exception('User session is invalid!')
            auth_services.destroy_auth_session(self.response)
            self.redirect(user_services.create_login_url(self.request.uri))
            return
        else:
            self.current_user_is_super_admin = (
                auth_claims is not None and auth_claims.role_is_super_admin)

        if (feconf.ENABLE_MAINTENANCE_MODE
                and not self.current_user_is_super_admin
                and self.request.path not in AUTH_HANDLER_PATHS):
            auth_services.destroy_auth_session(self.response)
            return

        if auth_claims:
            auth_id = auth_claims.auth_id
            user_settings = user_services.get_user_settings_by_auth_id(auth_id)
            if user_settings is None:
                # If the user settings are not yet created and the request leads
                # to signup page create a new user settings. Otherwise logout
                # the not-fully registered user.
                email = auth_claims.email
                if 'signup?' in self.request.uri:
                    user_settings = (user_services.create_new_user(
                        auth_id, email))
                else:
                    logging.error(
                        'Cannot find user %s with email %s on page %s' %
                        (auth_id, email, self.request.uri))
                    auth_services.destroy_auth_session(self.response)
                    return

            self.email = user_settings.email
            self.values['user_email'] = user_settings.email
            self.user_id = user_settings.user_id

            if user_settings.deleted:
                self.user_is_scheduled_for_deletion = user_settings.deleted
            elif (self.REDIRECT_UNFINISHED_SIGNUPS
                  and not user_services.has_fully_registered_account(
                      self.user_id)):
                self.partially_logged_in = True
            else:
                self.username = user_settings.username
                self.values['username'] = self.username
                # In order to avoid too many datastore writes, we do not bother
                # recording a log-in if the current time is sufficiently close
                # to the last log-in time.
                if (user_settings.last_logged_in is None
                        or not utils.are_datetimes_close(
                            datetime.datetime.utcnow(),
                            user_settings.last_logged_in)):
                    user_services.record_user_logged_in(self.user_id)

        self.role = (feconf.ROLE_ID_GUEST
                     if self.user_id is None else user_settings.role)
        self.user = user_services.get_user_actions_info(self.user_id)

        self.values['is_moderator'] = (user_services.is_at_least_moderator(
            self.user_id))
        self.values['is_admin'] = user_services.is_admin(self.user_id)
        self.values['is_topic_manager'] = (user_services.is_topic_manager(
            self.user_id))
        self.values['is_super_admin'] = self.current_user_is_super_admin
Exemplo n.º 3
0
    def handle_exception(self, exception, unused_debug_mode):
        """Overwrites the default exception handler.

        Args:
            exception: Exception. The exception that was thrown.
            unused_debug_mode: bool. True if the web application is running
                in debug mode.
        """
        if isinstance(exception, self.NotLoggedInException):
            # This checks if the response should be JSON or HTML.
            # For GET requests, there is no payload, so we check against
            # GET_HANDLER_ERROR_RETURN_TYPE.
            # Otherwise, we check whether self.payload exists.
            if (self.payload is not None or
                    self.GET_HANDLER_ERROR_RETURN_TYPE ==
                    feconf.HANDLER_TYPE_JSON):
                self.error(401)
                self._render_exception(
                    401, {
                        'error': (
                            'You must be logged in to access this resource.')})
            else:
                self.redirect(user_services.create_login_url(self.request.uri))
            return

        logging.error(b''.join(traceback.format_exception(*sys.exc_info())))

        if isinstance(exception, self.PageNotFoundException):
            logging.warning('Invalid URL requested: %s', self.request.uri)
            self.error(404)
            self._render_exception(
                404, {
                    'error': 'Could not find the page %s.' % self.request.uri})
            return

        logging.error('Exception raised: %s', exception)

        if isinstance(exception, self.UnauthorizedUserException):
            self.error(401)
            self._render_exception(401, {'error': python_utils.convert_to_bytes(
                exception)})
            return

        if isinstance(exception, self.InvalidInputException):
            self.error(400)
            self._render_exception(400, {'error': python_utils.convert_to_bytes(
                exception)})
            return

        if isinstance(exception, self.InternalErrorException):
            self.error(500)
            self._render_exception(500, {'error': python_utils.convert_to_bytes(
                exception)})
            return

        if isinstance(exception, self.TemporaryMaintenanceException):
            self.error(503)
            self._render_exception(503, {'error': python_utils.convert_to_bytes(
                exception)})
            return

        self.error(500)
        self._render_exception(
            500, {'error': python_utils.convert_to_bytes(exception)})
Exemplo n.º 4
0
    def handle_exception(self, exception, unused_debug_mode):
        """Overwrites the default exception handler.

        Args:
            exception: Exception. The exception that was thrown.
            unused_debug_mode: bool. True if the web application is running
                in debug mode.
        """
        if isinstance(exception, self.NotLoggedInException):
            # This checks if the response should be JSON or HTML.
            # For GET requests, there is no payload, so we check against
            # GET_HANDLER_ERROR_RETURN_TYPE.
            # Otherwise, we check whether self.payload exists.

            # This check is to avoid throwing of 401 when payload doesn't
            # exists and self.payload is replaced by RaiseErrorOnGet object.
            # TODO(#13155): Change this to self.normalized_payload
            #  once schema is implemented for all handlers.
            payload_exists = (
                self.payload is not None and
                not isinstance(self.payload, RaiseErrorOnGet)
            )
            if (
                    payload_exists or
                    self.GET_HANDLER_ERROR_RETURN_TYPE ==
                    feconf.HANDLER_TYPE_JSON
            ):
                self.error(401)
                self._render_exception(
                    401, {
                        'error': (
                            'You must be logged in to access this resource.')})
            else:
                self.redirect(user_services.create_login_url(self.request.uri))
            return

        logging.exception(
            'Exception raised at %s: %s', self.request.uri, exception)

        if isinstance(exception, self.PageNotFoundException):
            logging.warning('Invalid URL requested: %s', self.request.uri)
            self.error(404)
            self._render_exception(
                404, {
                    'error': 'Could not find the page %s.' % self.request.uri})
            return

        logging.exception('Exception raised: %s', exception)

        if isinstance(exception, self.UnauthorizedUserException):
            self.error(401)
            self._render_exception(401, {'error': str(exception)})
            return

        if isinstance(exception, self.InvalidInputException):
            self.error(400)
            self._render_exception(400, {'error': str(exception)})
            return

        if isinstance(exception, self.InternalErrorException):
            self.error(500)
            self._render_exception(500, {'error': str(exception)})
            return

        self.error(500)
        self._render_exception(500, {'error': str(exception)})