Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

matrix-org / synapse / 4532

23 Sep 2019 - 19:39 coverage decreased (-49.7%) to 17.596%
4532

Pull #6079

buildkite

Richard van der Hoff
update changelog
Pull Request #6079: Add submit_url response parameter to msisdn /requestToken

359 of 12986 branches covered (2.76%)

Branch coverage included in aggregate %.

0 of 7 new or added lines in 1 file covered. (0.0%)

18869 existing lines in 281 files now uncovered.

8809 of 39116 relevant lines covered (22.52%)

0.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

34.17
/synapse/events/__init__.py
1
# -*- coding: utf-8 -*-
2
# Copyright 2014-2016 OpenMarket Ltd
3
# Copyright 2019 New Vector Ltd
4
#
5
# Licensed under the Apache License, Version 2.0 (the "License");
6
# you may not use this file except in compliance with the License.
7
# You may obtain a copy of the License at
8
#
9
#     http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS,
13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
# See the License for the specific language governing permissions and
15
# limitations under the License.
16

17
import os
1×
18
from distutils.util import strtobool
1×
19

20
import six
1×
21

22
from unpaddedbase64 import encode_base64
1×
23

24
from synapse.api.errors import UnsupportedRoomVersionError
1×
25
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, EventFormatVersions
1×
26
from synapse.util.caches import intern_dict
1×
27
from synapse.util.frozenutils import freeze
1×
28

29
# Whether we should use frozen_dict in FrozenEvent. Using frozen_dicts prevents
30
# bugs where we accidentally share e.g. signature dicts. However, converting a
31
# dict to frozen_dicts is expensive.
32
#
33
# NOTE: This is overridden by the configuration by the Synapse worker apps, but
34
# for the sake of tests, it is set here while it cannot be configured on the
35
# homeserver object itself.
36
USE_FROZEN_DICTS = strtobool(os.environ.get("SYNAPSE_USE_FROZEN_DICTS", "0"))
1×
37

38

39
class _EventInternalMetadata(object):
1×
40
    def __init__(self, internal_metadata_dict):
1×
UNCOV
41
        self.__dict__ = dict(internal_metadata_dict)
!
42

43
    def get_dict(self):
1×
UNCOV
44
        return dict(self.__dict__)
!
45

46
    def is_outlier(self):
1×
UNCOV
47
        return getattr(self, "outlier", False)
!
48

49
    def is_out_of_band_membership(self):
1×
50
        """Whether this is an out of band membership, like an invite or an invite
51
        rejection. This is needed as those events are marked as outliers, but
52
        they still need to be processed as if they're new events (e.g. updating
53
        invite state in the database, relaying to clients, etc).
54
        """
UNCOV
55
        return getattr(self, "out_of_band_membership", False)
!
56

57
    def get_send_on_behalf_of(self):
1×
58
        """Whether this server should send the event on behalf of another server.
59
        This is used by the federation "send_join" API to forward the initial join
60
        event for a server in the room.
61

62
        returns a str with the name of the server this event is sent on behalf of.
63
        """
UNCOV
64
        return getattr(self, "send_on_behalf_of", None)
!
65

66
    def need_to_check_redaction(self):
1×
67
        """Whether the redaction event needs to be rechecked when fetching
68
        from the database.
69

70
        Starting in room v3 redaction events are accepted up front, and later
71
        checked to see if the redacter and redactee's domains match.
72

73
        If the sender of the redaction event is allowed to redact any event
74
        due to auth rules, then this will always return false.
75

76
        Returns:
77
            bool
78
        """
UNCOV
79
        return getattr(self, "recheck_redaction", False)
!
80

81
    def is_soft_failed(self):
1×
82
        """Whether the event has been soft failed.
83

84
        Soft failed events should be handled as usual, except:
85
            1. They should not go down sync or event streams, or generally
86
               sent to clients.
87
            2. They should not be added to the forward extremities (and
88
               therefore not to current state).
89

90
        Returns:
91
            bool
92
        """
UNCOV
93
        return getattr(self, "soft_failed", False)
!
94

95
    def should_proactively_send(self):
1×
96
        """Whether the event, if ours, should be sent to other clients and
97
        servers.
98

99
        This is used for sending dummy events internally. Servers and clients
100
        can still explicitly fetch the event.
101

102
        Returns:
103
            bool
104
        """
UNCOV
105
        return getattr(self, "proactively_send", True)
!
106

107
    def is_redacted(self):
1×
108
        """Whether the event has been redacted.
109

110
        This is used for efficiently checking whether an event has been
111
        marked as redacted without needing to make another database call.
112

113
        Returns:
114
            bool
115
        """
UNCOV
116
        return getattr(self, "redacted", False)
!
117

118

119
def _event_dict_property(key):
1×
120
    # We want to be able to use hasattr with the event dict properties.
121
    # However, (on python3) hasattr expects AttributeError to be raised. Hence,
122
    # we need to transform the KeyError into an AttributeError
123
    def getter(self):
1×
UNCOV
124
        try:
!
UNCOV
125
            return self._event_dict[key]
!
126
        except KeyError:
!
127
            raise AttributeError(key)
!
128

129
    def setter(self, v):
1×
130
        try:
!
131
            self._event_dict[key] = v
!
132
        except KeyError:
!
133
            raise AttributeError(key)
!
134

135
    def delete(self):
1×
136
        try:
!
137
            del self._event_dict[key]
!
138
        except KeyError:
!
139
            raise AttributeError(key)
!
140

141
    return property(getter, setter, delete)
1×
142

143

144
class EventBase(object):
1×
145
    def __init__(
1×
146
        self,
147
        event_dict,
148
        signatures={},
149
        unsigned={},
150
        internal_metadata_dict={},
151
        rejected_reason=None,
152
    ):
UNCOV
153
        self.signatures = signatures
!
UNCOV
154
        self.unsigned = unsigned
!
UNCOV
155
        self.rejected_reason = rejected_reason
!
156

UNCOV
157
        self._event_dict = event_dict
!
158

UNCOV
159
        self.internal_metadata = _EventInternalMetadata(internal_metadata_dict)
!
160

161
    auth_events = _event_dict_property("auth_events")
1×
162
    depth = _event_dict_property("depth")
1×
163
    content = _event_dict_property("content")
1×
164
    hashes = _event_dict_property("hashes")
1×
165
    origin = _event_dict_property("origin")
1×
166
    origin_server_ts = _event_dict_property("origin_server_ts")
1×
167
    prev_events = _event_dict_property("prev_events")
1×
168
    redacts = _event_dict_property("redacts")
1×
169
    room_id = _event_dict_property("room_id")
1×
170
    sender = _event_dict_property("sender")
1×
171
    user_id = _event_dict_property("sender")
1×
172

173
    @property
1×
174
    def membership(self):
UNCOV
175
        return self.content["membership"]
!
176

177
    def is_state(self):
1×
UNCOV
178
        return hasattr(self, "state_key") and self.state_key is not None
!
179

180
    def get_dict(self):
1×
UNCOV
181
        d = dict(self._event_dict)
!
UNCOV
182
        d.update({"signatures": self.signatures, "unsigned": dict(self.unsigned)})
!
183

UNCOV
184
        return d
!
185

186
    def get(self, key, default=None):
1×
UNCOV
187
        return self._event_dict.get(key, default)
!
188

189
    def get_internal_metadata_dict(self):
1×
190
        return self.internal_metadata.get_dict()
!
191

192
    def get_pdu_json(self, time_now=None):
1×
UNCOV
193
        pdu_json = self.get_dict()
!
194

UNCOV
195
        if time_now is not None and "age_ts" in pdu_json["unsigned"]:
Branches [[0, 196], [0, 201]] missed. !
UNCOV
196
            age = time_now - pdu_json["unsigned"]["age_ts"]
!
UNCOV
197
            pdu_json.setdefault("unsigned", {})["age"] = int(age)
!
UNCOV
198
            del pdu_json["unsigned"]["age_ts"]
!
199

200
        # This may be a frozen event
UNCOV
201
        pdu_json["unsigned"].pop("redacted_because", None)
!
202

UNCOV
203
        return pdu_json
!
204

205
    def __set__(self, instance, value):
1×
206
        raise AttributeError("Unrecognized attribute %s" % (instance,))
!
207

208
    def __getitem__(self, field):
1×
UNCOV
209
        return self._event_dict[field]
!
210

211
    def __contains__(self, field):
1×
212
        return field in self._event_dict
!
213

214
    def items(self):
1×
UNCOV
215
        return list(self._event_dict.items())
!
216

217
    def keys(self):
1×
UNCOV
218
        return six.iterkeys(self._event_dict)
!
219

220
    def prev_event_ids(self):
1×
221
        """Returns the list of prev event IDs. The order matches the order
222
        specified in the event, though there is no meaning to it.
223

224
        Returns:
225
            list[str]: The list of event IDs of this event's prev_events
226
        """
UNCOV
227
        return [e for e, _ in self.prev_events]
Branches [[0, 227], [0, 220]] missed. !
228

229
    def auth_event_ids(self):
1×
230
        """Returns the list of auth event IDs. The order matches the order
231
        specified in the event, though there is no meaning to it.
232

233
        Returns:
234
            list[str]: The list of event IDs of this event's auth_events
235
        """
UNCOV
236
        return [e for e, _ in self.auth_events]
Branches [[0, 236], [0, 229]] missed. !
237

238

239
class FrozenEvent(EventBase):
1×
240
    format_version = EventFormatVersions.V1  # All events of this type are V1
1×
241

242
    def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
1×
UNCOV
243
        event_dict = dict(event_dict)
!
244

245
        # Signatures is a dict of dicts, and this is faster than doing a
246
        # copy.deepcopy
UNCOV
247
        signatures = {
Branches [[0, 248], [0, 247], [0, 252]] missed. !
248
            name: {sig_id: sig for sig_id, sig in sigs.items()}
249
            for name, sigs in event_dict.pop("signatures", {}).items()
250
        }
251

UNCOV
252
        unsigned = dict(event_dict.pop("unsigned", {}))
!
253

254
        # We intern these strings because they turn up a lot (especially when
255
        # caching).
UNCOV
256
        event_dict = intern_dict(event_dict)
!
257

UNCOV
258
        if USE_FROZEN_DICTS:
Branches [[0, 259], [0, 261]] missed. !
259
            frozen_dict = freeze(event_dict)
!
260
        else:
UNCOV
261
            frozen_dict = event_dict
!
262

UNCOV
263
        self.event_id = event_dict["event_id"]
!
UNCOV
264
        self.type = event_dict["type"]
!
UNCOV
265
        if "state_key" in event_dict:
Branches [[0, 266], [0, 268]] missed. !
UNCOV
266
            self.state_key = event_dict["state_key"]
!
267

UNCOV
268
        super(FrozenEvent, self).__init__(
!
269
            frozen_dict,
270
            signatures=signatures,
271
            unsigned=unsigned,
272
            internal_metadata_dict=internal_metadata_dict,
273
            rejected_reason=rejected_reason,
274
        )
275

276
    def __str__(self):
1×
UNCOV
277
        return self.__repr__()
!
278

279
    def __repr__(self):
1×
UNCOV
280
        return "<FrozenEvent event_id='%s', type='%s', state_key='%s'>" % (
!
281
            self.get("event_id", None),
282
            self.get("type", None),
283
            self.get("state_key", None),
284
        )
285

286

287
class FrozenEventV2(EventBase):
1×
288
    format_version = EventFormatVersions.V2  # All events of this type are V2
1×
289

290
    def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
1×
UNCOV
291
        event_dict = dict(event_dict)
!
292

293
        # Signatures is a dict of dicts, and this is faster than doing a
294
        # copy.deepcopy
UNCOV
295
        signatures = {
Branches [[0, 296], [0, 295], [0, 300]] missed. !
296
            name: {sig_id: sig for sig_id, sig in sigs.items()}
297
            for name, sigs in event_dict.pop("signatures", {}).items()
298
        }
299

UNCOV
300
        assert "event_id" not in event_dict
!
301

UNCOV
302
        unsigned = dict(event_dict.pop("unsigned", {}))
!
303

304
        # We intern these strings because they turn up a lot (especially when
305
        # caching).
UNCOV
306
        event_dict = intern_dict(event_dict)
!
307

UNCOV
308
        if USE_FROZEN_DICTS:
Branches [[0, 309], [0, 311]] missed. !
309
            frozen_dict = freeze(event_dict)
!
310
        else:
UNCOV
311
            frozen_dict = event_dict
!
312

UNCOV
313
        self._event_id = None
!
UNCOV
314
        self.type = event_dict["type"]
!
UNCOV
315
        if "state_key" in event_dict:
Branches [[0, 316], [0, 318]] missed. !
UNCOV
316
            self.state_key = event_dict["state_key"]
!
317

UNCOV
318
        super(FrozenEventV2, self).__init__(
!
319
            frozen_dict,
320
            signatures=signatures,
321
            unsigned=unsigned,
322
            internal_metadata_dict=internal_metadata_dict,
323
            rejected_reason=rejected_reason,
324
        )
325

326
    @property
1×
327
    def event_id(self):
328
        # We have to import this here as otherwise we get an import loop which
329
        # is hard to break.
UNCOV
330
        from synapse.crypto.event_signing import compute_event_reference_hash
!
331

UNCOV
332
        if self._event_id:
Branches [[0, 333], [0, 334]] missed. !
UNCOV
333
            return self._event_id
!
UNCOV
334
        self._event_id = "$" + encode_base64(compute_event_reference_hash(self)[1])
!
UNCOV
335
        return self._event_id
!
336

337
    def prev_event_ids(self):
1×
338
        """Returns the list of prev event IDs. The order matches the order
339
        specified in the event, though there is no meaning to it.
340

341
        Returns:
342
            list[str]: The list of event IDs of this event's prev_events
343
        """
UNCOV
344
        return self.prev_events
!
345

346
    def auth_event_ids(self):
1×
347
        """Returns the list of auth event IDs. The order matches the order
348
        specified in the event, though there is no meaning to it.
349

350
        Returns:
351
            list[str]: The list of event IDs of this event's auth_events
352
        """
UNCOV
353
        return self.auth_events
!
354

355
    def __str__(self):
1×
UNCOV
356
        return self.__repr__()
!
357

358
    def __repr__(self):
1×
UNCOV
359
        return "<%s event_id='%s', type='%s', state_key='%s'>" % (
!
360
            self.__class__.__name__,
361
            self.event_id,
362
            self.get("type", None),
363
            self.get("state_key", None),
364
        )
365

366

367
class FrozenEventV3(FrozenEventV2):
1×
368
    """FrozenEventV3, which differs from FrozenEventV2 only in the event_id format"""
369

370
    format_version = EventFormatVersions.V3  # All events of this type are V3
1×
371

372
    @property
1×
373
    def event_id(self):
374
        # We have to import this here as otherwise we get an import loop which
375
        # is hard to break.
UNCOV
376
        from synapse.crypto.event_signing import compute_event_reference_hash
!
377

UNCOV
378
        if self._event_id:
Branches [[0, 379], [0, 380]] missed. !
UNCOV
379
            return self._event_id
!
UNCOV
380
        self._event_id = "$" + encode_base64(
!
381
            compute_event_reference_hash(self)[1], urlsafe=True
382
        )
UNCOV
383
        return self._event_id
!
384

385

386
def room_version_to_event_format(room_version):
1×
387
    """Converts a room version string to the event format
388

389
    Args:
390
        room_version (str)
391

392
    Returns:
393
        int
394

395
    Raises:
396
        UnsupportedRoomVersionError if the room version is unknown
397
    """
UNCOV
398
    v = KNOWN_ROOM_VERSIONS.get(room_version)
!
399

UNCOV
400
    if not v:
Branches [[0, 402], [0, 404]] missed. !
401
        # this can happen if support is withdrawn for a room version
402
        raise UnsupportedRoomVersionError()
!
403

UNCOV
404
    return v.event_format
!
405

406

407
def event_type_from_format_version(format_version):
1×
408
    """Returns the python type to use to construct an Event object for the
409
    given event format version.
410

411
    Args:
412
        format_version (int): The event format version
413

414
    Returns:
415
        type: A type that can be initialized as per the initializer of
416
        `FrozenEvent`
417
    """
418

UNCOV
419
    if format_version == EventFormatVersions.V1:
Branches [[0, 420], [0, 421]] missed. !
UNCOV
420
        return FrozenEvent
!
UNCOV
421
    elif format_version == EventFormatVersions.V2:
Branches [[0, 422], [0, 423]] missed. !
UNCOV
422
        return FrozenEventV2
!
UNCOV
423
    elif format_version == EventFormatVersions.V3:
Branches [[0, 424], [0, 426]] missed. !
UNCOV
424
        return FrozenEventV3
!
425
    else:
426
        raise Exception("No event format %r" % (format_version,))
!
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2019 Coveralls, LLC