diff options
Diffstat (limited to 'lib/private/Repair/Owncloud/SaveAccountsTableData.php')
-rw-r--r-- | lib/private/Repair/Owncloud/SaveAccountsTableData.php | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/lib/private/Repair/Owncloud/SaveAccountsTableData.php b/lib/private/Repair/Owncloud/SaveAccountsTableData.php new file mode 100644 index 00000000000..ab1560ddb8d --- /dev/null +++ b/lib/private/Repair/Owncloud/SaveAccountsTableData.php @@ -0,0 +1,181 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Repair\Owncloud; + +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; +use OCP\PreConditionNotMetException; + +/** + * Copies the email address from the accounts table to the preference table, + * before the data structure is changed and the information is gone + */ +class SaveAccountsTableData implements IRepairStep { + public const BATCH_SIZE = 75; + + /** @var IDBConnection */ + protected $db; + + /** @var IConfig */ + protected $config; + + protected $hasForeignKeyOnPersistentLocks = false; + + /** + * @param IDBConnection $db + * @param IConfig $config + */ + public function __construct(IDBConnection $db, IConfig $config) { + $this->db = $db; + $this->config = $config; + } + + /** + * @return string + */ + public function getName() { + return 'Copy data from accounts table when migrating from ownCloud'; + } + + /** + * @param IOutput $output + */ + public function run(IOutput $output) { + if (!$this->shouldRun()) { + return; + } + + $offset = 0; + $numUsers = $this->runStep($offset); + + while ($numUsers === self::BATCH_SIZE) { + $offset += $numUsers; + $numUsers = $this->runStep($offset); + } + + // oc_persistent_locks will be removed later on anyways so we can just drop and ignore any foreign key constraints here + $tableName = $this->config->getSystemValueString('dbtableprefix', 'oc_') . 'persistent_locks'; + $schema = $this->db->createSchema(); + $table = $schema->getTable($tableName); + foreach ($table->getForeignKeys() as $foreignKey) { + $table->removeForeignKey($foreignKey->getName()); + } + $this->db->migrateToSchema($schema); + + // Remove the table + if ($this->hasForeignKeyOnPersistentLocks) { + $this->db->dropTable('persistent_locks'); + } + $this->db->dropTable('accounts'); + } + + /** + * @return bool + */ + protected function shouldRun() { + $schema = $this->db->createSchema(); + $prefix = $this->config->getSystemValueString('dbtableprefix', 'oc_'); + + $tableName = $prefix . 'accounts'; + if (!$schema->hasTable($tableName)) { + return false; + } + + $table = $schema->getTable($tableName); + if (!$table->hasColumn('user_id')) { + return false; + } + + if ($schema->hasTable($prefix . 'persistent_locks')) { + $locksTable = $schema->getTable($prefix . 'persistent_locks'); + $foreignKeys = $locksTable->getForeignKeys(); + foreach ($foreignKeys as $foreignKey) { + if ($tableName === $foreignKey->getForeignTableName()) { + $this->hasForeignKeyOnPersistentLocks = true; + } + } + } + + return true; + } + + /** + * @param int $offset + * @return int Number of copied users + */ + protected function runStep($offset) { + $query = $this->db->getQueryBuilder(); + $query->select('*') + ->from('accounts') + ->orderBy('id') + ->setMaxResults(self::BATCH_SIZE); + + if ($offset > 0) { + $query->setFirstResult($offset); + } + + $result = $query->execute(); + + $update = $this->db->getQueryBuilder(); + $update->update('users') + ->set('displayname', $update->createParameter('displayname')) + ->where($update->expr()->eq('uid', $update->createParameter('userid'))); + + $updatedUsers = 0; + while ($row = $result->fetch()) { + try { + $this->migrateUserInfo($update, $row); + } catch (PreConditionNotMetException $e) { + // Ignore and continue + } catch (\UnexpectedValueException $e) { + // Ignore and continue + } + $updatedUsers++; + } + $result->closeCursor(); + + return $updatedUsers; + } + + /** + * @param IQueryBuilder $update + * @param array $userdata + * @throws PreConditionNotMetException + * @throws \UnexpectedValueException + */ + protected function migrateUserInfo(IQueryBuilder $update, $userdata) { + $state = (int)$userdata['state']; + if ($state === 3) { + // Deleted user, ignore + return; + } + + if ($userdata['email'] !== null) { + $this->config->setUserValue($userdata['user_id'], 'settings', 'email', $userdata['email']); + } + if ($userdata['quota'] !== null) { + $this->config->setUserValue($userdata['user_id'], 'files', 'quota', $userdata['quota']); + } + if ($userdata['last_login'] !== null) { + $this->config->setUserValue($userdata['user_id'], 'login', 'lastLogin', $userdata['last_login']); + } + if ($state === 1) { + $this->config->setUserValue($userdata['user_id'], 'core', 'enabled', 'true'); + } elseif ($state === 2) { + $this->config->setUserValue($userdata['user_id'], 'core', 'enabled', 'false'); + } + + if ($userdata['display_name'] !== null) { + $update->setParameter('displayname', $userdata['display_name']) + ->setParameter('userid', $userdata['user_id']); + $update->execute(); + } + } +} |