db_hosts: add ability to link more than one node
This commit is contained in:
parent
79d80e8c22
commit
e123367f40
11 changed files with 226 additions and 35 deletions
|
@ -12,6 +12,7 @@ use Pterodactyl\Transformers\Api\Application\DatabaseHostTransformer;
|
|||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\GetDatabaseRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\GetDatabasesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\DatabaseNodesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\StoreDatabaseRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\UpdateDatabaseRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\DeleteDatabaseRequest;
|
||||
|
@ -135,4 +136,48 @@ class DatabaseController extends ApplicationApiController
|
|||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* ?
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Databases\DatabaseNodesRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addNodes(DatabaseNodesRequest $request, DatabaseHost $databaseHost): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$nodes = $data['nodes'] ?? [];
|
||||
if (count($nodes) > 0) {
|
||||
$databaseHost->nodes()->syncWithoutDetaching($nodes);
|
||||
}
|
||||
|
||||
return $this->fractal->item($databaseHost)
|
||||
->transformWith($this->getTransformer(DatabaseHostTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* ?
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Databases\DatabaseNodesRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function deleteNodes(DatabaseNodesRequest $request, DatabaseHost $databaseHost): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$nodes = $data['nodes'] ?? [];
|
||||
if (count($nodes) > 0) {
|
||||
$databaseHost->nodes()->detach($nodes);
|
||||
}
|
||||
|
||||
return $this->fractal->item($databaseHost)
|
||||
->transformWith($this->getTransformer(DatabaseHostTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ use Pterodactyl\Transformers\Api\Application\MountTransformer;
|
|||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\GetMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\GetMountsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\MountEggsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\MountNodesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\StoreMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\UpdateMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\DeleteMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\MountAddEggsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\MountAddNodesRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class MountController extends ApplicationApiController
|
||||
|
@ -123,12 +123,12 @@ class MountController extends ApplicationApiController
|
|||
/**
|
||||
* ?
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountAddEggsRequest $request
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountEggsRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addEggs(MountAddEggsRequest $request, Mount $mount): array
|
||||
public function addEggs(MountEggsRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
|
@ -145,12 +145,12 @@ class MountController extends ApplicationApiController
|
|||
/**
|
||||
* ?
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountAddNodesRequest $request
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountNodesRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addNodes(MountAddNodesRequest $request, Mount $mount): array
|
||||
public function addNodes(MountNodesRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
|
@ -167,12 +167,12 @@ class MountController extends ApplicationApiController
|
|||
/**
|
||||
* ?
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountAddEggsRequest $request
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountEggsRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function deleteEggs(MountAddEggsRequest $request, Mount $mount): array
|
||||
public function deleteEggs(MountEggsRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
|
@ -189,12 +189,12 @@ class MountController extends ApplicationApiController
|
|||
/**
|
||||
* ?
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountAddNodesRequest $request
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Mounts\MountNodesRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function deleteNodes(MountAddNodesRequest $request, Mount $mount): array
|
||||
public function deleteNodes(MountNodesRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Requests\Api\Application\Databases;
|
||||
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class DatabaseNodesRequest extends ApplicationApiRequest
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $resource = AdminAcl::RESOURCE_DATABASE_HOSTS;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $permission = AdminAcl::WRITE;
|
||||
|
||||
/**
|
||||
* ?
|
||||
*
|
||||
* @param array|null $rules
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(array $rules = null): array
|
||||
{
|
||||
return $rules ?? ['nodes' => 'required|exists:nodes,id'];
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ namespace Pterodactyl\Http\Requests\Api\Application\Mounts;
|
|||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class MountAddEggsRequest extends ApplicationApiRequest
|
||||
class MountEggsRequest extends ApplicationApiRequest
|
||||
{
|
||||
/**
|
||||
* @var string
|
|
@ -5,7 +5,7 @@ namespace Pterodactyl\Http\Requests\Api\Application\Mounts;
|
|||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class MountAddNodesRequest extends ApplicationApiRequest
|
||||
class MountNodesRequest extends ApplicationApiRequest
|
||||
{
|
||||
/**
|
||||
* @var string
|
|
@ -8,12 +8,11 @@ namespace Pterodactyl\Models;
|
|||
* @property string $host
|
||||
* @property int $port
|
||||
* @property string $username
|
||||
* @property int $node_id
|
||||
* @property \Carbon\Carbon|null $created_at
|
||||
* @property \Carbon\Carbon|null $updated_at
|
||||
*
|
||||
* @property \Pterodactyl\Models\Node|null $node
|
||||
* @property \Pterodactyl\Models\Database[]|\Illuminate\Database\Eloquent\Collection $databases
|
||||
* @property \Pterodactyl\Models\Node[]|\Illuminate\Database\Eloquent\Collection $nodes
|
||||
*/
|
||||
class DatabaseHost extends Model
|
||||
{
|
||||
|
@ -43,7 +42,7 @@ class DatabaseHost extends Model
|
|||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'host', 'port', 'username', 'password', 'max_databases', 'node_id',
|
||||
'name', 'host', 'port', 'username', 'password', 'max_databases',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -54,7 +53,6 @@ class DatabaseHost extends Model
|
|||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'max_databases' => 'integer',
|
||||
'node_id' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -68,21 +66,10 @@ class DatabaseHost extends Model
|
|||
'port' => 'required|numeric|between:1,65535',
|
||||
'username' => 'required|string|max:32',
|
||||
'password' => 'nullable|string',
|
||||
'node_id' => 'sometimes|nullable|integer|exists:nodes,id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets the node associated with a database host.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function node()
|
||||
{
|
||||
return $this->belongsTo(Node::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the databases associated with this host.
|
||||
* Gets the databases associated with a database host.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
|
@ -90,4 +77,14 @@ class DatabaseHost extends Model
|
|||
{
|
||||
return $this->hasMany(Database::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nodes associated with a database host.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function nodes()
|
||||
{
|
||||
return $this->belongsToMany(Node::class);
|
||||
}
|
||||
}
|
||||
|
|
27
app/Models/DatabaseHostNode.php
Normal file
27
app/Models/DatabaseHostNode.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property int $node_id
|
||||
* @property int $database_host_id
|
||||
*/
|
||||
class DatabaseHostNode extends Model
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'database_host_node';
|
||||
|
||||
/**
|
||||
* @var null
|
||||
*/
|
||||
protected $primaryKey = null;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Pterodactyl\Transformers\Api\Application;
|
||||
|
||||
use Cake\Chronos\Chronos;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Pterodactyl\Models\Database;
|
||||
use Pterodactyl\Models\DatabaseHost;
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
|
@ -12,9 +13,7 @@ class DatabaseHostTransformer extends BaseTransformer
|
|||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'databases',
|
||||
];
|
||||
protected $availableIncludes = ['databases', 'nodes'];
|
||||
|
||||
/**
|
||||
* Return the resource name for the JSONAPI output.
|
||||
|
@ -68,6 +67,36 @@ class DatabaseHostTransformer extends BaseTransformer
|
|||
|
||||
$model->loadMissing('databases');
|
||||
|
||||
return $this->collection($model->getRelation('databases'), $this->makeTransformer(ServerDatabaseTransformer::class), Database::RESOURCE_NAME);
|
||||
return $this->collection(
|
||||
$model->getRelation('databases'),
|
||||
$this->makeTransformer(ServerDatabaseTransformer::class),
|
||||
Database::RESOURCE_NAME
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the nodes associated with this mount.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
*
|
||||
* @return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
|
||||
* @throws \Pterodactyl\Exceptions\Transformer\InvalidTransformerLevelException
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function includeNodes(DatabaseHost $model)
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_NODES)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
$model->loadMissing('nodes');
|
||||
|
||||
return $this->collection(
|
||||
$model->getRelation('nodes'),
|
||||
$this->makeTransformer(NodeTransformer::class),
|
||||
Node::RESOURCE_NAME
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace Pterodactyl\Transformers\Api\Application;
|
||||
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Pterodactyl\Models\Mount;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class MountTransformer extends BaseTransformer
|
||||
|
@ -64,7 +67,7 @@ class MountTransformer extends BaseTransformer
|
|||
return $this->collection(
|
||||
$mount->getRelation('eggs'),
|
||||
$this->makeTransformer(EggTransformer::class),
|
||||
'egg',
|
||||
Egg::RESOURCE_NAME
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -88,7 +91,7 @@ class MountTransformer extends BaseTransformer
|
|||
return $this->collection(
|
||||
$mount->getRelation('nodes'),
|
||||
$this->makeTransformer(NodeTransformer::class),
|
||||
'node',
|
||||
Node::RESOURCE_NAME
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -112,7 +115,7 @@ class MountTransformer extends BaseTransformer
|
|||
return $this->collection(
|
||||
$mount->getRelation('servers'),
|
||||
$this->makeTransformer(ServerTransformer::class),
|
||||
'server',
|
||||
Server::RESOURCE_NAME
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddDatabaseHostNodeTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('database_host_node', function (Blueprint $table) {
|
||||
$table->integer('node_id')->unique();
|
||||
$table->integer('database_host_id');
|
||||
|
||||
$table->unique(['node_id', 'database_host_id']);
|
||||
});
|
||||
|
||||
DB::transaction(function () {
|
||||
foreach (DB::select('SELECT id, node_id FROM database_hosts') as $datum) {
|
||||
if (! is_null($datum->node_id)) {
|
||||
DB::insert('INSERT INTO database_host_node (node_id, database_host_id) VALUES (?, ?)', [
|
||||
$datum->node_id,
|
||||
$datum->id
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Schema::table('database_hosts', function (Blueprint $table) {
|
||||
$table->dropForeign(['node_id']);
|
||||
$table->dropColumn('node_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('database_hosts', function (Blueprint $table) {
|
||||
$table->integer('node_id')->unsigned()->nullable()->after('max_databases');
|
||||
|
||||
$table->foreign('node_id')->references('id')->on('nodes')->onDelete('set null');
|
||||
});
|
||||
|
||||
Schema::dropIfExists('database_host_node');
|
||||
}
|
||||
}
|
|
@ -18,9 +18,12 @@ Route::group(['prefix' => '/databases'], function () {
|
|||
|
||||
Route::post('/', 'Databases\DatabaseController@store');
|
||||
|
||||
Route::put('/{databaseHost}/nodes', 'Databases\DatabaseController@addNodes');
|
||||
|
||||
Route::patch('/{databaseHost}', 'Databases\DatabaseController@update');
|
||||
|
||||
Route::delete('/{databaseHost}', 'Databases\DatabaseController@delete');
|
||||
Route::delete('/{databaseHost}/nodes', 'Databases\DatabaseController@deleteNodes');
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue