Add new dynamic view for creating API keys
This commit is contained in:
parent
87c09a921b
commit
722fd614a1
10 changed files with 311 additions and 492 deletions
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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',
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue