Implement application API Keys

This commit is contained in:
Dane Everitt 2018-01-18 21:36:15 -06:00
parent f9fc3f4370
commit c3b9738364
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
13 changed files with 454 additions and 3 deletions

View file

@ -0,0 +1,117 @@
<?php
namespace Pterodactyl\Http\Controllers\Admin;
use Illuminate\View\View;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Pterodactyl\Models\ApiKey;
use Illuminate\Http\RedirectResponse;
use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Services\Acl\Api\AdminAcl;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Api\KeyCreationService;
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Api\StoreApplicationApiKeyRequest;
class ApplicationApiController extends Controller
{
/**
* @var \Prologue\Alerts\AlertsMessageBag
*/
private $alert;
/**
* @var \Pterodactyl\Services\Api\KeyCreationService
*/
private $keyCreationService;
/**
* @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface
*/
private $repository;
/**
* ApplicationApiController constructor.
*
* @param \Prologue\Alerts\AlertsMessageBag $alert
* @param \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface $repository
* @param \Pterodactyl\Services\Api\KeyCreationService $keyCreationService
*/
public function __construct(
AlertsMessageBag $alert,
ApiKeyRepositoryInterface $repository,
KeyCreationService $keyCreationService
) {
$this->alert = $alert;
$this->keyCreationService = $keyCreationService;
$this->repository = $repository;
}
/**
* Render view showing all of a user's application API keys.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\View\View
*/
public function index(Request $request): View
{
return view('admin.api.index', [
'keys' => $this->repository->getApplicationKeys($request->user()),
]);
}
/**
* Render view allowing an admin to create a new application API key.
*
* @return \Illuminate\View\View
*/
public function create(): View
{
$resources = AdminAcl::getResourceList();
sort($resources);
return view('admin.api.new', [
'resources' => $resources,
'permissions' => [
'r' => AdminAcl::READ,
'rw' => AdminAcl::READ | AdminAcl::WRITE,
'n' => AdminAcl::NONE,
],
]);
}
/**
* Store the new key and redirect the user back to the application key listing.
*
* @param \Pterodactyl\Http\Requests\Admin\Api\StoreApplicationApiKeyRequest $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
*/
public function store(StoreApplicationApiKeyRequest $request): RedirectResponse
{
$this->keyCreationService->setKeyType(ApiKey::TYPE_APPLICATION)->handle([
'memo' => $request->input('memo'),
'user_id' => $request->user()->id,
], $request->getKeyPermissions());
$this->alert->success('A new application API key has been generated for your account.')->flash();
return redirect()->route('admin.api.index');
}
/**
* Delete an application API key from the database.
*
* @param \Illuminate\Http\Request $request
* @param string $identifier
* @return \Illuminate\Http\Response
*/
public function delete(Request $request, string $identifier): Response
{
$this->repository->deleteApplicationKey($request->user(), $identifier);
return response('', 204);
}
}

View file

@ -21,6 +21,7 @@ use Pterodactyl\Http\Middleware\RedirectIfAuthenticated;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Pterodactyl\Http\Middleware\Api\Admin\AuthenticateKey;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Pterodactyl\Http\Middleware\Api\Admin\AuthenticateUser;
use Pterodactyl\Http\Middleware\Api\Admin\SetSessionDriver;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Pterodactyl\Http\Middleware\Server\AuthenticateAsSubuser;
@ -66,10 +67,11 @@ class Kernel extends HttpKernel
RequireTwoFactorAuthentication::class,
],
'api' => [
'throttle:60,1',
'throttle:120,1',
SubstituteBindings::class,
SetSessionDriver::class,
AuthenticateKey::class,
AuthenticateUser::class,
AuthenticateIPAccess::class,
],
'daemon' => [

View file

@ -0,0 +1,27 @@
<?php
namespace Pterodactyl\Http\Middleware\Api\Admin;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class AuthenticateUser
{
/**
* Authenticate that the currently authenticated user is an administrator
* and should be allowed to proceede through the application API.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if (is_null($request->user()) || ! $request->user()->root_admin) {
throw new AccessDeniedHttpException;
}
return $next($request);
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace Pterodactyl\Http\Requests\Admin\Api;
use Pterodactyl\Models\ApiKey;
use Pterodactyl\Services\Acl\Api\AdminAcl;
use Pterodactyl\Http\Requests\Admin\AdminFormRequest;
class StoreApplicationApiKeyRequest extends AdminFormRequest
{
/**
* @return array
*/
public function rules()
{
$modelRules = ApiKey::getCreateRules();
return collect(AdminAcl::getResourceList())->mapWithKeys(function ($resource) use ($modelRules) {
return [AdminAcl::COLUMN_IDENTIFER . $resource => $modelRules['r_' . $resource]];
})->merge(['memo' => $modelRules['memo']])->toArray();
}
/**
* @return array
*/
public function attributes()
{
return [
'memo' => 'Description',
];
}
public function getKeyPermissions(): array
{
return collect($this->validated())->filter(function ($value, $key) {
return substr($key, 0, strlen(AdminAcl::COLUMN_IDENTIFER)) === AdminAcl::COLUMN_IDENTIFER;
})->toArray();
}
}