Add support for external_id on servers, closes #975
This commit is contained in:
parent
f655188c58
commit
633bba6d6e
11 changed files with 73 additions and 15 deletions
|
@ -10,6 +10,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Adds ability to include egg variables on an API request.
|
* Adds ability to include egg variables on an API request.
|
||||||
|
* Added `external_id` column to servers that allows for easier linking with external services such as WHMCS.
|
||||||
|
|
||||||
## v0.7.1 (Derelict Dermodactylus)
|
## v0.7.1 (Derelict Dermodactylus)
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -406,7 +406,7 @@ class ServersController extends Controller
|
||||||
public function setDetails(Request $request, Server $server)
|
public function setDetails(Request $request, Server $server)
|
||||||
{
|
{
|
||||||
$this->detailsModificationService->handle($server, $request->only([
|
$this->detailsModificationService->handle($server, $request->only([
|
||||||
'owner_id', 'name', 'description',
|
'owner_id', 'external_id', 'name', 'description',
|
||||||
]));
|
]));
|
||||||
|
|
||||||
$this->alert->success(trans('admin/server.alerts.details_updated'))->flash();
|
$this->alert->success(trans('admin/server.alerts.details_updated'))->flash();
|
||||||
|
|
|
@ -31,6 +31,7 @@ class StoreServerRequest extends ApplicationApiRequest
|
||||||
$rules = Server::getCreateRules();
|
$rules = Server::getCreateRules();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'external_id' => $rules['external_id'],
|
||||||
'name' => $rules['name'],
|
'name' => $rules['name'],
|
||||||
'description' => array_merge(['nullable'], $rules['description']),
|
'description' => array_merge(['nullable'], $rules['description']),
|
||||||
'user' => $rules['owner_id'],
|
'user' => $rules['owner_id'],
|
||||||
|
|
|
@ -53,6 +53,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected static $applicationRules = [
|
protected static $applicationRules = [
|
||||||
|
'external_id' => 'sometimes',
|
||||||
'owner_id' => 'required',
|
'owner_id' => 'required',
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'memory' => 'required',
|
'memory' => 'required',
|
||||||
|
@ -74,6 +75,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected static $dataIntegrityRules = [
|
protected static $dataIntegrityRules = [
|
||||||
|
'external_id' => 'nullable|string|between:1,191|unique:servers',
|
||||||
'owner_id' => 'integer|exists:users,id',
|
'owner_id' => 'integer|exists:users,id',
|
||||||
'name' => 'string|min:1|max:255',
|
'name' => 'string|min:1|max:255',
|
||||||
'node_id' => 'exists:nodes,id',
|
'node_id' => 'exists:nodes,id',
|
||||||
|
@ -122,13 +124,14 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $searchableColumns = [
|
protected $searchableColumns = [
|
||||||
'name' => 50,
|
'name' => 100,
|
||||||
'uuidShort' => 10,
|
'uuid' => 80,
|
||||||
'uuid' => 10,
|
'uuidShort' => 80,
|
||||||
'pack.name' => 5,
|
'external_id' => 50,
|
||||||
'user.email' => 20,
|
'user.email' => 40,
|
||||||
'user.username' => 20,
|
'user.username' => 30,
|
||||||
'node.name' => 10,
|
'node.name' => 10,
|
||||||
|
'pack.name' => 10,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -69,6 +69,7 @@ class DetailsModificationService
|
||||||
$this->connection->beginTransaction();
|
$this->connection->beginTransaction();
|
||||||
|
|
||||||
$response = $this->repository->setFreshModel($this->getUpdatedModel())->update($server->id, [
|
$response = $this->repository->setFreshModel($this->getUpdatedModel())->update($server->id, [
|
||||||
|
'external_id' => array_get($data, 'external_id'),
|
||||||
'owner_id' => array_get($data, 'owner_id'),
|
'owner_id' => array_get($data, 'owner_id'),
|
||||||
'name' => array_get($data, 'name'),
|
'name' => array_get($data, 'name'),
|
||||||
'description' => array_get($data, 'description') ?? '',
|
'description' => array_get($data, 'description') ?? '',
|
||||||
|
|
|
@ -211,6 +211,7 @@ class ServerCreationService
|
||||||
private function createModel(array $data): Server
|
private function createModel(array $data): Server
|
||||||
{
|
{
|
||||||
return $this->repository->create([
|
return $this->repository->create([
|
||||||
|
'external_id' => array_get($data, 'external_id'),
|
||||||
'uuid' => Uuid::uuid4()->toString(),
|
'uuid' => Uuid::uuid4()->toString(),
|
||||||
'uuidShort' => str_random(8),
|
'uuidShort' => str_random(8),
|
||||||
'node_id' => array_get($data, 'node_id'),
|
'node_id' => array_get($data, 'node_id'),
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Transformers\Api\Application;
|
namespace Pterodactyl\Transformers\Api\Application;
|
||||||
|
|
||||||
use Cake\Chronos\Chronos;
|
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||||
use Pterodactyl\Services\Servers\EnvironmentService;
|
use Pterodactyl\Services\Servers\EnvironmentService;
|
||||||
|
@ -63,6 +62,7 @@ class ServerTransformer extends BaseTransformer
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $server->getKey(),
|
'id' => $server->getKey(),
|
||||||
|
'external_id' => $server->external_id,
|
||||||
'uuid' => $server->uuid,
|
'uuid' => $server->uuid,
|
||||||
'identifier' => $server->uuidShort,
|
'identifier' => $server->uuidShort,
|
||||||
'name' => $server->name,
|
'name' => $server->name,
|
||||||
|
@ -87,8 +87,8 @@ class ServerTransformer extends BaseTransformer
|
||||||
'installed' => (int) $server->installed === 1,
|
'installed' => (int) $server->installed === 1,
|
||||||
'environment' => $this->environmentService->handle($server),
|
'environment' => $this->environmentService->handle($server),
|
||||||
],
|
],
|
||||||
'created_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $server->created_at)->setTimezone('UTC')->toIso8601String(),
|
$server->getUpdatedAtColumn() => $this->formatTimestamp($server->updated_at),
|
||||||
'updated_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $server->updated_at)->setTimezone('UTC')->toIso8601String(),
|
$server->getCreatedAtColumn() => $this->formatTimestamp($server->created_at),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddExternalIdColumnToServersTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('servers', function (Blueprint $table) {
|
||||||
|
$table->string('external_id')->after('id')->nullable()->unique();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('servers', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('external_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,12 +47,17 @@
|
||||||
<form action="{{ route('admin.servers.view.details', $server->id) }}" method="POST">
|
<form action="{{ route('admin.servers.view.details', $server->id) }}" method="POST">
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name" class="control-label">Server Name</label>
|
<label for="name" class="control-label">Server Name <span class="field-required"></span></label>
|
||||||
<input type="text" name="name" value="{{ old('name', $server->name) }}" class="form-control" />
|
<input type="text" name="name" value="{{ old('name', $server->name) }}" class="form-control" />
|
||||||
<p class="text-muted small">Character limits: <code>a-zA-Z0-9_-</code> and <code>[Space]</code> (max 35 characters).</p>
|
<p class="text-muted small">Character limits: <code>a-zA-Z0-9_-</code> and <code>[Space]</code> (max 35 characters).</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pUserId" class="control-label">Server Owner</label>
|
<label for="external_id" class="control-label">External Identifier</label>
|
||||||
|
<input type="text" name="external_id" value="{{ old('external_id', $server->external_id) }}" class="form-control" />
|
||||||
|
<p class="text-muted small">Leave empty to not assign an external identifier for this server. The external ID should be unique to this server and not be in use by any other servers.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="pUserId" class="control-label">Server Owner <span class="field-required"></span></label>
|
||||||
<select name="owner_id" class="form-control" id="pUserId">
|
<select name="owner_id" class="form-control" id="pUserId">
|
||||||
<option value="{{ $server->owner_id }}" selected>{{ $server->user->email }}</option>
|
<option value="{{ $server->owner_id }}" selected>{{ $server->user->email }}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -47,6 +47,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body table-responsive no-padding">
|
<div class="box-body table-responsive no-padding">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
|
<tr>
|
||||||
|
<td>Internal Identifier</td>
|
||||||
|
<td><code>{{ $server->id }}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>External Identifier</td>
|
||||||
|
@if(is_null($server->external_id))
|
||||||
|
<td><span class="label label-default">Not Set</span></td>
|
||||||
|
@else
|
||||||
|
<td><code>{{ $server->external_id }}</code></td>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>UUID / Docker Container ID</td>
|
<td>UUID / Docker Container ID</td>
|
||||||
<td><code>{{ $server->uuid }}</code></td>
|
<td><code>{{ $server->uuid }}</code></td>
|
||||||
|
@ -127,7 +139,7 @@
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="small-box bg-gray">
|
<div class="small-box bg-gray">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ str_limit($server->user->username, 8) }}</h3>
|
<h3>{{ str_limit($server->user->username, 16) }}</h3>
|
||||||
<p>Server Owner</p>
|
<p>Server Owner</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon"><i class="fa fa-user"></i></div>
|
<div class="icon"><i class="fa fa-user"></i></div>
|
||||||
|
@ -139,7 +151,7 @@
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="small-box bg-gray">
|
<div class="small-box bg-gray">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ str_limit($server->node->name, 8) }}</h3>
|
<h3>{{ str_limit($server->node->name, 16) }}</h3>
|
||||||
<p>Server Node</p>
|
<p>Server Node</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon"><i class="fa fa-codepen"></i></div>
|
<div class="icon"><i class="fa fa-codepen"></i></div>
|
||||||
|
|
|
@ -58,6 +58,7 @@ class DetailsModificationServiceTest extends TestCase
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
||||||
$this->repository->shouldReceive('setFreshModel')->once()->with(false)->andReturnSelf();
|
$this->repository->shouldReceive('setFreshModel')->once()->with(false)->andReturnSelf();
|
||||||
$this->repository->shouldReceive('update')->once()->with($server->id, [
|
$this->repository->shouldReceive('update')->once()->with($server->id, [
|
||||||
|
'external_id' => null,
|
||||||
'owner_id' => $data['owner_id'],
|
'owner_id' => $data['owner_id'],
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'description' => $data['description'],
|
'description' => $data['description'],
|
||||||
|
@ -95,11 +96,12 @@ class DetailsModificationServiceTest extends TestCase
|
||||||
'owner_id' => 1,
|
'owner_id' => 1,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data = ['owner_id' => 2, 'name' => 'New Name', 'description' => 'New Description'];
|
$data = ['owner_id' => 2, 'name' => 'New Name', 'description' => 'New Description', 'external_id' => 'abcd1234'];
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
||||||
$this->repository->shouldReceive('setFreshModel')->once()->with(false)->andReturnSelf();
|
$this->repository->shouldReceive('setFreshModel')->once()->with(false)->andReturnSelf();
|
||||||
$this->repository->shouldReceive('update')->once()->with($server->id, [
|
$this->repository->shouldReceive('update')->once()->with($server->id, [
|
||||||
|
'external_id' => 'abcd1234',
|
||||||
'owner_id' => $data['owner_id'],
|
'owner_id' => $data['owner_id'],
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'description' => $data['description'],
|
'description' => $data['description'],
|
||||||
|
|
Loading…
Reference in a new issue