Skip to content

Commit 4de326a

Browse files
committed
Add command to disable 2FA for a user account.
1 parent 34f1152 commit 4de326a

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
/*
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
namespace Pterodactyl\Console\Commands\User;
26+
27+
use Illuminate\Console\Command;
28+
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
29+
30+
class DisableTwoFactorCommand extends Command
31+
{
32+
/**
33+
* @var string
34+
*/
35+
protected $description = 'Disable two-factor authentication for a specific user in the Panel.';
36+
37+
/**
38+
* @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface
39+
*/
40+
protected $repository;
41+
42+
/**
43+
* @var string
44+
*/
45+
protected $signature = 'p:user:disable2fa {--email= : The email of the user to disable 2-Factor for.}';
46+
47+
/**
48+
* DisableTwoFactorCommand constructor.
49+
*
50+
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository
51+
*/
52+
public function __construct(UserRepositoryInterface $repository)
53+
{
54+
parent::__construct();
55+
56+
$this->repository = $repository;
57+
}
58+
59+
/**
60+
* Handle command execution process.
61+
*
62+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
63+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
64+
*/
65+
public function handle()
66+
{
67+
if ($this->input->isInteractive()) {
68+
$this->output->warning(trans('command/messages.user.2fa_help_text'));
69+
}
70+
71+
$email = $this->option('email') ?? $this->ask(trans('command/messages.user.ask_email'));
72+
$user = $this->repository->withColumns(['id', 'email'])->findFirstWhere([['email', '=', $email]]);
73+
74+
$this->repository->withoutFresh()->update($user->id, [
75+
'use_totp' => false,
76+
'totp_secret' => null,
77+
]);
78+
$this->info(trans('command/messages.user.2fa_disabled', ['email' => $user->email]));
79+
}
80+
}

app/Console/Kernel.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Pterodactyl\Console\Commands\User\DeleteUserCommand;
88
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
99
use Pterodactyl\Console\Commands\Location\MakeLocationCommand;
10+
use Pterodactyl\Console\Commands\User\DisableTwoFactorCommand;
1011
use Pterodactyl\Console\Commands\Location\DeleteLocationCommand;
1112

1213
class Kernel extends ConsoleKernel
@@ -19,6 +20,7 @@ class Kernel extends ConsoleKernel
1920
protected $commands = [
2021
DeleteLocationCommand::class,
2122
DeleteUserCommand::class,
23+
DisableTwoFactorCommand::class,
2224
MakeLocationCommand::class,
2325
MakeUserCommand::class,
2426
// \Pterodactyl\Console\Commands\MakeUser::class,

resources/lang/en/command/messages.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,10 @@
4545
'ask_password' => 'Password',
4646
'ask_password_tip' => 'If you would like to create an account with a random password emailed to the user, re-run this command (CTRL+C) and pass the `--no-password` flag.',
4747
'ask_password_help' => 'Passwords must be at least 8 characters in length and contain at least one capital letter and number.',
48+
'2fa_help_text' => [
49+
'This command will disable 2-factor authentication for a user\'s account if it is enabled. This should only be used as an account recovery command if the user is locked out of their account.',
50+
'If this is not what you wanted to do, press CTRL+C to exit this process.',
51+
],
52+
'2fa_disabled' => '2-Factor authentication has been disabled for :email.',
4853
],
4954
];
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
/*
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
namespace Tests\Unit\Commands\User;
26+
27+
use Mockery as m;
28+
use Tests\TestCase;
29+
use Pterodactyl\Models\User;
30+
use Symfony\Component\Console\Tester\CommandTester;
31+
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
32+
use Pterodactyl\Console\Commands\User\DisableTwoFactorCommand;
33+
34+
class DisableTwoFactorCommandTest extends TestCase
35+
{
36+
/**
37+
* @var \Pterodactyl\Console\Commands\User\DisableTwoFactorCommand
38+
*/
39+
protected $command;
40+
41+
/**
42+
* @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface
43+
*/
44+
protected $repository;
45+
46+
public function setUp()
47+
{
48+
parent::setUp();
49+
50+
$this->repository = m::mock(UserRepositoryInterface::class);
51+
52+
$this->command = new DisableTwoFactorCommand($this->repository);
53+
$this->command->setLaravel($this->app);
54+
}
55+
56+
/**
57+
* Test 2-factor auth is disabled when no option is passed.
58+
*/
59+
public function testTwoFactorIsDisabledWhenNoOptionIsPassed()
60+
{
61+
$user = factory(User::class)->make();
62+
63+
$this->repository->shouldReceive('withColumns')->with(['id', 'email'])->once()->andReturnSelf()
64+
->shouldReceive('findFirstWhere')->with([['email', '=', $user->email]])->once()->andReturn($user);
65+
$this->repository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf()
66+
->shouldReceive('update')->with($user->id, [
67+
'use_totp' => false,
68+
'totp_secret' => null,
69+
])->once()->andReturnNull();
70+
71+
$response = new CommandTester($this->command);
72+
$response->setInputs([$user->email]);
73+
$response->execute([]);
74+
75+
$display = $response->getDisplay();
76+
$this->assertNotEmpty($display);
77+
$this->assertContains(trans('command/messages.user.2fa_disabled', ['email' => $user->email]), $display);
78+
}
79+
80+
/**
81+
* Test 2-factor auth is disabled when user is passed in option.
82+
*/
83+
public function testTwoFactorIsDisabledWhenOptionIsPassed()
84+
{
85+
$user = factory(User::class)->make();
86+
87+
$this->repository->shouldReceive('withColumns')->with(['id', 'email'])->once()->andReturnSelf()
88+
->shouldReceive('findFirstWhere')->with([['email', '=', $user->email]])->once()->andReturn($user);
89+
$this->repository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf()
90+
->shouldReceive('update')->with($user->id, [
91+
'use_totp' => false,
92+
'totp_secret' => null,
93+
])->once()->andReturnNull();
94+
95+
$response = new CommandTester($this->command);
96+
$response->execute([
97+
'--email' => $user->email,
98+
]);
99+
100+
$display = $response->getDisplay();
101+
$this->assertNotEmpty($display);
102+
$this->assertContains(trans('command/messages.user.2fa_disabled', ['email' => $user->email]), $display);
103+
}
104+
}

0 commit comments

Comments
 (0)