Add new dynamic view for creating API keys

This commit is contained in:
Dane Everitt 2017-04-09 18:59:54 -04:00
parent 87c09a921b
commit 722fd614a1
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
10 changed files with 311 additions and 492 deletions

View file

@ -39,7 +39,7 @@ class CoreController extends Controller
*/
public function index(Request $request)
{
$this->authorize('user-server-list', $request->apiKey());
$this->authorize('user.server-list', $request->apiKey());
$servers = $request->user()->access('service', 'node', 'allocation', 'option')->get();

View file

@ -43,7 +43,7 @@ class ServerController extends Controller
*/
public function index(Request $request, $uuid)
{
$this->authorize('user-server-view', $request->apiKey());
$this->authorize('user.server-view', $request->apiKey());
$server = Server::byUuid($uuid);
$fractal = Fractal::create()->item($server);
@ -66,7 +66,7 @@ class ServerController extends Controller
*/
public function power(Request $request, $uuid)
{
$this->authorize('user-server-power', $request->apiKey());
$this->authorize('user.server-power', $request->apiKey());
$server = Server::byUuid($uuid);
$request->user()->can('power-' . $request->input('action'), $server);
@ -86,7 +86,7 @@ class ServerController extends Controller
*/
public function command(Request $request, $uuid)
{
$this->authorize('user-server-command', $request->apiKey());
$this->authorize('user.server-command', $request->apiKey());
$server = Server::byUuid($uuid);
$request->user()->can('send-command', $server);

View file

@ -27,8 +27,9 @@ namespace Pterodactyl\Http\Controllers\Base;
use Log;
use Alert;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Models\APIKey;
use Pterodactyl\Models\APIPermission;
use Pterodactyl\Repositories\APIRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
@ -45,7 +46,7 @@ class APIController extends Controller
public function index(Request $request)
{
return view('base.api.index', [
'keys' => Models\APIKey::where('user_id', $request->user()->id)->get(),
'keys' => APIKey::where('user_id', $request->user()->id)->get(),
]);
}
@ -57,7 +58,12 @@ class APIController extends Controller
*/
public function create(Request $request)
{
return view('base.api.new');
return view('base.api.new', [
'permissions' => [
'user' => collect(APIPermission::permissions())->pull('_user'),
'admin' => collect(APIPermission::permissions())->except('_user')->toArray(),
],
]);
}
/**
@ -66,13 +72,13 @@ class APIController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function save(Request $request)
public function store(Request $request)
{
try {
$repo = new APIRepository($request->user());
$secret = $repo->create($request->intersect([
'memo', 'allowed_ips',
'adminPermissions', 'permissions',
'admin_permissions', 'permissions',
]));
Alert::success('An API Key-Pair has successfully been generated. The API secret for this public key is shown below and will not be shown again.<br /><br /><code>' . $secret . '</code>')->flash();

View file

@ -77,16 +77,45 @@ class APIPermission extends Model
// All other pemissions below are administrative actions.
'server' => [
'list',
'view',
'delete',
'create',
'view',
'edit-details',
'edit-container',
'edit-build',
'edit-startup',
'suspend',
'install',
'rebuild',
'edit-build',
'edit-startup',
'delete',
],
'location' => [
'list',
],
'node' => [
'list',
'view',
'view-config',
'create',
'delete',
],
'user' => [
'list',
'view',
'create',
'edit',
'delete',
],
'service' => [
'list',
'view',
],
'option' => [
'list',
'view',
],
'pack' => [
'list',
'view',
],
];

View file

@ -42,6 +42,11 @@ class APIKeyPolicy
*/
protected function checkPermission(User $user, Key $key, $permission)
{
// Non-administrative users cannot use administrative routes.
if (! starts_with('user.') && ! $user->isRootAdmin()) {
return false;
}
// We don't tag this cache key with the user uuid because the key is already unique,
// and multiple users are not defiend for a single key.
$permissions = Cache::remember('APIKeyPolicy.' . $key->public, Carbon::now()->addSeconds(5), function () use ($key) {

View file

@ -29,65 +29,14 @@ use Auth;
use Crypt;
use Validator;
use IPTools\Network;
use Pterodactyl\Models;
use Pterodactyl\Models\User;
use Pterodactyl\Models\APIKey as Key;
use Pterodactyl\Models\APIPermission as Permission;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
class APIRepository
{
/**
* Valid API permissions.
*
* @var array
*/
protected $permissions = [
'admin' => [
'*',
// User Management Routes
'users.list',
'users.create',
'users.view',
'users.update',
'users.delete',
// Server Manaement Routes
'servers.list',
'servers.create',
'servers.view',
'servers.config',
'servers.build',
'servers.suspend',
'servers.unsuspend',
'servers.delete',
// Node Management Routes
'nodes.list',
'nodes.view',
'nodes.create',
'nodes.allocations',
'nodes.delete',
// Service Routes
'services.list',
'services.view',
// Location Routes
'locations.list',
],
'user' => [
'*',
// Informational
'me',
// Server Control
'server',
'server.power',
],
];
/**
* Holder for listing of allowed IPs when creating a new key.
*
@ -108,11 +57,11 @@ class APIRepository
* @param null|\Pterodactyl\Models\User $user
* @return void
*/
public function __construct(Models\User $user = null)
public function __construct(User $user = null)
{
$this->user = is_null($user) ? Auth::user() : $user;
if (is_null($this->user)) {
throw new \Exception('Cannot access API Repository without passing a user to constructor.');
throw new \Exception('Unable to initialize user for API repository instance.');
}
}
@ -129,8 +78,9 @@ class APIRepository
{
$validator = Validator::make($data, [
'memo' => 'string|max:500',
'allowed_ips' => 'sometimes|string',
'permissions' => 'sometimes|required|array',
'adminPermissions' => 'sometimes|required|array',
'admin_permissions' => 'sometimes|required|array',
]);
$validator->after(function ($validator) use ($data) {
@ -156,8 +106,7 @@ class APIRepository
DB::beginTransaction();
try {
$secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7);
$key = new Models\APIKey;
$key->fill([
$key = Key::create([
'user_id' => $this->user->id,
'public' => str_random(16),
'secret' => Crypt::encrypt($secretKey),
@ -165,44 +114,61 @@ class APIRepository
'memo' => $data['memo'],
'expires_at' => null,
]);
$key->save();
$totalPermissions = 0;
$pNodes = Permission::permissions();
if (isset($data['permissions'])) {
foreach ($data['permissions'] as $permNode) {
if (! strpos($permNode, ':')) {
foreach ($data['permissions'] as $permission) {
$parts = explode('-', $permission);
if (count($parts) !== 2) {
continue;
}
list($toss, $permission) = explode(':', $permNode);
if (in_array($permission, $this->permissions['user'])) {
$totalPermissions++;
$model = new Models\APIPermission;
$model->fill([
'key_id' => $key->id,
'permission' => 'api.user.' . $permission,
]);
$model->save();
list($block, $search) = $parts;
if (! array_key_exists($block, $pNodes['_user'])) {
continue;
}
if (! in_array($search, $pNodes['_user'][$block])) {
continue;
}
$totalPermissions++;
Permission::create([
'key_id' => $key->id,
'permission' => 'user.' . $permission,
]);
}
}
if ($this->user->isRootAdmin() && isset($data['adminPermissions'])) {
foreach ($data['adminPermissions'] as $permNode) {
if (! strpos($permNode, ':')) {
if ($this->user->isRootAdmin() && isset($data['admin_permissions'])) {
unset($pNodes['_user']);
foreach ($data['admin_permissions'] as $permNode) {
$parts = explode('-', $permission);
if (count($parts) !== 2) {
continue;
}
list($toss, $permission) = explode(':', $permNode);
if (in_array($permission, $this->permissions['admin'])) {
$totalPermissions++;
$model = new Models\APIPermission;
$model->fill([
'key_id' => $key->id,
'permission' => 'api.admin.' . $permission,
]);
$model->save();
list($block, $search) = $parts;
if (! array_key_exists($block, $pNodes)) {
continue;
}
if (! in_array($search, $pNodes[$block])) {
continue;
}
$totalPermissions++;
Permission::create([
'key_id' => $key->id,
'permission' => $permission,
]);
}
}
@ -229,20 +195,13 @@ class APIRepository
*/
public function revoke($key)
{
DB::beginTransaction();
try {
$model = Models\APIKey::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
DB::transaction(function () use ($key) {
$model = Key::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
foreach ($model->permissions as &$permission) {
$permission->delete();
}
$model->delete();
DB::commit();
} catch (\Exception $ex) {
DB::rollBack();
throw $ex;
}
});
}
}