1
1
mirror of https://github.com/pterodactyl/panel.git synced 2024-11-25 10:32:31 +01:00

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;
}
});
}
}

View File

@ -46,122 +46,162 @@ return [
'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.',
],
'base' => [
'title' => 'Base Information',
'information' => [
'title' => 'Base Information',
'description' => 'Returns a listing of all servers that this account has access to.',
],
],
'user_management' => [
'title' => 'User Management',
'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',
],
'permissions' => [
'user' => [
'server_header' => 'User Server Permissions',
'server' => [
'title' => 'Server Info',
'description' => 'Allows access to viewing information about a single server including current stats and allocations.',
],
'power' => [
'title' => 'Server Power',
'description' => 'Allows access to control server power status.',
],
'command' => [
'title' => 'Send Command',
'description' => 'Allows a user to send a command to a specified server.',
],
'view' => [
'title' => 'Show Single Server',
'description' => 'Allows viewing details about a specific server including the daemon_token as well as current process information.',
],
'list' => [
'title' => 'List Servers',
'description' => 'Allows listing of all servers currently on the system.',
],
'create' => [
'title' => 'Create Server',
'description' => 'Allows creating a new server on the system.',
],
'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' => [
'title' => 'Delete Server',
'description' => 'Allows deleting a server.',
'list' => [
'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' => [
'title' => 'Toggle Power',
'desc'=> 'Allow toggling of power status for a server.',
],
'command' => [
'title' => 'Send Command',
'desc'=> 'Allow sending of a command to a running server.',
],
],
],
'service_management' => [
'title' => 'Service Management',
'list' => [
'title' => 'List Services',
'description' => 'Allows listing of all services configured on the system.',
'admin' => [
'server_header' => 'Server Control',
'server' => [
'list' => [
'title' => 'List Servers',
'desc' => 'Allows listing of all servers currently on the system.',
],
'view' => [
'title' => 'View Server',
'desc' => 'Allows view of single server including service and details.',
],
'delete' => [
'title' => 'Delete 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.',
],
],
'view' => [
'title' => 'List Single Service',
'description' => 'Allows listing details about each service on the system including service options and variables.',
'location_header' => 'Location Control',
'location' => [
'list' => [
'title' => 'List Locations',
'desc' => 'Allows listing all locations and thier associated nodes.',
],
],
],
'location_management' => [
'title' => 'Location Management',
'list' => [
'title' => 'List Locations',
'description' => '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
@section('content')
<div class="row">
<form action="{{ route('account.api.new') }}" method="POST" id="permsForm">
<form action="{{ route('account.api.new') }}" method="POST">
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header with-border">
@ -75,292 +75,70 @@
</div>
</div>
<div class="col-xs-6">
{!! csrf_field() !!}
<button class="btn btn-success pull-right">@lang('strings.create') &rarr;</button>
</div>
</div>
<div class="text-right">
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-lg-6">
<div class="box">
<div class="box-header with-border">
<div class="box-title">@lang('base.api.new.base.title')</div>
</div>
<div class="box-body">
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="user:*" name="permissions[]" type="checkbox" value="user:*">
<label for="user:*" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.base.information.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.base.information.description')</p>
</div>
<div class="row">
@foreach($permissions['user'] as $block => $perms)
<div class="col-sm-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">@lang('base.api.permissions.user.' . $block . '_header')</h3>
</div>
<div class="box-body">
@foreach($perms as $permission)
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="{{ 'user.' . $block . '-' . $permission }}" name="permissions[]" type="checkbox" value="{{ $block . '-' . $permission }}"/>
<label for="{{ 'user.' . $block . '-' . $permission }}" class="strong">
@lang('base.api.permissions.user.' . $block . '.' . $permission . '.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.permissions.user.' . $block . '.' . $permission . '.desc')</p>
</div>
@endforeach
</div>
</div>
</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>
@if ($loop->iteration % 2 === 0)
<div class="clearfix visible-lg-block visible-md-block visible-sm-block"></div>
@endif
</div>
<div class="col-xs-12 col-lg-6">
<div class="box">
<div class="box-header with-border">
<div class="box-title">@lang('base.api.new.server_management.title')</div>
</div>
<div class="box-body">
<div class="form-group">
<div class="checkbox checkbox-primary no-margin-bottom">
<input id="user:server" name="permissions[]" type="checkbox" value="user:server">
<label for="user:server" class="strong">
<span class="label label-default">GET</span> @lang('base.api.new.server_management.server.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.new.server_management.server.description')</p>
</div>
<div class="form-group">
<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>
<p class="text-muted small">@lang('base.api.new.server_management.power.description')</p>
</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>
@endif
</div>
</div>
@if(Auth::user()->isRootAdmin())
<div class="box">
@endforeach
</div>
<div class="row">
@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-title">@lang('base.api.new.service_management.title')</div>
<h3 class="box-title">@lang('base.api.permissions.admin.' . $block . '_header')</h3>
</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>
@foreach($perms as $permission)
<div class="form-group">
<div class="checkbox {{ $permission === 'delete' ? 'checkbox-danger' : 'checkbox-primary' }} no-margin-bottom">
<input id="{{ $block . '-' . $permission }}" name="admin_permissions[]" type="checkbox" value="{{ $block . '-' . $permission }}"/>
<label for="{{ $block . '-' . $permission }}" class="strong">
@lang('base.api.permissions.admin.' . $block . '.' . $permission . '.title')
</label>
</div>
<p class="text-muted small">@lang('base.api.permissions.admin.' . $block . '.' . $permission . '.desc')</p>
</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>
@endforeach
</div>
</div>
</div>
@if ($loop->iteration % 3 === 0)
<div class="clearfix visible-lg-block"></div>
@endif
</div>
{!! csrf_field() !!}
</form>
</div>
@if ($loop->iteration % 2 === 0)
<div class="clearfix visible-md-block visible-sm-block"></div>
@endif
@endforeach
</div>
</form>
@endsection

View File

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

View File

@ -51,9 +51,9 @@ Route::group(['prefix' => 'account'], function () {
*/
Route::group(['prefix' => 'account/api'], function () {
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');
});