# Buggy code
def check_redaction(
    room_version_obj: RoomVersion,
    event: EventBase,
    auth_events: StateMap[EventBase],
) -> bool:
    """Check whether the event sender is allowed to redact the target event.

    Returns:
        True if the the sender is allowed to redact the target event if the
        target event was created by them.
        False if the sender is allowed to redact the target event with no
        further checks.

    Raises:
        AuthError if the event sender is definitely not allowed to redact
        the target event.
    """
    user_level = get_user_power_level(event.user_id, auth_events)

    redact_level = _get_named_level(auth_events, "redact", 50)

    if user_level >= redact_level:
        return False

    if room_version_obj.event_format == EventFormatVersions.V1:
        redacter_domain = get_domain_from_id(event.event_id)
        redactee_domain = get_domain_from_id(event.redacts)
        if redacter_domain == redactee_domain:
            return True
    else:
        event.internal_metadata.recheck_redaction = True
        return True

    raise AuthError(403, "You don't have permission to redact events")


# Traceback (FirstError)
synapse_1  | 2020-09-24 18:15:54,480 - synapse.handlers.federation - 1146 - ERROR - GET-3753 - Failed to backfill from t2bot.io because FirstError[#0, [Failure instance: Traceback: <class 'AttributeError'>: 'NoneType' object has no attribute 'find'
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:460:callback
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:568:_startRunCallbacks
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:654:_runCallbacks
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:1475:gotResult
synapse_1  | --- <exception caught here> ---
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:1418:_inlineCallbacks
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py:1984:prep
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py:2134:_prep_event
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py:2322:do_auth
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/event_auth.py:190:check
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/event_auth.py:449:check_redaction
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/types.py:152:get_domain_from_id
synapse_1  | ]]
synapse_1  | Traceback (most recent call last):
synapse_1  |   File "/usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py", line 1115, in try_backfill
synapse_1  |     dom, room_id, limit=100, extremities=extremities
synapse_1  |   File "/usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py", line 926, in backfill
synapse_1  |     await self._handle_new_events(dest, ev_infos, backfilled=True)
synapse_1  |   File "/usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py", line 1991, in _handle_new_events
synapse_1  |     consumeErrors=True,
synapse_1  | twisted.internet.defer.FirstError: FirstError[#0, [Failure instance: Traceback: <class 'AttributeError'>: 'NoneType' object has no attribute 'find'
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:460:callback
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:568:_startRunCallbacks
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:654:_runCallbacks
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:1475:gotResult
synapse_1  | --- <exception caught here> ---
synapse_1  | /usr/local/lib/python3.7/site-packages/twisted/internet/defer.py:1418:_inlineCallbacks
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py:1984:prep
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py:2134:_prep_event
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/handlers/federation.py:2322:do_auth
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/event_auth.py:190:check
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/event_auth.py:449:check_redaction
synapse_1  | /usr/local/lib/python3.7/site-packages/synapse/types.py:152:get_domain_from_id
synapse_1  | ]]

# Fixed code
def check_redaction(
    room_version_obj: RoomVersion,
    event: EventBase,
    auth_events: StateMap[EventBase],
) -> bool:
    """Check whether the event sender is allowed to redact the target event.

    Returns:
        True if the the sender is allowed to redact the target event if the
        target event was created by them.
        False if the sender is allowed to redact the target event with no
        further checks.

    Raises:
        AuthError if the event sender is definitely not allowed to redact
        the target event.
    """
    user_level = get_user_power_level(event.user_id, auth_events)

    redact_level = _get_named_level(auth_events, "redact", 50)

    if user_level >= redact_level:
        return False

    if room_version_obj.event_format == EventFormatVersions.V1:
        redacter_domain = get_domain_from_id(event.event_id)
        if not isinstance(event.redacts, str):
            return False
        redactee_domain = get_domain_from_id(event.redacts)
        if redacter_domain == redactee_domain:
            return True
    else:
        event.internal_metadata.recheck_redaction = True
        return True

    raise AuthError(403, "You don't have permission to redact events")