misc_pterodactyl-panel/app/Services/Sftp/AuthenticateUsingPasswordService.php

108 lines
4 KiB
PHP

<?php
namespace Pterodactyl\Services\Sftp;
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\SubuserRepositoryInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class AuthenticateUsingPasswordService
{
/**
* @var \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService
*/
private $keyProviderService;
/**
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
*/
private $repository;
/**
* @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface
*/
private $userRepository;
/**
* @var \Pterodactyl\Contracts\Repository\SubuserRepositoryInterface
*/
private $subuserRepository;
/**
* AuthenticateUsingPasswordService constructor.
*
* @param \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService $keyProviderService
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
* @param \Pterodactyl\Contracts\Repository\SubuserRepositoryInterface $subuserRepository
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $userRepository
*/
public function __construct(
DaemonKeyProviderService $keyProviderService,
ServerRepositoryInterface $repository,
SubuserRepositoryInterface $subuserRepository,
UserRepositoryInterface $userRepository
) {
$this->keyProviderService = $keyProviderService;
$this->repository = $repository;
$this->subuserRepository = $subuserRepository;
$this->userRepository = $userRepository;
}
/**
* Attempt to authenticate a provided username and password and determine if they
* have permission to access a given server. This function does not account for
* subusers currently. Only administrators and server owners can login to access
* their files at this time.
*
* Server must exist on the node that the API call is being made from in order for a
* valid response to be provided.
*
* @param string $username
* @param string $password
* @param int $node
* @param string|null $server
* @return array
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
*/
public function handle(string $username, string $password, int $node, string $server = null): array
{
if (is_null($server)) {
throw new RecordNotFoundException;
}
$user = $this->userRepository->setColumns(['id', 'root_admin', 'password'])->findFirstWhere([['username', '=', $username]]);
if (! password_verify($password, $user->password)) {
throw new RecordNotFoundException;
}
$server = $this->repository->setColumns(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->getByUuid($server);
if ($server->node_id !== $node) {
throw new RecordNotFoundException;
}
if (! $user->root_admin && $server->owner_id !== $user->id) {
$subuser = $this->subuserRepository->getWithPermissionsUsingUserAndServer($user->id, $server->id);
$permissions = $subuser->getRelation('permissions')->pluck('permission')->toArray();
if (! in_array('access-sftp', $permissions)) {
throw new RecordNotFoundException;
}
}
if ($server->installed !== 1 || $server->suspended) {
throw new BadRequestHttpException;
}
return [
'server' => $server->uuid,
'token' => $this->keyProviderService->handle($server, $user),
'permissions' => $permissions ?? ['*'],
];
}
}