summary refs log tree commit diff
path: root/synapse/api/events/validator.py
blob: 59b486d6d7c06a6a4a56ac78466e7b9096a182b2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# -*- coding: utf-8 -*-
# Copyright 2014 OpenMarket Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from synapse.api.errors import SynapseError, Codes


class EventValidator(object):
    def __init__(self, hs):
        pass

    def validate(self, event):
        """Checks the given JSON content abides by the rules of the template.

        Args:
            content : A JSON object to check.
            raises: True to raise a SynapseError if the check fails.
        Returns:
            True if the content passes the template. Returns False if the check
            fails and raises=False.
        Raises:
            SynapseError if the check fails and raises=True.
        """
        # recursively call to inspect each layer
        err_msg = self._check_json_template(
            event.content,
            event.get_content_template()
        )
        if err_msg:
            raise SynapseError(400, err_msg, Codes.BAD_JSON)
        else:
            return True

    def _check_json_template(self, content, template):
        """Check content and template matches.

        If the template is a dict, each key in the dict will be validated with
        the content, else it will just compare the types of content and
        template. This basic type check is required because this function will
        be recursively called and could be called with just strs or ints.

        Args:
            content: The content to validate.
            template: The validation template.
        Returns:
            str: An error message if the validation fails, else None.
        """
        if type(content) != type(template):
            return "Mismatched types: %s" % template

        if type(template) == dict:
            for key in template:
                if key not in content:
                    return "Missing %s key" % key

                if type(content[key]) != type(template[key]):
                    return "Key %s is of the wrong type (got %s, want %s)" % (
                        key, type(content[key]), type(template[key]))

                if type(content[key]) == dict:
                    # we must go deeper
                    msg = self._check_json(content[key], template[key])
                    if msg:
                        return msg
                elif type(content[key]) == list:
                    # make sure each item type in content matches the template
                    for entry in content[key]:
                        msg = self._check_json(entry, template[key][0])
                        if msg:
                            return msg