Temporary patch to get user management pages displaying correctly
This commit is contained in:
parent
06e5a05f22
commit
c087f6429f
6 changed files with 32 additions and 119 deletions
|
@ -164,27 +164,11 @@ class UserController extends Controller
|
||||||
*/
|
*/
|
||||||
public function update(UserFormRequest $request, User $user)
|
public function update(UserFormRequest $request, User $user)
|
||||||
{
|
{
|
||||||
$this->updateService->setUserLevel(User::USER_LEVEL_ADMIN);
|
$this->updateService
|
||||||
$data = $this->updateService->handle($user, $request->normalize());
|
->setUserLevel(User::USER_LEVEL_ADMIN)
|
||||||
|
->handle($user, $request->normalize());
|
||||||
|
|
||||||
if (! empty($data->get('exceptions'))) {
|
$this->alert->success(trans('admin/user.notices.account_updated'))->flash();
|
||||||
foreach ($data->get('exceptions') as $node => $exception) {
|
|
||||||
/** @var \GuzzleHttp\Exception\RequestException $exception */
|
|
||||||
/** @var \GuzzleHttp\Psr7\Response|null $response */
|
|
||||||
$response = method_exists($exception, 'getResponse') ? $exception->getResponse() : null;
|
|
||||||
$message = trans('admin/server.exceptions.daemon_exception', [
|
|
||||||
'code' => is_null($response) ? 'E_CONN_REFUSED' : $response->getStatusCode(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->alert->danger(trans('exceptions.users.node_revocation_failed', [
|
|
||||||
'node' => $node,
|
|
||||||
'error' => $message,
|
|
||||||
'link' => route('admin.nodes.view', $node),
|
|
||||||
]))->flash();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->alert->success($this->translator->trans('admin/user.notices.account_updated'))->flash();
|
|
||||||
|
|
||||||
return redirect()->route('admin.users.view', $user->id);
|
return redirect()->route('admin.users.view', $user->id);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +177,7 @@ class UserController extends Controller
|
||||||
* Get a JSON response of users on the system.
|
* Get a JSON response of users on the system.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Database\Eloquent\Collection
|
* @return \Illuminate\Support\Collection
|
||||||
*/
|
*/
|
||||||
public function json(Request $request)
|
public function json(Request $request)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Pterodactyl\Http\Requests\Admin;
|
namespace Pterodactyl\Http\Requests\Admin;
|
||||||
|
|
||||||
use Pterodactyl\Models\User;
|
use Pterodactyl\Models\User;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class UserFormRequest extends AdminFormRequest
|
class UserFormRequest extends AdminFormRequest
|
||||||
{
|
{
|
||||||
|
@ -12,16 +13,16 @@ class UserFormRequest extends AdminFormRequest
|
||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
$rules = collect(User::getRules());
|
return Collection::make(
|
||||||
if ($this->method() === 'PATCH') {
|
User::getRulesForUpdate($this->route()->parameter('user'))
|
||||||
$rules = collect(User::getRulesForUpdate($this->route()->parameter('user')))->merge([
|
)->only([
|
||||||
'ignore_connection_error' => ['sometimes', 'nullable', 'boolean'],
|
'email',
|
||||||
]);
|
'username',
|
||||||
}
|
'name_first',
|
||||||
|
'name_last',
|
||||||
return $rules->only([
|
'password',
|
||||||
'email', 'username', 'name_first', 'name_last', 'password',
|
'language',
|
||||||
'language', 'ignore_connection_error', 'root_admin',
|
'root_admin',
|
||||||
])->toArray();
|
])->toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ class User extends Validable implements
|
||||||
'username' => 'required|between:1,255|unique:users,username',
|
'username' => 'required|between:1,255|unique:users,username',
|
||||||
'name_first' => 'required|string|between:1,255',
|
'name_first' => 'required|string|between:1,255',
|
||||||
'name_last' => 'required|string|between:1,255',
|
'name_last' => 'required|string|between:1,255',
|
||||||
'password' => 'required|nullable|string',
|
'password' => 'sometimes|nullable|string',
|
||||||
'root_admin' => 'boolean',
|
'root_admin' => 'boolean',
|
||||||
'language' => 'required|string',
|
'language' => 'required|string',
|
||||||
'use_totp' => 'boolean',
|
'use_totp' => 'boolean',
|
||||||
|
|
|
@ -5,18 +5,12 @@ namespace Pterodactyl\Services\Users;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Pterodactyl\Models\User;
|
use Pterodactyl\Models\User;
|
||||||
use PragmaRX\Google2FA\Google2FA;
|
use PragmaRX\Google2FA\Google2FA;
|
||||||
use Illuminate\Contracts\Config\Repository;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
use Illuminate\Contracts\Encryption\Encrypter;
|
||||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
||||||
use Pterodactyl\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid;
|
use Pterodactyl\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid;
|
||||||
|
|
||||||
class ToggleTwoFactorService
|
class ToggleTwoFactorService
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Config\Repository
|
|
||||||
*/
|
|
||||||
private $config;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||||
*/
|
*/
|
||||||
|
@ -37,16 +31,13 @@ class ToggleTwoFactorService
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||||
* @param \PragmaRX\Google2FA\Google2FA $google2FA
|
* @param \PragmaRX\Google2FA\Google2FA $google2FA
|
||||||
* @param \Illuminate\Contracts\Config\Repository $config
|
|
||||||
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository
|
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Encrypter $encrypter,
|
Encrypter $encrypter,
|
||||||
Google2FA $google2FA,
|
Google2FA $google2FA,
|
||||||
Repository $config,
|
|
||||||
UserRepositoryInterface $repository
|
UserRepositoryInterface $repository
|
||||||
) {
|
) {
|
||||||
$this->config = $config;
|
|
||||||
$this->encrypter = $encrypter;
|
$this->encrypter = $encrypter;
|
||||||
$this->google2FA = $google2FA;
|
$this->google2FA = $google2FA;
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
|
@ -60,16 +51,18 @@ class ToggleTwoFactorService
|
||||||
* @param bool|null $toggleState
|
* @param bool|null $toggleState
|
||||||
* @return bool
|
* @return bool
|
||||||
*
|
*
|
||||||
|
* @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
|
||||||
|
* @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
|
||||||
|
* @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
* @throws \Pterodactyl\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid
|
* @throws \Pterodactyl\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid
|
||||||
*/
|
*/
|
||||||
public function handle(User $user, string $token, bool $toggleState = null): bool
|
public function handle(User $user, string $token, bool $toggleState = null): bool
|
||||||
{
|
{
|
||||||
$window = $this->config->get('pterodactyl.auth.2fa.window');
|
|
||||||
$secret = $this->encrypter->decrypt($user->totp_secret);
|
$secret = $this->encrypter->decrypt($user->totp_secret);
|
||||||
|
|
||||||
$isValidToken = $this->google2FA->verifyKey($secret, $token, $window);
|
$isValidToken = $this->google2FA->verifyKey($secret, $token, config()->get('pterodactyl.auth.2fa.window'));
|
||||||
|
|
||||||
if (! $isValidToken) {
|
if (! $isValidToken) {
|
||||||
throw new TwoFactorAuthenticationTokenInvalid;
|
throw new TwoFactorAuthenticationTokenInvalid;
|
||||||
|
|
|
@ -3,11 +3,9 @@
|
||||||
namespace Pterodactyl\Services\Users;
|
namespace Pterodactyl\Services\Users;
|
||||||
|
|
||||||
use Pterodactyl\Models\User;
|
use Pterodactyl\Models\User;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Illuminate\Contracts\Hashing\Hasher;
|
use Illuminate\Contracts\Hashing\Hasher;
|
||||||
use Pterodactyl\Traits\Services\HasUserLevels;
|
use Pterodactyl\Traits\Services\HasUserLevels;
|
||||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
use Pterodactyl\Repositories\Eloquent\UserRepository;
|
||||||
use Pterodactyl\Services\DaemonKeys\RevokeMultipleDaemonKeysService;
|
|
||||||
|
|
||||||
class UserUpdateService
|
class UserUpdateService
|
||||||
{
|
{
|
||||||
|
@ -19,44 +17,33 @@ class UserUpdateService
|
||||||
private $hasher;
|
private $hasher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface
|
* @var \Pterodactyl\Repositories\Eloquent\UserRepository
|
||||||
*/
|
*/
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\DaemonKeys\RevokeMultipleDaemonKeysService
|
|
||||||
*/
|
|
||||||
private $revocationService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UpdateService constructor.
|
* UpdateService constructor.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Contracts\Hashing\Hasher $hasher
|
* @param \Illuminate\Contracts\Hashing\Hasher $hasher
|
||||||
* @param \Pterodactyl\Services\DaemonKeys\RevokeMultipleDaemonKeysService $revocationService
|
* @param \Pterodactyl\Repositories\Eloquent\UserRepository $repository
|
||||||
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(Hasher $hasher, UserRepository $repository)
|
||||||
Hasher $hasher,
|
{
|
||||||
RevokeMultipleDaemonKeysService $revocationService,
|
|
||||||
UserRepositoryInterface $repository
|
|
||||||
) {
|
|
||||||
$this->hasher = $hasher;
|
$this->hasher = $hasher;
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
$this->revocationService = $revocationService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the user model instance. If the user has been removed as an administrator
|
* Update the user model instance.
|
||||||
* revoke all of the authentication tokens that have been assigned to their account.
|
|
||||||
*
|
*
|
||||||
* @param \Pterodactyl\Models\User $user
|
* @param \Pterodactyl\Models\User $user
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return \Illuminate\Support\Collection
|
* @return \Pterodactyl\Models\User
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
*/
|
*/
|
||||||
public function handle(User $user, array $data): Collection
|
public function handle(User $user, array $data)
|
||||||
{
|
{
|
||||||
if (! empty(array_get($data, 'password'))) {
|
if (! empty(array_get($data, 'password'))) {
|
||||||
$data['password'] = $this->hasher->make($data['password']);
|
$data['password'] = $this->hasher->make($data['password']);
|
||||||
|
@ -64,17 +51,9 @@ class UserUpdateService
|
||||||
unset($data['password']);
|
unset($data['password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isUserLevel(User::USER_LEVEL_ADMIN)) {
|
/** @var \Pterodactyl\Models\User $response */
|
||||||
if (array_get($data, 'root_admin', 0) == 0 && $user->root_admin) {
|
$response = $this->repository->update($user->id, $data);
|
||||||
$this->revocationService->handle($user, array_get($data, 'ignore_connection_error', false));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unset($data['root_admin']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return collect([
|
return $response;
|
||||||
'model' => $this->repository->update($user->id, $data),
|
|
||||||
'exceptions' => $this->revocationService->getExceptions(),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,55 +102,11 @@
|
||||||
</select>
|
</select>
|
||||||
<p class="text-muted"><small>Setting this to 'Yes' gives a user full administrative access.</small></p>
|
<p class="text-muted"><small>Setting this to 'Yes' gives a user full administrative access.</small></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox checkbox-primary">
|
|
||||||
<input type="checkbox" id="pIgnoreConnectionError" value="1" name="ignore_connection_error">
|
|
||||||
<label for="pIgnoreConnectionError"> Ignore exceptions raised while revoking keys.</label>
|
|
||||||
<p class="text-muted small">If checked, any errors thrown while revoking keys across nodes will be ignored. You should avoid this checkbox if possible as any non-revoked keys could continue to be active for up to 24 hours after this account is changed. If you are needing to revoke account permissions immediately and are facing node issues, you should check this box and then restart any nodes that failed to be updated to clear out any stored keys.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{--<div class="col-xs-12">--}}
|
|
||||||
{{--<div class="box">--}}
|
|
||||||
{{--<div class="box-header with-border">--}}
|
|
||||||
{{--<h3 class="box-title">Associated Servers</h3>--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
{{--<div class="box-body table-responsive no-padding">--}}
|
|
||||||
{{--<table class="table table-hover">--}}
|
|
||||||
{{--<thead>--}}
|
|
||||||
{{--<tr>--}}
|
|
||||||
{{--<th style="width:2%;"></th>--}}
|
|
||||||
{{--<th>Identifier</th>--}}
|
|
||||||
{{--<th>Server Name</th>--}}
|
|
||||||
{{--<th>Access</th>--}}
|
|
||||||
{{--<th>Node</th>--}}
|
|
||||||
{{--<th style="width:10%;"></th>--}}
|
|
||||||
{{--</tr>--}}
|
|
||||||
{{--</thead>--}}
|
|
||||||
{{--<tbody>--}}
|
|
||||||
{{--@foreach($user->setAccessLevel('subuser')->access()->get() as $server)--}}
|
|
||||||
{{--<tr>--}}
|
|
||||||
{{--<td><a href="{{ route('server.index', $server->uuidShort) }}/"><i class="fa fa-tachometer"></i></a></td>--}}
|
|
||||||
{{--<td><code>{{ $server->uuidShort }}</code></td>--}}
|
|
||||||
{{--<td><a href="{{ route('admin.servers.view', $server->id) }}">{{ $server->name }}</a></td>--}}
|
|
||||||
{{--<td>--}}
|
|
||||||
{{--@if($server->owner_id === $user->id)--}}
|
|
||||||
{{--<span class="label bg-purple">Owner</span>--}}
|
|
||||||
{{--@else--}}
|
|
||||||
{{--<span class="label bg-blue">Subuser</span>--}}
|
|
||||||
{{--@endif--}}
|
|
||||||
{{--</td>--}}
|
|
||||||
{{--<td><a href="{{ route('admin.nodes.view', $server->node->id) }}">{{ $server->node->name }}</a></td>--}}
|
|
||||||
{{--<td class="centered">@if($server->suspended === 0)<span class="label muted muted-hover label-success">Active</span>@else<span class="label label-warning">Suspended</span>@endif</td>--}}
|
|
||||||
{{--</td>--}}
|
|
||||||
{{--@endforeach--}}
|
|
||||||
{{--</tbody>--}}
|
|
||||||
{{--</table>--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<div class="box box-danger">
|
<div class="box box-danger">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
|
|
Loading…
Reference in a new issue