@@ -311,6 +311,8 @@ async def user_leave_room(
311
311
) as client :
312
312
res = await client .room_leave (room_id )
313
313
if isinstance (res , RoomLeaveError ):
314
+ if "not in room" in res .message :
315
+ return None
314
316
raise Exception (res .message )
315
317
316
318
@@ -1313,7 +1315,6 @@ def create_durable_operations(
1313
1315
"""
1314
1316
from fractal_database .models import DurableOperation
1315
1317
1316
- # remove the user from the main space
1317
1318
DurableOperation .objects .create (
1318
1319
instance = instance ,
1319
1320
module = cls .operation_module (),
@@ -1361,6 +1362,36 @@ async def run(self, operation: "DurableOperation") -> None:
1361
1362
return None
1362
1363
1363
1364
1365
+ class RemoveUserFromDatabase (RemoveUserFromRoom ):
1366
+ @classmethod
1367
+ def create_durable_operations (
1368
+ cls ,
1369
+ instance : "DatabaseMembership" ,
1370
+ channel : "ReplicationChannel" ,
1371
+ ):
1372
+ """
1373
+ Create the optional operations (tasks) for removing a user from a Matrix Database
1374
+ """
1375
+ from fractal_database .models import DurableOperation
1376
+
1377
+ # create operations to remove the user from all of the rooms on the channel
1378
+ for room_id_label in channel .metadata .keys ():
1379
+ DurableOperation .objects .create (
1380
+ instance = instance ,
1381
+ module = RemoveUserFromRoom .operation_module (),
1382
+ channel = channel ,
1383
+ metadata = {"room_id_label" : room_id_label },
1384
+ )
1385
+
1386
+ return None
1387
+
1388
+ async def run (self , operation : "DurableOperation" ) -> None :
1389
+ # this operation needs to simply create the operations to remove the user from the rooms
1390
+ # those will individually handle the actual removal
1391
+ # this does not need to do anything else
1392
+ return None
1393
+
1394
+
1364
1395
class RemoveDeviceFromRoom (RemoveUserFromRoom ):
1365
1396
async def run (self , operation : "DurableOperation" ) -> None :
1366
1397
try :
@@ -1369,8 +1400,10 @@ async def run(self, operation: "DurableOperation") -> None:
1369
1400
raise Exception ("room_id_label must be specified in operation metadata" )
1370
1401
1371
1402
model_class = operation .content_type .model_class () # type: ignore
1372
- membership : "DeviceMembership" = await model_class .objects .select_related ("device" ).aget (
1373
- pk = operation .object_id
1403
+ membership : "DeviceMembership" = (
1404
+ await model_class .objects .select_related ("device" )
1405
+ .prefetch_related ("device__matrixcredentials_set" )
1406
+ .aget (pk = operation .object_id )
1374
1407
) # type: ignore
1375
1408
1376
1409
# fetch channel in order to get room_id for the group to invite user to
@@ -1380,9 +1413,9 @@ async def run(self, operation: "DurableOperation") -> None:
1380
1413
.aget (pk = operation .channel_id )
1381
1414
) # type: ignore
1382
1415
1383
- device_creds = membership .device .matrixcredentials_set .filter (
1416
+ device_creds = await membership .device .matrixcredentials_set .filter (
1384
1417
homeserver = channel .homeserver
1385
- ).first ()
1418
+ ).afirst ()
1386
1419
if not device_creds :
1387
1420
# FIXME: Determine if logged in user is an admin in the room. If so, they can "kick" the device (only works if device is not admin)
1388
1421
raise Exception (
@@ -1406,6 +1439,36 @@ async def run(self, operation: "DurableOperation") -> None:
1406
1439
return None
1407
1440
1408
1441
1442
+ class RemoveDeviceFromDatabase (RemoveDeviceFromRoom ):
1443
+ @classmethod
1444
+ def create_durable_operations (
1445
+ cls ,
1446
+ instance : "DatabaseMembership" ,
1447
+ channel : "ReplicationChannel" ,
1448
+ ):
1449
+ """
1450
+ Create the optional operations (tasks) for removing a device from a Matrix Database
1451
+ """
1452
+ from fractal_database .models import DurableOperation
1453
+
1454
+ # create the operations to remove the device from all of the rooms on the channel
1455
+ for room_id_label in channel .metadata .keys ():
1456
+ DurableOperation .objects .create (
1457
+ instance = instance ,
1458
+ module = RemoveDeviceFromRoom .operation_module (),
1459
+ channel = channel ,
1460
+ metadata = {"room_id_label" : room_id_label },
1461
+ )
1462
+
1463
+ return None
1464
+
1465
+ async def run (self , operation : "DurableOperation" ) -> None :
1466
+ # this operation needs to simply create the operations to remove the device from the rooms
1467
+ # those operations will individually handle the actual removal
1468
+ # this does not need to do anything else
1469
+ return None
1470
+
1471
+
1409
1472
class InviteDatabaseMemberToSpace (MatrixOperation ):
1410
1473
@classmethod
1411
1474
def create_durable_operations (
0 commit comments