sqlalchemy-jsonapi icon indicating copy to clipboard operation
sqlalchemy-jsonapi copied to clipboard

TypeError occurs when formatting detail when raising BadRequestError with garbage relationships in post_collection

Open kaitj91 opened this issue 8 years ago • 3 comments

Here is a test that should return a BadRequestError:

    def test_add_resource_with_invalid_relationships(self):
        """Create resource with unknown OneToMany relationship key returns 400.

        A BadRequestError is raised.
        """
        payload = {
            'data': {
                'attributes': {
                    'first': 'Sally',
                    'last': 'Smith',
                    'username': 'SallySmith1',
                    'password': 'password',
                },
                'type': 'users',
                'relationships': {
                    'posts': {
                        'data': [{
                            'type': 'posts',
                            'id': 1
                        },
                        {
                            'type': 'posts',
                            'id': 2
                        }]
                    },
                    'dogs': {
                        'data': [{
                            'id': 1,
                            'type': 'dogs'
                        }]
                    }
                }
            }
        }

        with self.assertRaises(errors.BadRequestError) as error:
            models.serializer.post_collection(
                self.session, payload, 'users')

        self.assertEqual(error.exception.detail, 'dogs not relationship for users')
        self.assertEqual(error.exception.status_code, 400)

However this test will never actually return this detail message because when this check happens:

         data_keys = set(map((
            lambda x: resource.__jsonapi_map_to_py__.get(x, None)),
            data['data'].get('relationships', {}).keys()))
        model_keys = set(resource.__mapper__.relationships.keys())
        if not data_keys <= model_keys:
            raise BadRequestError(
                '{} not relationships for {}'.format(
                    ', '.join(list(data_keys -
                                   model_keys)), model.__jsonapi_type__))

When we take the difference between data_keys and model_keys we are getting {None} because data_keys = {'posts',None'} and model_keys = {'posts','comments',logs'}.

When the BadRequestError is raised we get a TypeError: sequence 0: expected str instance, NoneType found.

This happens on both python3 and python2. I will look at more as to how to fix this.

kaitj91 avatar Mar 17 '17 18:03 kaitj91

This same TypeError: sequence 0: expected str instance, NoneType found also occurs in patch_resource when trying to raise a BadRequestError. Will put up issue.

kaitj91 avatar Mar 21 '17 22:03 kaitj91

Do you know what the expression not data_keys <= model_keys is trying to figure out?

Anderycks avatar Mar 23 '17 15:03 Anderycks

Yes. Basically if you look at the test I posted above, we are trying to make sure we flag relationships that are not existent and raise a BadRequestError for those. So someone could send garbage input for the relationship keys, as I did in that test with dogs, and we would give a meaningful error message back so they understand the relationship between 'dogs' and 'users' does not exist. In other words, we are checking if data_keys is a subset of model_keys.

kaitj91 avatar Mar 24 '17 16:03 kaitj91