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

View file

@ -27,8 +27,9 @@ namespace Pterodactyl\Http\Controllers\Base;
use Log; use Log;
use Alert; use Alert;
use Pterodactyl\Models;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Models\APIKey;
use Pterodactyl\Models\APIPermission;
use Pterodactyl\Repositories\APIRepository; use Pterodactyl\Repositories\APIRepository;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
@ -45,7 +46,7 @@ class APIController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
return view('base.api.index', [ 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) 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 * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function save(Request $request) public function store(Request $request)
{ {
try { try {
$repo = new APIRepository($request->user()); $repo = new APIRepository($request->user());
$secret = $repo->create($request->intersect([ $secret = $repo->create($request->intersect([
'memo', 'allowed_ips', '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(); 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. // All other pemissions below are administrative actions.
'server' => [ 'server' => [
'list', 'list',
'view',
'delete',
'create', 'create',
'view',
'edit-details', 'edit-details',
'edit-container', 'edit-container',
'edit-build',
'edit-startup',
'suspend', 'suspend',
'install', 'install',
'rebuild', 'rebuild',
'edit-build', 'delete',
'edit-startup', ],
'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) 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, // 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. // and multiple users are not defiend for a single key.
$permissions = Cache::remember('APIKeyPolicy.' . $key->public, Carbon::now()->addSeconds(5), function () use ($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 Crypt;
use Validator; use Validator;
use IPTools\Network; 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\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException; use Pterodactyl\Exceptions\DisplayValidationException;
class APIRepository 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. * Holder for listing of allowed IPs when creating a new key.
* *
@ -108,11 +57,11 @@ class APIRepository
* @param null|\Pterodactyl\Models\User $user * @param null|\Pterodactyl\Models\User $user
* @return void * @return void
*/ */
public function __construct(Models\User $user = null) public function __construct(User $user = null)
{ {
$this->user = is_null($user) ? Auth::user() : $user; $this->user = is_null($user) ? Auth::user() : $user;
if (is_null($this->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, [ $validator = Validator::make($data, [
'memo' => 'string|max:500', 'memo' => 'string|max:500',
'allowed_ips' => 'sometimes|string',
'permissions' => 'sometimes|required|array', 'permissions' => 'sometimes|required|array',
'adminPermissions' => 'sometimes|required|array', 'admin_permissions' => 'sometimes|required|array',
]); ]);
$validator->after(function ($validator) use ($data) { $validator->after(function ($validator) use ($data) {
@ -156,8 +106,7 @@ class APIRepository
DB::beginTransaction(); DB::beginTransaction();
try { try {
$secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7); $secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7);
$key = new Models\APIKey; $key = Key::create([
$key->fill([
'user_id' => $this->user->id, 'user_id' => $this->user->id,
'public' => str_random(16), 'public' => str_random(16),
'secret' => Crypt::encrypt($secretKey), 'secret' => Crypt::encrypt($secretKey),
@ -165,44 +114,61 @@ class APIRepository
'memo' => $data['memo'], 'memo' => $data['memo'],
'expires_at' => null, 'expires_at' => null,
]); ]);
$key->save();
$totalPermissions = 0; $totalPermissions = 0;
$pNodes = Permission::permissions();
if (isset($data['permissions'])) { if (isset($data['permissions'])) {
foreach ($data['permissions'] as $permNode) { foreach ($data['permissions'] as $permission) {
if (! strpos($permNode, ':')) { $parts = explode('-', $permission);
if (count($parts) !== 2) {
continue; continue;
} }
list($toss, $permission) = explode(':', $permNode); list($block, $search) = $parts;
if (in_array($permission, $this->permissions['user'])) {
$totalPermissions++;
$model = new Models\APIPermission;
$model->fill([
'key_id' => $key->id,
'permission' => 'api.user.' . $permission,
]);
$model->save();
}
}
}
if ($this->user->isRootAdmin() && isset($data['adminPermissions'])) { if (! array_key_exists($block, $pNodes['_user'])) {
foreach ($data['adminPermissions'] as $permNode) {
if (! strpos($permNode, ':')) {
continue; continue;
} }
list($toss, $permission) = explode(':', $permNode); if (! in_array($search, $pNodes['_user'][$block])) {
if (in_array($permission, $this->permissions['admin'])) { continue;
$totalPermissions++;
$model = new Models\APIPermission;
$model->fill([
'key_id' => $key->id,
'permission' => 'api.admin.' . $permission,
]);
$model->save();
} }
$totalPermissions++;
Permission::create([
'key_id' => $key->id,
'permission' => 'user.' . $permission,
]);
}
}
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($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) public function revoke($key)
{ {
DB::beginTransaction(); DB::transaction(function () use ($key) {
$model = Key::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
try {
$model = Models\APIKey::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
foreach ($model->permissions as &$permission) { foreach ($model->permissions as &$permission) {
$permission->delete(); $permission->delete();
} }
$model->delete(); $model->delete();
});
DB::commit();
} catch (\Exception $ex) {
DB::rollBack();
throw $ex;
}
} }
} }

View file

@ -46,122 +46,162 @@ return [
'title' => 'Allowed IPs', 'title' => 'Allowed IPs',
'description' => 'Enter a line delimitated list of IPs that are allowed to access the API using this key. CIDR notation is allowed. Leave blank to allow any IP.', 'description' => 'Enter a line delimitated list of IPs that are allowed to access the API using this key. CIDR notation is allowed. Leave blank to allow any IP.',
], ],
'base' => [
'title' => 'Base Information',
'information' => [
'title' => 'Base Information',
'description' => 'Returns a listing of all servers that this account has access to.',
], ],
], 'permissions' => [
'user_management' => [ 'user' => [
'title' => 'User Management', 'server_header' => 'User Server Permissions',
'list' => [
'title' => 'List Users',
'description' => 'Allows listing of all users currently on the system.',
],
'create' => [
'title' => 'Create User',
'description' => 'Allows creating a new user on the system.',
],
'view' => [
'title' => 'List Single User',
'description' => 'Allows viewing details about a specific user including active services.',
],
'update' => [
'title' => 'Update User',
'description' => 'Allows modifying user details (email, password, TOTP information).',
],
'delete' => [
'title' => 'Delete User',
'description' => 'Allows deleting a user.',
],
],
'node_management' => [
'title' => 'Node Management',
'list' => [
'title' => 'List Nodes',
'description' => 'Allows listing of all nodes currently on the system.',
],
'create' => [
'title' => 'Create Node',
'description' => 'Allows creating a new node on the system.',
],
'view' => [
'title' => 'List Single Node',
'description' => 'Allows viewing details about a specific node including active services.',
],
'allocations' => [
'title' => 'List Allocations',
'description' => 'Allows viewing all allocations on the panel for all nodes.',
],
'delete' => [
'title' => 'Delete Node',
'description' => 'Allows deleting a node.',
],
],
'server_management' => [
'title' => 'Server Management',
'server' => [ 'server' => [
'title' => 'Server Info', 'list' => [
'description' => 'Allows access to viewing information about a single server including current stats and allocations.', 'title' => 'List Servers',
'desc' => 'Allows listing of all servers a user owns or has access to as a subuser.',
],
'view' => [
'title' => 'View Server',
'desc'=> 'Allows viewing of specific server user can access.',
], ],
'power' => [ 'power' => [
'title' => 'Server Power', 'title' => 'Toggle Power',
'description' => 'Allows access to control server power status.', 'desc'=> 'Allow toggling of power status for a server.',
], ],
'command' => [ 'command' => [
'title' => 'Send Command', 'title' => 'Send Command',
'description' => 'Allows a user to send a command to a specified server.', 'desc'=> 'Allow sending of a command to a running server.',
], ],
'view' => [
'title' => 'Show Single Server',
'description' => 'Allows viewing details about a specific server including the daemon_token as well as current process information.',
], ],
],
'admin' => [
'server_header' => 'Server Control',
'server' => [
'list' => [ 'list' => [
'title' => 'List Servers', 'title' => 'List Servers',
'description' => 'Allows listing of all servers currently on the system.', 'desc' => 'Allows listing of all servers currently on the system.',
], ],
'create' => [ 'view' => [
'title' => 'Create Server', 'title' => 'View Server',
'description' => 'Allows creating a new server on the system.', 'desc' => 'Allows view of single server including service and details.',
],
'config' => [
'title' => 'Update Configuration',
'description' => 'Allows modifying server config (name, owner, and access token).',
],
'build' => [
'title' => 'Update Build',
'description' => 'Allows modifying a server\'s build parameters such as memory, CPU, and disk space along with assigned and default IPs.',
],
'suspend' => [
'title' => 'Suspend Server',
'description' => 'Allows suspending a server instance.',
],
'unsuspend' => [
'title' => 'Unsuspend Server',
'description' => 'Allows unsuspending a server instance.',
], ],
'delete' => [ 'delete' => [
'title' => 'Delete Server', 'title' => 'Delete Server',
'description' => 'Allows deleting a server.', 'desc' => 'Allows deletion of a server from the system.',
],
'create' => [
'title' => 'Create Server',
'desc' => 'Allows creation of a new server on the system.',
],
'edit-details' => [
'title' => 'Edit Server Details',
'desc' => 'Allows editing of server details such as name, owner, description, and secret key.',
],
'edit-container' => [
'title' => 'Edit Server Container',
'desc' => 'Allows for modification of the docker container the server runs in.',
],
'suspend' => [
'title' => 'Suspend Server',
'desc' => 'Allows for the suspension and unsuspension of a given server.',
],
'install' => [
'title' => 'Toggle Install Status',
'desc' => '',
],
'rebuild' => [
'title' => 'Rebuild Server',
'desc' => '',
],
'edit-build' => [
'title' => 'Edit Server Build',
'desc' => 'Allows editing of server build setting such as CPU and memory allocations.',
],
'edit-startup' => [
'title' => 'Edit Server Startup',
'desc' => 'Allows modification of server startup commands and parameters.',
], ],
], ],
'service_management' => [ 'location_header' => 'Location Control',
'title' => 'Service Management', 'location' => [
'list' => [
'title' => 'List Services',
'description' => 'Allows listing of all services configured on the system.',
],
'view' => [
'title' => 'List Single Service',
'description' => 'Allows listing details about each service on the system including service options and variables.',
],
],
'location_management' => [
'title' => 'Location Management',
'list' => [ 'list' => [
'title' => 'List Locations', 'title' => 'List Locations',
'description' => 'Allows listing all locations and thier associated nodes.', 'desc' => 'Allows listing all locations and thier associated nodes.',
],
],
'node_header' => 'Node Control',
'node' => [
'list' => [
'title' => 'List Nodes',
'desc' => 'Allows listing of all nodes currently on the system.',
],
'view' => [
'title' => 'View Node',
'desc' => 'llows viewing details about a specific node including active services.',
],
'view-config' => [
'title' => 'View Node Configuration',
'desc' => 'Danger. This allows the viewing of the node configuration file used by the daemon, and exposes secret daemon tokens.',
],
'create' => [
'title' => 'Create Node',
'desc' => 'Allows creating a new node on the system.',
],
'delete' => [
'title' => 'Delete Node',
'desc' => 'Allows deletion of a node from the system.',
],
],
'user_header' => 'User Control',
'user' => [
'list' => [
'title' => 'List Users',
'desc' => 'Allows listing of all users currently on the system.',
],
'view' => [
'title' => 'View User',
'desc' => 'Allows viewing details about a specific user including active services.',
],
'create' => [
'title' => 'Create User',
'desc' => 'Allows creating a new user on the system.',
],
'edit' => [
'title' => 'Update User',
'desc' => 'Allows modification of user details.',
],
'delete' => [
'title' => 'Delete User',
'desc' => 'Allows deleting a user.',
],
],
'service_header' => 'Service Control',
'service' => [
'list' => [
'title' => 'List Services',
'desc' => 'Allows listing of all services configured on the system.',
],
'view' => [
'title' => 'View Service',
'desc' => 'Allows listing details about each service on the system including service options and variables.',
],
],
'option_header' => 'Option Control',
'option' => [
'list' => [
'title' => 'List Options',
'desc' => '',
],
'view' => [
'title' => 'View Option',
'desc' => '',
],
],
'pack_header' => 'Pack Control',
'pack' => [
'list' => [
'title' => 'List Packs',
'desc' => '',
],
'view' => [
'title' => 'View Pack',
'desc' => '',
],
], ],
], ],
], ],

View file

@ -47,8 +47,8 @@
@endsection @endsection
@section('content') @section('content')
<form action="{{ route('account.api.new') }}" method="POST">
<div class="row"> <div class="row">
<form action="{{ route('account.api.new') }}" method="POST" id="permsForm">
<div class="col-xs-12"> <div class="col-xs-12">
<div class="box"> <div class="box">
<div class="box-header with-border"> <div class="box-header with-border">
@ -75,292 +75,70 @@
</div> </div>
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
{!! csrf_field() !!}
<button class="btn btn-success pull-right">@lang('strings.create') &rarr;</button> <button class="btn btn-success pull-right">@lang('strings.create') &rarr;</button>
</div> </div>
</div> </div>
<div class="text-right">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-xs-12 col-lg-6"> <div class="row">
<div class="box"> @foreach($permissions['user'] as $block => $perms)
<div class="col-sm-12">
<div class="box box-primary">
<div class="box-header with-border"> <div class="box-header with-border">
<div class="box-title">@lang('base.api.new.base.title')</div> <h3 class="box-title">@lang('base.api.permissions.user.' . $block . '_header')</h3>
</div> </div>
<div class="box-body"> <div class="box-body">
@foreach($perms as $permission)
<div class="form-group"> <div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom"> <div class="checkbox checkbox-primary no-margin-bottom">
<input id="user:*" name="permissions[]" type="checkbox" value="user:*"> <input id="{{ 'user.' . $block . '-' . $permission }}" name="permissions[]" type="checkbox" value="{{ $block . '-' . $permission }}"/>
<label for="user:*" class="strong"> <label for="{{ 'user.' . $block . '-' . $permission }}" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.base.information.title') @lang('base.api.permissions.user.' . $block . '.' . $permission . '.title')
</label> </label>
</div> </div>
<p class="text-muted small">@lang('base.api.new.base.information.description')</p> <p class="text-muted small">@lang('base.api.permissions.user.' . $block . '.' . $permission . '.desc')</p>
</div> </div>
</div> @endforeach
</div>
@if(Auth::user()->isRootAdmin())
<div class="box">
<div class="box-header with-border">
<div class="box-title">@lang('base.api.new.user_management.title')</div>
</div>
<div class="box-body">
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:users.list" name="adminPermissions[]" type="checkbox" value="admin:users.list">
<label for="admin:users.list" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.user_management.list.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.user_management.list.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:users.create" name="adminPermissions[]" type="checkbox" value="admin:users.create">
<label for="admin:users.create" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.user_management.create.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.user_management.create.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:users.view" name="adminPermissions[]" type="checkbox" value="admin:users.view">
<label for="admin:users.view" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.user_management.view.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.user_management.view.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:users.update" name="adminPermissions[]" type="checkbox" value="admin:users.update">
<label for="admin:users.update" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.user_management.update.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.user_management.update.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-danger no-margin-bottom">
<input id="admin:users.delete" name="adminPermissions[]" type="checkbox" value="admin:users.delete">
<label for="admin:users.delete" class="strong">
<span class="label label-danger">DELETE</span> @lang('base.api.new.user_management.delete.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.user_management.delete.description')</p>
</div>
</div>
</div>
<div class="box">
<div class="box-header with-border">
<div class="box-title">@lang('base.api.new.node_management.title')</div>
</div>
<div class="box-body">
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:nodes.list" name="adminPermissions[]" type="checkbox" value="admin:nodes.list">
<label for="admin:nodes.list" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.node_management.list.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.node_management.list.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:nodes.create" name="adminPermissions[]" type="checkbox" value="admin:nodes.create">
<label for="admin:nodes.create" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.node_management.create.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.node_management.create.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:nodes.view" name="adminPermissions[]" type="checkbox" value="admin:nodes.view">
<label for="admin:nodes.view" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.node_management.view.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.node_management.view.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:nodes.allocations" name="adminPermissions[]" type="checkbox" value="admin:nodes.allocations">
<label for="admin:nodes.allocations" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.node_management.allocations.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.node_management.allocations.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-danger no-margin-bottom">
<input id="admin:nodes.delete" name="adminPermissions[]" type="checkbox" value="admin:nodes.delete">
<label for="admin:nodes.delete" class="strong">
<span class="label label-danger">DELETE</span> @lang('base.api.new.node_management.delete.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.node_management.delete.description')</p>
</div>
</div>
</div>
<div class="box">
<div class="box-header with-border">
<div class="box-title">@lang('base.api.new.location_management.title')</div>
</div>
<div class="box-body">
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:locations.list" name="adminPermissions[]" type="checkbox" value="admin:locations.list">
<label for="admin:locations.list" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.location_management.list.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.location_management.list.description')</p>
</div> </div>
</div> </div>
</div> </div>
@if ($loop->iteration % 2 === 0)
<div class="clearfix visible-lg-block visible-md-block visible-sm-block"></div>
@endif @endif
@endforeach
</div> </div>
<div class="col-xs-12 col-lg-6"> <div class="row">
<div class="box"> @foreach($permissions['admin'] as $block => $perms)
<div class="col-lg-4 col-sm-6">
<div class="box box-danger">
<div class="box-header with-border"> <div class="box-header with-border">
<div class="box-title">@lang('base.api.new.server_management.title')</div> <h3 class="box-title">@lang('base.api.permissions.admin.' . $block . '_header')</h3>
</div> </div>
<div class="box-body"> <div class="box-body">
@foreach($perms as $permission)
<div class="form-group"> <div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom"> <div class="checkbox {{ $permission === 'delete' ? 'checkbox-danger' : 'checkbox-primary' }} no-margin-bottom">
<input id="user:server" name="permissions[]" type="checkbox" value="user:server"> <input id="{{ $block . '-' . $permission }}" name="admin_permissions[]" type="checkbox" value="{{ $block . '-' . $permission }}"/>
<label for="user:server" class="strong"> <label for="{{ $block . '-' . $permission }}" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.server_management.server.title') @lang('base.api.permissions.admin.' . $block . '.' . $permission . '.title')
</label> </label>
</div> </div>
<p class="text-muted small">@lang('base.api.new.server_management.server.description')</p> <p class="text-muted small">@lang('base.api.permissions.admin.' . $block . '.' . $permission . '.desc')</p>
</div> </div>
<div class="form-group"> @endforeach
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="user:server.power" name="permissions[]" type="checkbox" value="user:server.power">
<label for="user:server.power" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.server_management.power.title')
</label>
</div> </div>
<p class="text-muted small">@lang('base.api.new.server_management.power.description')</p>
</div> </div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="user:server.command" name="permissions[]" type="checkbox" value="user:server.command">
<label for="user:server.command" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.server_management.command.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.command.description')</p>
</div>
@if(Auth::user()->isRootAdmin())
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:servers.view" name="adminPermissions[]" type="checkbox" value="admin:servers.view">
<label for="admin:servers.view" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.server_management.view.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.view.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:servers.list" name="adminPermissions[]" type="checkbox" value="admin:servers.list">
<label for="admin:servers.list" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.server_management.list.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.list.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:servers.create" name="adminPermissions[]" type="checkbox" value="admin:servers.create">
<label for="admin:servers.create" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.server_management.create.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.create.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:servers.config" name="adminPermissions[]" type="checkbox" value="admin:servers.config">
<label for="admin:servers.config" class="strong">
<span class="label label-default">PATCH</span> @lang('base.api.new.server_management.config.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.config.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:servers.build" name="adminPermissions[]" type="checkbox" value="admin:servers.build">
<label for="admin:servers.build" class="strong">
<span class="label label-default">PATCH</span> @lang('base.api.new.server_management.build.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.build.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-warning no-margin-bottom">
<input id="admin:servers.suspend" name="adminPermissions[]" type="checkbox" value="admin:servers.suspend">
<label for="admin:servers.suspend" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.server_management.suspend.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.suspend.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-warning no-margin-bottom">
<input id="admin:servers.unsuspend" name="adminPermissions[]" type="checkbox" value="admin:servers.unsuspend">
<label for="admin:servers.unsuspend" class="strong">
<span class="label label-default">POST</span> @lang('base.api.new.server_management.unsuspend.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.unsuspend.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-danger no-margin-bottom">
<input id="admin:servers.delete" name="adminPermissions[]" type="checkbox" value="admin:servers.delete">
<label for="admin:servers.delete" class="strong">
<span class="label label-danger">DELETE</span> @lang('base.api.new.server_management.delete.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.delete.description')</p>
</div> </div>
@if ($loop->iteration % 3 === 0)
<div class="clearfix visible-lg-block"></div>
@endif @endif
</div> @if ($loop->iteration % 2 === 0)
</div> <div class="clearfix visible-md-block visible-sm-block"></div>
@if(Auth::user()->isRootAdmin())
<div class="box">
<div class="box-header with-border">
<div class="box-title">@lang('base.api.new.service_management.title')</div>
</div>
<div class="box-body">
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:services.list" name="adminPermissions[]" type="checkbox" value="admin:services.list">
<label for="admin:services.list" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.service_management.list.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.service_management.list.description')</p>
</div>
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="admin:services.view" name="adminPermissions[]" type="checkbox" value="admin:services.view">
<label for="admin:services.view" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.service_management.view.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.service_management.view.description')</p>
</div>
</div>
</div>
@endif @endif
@endforeach
</div> </div>
{!! csrf_field() !!}
</form> </form>
</div>
@endsection @endsection

View file

@ -95,6 +95,8 @@ Route::group(['prefix' => '/users'], function () {
Route::post('/', 'UserController@store'); Route::post('/', 'UserController@store');
Route::put('/{id}', 'UserController@update');
Route::delete('/{id}', 'UserController@delete'); Route::delete('/{id}', 'UserController@delete');
}); });

View file

@ -51,9 +51,9 @@ Route::group(['prefix' => 'account'], function () {
*/ */
Route::group(['prefix' => 'account/api'], function () { Route::group(['prefix' => 'account/api'], function () {
Route::get('/', 'APIController@index')->name('account.api'); Route::get('/', 'APIController@index')->name('account.api');
Route::get('/new', 'APIController@new')->name('account.api.new'); Route::get('/new', 'APIController@create')->name('account.api.new');
Route::post('/new', 'APIController@save'); Route::post('/new', 'APIController@store');
Route::delete('/revoke/{key}', 'APIController@revoke')->name('account.api.revoke'); Route::delete('/revoke/{key}', 'APIController@revoke')->name('account.api.revoke');
}); });