Split migration types into different job class

master
Florian Charlaix 9 months ago
parent 50df5e1de0
commit 6e49aa5699
  1. 16
      lib/AppInfo/Application.php
  2. 115
      lib/Migration/DataJob.php
  3. 100
      lib/Migration/GroupJob.php
  4. 88
      lib/Migration/QuotaJob.php
  5. 146
      lib/Migration/ShareJob.php
  6. 92
      lib/Migration/Utils.php

@ -23,6 +23,8 @@
namespace OCA\FirstRunMigrate\AppInfo;
use OCA\FirstRunMigrate\Migration\DataJob;
use OCA\FirstRunMigrate\Migration\GroupJob;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IBootContext;
@ -32,11 +34,11 @@ use OCP\User\Events\UserFirstTimeLoggedInEvent;
use Psr\Log\LoggerInterface;
use OCP\BackgroundJob\IJobList;
use OCA\FirstRunMigrate\Migration\Notifier;
use OCA\FirstRunMigrate\Migration\QuotaJob;
use OCA\FirstRunMigrate\Migration\Utils;
class Application extends App implements IBootstrap {
public const APP_ID = 'firstrunmigrate';
public const MIGRATION_JOB = 'OCA\FirstRunMigrate\Migration\BackgroundJob';
public function __construct() {
parent::__construct('firstrunmigrate');
@ -67,25 +69,25 @@ class Application extends App implements IBootstrap {
}
$logger->debug("Checking $uid migrations");
if (Utils::isMigrationData()){
if (DataJob::isMigration()){
$logger->debug("Scheduling $uid data migrations");
$jobList->add(self::MIGRATION_JOB, ['uid' => $uid, 'type' => 'data']);
$jobList->add(DataJob::class, ['uid' => $uid]);
Utils::setMigrationStatus('data', 'scheduled', $user);
} else {
$logger->info("$uid don't have data migrations");
}
if (Utils::isMigrationGroups()) {
if (GroupJob::isMigration()) {
$logger->debug("Scheduling $uid groups migrations");
$jobList->add(self::MIGRATION_JOB, ['uid' => $uid, 'type' => 'group']);
$jobList->add(GroupJob::class, ['uid' => $uid]);
Utils::setMigrationStatus('group', 'scheduled', $user);
} else {
$logger->info("$uid don't have groups migrations");
}
if (Utils::isMigrationQuotas()) {
if (QuotaJob::isMigration()) {
$logger->debug("Scheduling $uid quota migrations");
$jobList->add(self::MIGRATION_JOB, ['uid' => $uid, 'type' => 'quota']);
$jobList->add(QuotaJob::class, ['uid' => $uid]);
Utils::setMigrationStatus('quota', 'scheduled', $user);
} else {
$logger->info("$uid don't have quota migrations");

@ -0,0 +1,115 @@
<?php
/**
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FirstRunMigrate\Migration;
use OCP\BackgroundJob\QueuedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OC_Util;
use OCA\FirstRunMigrate\Migration\Utils;
use OCP\IConfig;
use OCP\IUserManager;
use OCP\IUser;
use OCP\BackgroundJob\IJobList;
use OCP\Files\IRootFolder;
use Psr\Log\LoggerInterface;
class DataJob extends QueuedJob {
protected LoggerInterface $logger;
protected IUserManager $userManager;
protected IJobList $jobList;
protected IRootFolder $rootFolder;
/**
* BackgroundJob constructor.
*
* @param INotificationManager $notificationManager
*/
public function __construct(ITimeFactory $timeFactory, IUserManager $userManager, LoggerInterface $logger,
IJobList $jobList, IRootFolder $rootFolder) {
parent::__construct($timeFactory);
$this->logger = $logger;
$this->userManager = $userManager;
$this->jobList = $jobList;
$this->rootFolder = $rootFolder;
}
/**
* @param array $argument
*/
protected function run($argument) {
$this->logger->debug("Starting datas migration job {$this->getId()} with args " . json_encode($argument));
$uid = $argument['uid'];
$user = $this->userManager->get($uid);
Utils::setMigrationStatus('data', 'started', $user);
if ($migrate_dir = $this->getUserMigration($user)) {
// Trigger creation of user home and /files folder
$userFolder = $this->rootFolder->getUserFolder($uid);
$quota = $user->getQuota();
$user->setQuota('none');
OC_Util::copyr($migrate_dir, $userFolder);
$user->setQuota($quota);
// update the file cache
$userFolder->getStorage()->getScanner()->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE);
} else {
$this->logger->info("{$this->getId()}: No dir to migrate");
}
// Schedule share migration only after migration user's datas
if (ShareJob::isMigration()) {
$this->logger->debug("Scheduling $uid share migrations");
$this->jobList->add(ShareJob::class, ['uid' => $uid]);
Utils::setMigrationStatus('share', 'scheduled', $user);
} else {
$this->logger->info("$uid don't have share migrations");
}
Utils::setMigrationStatus('data', 'finished', $user);
}
private static function getMigrationDir() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_dir', null);
}
public static function isMigration() : bool {
return ($file = self::getMigrationDir()) && file_exists($file);
}
private static function getUserMigration(IUser $user) : ?string {
$dir = self::getMigrationDir() . '/' . Utils::getUserId($user);
if (file_exists($dir)) {
return $dir;
} else {
return null;
}
}
}

@ -0,0 +1,100 @@
<?php
/**
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FirstRunMigrate\Migration;
use OCP\BackgroundJob\QueuedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCA\FirstRunMigrate\Migration\Utils;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\IUser;
use Psr\Log\LoggerInterface;
class GroupJob extends QueuedJob {
protected LoggerInterface $logger;
protected IUserManager $userManager;
protected IGroupManager $groupManager;
/**
* BackgroundJob constructor.
*
* @param INotificationManager $notificationManager
*/
public function __construct(ITimeFactory $timeFactory, IUserManager $userManager,
IGroupManager $groupManager, LoggerInterface $logger) {
parent::__construct($timeFactory);
$this->logger = $logger;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
}
/**
* @param array $argument
*/
protected function run($argument) {
$this->logger->debug("Starting groups migration job {$this->getId()} with args " . json_encode($argument));
$user = $this->userManager->get($argument['uid']);
Utils::setMigrationStatus('group', 'started', $user);
if ($groups = $this->getUserMigration($user)) {
foreach ($groups as $group) {
if ($this->groupManager->groupExists($group)) {
$group = $this->groupManager->get($group);
} else {
$group = $this->groupManager->createGroup($group);
}
$group->addUser($user);
}
} else {
$this->logger->info("{$this->getId()}: No groups to migrate");
}
Utils::setMigrationStatus('group', 'finished', $user);
}
private static function getMigrationFile() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_groups', null);
}
public static function isMigration() : bool {
return ($file = self::getMigrationFile()) && file_exists($file);
}
private static function getUserMigration(IUser $user) : ?array {
$groups = json_decode(file_get_contents(self::getMigrationFile()), true);
$id = Utils::getUserId($user);
if (array_key_exists($id, $groups)) {
return $groups[$id];
} else {
return null;
}
}
}

@ -0,0 +1,88 @@
<?php
/**
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FirstRunMigrate\Migration;
use OCP\BackgroundJob\QueuedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCA\FirstRunMigrate\Migration\Utils;
use OCP\IConfig;
use OCP\IUserManager;
use OCP\IUser;
use Psr\Log\LoggerInterface;
class QuotaJob extends QueuedJob {
protected LoggerInterface $logger;
protected IUserManager $userManager;
/**
* BackgroundJob constructor.
*
* @param INotificationManager $notificationManager
*/
public function __construct(ITimeFactory $timeFactory, IUserManager $userManager, LoggerInterface $logger) {
parent::__construct($timeFactory);
$this->logger = $logger;
$this->userManager = $userManager;
}
/**
* @param array $argument
*/
protected function run($argument) {
$this->logger->debug("Starting quota migration job {$this->getId()} with args " . json_encode($argument));
$user = $this->userManager->get($argument['uid']);
$this->logger->debug("{$this->getId()}: Migrating quota");
Utils::setMigrationStatus('quota', 'started', $user);
if ($quota = $this->getUserMigration($user)) {
$user->setQuota($quota);
} else {
$this->logger->info("{$this->getId()}: No quota to migrate");
}
Utils::setMigrationStatus('quota', 'finished', $user);
}
private static function getMigrationFile() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_quotas', null);
}
public static function isMigration() : bool {
return ($file = self::getMigrationFile()) && file_exists($file);
}
private function getUserMigration(IUser $user) : ?string {
$quotas = json_decode(file_get_contents(self::getMigrationFile()), true);
$id = Utils::getUserId($user);
if (array_key_exists($id, $quotas)) {
return $quotas[$id];
} else {
return null;
}
}
}

@ -26,32 +26,22 @@ use Exception;
use OC\Share20\DefaultShareProvider;
use OC\Share20\ShareAttributes;
use OC\Share20\Share;
use OCP\IUser;
use OCP\IConfig;
use OCP\Share\IShare;
use OCP\BackgroundJob\QueuedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OC_Util;
use OCA\FirstRunMigrate\Migration\Utils;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
use OCP\BackgroundJob\IJobList;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Share\IShareProvider;
use Psr\Log\LoggerInterface;
class BackgroundJob extends QueuedJob {
protected IConfig $config;
class ShareJob extends QueuedJob {
protected LoggerInterface $logger;
protected IUserManager $userManager;
protected IGroupManager $groupManager;
protected IJobList $jobList;
protected DefaultShareProvider $shareProvider;
protected IRootFolder $rootFolder;
@ -61,15 +51,11 @@ class BackgroundJob extends QueuedJob {
*
* @param INotificationManager $notificationManager
*/
public function __construct(ITimeFactory $timeFactory, IConfig $config,
IUserManager $userManager, IGroupManager $groupManager, LoggerInterface $logger,
IJobList $jobList, IRootFolder $rootFolder) {
public function __construct(ITimeFactory $timeFactory, IUserManager $userManager,
LoggerInterface $logger, IRootFolder $rootFolder) {
parent::__construct($timeFactory);
$this->config = $config;
$this->logger = $logger;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->jobList = $jobList;
$this->shareProvider = \OC::$server->get(DefaultShareProvider::class);
$this->rootFolder = $rootFolder;
}
@ -78,101 +64,12 @@ class BackgroundJob extends QueuedJob {
* @param array $argument
*/
protected function run($argument) {
$this->logger->debug("Starting job {$this->getId()} with args " . json_encode($argument));
$uid = $argument['uid'];
$user = $this->userManager->get($uid);
$type = $argument['type'];
switch ($type) {
case 'data':
$this->data($user);
break;
case 'group':
$this->group($user);
break;
case 'quota':
$this->quota($user);
break;
case 'share';
$this->share($user);
break;
default:
throw new \Exception("Invalid migration type");
}
}
private function data(IUser $user) {
$this->logger->debug("{$this->getId()}: Migrating datas");
$uid = $user->getUID();
Utils::setMigrationStatus('data', 'started', $user);
if ($migrate_dir = Utils::getUserMigrationDir($user)) {
// Trigger creation of user home and /files folder
$userFolder = $this->rootFolder->getUserFolder($uid);
$quota = $user->getQuota();
$user->setQuota('none');
OC_Util::copyr($migrate_dir, $userFolder);
$user->setQuota($quota);
// update the file cache
$userFolder->getStorage()->getScanner()->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE);
} else {
$this->logger->info("{$this->getId()}: No dir to migrate");
}
// Schedule share migration only after migration user's datas
if (Utils::isMigrationShares()) {
$this->logger->debug("Scheduling $uid share migrations");
$this->jobList->add(self::class, ['uid' => $uid, 'type' => 'share']);
Utils::setMigrationStatus('share', 'scheduled', $user);
} else {
$this->logger->info("$uid don't have share migrations");
}
Utils::setMigrationStatus('data', 'finished', $user);
}
private function group(IUser $user) {
$this->logger->debug("{$this->getId()}: Migrating groups");
Utils::setMigrationStatus('group', 'started', $user);
$this->logger->debug("Starting shares migration job {$this->getId()} with args " . json_encode($argument));
$user = $this->userManager->get($argument['uid']);
if ($groups = Utils::getUserMigrationGroups($user)) {
foreach ($groups as $group) {
if ($this->groupManager->groupExists($group)) {
$group = $this->groupManager->get($group);
} else {
$group = $this->groupManager->createGroup($group);
}
$group->addUser($user);
}
} else {
$this->logger->info("{$this->getId()}: No groups to migrate");
}
Utils::setMigrationStatus('group', 'finished', $user);
}
private function quota(IUser $user) {
$this->logger->debug("{$this->getId()}: Migrating quota");
Utils::setMigrationStatus('quota', 'started', $user);
if ($quota = Utils::getUserMigrationQuota($user)) {
$user->setQuota($quota);
} else {
$this->logger->info("{$this->getId()}: No quota to migrate");
}
Utils::setMigrationStatus('quota', 'finished', $user);
}
private function share(IUser $user) {
$this->logger->debug("{$this->getId()}: Migrating shares");
Utils::setMigrationStatus('share', 'started', $user);
$shares = Utils::getUserShares($user);
$shares = $this->getUserShares($user);
if (!empty($shares)) {
$this->logger->debug("{$this->getId()}: Migrating shares");
@ -263,4 +160,31 @@ class BackgroundJob extends QueuedJob {
$this->logger->debug("{$this->getId()}: $migrated shares migrated, $missingUser waiting");
Utils::setMigrationStatus('share', 'finished', $user, [$migrated, $missingUser, $errors]);
}
private static function getMigrationFile() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_shares', null);
}
public static function isMigration(): bool {
return ($file = self::getMigrationFile()) && file_exists($file);
}
private function getUserShares(IUser $user) : array {
$id = Utils::getUserId($user);
$shares = json_decode(file_get_contents(self::getMigrationFile()), true);
return array_filter($shares, function (array $v) use ($id) {
if ($v["type"] === "user" && $v["with"] == $id) {
return true;
} elseif ($v["owner"] === $id) {
return true;
} elseif ($v["type"] === $id) {
return true;
} else {
return false;
}
});
}
}

@ -36,98 +36,6 @@ class Utils {
return $config->getUserValue($user->getUID(), 'settings', 'email', null);
}
private static function getMigrationDataDir() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_dir', null);
}
public static function isMigrationData() : bool {
return ($file = self::getMigrationDataDir()) && file_exists($file);
}
public static function getUserMigrationDir(IUser $user) : ?string {
$dir = self::getMigrationDataDir() . '/' . self::getUserId($user);
if (file_exists($dir)) {
return $dir;
} else {
return null;
}
}
private static function getMigrationGroupsFile() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_groups', null);
}
public static function isMigrationGroups() : bool {
return ($file = self::getMigrationGroupsFile()) && file_exists($file);
}
public static function getUserMigrationGroups(IUser $user) : ?array {
$groups = json_decode(file_get_contents(self::getMigrationGroupsFile()), true);
$id = self::getUserId($user);
if (array_key_exists($id, $groups)) {
return $groups[$id];
} else {
return null;
}
}
private static function getMigrationQuotasFile() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_quotas', null);
}
public static function isMigrationQuotas() : bool {
return ($file = self::getMigrationQuotasFile()) && file_exists($file);
}
public static function getUserMigrationQuota(IUser $user) : ?string {
$quotas = json_decode(file_get_contents(self::getMigrationQuotasFile()), true);
$id = self::getUserId($user);
if (array_key_exists($id, $quotas)) {
return $quotas[$id];
} else {
return null;
}
}
private static function getMigrationSharesFile() : ?string {
/** @var IConfig */
$config = \OC::$server->get(IConfig::class);
return $config->getSystemValue('firstrunmigrate_shares', null);
}
public static function isMigrationShares(): bool {
return ($file = self::getMigrationSharesFile()) && file_exists($file);
}
public static function getUserShares(IUser $user) : array {
$id = self::getUserId($user);
$shares = json_decode(file_get_contents(self::getMigrationSharesFile()), true);
return array_filter($shares, function (array $v) use ($id) {
if ($v["type"] === "user" && $v["with"] == $id) {
return true;
} elseif ($v["owner"] === $id) {
return true;
} elseif ($v["type"] === $id) {
return true;
} else {
return false;
}
});
}
public static function isUserMigrated(IUser $user, string $migration) : bool {
// If user never logged into Nextcloud
if ($user->getLastLogin() == 0) {

Loading…
Cancel
Save