|
|
|
@ -160,26 +160,57 @@ class CleanS3User: |
|
|
|
|
def transfer_data(self, cursor, user: str, dest_user: str): |
|
|
|
|
""" |
|
|
|
|
Transfer user files and shares to another |
|
|
|
|
:param cursor: The database cursor |
|
|
|
|
:param user: The source user UID |
|
|
|
|
:param dest_user: The destination user UID |
|
|
|
|
""" |
|
|
|
|
self.logger.info(f"↪️ Transferring {user}'s data to {dest_user}") |
|
|
|
|
# Save all shares and calculate new path |
|
|
|
|
|
|
|
|
|
# Workaround Nextcloud incomplete S3 integration: https://github.com/nextcloud/server/pull/32781 |
|
|
|
|
self.logger.info(f"🩹 Saving {user}'s shares") |
|
|
|
|
cursor.execute("CREATE OR REPLACE TEMPORARY TABLE save_shares AS " |
|
|
|
|
"SELECT sh.id, CONCAT('files/transferred from ', CONCAT(sh.uid_owner, ' on%/', SUBSTR(fc.path, 7))) as new_path " |
|
|
|
|
# Create or replace a temporary table to store transferring shares information |
|
|
|
|
"SELECT sh.id, CONCAT('files/transferred from ', CONCAT(REPLACE(sh.uid_owner, '%', '\%'), ' on%/', REPLACE(SUBSTR(fc.path, 7), '%', '\%'))) as new_path " |
|
|
|
|
# Store share id and determine the new path of the share with % escape to avoid interfering LIKE |
|
|
|
|
"FROM oc_share sh " |
|
|
|
|
# Get all share |
|
|
|
|
"INNER JOIN oc_filecache fc ON fc.fileid = sh.file_source " |
|
|
|
|
"WHERE sh.uid_owner = ?", (user,)) |
|
|
|
|
# Join the filecache of each share to get the current path |
|
|
|
|
"WHERE sh.uid_owner = ?", |
|
|
|
|
# Filter share owner for source user |
|
|
|
|
(user,)) |
|
|
|
|
|
|
|
|
|
self.logger.info(f"↪️ Transferring {user}'s data to {dest_user}") |
|
|
|
|
self.occ(["files:transfer-ownership", user, dest_user], json=False) |
|
|
|
|
self.db.commit() |
|
|
|
|
|
|
|
|
|
# Continuation of the workaround |
|
|
|
|
self.logger.info(f"🩹 Transferring {user}'s shares to {dest_user}") |
|
|
|
|
self.db.commit() # Get database modification from the ownership transfer |
|
|
|
|
|
|
|
|
|
cursor.execute("UPDATE oc_share sh " |
|
|
|
|
# Get all shares |
|
|
|
|
"INNER JOIN save_shares save ON save.id = sh.id " |
|
|
|
|
# Join to have only saved shares in transfer |
|
|
|
|
"INNER JOIN oc_filecache fc ON fc.path LIKE save.new_path " |
|
|
|
|
# Get filecache of each share from new path |
|
|
|
|
"INNER JOIN oc_storages s ON s.numeric_id = fc.storage AND s.id = CONCAT('object::user:', ?) " |
|
|
|
|
"SET sh.uid_owner = SUBSTR(s.id, 14), sh.uid_initiator = SUBSTR(s.id, 14), sh.item_source = fc.fileid, sh.file_source = fc.fileid", |
|
|
|
|
(dest_user,)) |
|
|
|
|
# Get storage of filecache to filter only destination user files |
|
|
|
|
"SET sh.uid_owner = SUBSTR(s.id, 14), sh.uid_initiator = SUBSTR(s.id, 14), " |
|
|
|
|
"sh.item_source = fc.fileid, sh.file_source = fc.fileid " |
|
|
|
|
# Update uid_owner and uid_initiator to dest user, item_source and file_source to new file id |
|
|
|
|
"WHERE sh.share_with IS NULL OR sh.share_with != ?", |
|
|
|
|
# Avoid self sharing |
|
|
|
|
(dest_user, dest_user)) |
|
|
|
|
|
|
|
|
|
self.logger.info(f"🩹 Removing {user} shares to {dest_user}") |
|
|
|
|
cursor.execute("DELETE sh.* " |
|
|
|
|
# Rome share |
|
|
|
|
"FROM oc_share sh " |
|
|
|
|
# Get all shares |
|
|
|
|
"INNER JOIN save_shares save ON save.id = sh.id " |
|
|
|
|
# Join to have only saved shares in transfer |
|
|
|
|
"WHERE sh.share_with = ?", |
|
|
|
|
# Get only self sharing |
|
|
|
|
(dest_user, )) |
|
|
|
|
self.db.commit() |
|
|
|
|
|
|
|
|
|
def get_user_cache(self, cursor, user: str): |
|
|
|
|