@ -1533,71 +1533,6 @@ class DeviceBackgroundUpdateStore(SQLBaseStore):
return rows
return rows
async def check_too_many_devices_for_user ( self , user_id : str ) - > Collection [ str ] :
""" Check if the user has a lot of devices, and if so return the set of
devices we can prune .
This does * not * return hidden devices or devices with E2E keys .
"""
num_devices = await self . db_pool . simple_select_one_onecol (
table = " devices " ,
keyvalues = { " user_id " : user_id , " hidden " : False } ,
retcol = " COALESCE(COUNT(*), 0) " ,
desc = " count_devices " ,
)
# We let users have up to ten devices without pruning.
if num_devices < = 10 :
return ( )
# We prune everything older than N days.
max_last_seen = self . _clock . time_msec ( ) - 14 * 24 * 60 * 60 * 1000
if num_devices > 50 :
# If the user has more than 50 devices, then we chose a last seen
# that ensures we keep at most 50 devices.
sql = """
SELECT last_seen FROM devices
LEFT JOIN e2e_device_keys_json USING ( user_id , device_id )
WHERE
user_id = ?
AND NOT hidden
AND last_seen IS NOT NULL
AND key_json IS NULL
ORDER BY last_seen DESC
LIMIT 1
OFFSET 50
"""
rows = await self . db_pool . execute (
" check_too_many_devices_for_user_last_seen " , None , sql , ( user_id , )
)
if rows :
max_last_seen = max ( rows [ 0 ] [ 0 ] , max_last_seen )
# Now fetch the devices to delete.
sql = """
SELECT DISTINCT device_id FROM devices
LEFT JOIN e2e_device_keys_json USING ( user_id , device_id )
WHERE
user_id = ?
AND NOT hidden
AND last_seen < ?
AND key_json IS NULL
"""
def check_too_many_devices_for_user_txn (
txn : LoggingTransaction ,
) - > Collection [ str ] :
txn . execute ( sql , ( user_id , max_last_seen ) )
return { device_id for device_id , in txn }
return await self . db_pool . runInteraction (
" check_too_many_devices_for_user " ,
check_too_many_devices_for_user_txn ,
)
class DeviceStore ( DeviceWorkerStore , DeviceBackgroundUpdateStore ) :
class DeviceStore ( DeviceWorkerStore , DeviceBackgroundUpdateStore ) :
# Because we have write access, this will be a StreamIdGenerator
# Because we have write access, this will be a StreamIdGenerator
@ -1656,7 +1591,6 @@ class DeviceStore(DeviceWorkerStore, DeviceBackgroundUpdateStore):
values = { } ,
values = { } ,
insertion_values = {
insertion_values = {
" display_name " : initial_device_display_name ,
" display_name " : initial_device_display_name ,
" last_seen " : self . _clock . time_msec ( ) ,
" hidden " : False ,
" hidden " : False ,
} ,
} ,
desc = " store_device " ,
desc = " store_device " ,
@ -1702,7 +1636,7 @@ class DeviceStore(DeviceWorkerStore, DeviceBackgroundUpdateStore):
)
)
raise StoreError ( 500 , " Problem storing device. " )
raise StoreError ( 500 , " Problem storing device. " )
async def delete_devices ( self , user_id : str , device_ids : Collection [ str ] ) - > None :
async def delete_devices ( self , user_id : str , device_ids : List [ str ] ) - > None :
""" Deletes several devices.
""" Deletes several devices.
Args :
Args :