mirror of
				https://github.com/matrix-org/synapse.git
				synced 2025-11-04 02:01:03 +01:00 
			
		
		
		
	Merge pull request #3201 from matrix-org/dbkr/leave_rooms_on_deactivate
Part user from rooms on account deactivate
This commit is contained in:
		
						commit
						8cbbfd16fb
					
				@ -1,5 +1,5 @@
 | 
				
			|||||||
# -*- coding: utf-8 -*-
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
# Copyright 2017 New Vector Ltd
 | 
					# Copyright 2017, 2018 New Vector Ltd
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
# you may not use this file except in compliance with the License.
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
@ -12,9 +12,11 @@
 | 
				
			|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
# See the License for the specific language governing permissions and
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
# limitations under the License.
 | 
					# limitations under the License.
 | 
				
			||||||
from twisted.internet import defer
 | 
					from twisted.internet import defer, reactor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ._base import BaseHandler
 | 
					from ._base import BaseHandler
 | 
				
			||||||
 | 
					from synapse.types import UserID, create_requester
 | 
				
			||||||
 | 
					from synapse.util.logcontext import run_in_background
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,6 +29,14 @@ class DeactivateAccountHandler(BaseHandler):
 | 
				
			|||||||
        super(DeactivateAccountHandler, self).__init__(hs)
 | 
					        super(DeactivateAccountHandler, self).__init__(hs)
 | 
				
			||||||
        self._auth_handler = hs.get_auth_handler()
 | 
					        self._auth_handler = hs.get_auth_handler()
 | 
				
			||||||
        self._device_handler = hs.get_device_handler()
 | 
					        self._device_handler = hs.get_device_handler()
 | 
				
			||||||
 | 
					        self._room_member_handler = hs.get_room_member_handler()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Flag that indicates whether the process to part users from rooms is running
 | 
				
			||||||
 | 
					        self._user_parter_running = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Start the user parter loop so it can resume parting users from rooms where
 | 
				
			||||||
 | 
					        # it left off (if it has work left to do).
 | 
				
			||||||
 | 
					        reactor.callWhenRunning(self._start_user_parting)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @defer.inlineCallbacks
 | 
					    @defer.inlineCallbacks
 | 
				
			||||||
    def deactivate_account(self, user_id):
 | 
					    def deactivate_account(self, user_id):
 | 
				
			||||||
@ -50,3 +60,70 @@ class DeactivateAccountHandler(BaseHandler):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        yield self.store.user_delete_threepids(user_id)
 | 
					        yield self.store.user_delete_threepids(user_id)
 | 
				
			||||||
        yield self.store.user_set_password_hash(user_id, None)
 | 
					        yield self.store.user_set_password_hash(user_id, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Add the user to a table of users penpding deactivation (ie.
 | 
				
			||||||
 | 
					        # removal from all the rooms they're a member of)
 | 
				
			||||||
 | 
					        yield self.store.add_user_pending_deactivation(user_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Now start the process that goes through that list and
 | 
				
			||||||
 | 
					        # parts users from rooms (if it isn't already running)
 | 
				
			||||||
 | 
					        self._start_user_parting()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _start_user_parting(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Start the process that goes through the table of users
 | 
				
			||||||
 | 
					        pending deactivation, if it isn't already running.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if not self._user_parter_running:
 | 
				
			||||||
 | 
					            run_in_background(self._user_parter_loop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @defer.inlineCallbacks
 | 
				
			||||||
 | 
					    def _user_parter_loop(self):
 | 
				
			||||||
 | 
					        """Loop that parts deactivated users from rooms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self._user_parter_running = True
 | 
				
			||||||
 | 
					        logger.info("Starting user parter")
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            while True:
 | 
				
			||||||
 | 
					                user_id = yield self.store.get_user_pending_deactivation()
 | 
				
			||||||
 | 
					                if user_id is None:
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					                logger.info("User parter parting %r", user_id)
 | 
				
			||||||
 | 
					                yield self._part_user(user_id)
 | 
				
			||||||
 | 
					                yield self.store.del_user_pending_deactivation(user_id)
 | 
				
			||||||
 | 
					                logger.info("User parter finished parting %r", user_id)
 | 
				
			||||||
 | 
					            logger.info("User parter finished: stopping")
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            self._user_parter_running = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @defer.inlineCallbacks
 | 
				
			||||||
 | 
					    def _part_user(self, user_id):
 | 
				
			||||||
 | 
					        """Causes the given user_id to leave all the rooms they're joined to
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        user = UserID.from_string(user_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rooms_for_user = yield self.store.get_rooms_for_user(user_id)
 | 
				
			||||||
 | 
					        for room_id in rooms_for_user:
 | 
				
			||||||
 | 
					            logger.info("User parter parting %r from %r", user_id, room_id)
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                yield self._room_member_handler.update_membership(
 | 
				
			||||||
 | 
					                    create_requester(user),
 | 
				
			||||||
 | 
					                    user,
 | 
				
			||||||
 | 
					                    room_id,
 | 
				
			||||||
 | 
					                    "leave",
 | 
				
			||||||
 | 
					                    ratelimit=False,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            except Exception:
 | 
				
			||||||
 | 
					                logger.exception(
 | 
				
			||||||
 | 
					                    "Failed to part user %r from room %r: ignoring and continuing",
 | 
				
			||||||
 | 
					                    user_id, room_id,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
				
			|||||||
@ -526,3 +526,42 @@ class RegistrationStore(RegistrationWorkerStore,
 | 
				
			|||||||
        except self.database_engine.module.IntegrityError:
 | 
					        except self.database_engine.module.IntegrityError:
 | 
				
			||||||
            ret = yield self.get_3pid_guest_access_token(medium, address)
 | 
					            ret = yield self.get_3pid_guest_access_token(medium, address)
 | 
				
			||||||
            defer.returnValue(ret)
 | 
					            defer.returnValue(ret)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_user_pending_deactivation(self, user_id):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Adds a user to the table of users who need to be parted from all the rooms they're
 | 
				
			||||||
 | 
					        in
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._simple_insert(
 | 
				
			||||||
 | 
					            "users_pending_deactivation",
 | 
				
			||||||
 | 
					            values={
 | 
				
			||||||
 | 
					                "user_id": user_id,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            desc="add_user_pending_deactivation",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def del_user_pending_deactivation(self, user_id):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Removes the given user to the table of users who need to be parted from all the
 | 
				
			||||||
 | 
					        rooms they're in, effectively marking that user as fully deactivated.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._simple_delete_one(
 | 
				
			||||||
 | 
					            "users_pending_deactivation",
 | 
				
			||||||
 | 
					            keyvalues={
 | 
				
			||||||
 | 
					                "user_id": user_id,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            desc="del_user_pending_deactivation",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_user_pending_deactivation(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Gets one user from the table of users waiting to be parted from all the rooms
 | 
				
			||||||
 | 
					        they're in.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._simple_select_one_onecol(
 | 
				
			||||||
 | 
					            "users_pending_deactivation",
 | 
				
			||||||
 | 
					            keyvalues={},
 | 
				
			||||||
 | 
					            retcol="user_id",
 | 
				
			||||||
 | 
					            allow_none=True,
 | 
				
			||||||
 | 
					            desc="get_users_pending_deactivation",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										25
									
								
								synapse/storage/schema/delta/48/deactivated_users.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								synapse/storage/schema/delta/48/deactivated_users.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					/* Copyright 2018 New Vector 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Store any accounts that have been requested to be deactivated.
 | 
				
			||||||
 | 
					 * We part the account from all the rooms its in when its
 | 
				
			||||||
 | 
					 * deactivated. This can take some time and synapse may be restarted
 | 
				
			||||||
 | 
					 * before it completes, so store the user IDs here until the process
 | 
				
			||||||
 | 
					 * is complete.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					CREATE TABLE users_pending_deactivation (
 | 
				
			||||||
 | 
					    user_id TEXT NOT NULL
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user