# Buggy code
async def on_PUT(self, request, user_id):
    requester = await self.auth.get_user_by_req(request)
    await assert_user_is_admin(self.auth, requester.user)

    target_user = UserID.from_string(user_id)
    body = parse_json_object_from_request(request)

    if not self.hs.is_mine(target_user):
        raise SynapseError(400, "This endpoint can only be used with local users")

    user = await self.admin_handler.get_user(target_user)
    user_id = target_user.to_string()

    if user:  # modify user
        if "displayname" in body:
            await self.profile_handler.set_displayname(
                target_user, requester, body["displayname"], True
            )

        if "threepids" in body:
            # check for required parameters for each threepid
            for threepid in body["threepids"]:
                assert_params_in_dict(threepid, ["medium", "address"])

            # remove old threepids from user
            threepids = await self.store.user_get_threepids(user_id)
            for threepid in threepids:
                try:
                    await self.auth_handler.delete_threepid(
                        user_id, threepid["medium"], threepid["address"], None
                    )
                except Exception:
                    logger.exception("Failed to remove threepids")
                    raise SynapseError(500, "Failed to remove threepids")

            # add new threepids to user
            current_time = self.hs.get_clock().time_msec()
            for threepid in body["threepids"]:
                await self.auth_handler.add_threepid(
                    user_id, threepid["medium"], threepid["address"], current_time
                )

        if "avatar_url" in body:
            await self.profile_handler.set_avatar_url(
                target_user, requester, body["avatar_url"], True
            )

        if "admin" in body:
            set_admin_to = bool(body["admin"])
            if set_admin_to != user["admin"]:
                auth_user = requester.user
                if target_user == auth_user and not set_admin_to:
                    raise SynapseError(400, "You may not demote yourself.")

                await self.admin_handler.set_user_server_admin(
                    target_user, set_admin_to
                )

        if "password" in body:
            if (
                not isinstance(body["password"], text_type)
                or len(body["password"]) > 512
            ):
                raise SynapseError(400, "Invalid password")
            else:
                new_password = body["password"]
                await self.set_password_handler.set_password(
                    target_user.to_string(), new_password, requester
                )

        if "deactivated" in body:
            deactivate = bool(body["deactivated"])
            if deactivate and not user["deactivated"]:
                result = await self.deactivate_account_handler.deactivate_account(
                    target_user.to_string(), False
                )
                if not result:
                    raise SynapseError(500, "Could not deactivate user")

        user = await self.admin_handler.get_user(target_user)
        return 200, user

    else:  # create user
        password = body.get("password")
        if password is not None and (
            not isinstance(body["password"], text_type) or len(body["password"]) > 512
        ):
            raise SynapseError(400, "Invalid password")

        admin = body.get("admin", None)
        user_type = body.get("user_type", None)
        displayname = body.get("displayname", None)
        threepids = body.get("threepids", None)

        if user_type is not None and user_type not in UserTypes.ALL_USER_TYPES:
            raise SynapseError(400, "Invalid user type")

        user_id = await self.registration_handler.register_user(
            localpart=target_user.localpart,
            password=password,
            admin=bool(admin),
            default_display_name=displayname,
            user_type=user_type,
        )

        if "threepids" in body:
            # check for required parameters for each threepid
            for threepid in body["threepids"]:
                assert_params_in_dict(threepid, ["medium", "address"])

            current_time = self.hs.get_clock().time_msec()
            for threepid in body["threepids"]:
                await self.auth_handler.add_threepid(
                    user_id, threepid["medium"], threepid["address"], current_time
                )

        if "avatar_url" in body:
            await self.profile_handler.set_avatar_url(
                user_id, requester, body["avatar_url"], True
            )

        ret = await self.admin_handler.get_user(target_user)

        return 201, ret


# Traceback (AttributeError)
2020-02-13 19:15:53,449 - synapse.http.server - 110 - ERROR - PUT-31 - Failed handle request via 'UserRestServletV2': <SynapseRequest at 0x7f6a6035bfd0 method='PUT' uri='/_synapse/admin/v2/users/@mjolnir-dev:redacted' clientproto='HTTP/1.0' site=8008>
Traceback (most recent call last):
File "/home/matrix/.synapse/local/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
StopIteration: {'displayname': 'mjolnir-dev', 'avatar_url': None}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/matrix/.synapse/local/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
StopIteration: {'displayname': 'mjolnir-dev', 'avatar_url': None}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/matrix/.synapse/local/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
StopIteration: ProfileInfo(avatar_url=None, display_name='mjolnir-dev')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/matrix/.synapse/local/lib/python3.6/site-packages/synapse/http/server.py", line 78, in wrapped_request_handler
await h(self, request)
File "/home/matrix/.synapse/local/lib/python3.6/site-packages/synapse/http/server.py", line 331, in _async_render
callback_return = await callback_return
File "/home/matrix/.synapse/local/lib/python3.6/site-packages/synapse/rest/admin/users.py", line 185, in on_PUT
await self.admin_handler.set_user_server_admin(
AttributeError: 'AdminHandler' object has no attribute 'set_user_server_admin'

# Fixed code
async def on_PUT(self, request, user_id):
    requester = await self.auth.get_user_by_req(request)
    await assert_user_is_admin(self.auth, requester.user)

    target_user = UserID.from_string(user_id)
    body = parse_json_object_from_request(request)

    if not self.hs.is_mine(target_user):
        raise SynapseError(400, "This endpoint can only be used with local users")

    user = await self.admin_handler.get_user(target_user)
    user_id = target_user.to_string()

    if user:  # modify user
        if "displayname" in body:
            await self.profile_handler.set_displayname(
                target_user, requester, body["displayname"], True
            )

        if "threepids" in body:
            # check for required parameters for each threepid
            for threepid in body["threepids"]:
                assert_params_in_dict(threepid, ["medium", "address"])

            # remove old threepids from user
            threepids = await self.store.user_get_threepids(user_id)
            for threepid in threepids:
                try:
                    await self.auth_handler.delete_threepid(
                        user_id, threepid["medium"], threepid["address"], None
                    )
                except Exception:
                    logger.exception("Failed to remove threepids")
                    raise SynapseError(500, "Failed to remove threepids")

            # add new threepids to user
            current_time = self.hs.get_clock().time_msec()
            for threepid in body["threepids"]:
                await self.auth_handler.add_threepid(
                    user_id, threepid["medium"], threepid["address"], current_time
                )

        if "avatar_url" in body:
            await self.profile_handler.set_avatar_url(
                target_user, requester, body["avatar_url"], True
            )

        if "admin" in body:
            set_admin_to = bool(body["admin"])
            if set_admin_to != user["admin"]:
                auth_user = requester.user
                if target_user == auth_user and not set_admin_to:
                    raise SynapseError(400, "You may not demote yourself.")

                await self.store.set_server_admin(target_user, set_admin_to)

        if "password" in body:
            if (
                not isinstance(body["password"], text_type)
                or len(body["password"]) > 512
            ):
                raise SynapseError(400, "Invalid password")
            else:
                new_password = body["password"]
                await self.set_password_handler.set_password(
                    target_user.to_string(), new_password, requester
                )

        if "deactivated" in body:
            deactivate = bool(body["deactivated"])
            if deactivate and not user["deactivated"]:
                result = await self.deactivate_account_handler.deactivate_account(
                    target_user.to_string(), False
                )
                if not result:
                    raise SynapseError(500, "Could not deactivate user")

        user = await self.admin_handler.get_user(target_user)
        return 200, user

    else:  # create user
        password = body.get("password")
        if password is not None and (
            not isinstance(body["password"], text_type) or len(body["password"]) > 512
        ):
            raise SynapseError(400, "Invalid password")

        admin = body.get("admin", None)
        user_type = body.get("user_type", None)
        displayname = body.get("displayname", None)
        threepids = body.get("threepids", None)

        if user_type is not None and user_type not in UserTypes.ALL_USER_TYPES:
            raise SynapseError(400, "Invalid user type")

        user_id = await self.registration_handler.register_user(
            localpart=target_user.localpart,
            password=password,
            admin=bool(admin),
            default_display_name=displayname,
            user_type=user_type,
        )

        if "threepids" in body:
            # check for required parameters for each threepid
            for threepid in body["threepids"]:
                assert_params_in_dict(threepid, ["medium", "address"])

            current_time = self.hs.get_clock().time_msec()
            for threepid in body["threepids"]:
                await self.auth_handler.add_threepid(
                    user_id, threepid["medium"], threepid["address"], current_time
                )

        if "avatar_url" in body:
            await self.profile_handler.set_avatar_url(
                user_id, requester, body["avatar_url"], True
            )

        ret = await self.admin_handler.get_user(target_user)

        return 201, ret