Now that we can enforce 2FA we also should notify users that have enabled 2FA but do not yet have backup codes generated. This adds a repair step that inserts a background job to do this. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>pull/11549/head
parent
98bac99522
commit
36bf522c8b
@ -0,0 +1,66 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @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\TwoFactorBackupCodes\BackgroundJob; |
||||
|
||||
use OC\Authentication\TwoFactorAuth\Manager; |
||||
use OC\BackgroundJob\QueuedJob; |
||||
use OCP\Authentication\TwoFactorAuth\IRegistry; |
||||
use OCP\BackgroundJob\IJobList; |
||||
use OCP\IUser; |
||||
use OCP\IUserManager; |
||||
|
||||
class CheckBackupCodes extends QueuedJob { |
||||
|
||||
/** @var IUserManager */ |
||||
private $userManager; |
||||
|
||||
/** @var IJobList */ |
||||
private $jobList; |
||||
|
||||
/** @var Manager */ |
||||
private $registry; |
||||
|
||||
/** @var Manager */ |
||||
private $twofactorManager; |
||||
|
||||
public function __construct(IUserManager $userManager, IJobList $jobList, Manager $twofactorManager, IRegistry $registry) { |
||||
$this->userManager = $userManager; |
||||
$this->jobList = $jobList; |
||||
$this->twofactorManager = $twofactorManager; |
||||
$this->registry = $registry; |
||||
} |
||||
|
||||
protected function run($argument) { |
||||
$this->userManager->callForSeenUsers(function(IUser $user) { |
||||
$providers = $this->registry->getProviderStates($user); |
||||
$isTwoFactorAuthenticated = $this->twofactorManager->isTwoFactorAuthenticated($user); |
||||
|
||||
if ($isTwoFactorAuthenticated && isset($providers['backup_codes']) && $providers['backup_codes'] === false) { |
||||
$this->jobList->add(RememberBackupCodesJob::class, ['uid' => $user->getUID()]); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @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\TwoFactorBackupCodes\Migration; |
||||
|
||||
use OCP\BackgroundJob\IJobList; |
||||
use OCP\Migration\IOutput; |
||||
use OCP\Migration\IRepairStep; |
||||
|
||||
class CheckBackupCodes implements IRepairStep { |
||||
|
||||
/** @var IJobList */ |
||||
private $jobList; |
||||
|
||||
public function __construct(IJobList $jobList) { |
||||
$this->jobList = $jobList; |
||||
} |
||||
|
||||
public function getName(): string { |
||||
return 'Add background job to check for backup codes'; |
||||
} |
||||
|
||||
public function run(IOutput $output) { |
||||
$this->jobList->add(\OCA\TwoFactorBackupCodes\BackgroundJob\CheckBackupCodes::class); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,133 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @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\TwoFactorBackupCodes\Tests\Unit\BackgroundJob; |
||||
|
||||
use OC\Authentication\TwoFactorAuth\Manager; |
||||
use OCA\TwoFactorBackupCodes\BackgroundJob\CheckBackupCodes; |
||||
use OCA\TwoFactorBackupCodes\BackgroundJob\RememberBackupCodesJob; |
||||
use OCP\Authentication\TwoFactorAuth\IRegistry; |
||||
use OCP\BackgroundJob\IJobList; |
||||
use OCP\IUser; |
||||
use OCP\IUserManager; |
||||
use PHPUnit\Framework\MockObject\MockObject; |
||||
use Test\TestCase; |
||||
|
||||
class CheckBackupCodeTest extends TestCase { |
||||
|
||||
/** @var IUserManager|MockObject */ |
||||
private $userManager; |
||||
|
||||
/** @var IJobList|MockObject */ |
||||
private $jobList; |
||||
|
||||
/** @var IRegistry|MockObject */ |
||||
private $registry; |
||||
|
||||
/** @var Manager|MockObject */ |
||||
private $manager; |
||||
|
||||
/** @var IUser|MockObject */ |
||||
private $user; |
||||
|
||||
/** @var CheckBackupCodes */ |
||||
private $checkBackupCodes; |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
|
||||
$this->userManager = $this->createMock(IUserManager::class); |
||||
$this->jobList = $this->createMock(IJobList::class); |
||||
$this->registry = $this->createMock(IRegistry::class); |
||||
$this->manager = $this->createMock(Manager::class); |
||||
|
||||
$this->user = $this->createMock(IUser::class); |
||||
|
||||
$this->userManager->method('callForSeenUsers') |
||||
->will($this->returnCallback(function(\Closure $e) { |
||||
$e($this->user); |
||||
})); |
||||
|
||||
$this->checkBackupCodes = new CheckBackupCodes( |
||||
$this->userManager, |
||||
$this->jobList, |
||||
$this->manager, |
||||
$this->registry |
||||
); |
||||
} |
||||
|
||||
public function testRunAlreadyGenerated() { |
||||
$this->registry->method('getProviderStates') |
||||
->with($this->user) |
||||
->willReturn(['backup_codes' => true]); |
||||
$this->manager->method('isTwoFactorAuthenticated') |
||||
->with($this->user) |
||||
->willReturn(true); |
||||
$this->jobList->expects($this->never()) |
||||
->method($this->anything()); |
||||
|
||||
$this->invokePrivate($this->checkBackupCodes, 'run', [[]]); |
||||
} |
||||
|
||||
public function testRun() { |
||||
$this->user->method('getUID') |
||||
->willReturn('myUID'); |
||||
|
||||
$this->registry->expects($this->once()) |
||||
->method('getProviderStates') |
||||
->with($this->user) |
||||
->willReturn([ |
||||
'backup_codes' => false, |
||||
]); |
||||
$this->jobList->expects($this->once()) |
||||
->method('add') |
||||
->with( |
||||
$this->equalTo(RememberBackupCodesJob::class), |
||||
['uid' => 'myUID'] |
||||
); |
||||
$this->manager->method('isTwoFactorAuthenticated') |
||||
->with($this->user) |
||||
->willReturn(true); |
||||
|
||||
$this->invokePrivate($this->checkBackupCodes, 'run', [[]]); |
||||
} |
||||
|
||||
public function testRunNoProviders() { |
||||
$this->registry->expects($this->once()) |
||||
->method('getProviderStates') |
||||
->with($this->user) |
||||
->willReturn([ |
||||
'backup_codes' => false, |
||||
]); |
||||
$this->jobList->expects($this->never()) |
||||
->method($this->anything()); |
||||
$this->manager->method('isTwoFactorAuthenticated') |
||||
->with($this->user) |
||||
->willReturn(false); |
||||
|
||||
$this->invokePrivate($this->checkBackupCodes, 'run', [[]]); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,65 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @author Christoph Wurst <christoph@winzerhof-wurst.at> |
||||
* |
||||
* @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\TwoFactorBackupCodes\Tests\Unit\Migration; |
||||
|
||||
use OCA\TwoFactorBackupCodes\Event\CodesGenerated; |
||||
use OCA\TwoFactorBackupCodes\Listener\RegistryUpdater; |
||||
use OCA\TwoFactorBackupCodes\Migration\CheckBackupCodes; |
||||
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider; |
||||
use OCP\Authentication\TwoFactorAuth\IRegistry; |
||||
use OCP\BackgroundJob\IJobList; |
||||
use OCP\IUser; |
||||
use OCP\Migration\IOutput; |
||||
use Symfony\Component\EventDispatcher\Event; |
||||
use Test\TestCase; |
||||
|
||||
class CheckBackupCodeTest extends TestCase { |
||||
|
||||
/** @var IJobList|\PHPunit\Framework\MockObject\MockObject */ |
||||
private $jobList; |
||||
|
||||
/** @var CheckBackupCodes */ |
||||
private $checkBackupsCodes; |
||||
|
||||
protected function setUp() { |
||||
parent::setUp(); |
||||
|
||||
$this->jobList = $this->createMock(IJobList::class); |
||||
$this->checkBackupsCodes = new CheckBackupCodes($this->jobList); |
||||
} |
||||
|
||||
public function testGetName() { |
||||
$this->assertSame('Add background job to check for backup codes', $this->checkBackupsCodes->getName()); |
||||
} |
||||
|
||||
public function testRun() { |
||||
$this->jobList->expects($this->once()) |
||||
->method('add') |
||||
->with( |
||||
$this->equalTo(\OCA\TwoFactorBackupCodes\BackgroundJob\CheckBackupCodes::class) |
||||
); |
||||
|
||||
$this->checkBackupsCodes->run($this->createMock(IOutput::class)); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue