Ejemplo n.º 1
0
    def test_valid_args_do_not_raises_exception(self) -> None:
        # List of 3-tuples, where the first element is a valid argument dict,
        # the second element is a schema dict and the third element is the
        # normalized value of the corresponding argument.
        list_of_valid_args_with_schmea = [({}, {
            'exploration_id': {
                'schema': {
                    'type': 'basestring'
                },
                'default_value': None
            }
        }, {}),
                                          ({}, {
                                              'exploration_id': {
                                                  'schema': {
                                                      'type': 'basestring'
                                                  },
                                                  'default_value':
                                                  'default_exp_id'
                                              }
                                          }, {
                                              'exploration_id':
                                              'default_exp_id'
                                          }),
                                          ({
                                              'exploration_id': 'any_exp_id'
                                          }, {
                                              'exploration_id': {
                                                  'schema': {
                                                      'type': 'basestring'
                                                  }
                                              }
                                          }, {
                                              'exploration_id': 'any_exp_id'
                                          }),
                                          ({
                                              'apply_draft': 'true'
                                          }, {
                                              'apply_draft': {
                                                  'schema': {
                                                      'type': 'bool'
                                                  }
                                              }
                                          }, {
                                              'apply_draft': True
                                          })]
        for handler_args, handler_args_schema, normalized_value_for_args in (
                list_of_valid_args_with_schmea):
            normalized_value, errors = payload_validator.validate(
                handler_args,
                handler_args_schema,
                allowed_extra_args=False,
                allow_string_to_bool_conversion=True)

            self.assertEqual(normalized_value, normalized_value_for_args)
            self.assertEqual(errors, [])
Ejemplo n.º 2
0
    def test_invalid_args_raises_exceptions(self) -> None:
        # List of 3-tuples, where the first element is an invalid argument dict,
        # the second element is a schema dict and the third element
        # is a list of errors.

        list_of_invalid_args_with_schema_and_errors = [
            ({
                'exploration_id': 2
            }, {
                'exploration_id': {
                    'schema': {
                        'type': 'basestring'
                    }
                }
            }, [
                'Schema validation for \'exploration_id\' failed: '
                'Expected string, received 2'
            ]),
            ({
                'version': 'random_string'
            }, {
                'version': {
                    'schema': {
                        'type': 'int'
                    }
                }
            }, [
                'Schema validation for \'version\' failed: '
                'Could not convert str to int: random_string'
            ]),
            ({
                'exploration_id': 'any_exp_id'
            }, {}, ['Found extra args: [\'exploration_id\'].']),
            ({}, {
                'exploration_id': {
                    'schema': {
                        'type': 'basestring'
                    }
                }
            }, ['Missing key in handler args: exploration_id.'])
        ]
        for handler_args, handler_args_schema, error_msg in (
                list_of_invalid_args_with_schema_and_errors):
            normalized_value, errors = payload_validator.validate(
                handler_args,
                handler_args_schema,
                allowed_extra_args=False,
                allow_string_to_bool_conversion=False)

            self.assertEqual(normalized_value, {})
            self.assertEqual(error_msg, errors)
Ejemplo n.º 3
0
    def test_valid_args_do_not_raises_exception(self):
        # type: () -> None

        # List of 3-tuples, where the first element is a valid argument dict,
        # the second element is a schema dict and the third element is the
        # normalized value of the corresponding argument.
        list_of_valid_args_with_schmea = [({}, {
            'exploration_id': {
                'schema': {
                    'type': 'basestring'
                },
                'default_value': None
            }
        }, {}),
                                          ({}, {
                                              'exploration_id': {
                                                  'schema': {
                                                      'type': 'basestring'
                                                  },
                                                  'default_value':
                                                  'default_exp_id'
                                              }
                                          }, {
                                              'exploration_id':
                                              'default_exp_id'
                                          }),
                                          ({
                                              'exploration_id': 'any_exp_id'
                                          }, {
                                              'exploration_id': {
                                                  'schema': {
                                                      'type': 'basestring'
                                                  }
                                              }
                                          }, {
                                              'exploration_id': 'any_exp_id'
                                          })]
        for handler_args, handler_args_schema, normalized_value_for_args in (
                list_of_valid_args_with_schmea):
            normalized_value_for_args, errors = payload_validator.validate(
                handler_args, handler_args_schema, False)

            self.assertEqual(normalized_value_for_args,
                             normalized_value_for_args)
            self.assertEqual(errors, [])
Ejemplo n.º 4
0
    def vaidate_and_normalize_args(self):
        """Validates schema for controller layer handler class arguments.

        Raises:
            InvalidInputException. Schema validation failed.
            NotImplementedError. Schema is not provided in handler class.
        """
        handler_class_name = self.__class__.__name__
        request_method = self.request.environ['REQUEST_METHOD']
        url_path_args = self.request.route_kwargs
        handler_class_names_with_no_schema = (
            payload_validator.HANDLER_CLASS_NAMES_WITH_NO_SCHEMA)

        if handler_class_name in handler_class_names_with_no_schema:
            return

        handler_args = {}
        payload_arg_keys = []
        request_arg_keys = []
        for arg in self.request.arguments():
            if arg == 'csrf_token':
                # 'csrf_token' has been already validated in the
                # dispatch method.
                continue
            elif arg == 'source':
                source_url = self.request.get('source')
                regex_pattern = (
                    r'http[s]?://(?:[a-zA-Z]|[0-9]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+' # pylint: disable=line-too-long
                )
                regex_verified_url = re.findall(regex_pattern, source_url)
                if not regex_verified_url:
                    raise self.InvalidInputException(
                        'Not a valid source url.')
            elif arg == 'payload':
                payload_args = self.payload
                if payload_args is not None:
                    payload_arg_keys = list(payload_args.keys())
                    handler_args.update(payload_args)
            else:
                request_arg_keys.append(arg)
                handler_args[arg] = self.request.get(arg)

        # For html handlers, extra args are allowed (to accommodate
        # e.g. utm parameters which are not used by the backend but
        # needed for analytics).
        extra_args_are_allowed = (
            self.GET_HANDLER_ERROR_RETURN_TYPE == 'html' and
            request_method == 'GET')

        if self.URL_PATH_ARGS_SCHEMAS is None:
            raise NotImplementedError(
                'Missing schema for url path args in %s handler class.' % (
                    handler_class_name))

        schema_for_url_path_args = self.URL_PATH_ARGS_SCHEMAS
        normalized_arg_values, errors = (
            payload_validator.validate(
                url_path_args, schema_for_url_path_args, extra_args_are_allowed)
        )

        if errors:
            raise self.InvalidInputException('\n'.join(errors))

        # This check ensures that if a request method is not defined
        # in the handler class then schema validation will not raise
        # NotImplementedError for that corresponding request method.
        if request_method in ['GET', 'POST', 'PUT', 'DELETE'] and (
                getattr(self.__class__, request_method.lower()) ==
                getattr(BaseHandler, request_method.lower())):
            return

        try:
            schema_for_request_method = self.HANDLER_ARGS_SCHEMAS[
                request_method]
        except Exception:
            raise NotImplementedError(
                'Missing schema for %s method in %s handler class.' % (
                    request_method, handler_class_name))

        normalized_arg_values, errors = (
            payload_validator.validate(
                handler_args, schema_for_request_method, extra_args_are_allowed)
        )

        self.normalized_payload = {
            arg: normalized_arg_values.get(arg) for arg in payload_arg_keys
        }
        self.normalized_request = {
            arg: normalized_arg_values.get(arg) for arg in request_arg_keys
        }

        # The following keys are absent in request/payload but present in
        # normalized_arg_values because these args are populated from their
        # default_value provided in the schema.
        keys_that_correspond_to_default_values = list(
            set(normalized_arg_values.keys()) -
            set(payload_arg_keys + request_arg_keys)
        )
        # Populate the payload/request with the default args before passing
        # execution onwards to the handler.
        for arg in keys_that_correspond_to_default_values:
            if request_method in ['GET', 'DELETE']:
                self.normalized_request[arg] = normalized_arg_values.get(arg)
            else:
                self.normalized_payload[arg] = normalized_arg_values.get(arg)

        if errors:
            raise self.InvalidInputException('\n'.join(errors))