Add initial go at user created databases for servers, still needs cleaning
This commit is contained in:
parent
87b96bdfc8
commit
07893effa3
11 changed files with 314 additions and 25 deletions
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Exceptions\Service\Database;
|
||||||
|
|
||||||
|
use Pterodactyl\Exceptions\PterodactylException;
|
||||||
|
|
||||||
|
class DatabaseClientFeatureNotEnabledException extends PterodactylException
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('Client database creation is not enabled in this Panel.');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Exceptions\Service\Database;
|
||||||
|
|
||||||
|
use Pterodactyl\Exceptions\DisplayException;
|
||||||
|
|
||||||
|
class NoSuitableDatabaseHostException extends DisplayException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* NoSuitableDatabaseHostException constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('No database host was found that meets the requirements for this server.');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Exceptions\Service\Database;
|
||||||
|
|
||||||
|
use Pterodactyl\Exceptions\DisplayException;
|
||||||
|
|
||||||
|
class TooManyDatabasesException extends DisplayException
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('Operation aborted: creating a new database would put this server over the defined limit.');
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,33 +5,64 @@ namespace Pterodactyl\Http\Controllers\Server;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Prologue\Alerts\AlertsMessageBag;
|
||||||
use Pterodactyl\Http\Controllers\Controller;
|
use Pterodactyl\Http\Controllers\Controller;
|
||||||
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
||||||
use Pterodactyl\Services\Databases\DatabasePasswordService;
|
use Pterodactyl\Services\Databases\DatabasePasswordService;
|
||||||
|
use Pterodactyl\Services\Databases\DeployServerDatabaseService;
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||||
|
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
||||||
|
use Pterodactyl\Http\Requests\Server\Database\StoreServerDatabaseRequest;
|
||||||
|
|
||||||
class DatabaseController extends Controller
|
class DatabaseController extends Controller
|
||||||
{
|
{
|
||||||
use JavascriptInjection;
|
use JavascriptInjection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Prologue\Alerts\AlertsMessageBag
|
||||||
|
*/
|
||||||
|
private $alert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Services\Databases\DeployServerDatabaseService
|
||||||
|
*/
|
||||||
|
private $deployServerDatabaseService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface
|
||||||
|
*/
|
||||||
|
private $databaseHostRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Services\Databases\DatabasePasswordService
|
* @var \Pterodactyl\Services\Databases\DatabasePasswordService
|
||||||
*/
|
*/
|
||||||
protected $passwordService;
|
private $passwordService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface
|
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface
|
||||||
*/
|
*/
|
||||||
protected $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DatabaseController constructor.
|
* DatabaseController constructor.
|
||||||
*
|
*
|
||||||
* @param \Pterodactyl\Services\Databases\DatabasePasswordService $passwordService
|
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||||
* @param \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface $repository
|
* @param \Pterodactyl\Services\Databases\DeployServerDatabaseService $deployServerDatabaseService
|
||||||
|
* @param \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface $databaseHostRepository
|
||||||
|
* @param \Pterodactyl\Services\Databases\DatabasePasswordService $passwordService
|
||||||
|
* @param \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface $repository
|
||||||
*/
|
*/
|
||||||
public function __construct(DatabasePasswordService $passwordService, DatabaseRepositoryInterface $repository)
|
public function __construct(
|
||||||
{
|
AlertsMessageBag $alert,
|
||||||
|
DeployServerDatabaseService $deployServerDatabaseService,
|
||||||
|
DatabaseHostRepositoryInterface $databaseHostRepository,
|
||||||
|
DatabasePasswordService $passwordService,
|
||||||
|
DatabaseRepositoryInterface $repository
|
||||||
|
) {
|
||||||
|
$this->alert = $alert;
|
||||||
|
$this->databaseHostRepository = $databaseHostRepository;
|
||||||
|
$this->deployServerDatabaseService = $deployServerDatabaseService;
|
||||||
$this->passwordService = $passwordService;
|
$this->passwordService = $passwordService;
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
}
|
}
|
||||||
|
@ -50,11 +81,42 @@ class DatabaseController extends Controller
|
||||||
$this->authorize('view-databases', $server);
|
$this->authorize('view-databases', $server);
|
||||||
$this->setRequest($request)->injectJavascript();
|
$this->setRequest($request)->injectJavascript();
|
||||||
|
|
||||||
|
$canCreateDatabase = config('pterodactyl.client_features.databases.enabled');
|
||||||
|
$allowRandom = config('pterodactyl.client_features.databases.allow_random');
|
||||||
|
|
||||||
|
if ($this->databaseHostRepository->findCountWhere([['node_id', '=', $server->node_id]]) === 0) {
|
||||||
|
if ($canCreateDatabase && ! $allowRandom) {
|
||||||
|
$canCreateDatabase = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$databases = $this->repository->getDatabasesForServer($server->id);
|
||||||
|
|
||||||
return view('server.databases.index', [
|
return view('server.databases.index', [
|
||||||
'databases' => $this->repository->getDatabasesForServer($server->id),
|
'allowCreation' => $canCreateDatabase,
|
||||||
|
'overLimit' => ! is_null($server->database_limit) && count($databases) >= $server->database_limit,
|
||||||
|
'databases' => $databases,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a request from a user to create a new database for the server.
|
||||||
|
*
|
||||||
|
* @param \Pterodactyl\Http\Requests\Server\Database\StoreServerDatabaseRequest $request
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
* @throws \Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException
|
||||||
|
*/
|
||||||
|
public function store(StoreServerDatabaseRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$this->deployServerDatabaseService->handle($request->getServer(), $request->validated());
|
||||||
|
|
||||||
|
$this->alert->success('Successfully created a new database.')->flash();
|
||||||
|
|
||||||
|
return redirect()->route('server.databases.index', $request->getServer()->uuidShort);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a request to update the password for a specific database.
|
* Handle a request to update the password for a specific database.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Http\Requests\Server\Database;
|
||||||
|
|
||||||
|
use Pterodactyl\Http\Requests\Server\ServerFormRequest;
|
||||||
|
|
||||||
|
class StoreServerDatabaseRequest extends ServerFormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
if (! parent::authorize()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config('pterodactyl.client_features.databases.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the user permission to validate this request aganist.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function permission(): string
|
||||||
|
{
|
||||||
|
return 'create-database';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rules to validate this request aganist.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'database' => 'required|string|min:1',
|
||||||
|
'remote' => 'required|string|regex:/^[0-9%.]{1,15}$/',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Requests\Server;
|
namespace Pterodactyl\Http\Requests\Server;
|
||||||
|
|
||||||
|
use Pterodactyl\Models\Server;
|
||||||
use Pterodactyl\Http\Requests\FrontendUserFormRequest;
|
use Pterodactyl\Http\Requests\FrontendUserFormRequest;
|
||||||
|
|
||||||
abstract class ServerFormRequest extends FrontendUserFormRequest
|
abstract class ServerFormRequest extends FrontendUserFormRequest
|
||||||
|
@ -24,6 +25,11 @@ abstract class ServerFormRequest extends FrontendUserFormRequest
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->user()->can($this->permission(), $this->attributes->get('server'));
|
return $this->user()->can($this->permission(), $this->getServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getServer(): Server
|
||||||
|
{
|
||||||
|
return $this->attributes->get('server');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,22 +13,27 @@ class DatabaseManagementService
|
||||||
/**
|
/**
|
||||||
* @var \Illuminate\Database\DatabaseManager
|
* @var \Illuminate\Database\DatabaseManager
|
||||||
*/
|
*/
|
||||||
protected $database;
|
private $database;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Extensions\DynamicDatabaseConnection
|
* @var \Pterodactyl\Extensions\DynamicDatabaseConnection
|
||||||
*/
|
*/
|
||||||
protected $dynamic;
|
private $dynamic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||||
*/
|
*/
|
||||||
protected $encrypter;
|
private $encrypter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface
|
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface
|
||||||
*/
|
*/
|
||||||
protected $repository;
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $useRandomHost = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CreationService constructor.
|
* CreationService constructor.
|
||||||
|
@ -55,7 +60,7 @@ class DatabaseManagementService
|
||||||
*
|
*
|
||||||
* @param int $server
|
* @param int $server
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return \Illuminate\Database\Eloquent\Model
|
* @return \Pterodactyl\Models\Database
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
|
|
87
app/Services/Databases/DeployServerDatabaseService.php
Normal file
87
app/Services/Databases/DeployServerDatabaseService.php
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Services\Databases;
|
||||||
|
|
||||||
|
use Pterodactyl\Models\Server;
|
||||||
|
use Pterodactyl\Models\Database;
|
||||||
|
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||||
|
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
||||||
|
use Pterodactyl\Exceptions\Service\Database\TooManyDatabasesException;
|
||||||
|
use Pterodactyl\Exceptions\Service\Database\NoSuitableDatabaseHostException;
|
||||||
|
use Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException;
|
||||||
|
|
||||||
|
class DeployServerDatabaseService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface
|
||||||
|
*/
|
||||||
|
private $databaseHostRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Services\Databases\DatabaseManagementService
|
||||||
|
*/
|
||||||
|
private $managementService;
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface
|
||||||
|
*/
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServerDatabaseCreationService constructor.
|
||||||
|
*
|
||||||
|
* @param \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface $repository
|
||||||
|
* @param \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface $databaseHostRepository
|
||||||
|
* @param \Pterodactyl\Services\Databases\DatabaseManagementService $managementService
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
DatabaseRepositoryInterface $repository,
|
||||||
|
DatabaseHostRepositoryInterface $databaseHostRepository,
|
||||||
|
DatabaseManagementService $managementService
|
||||||
|
) {
|
||||||
|
$this->databaseHostRepository = $databaseHostRepository;
|
||||||
|
$this->managementService = $managementService;
|
||||||
|
$this->repository = $repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Pterodactyl\Models\Server $server
|
||||||
|
* @param array $data
|
||||||
|
* @return \Pterodactyl\Models\Database
|
||||||
|
*
|
||||||
|
* @throws \Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function handle(Server $server, array $data): Database
|
||||||
|
{
|
||||||
|
if (! config('pterodactyl.client_features.databases.enabled')) {
|
||||||
|
throw new DatabaseClientFeatureNotEnabledException;
|
||||||
|
}
|
||||||
|
|
||||||
|
$databases = $this->repository->findCountWhere([['server_id', '=', $server->id]]);
|
||||||
|
if (! is_null($server->database_limit) && $databases >= $server->database_limit) {
|
||||||
|
throw new TooManyDatabasesException;
|
||||||
|
}
|
||||||
|
|
||||||
|
$allowRandom = config('pterodactyl.client_features.databases.allow_random');
|
||||||
|
$host = $this->databaseHostRepository->setColumns(['id'])->findWhere([
|
||||||
|
['node_id', '=', $server->node_id],
|
||||||
|
])->random();
|
||||||
|
|
||||||
|
if (empty($host) && ! $allowRandom) {
|
||||||
|
throw new NoSuitableDatabaseHostException;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($host)) {
|
||||||
|
$host = $this->databaseHostRepository->setColumns(['id'])->all()->random();
|
||||||
|
if (empty($host)) {
|
||||||
|
throw new NoSuitableDatabaseHostException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->managementService->create($server->id, [
|
||||||
|
'database_host_id' => $host->id,
|
||||||
|
'database' => array_get($data, 'database'),
|
||||||
|
'remote' => array_get($data, 'remote'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -163,6 +163,21 @@ return [
|
||||||
'in_context' => env('PHRASE_IN_CONTEXT', false),
|
'in_context' => env('PHRASE_IN_CONTEXT', false),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Language Editor
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set `PHRASE_IN_CONTEXT` to true to enable the PhaseApp in-context editor
|
||||||
|
| on this site which allows you to translate the panel, from the panel.
|
||||||
|
*/
|
||||||
|
'client_features' => [
|
||||||
|
'databases' => [
|
||||||
|
'enabled' => env('PTERODACTYL_CLIENT_DATABASES_ENABLED', true),
|
||||||
|
'allow_random' => env('PTERODACTYL_CLIENT_DATABASES_ALLOW_RANDOM', true),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| File Editor
|
| File Editor
|
||||||
|
|
|
@ -21,15 +21,10 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="{{ $allowCreation ? 'col-xs-12 col-sm-8' : 'col-xs-12' }}">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">@lang('server.config.database.your_dbs')</h3>
|
<h3 class="box-title">@lang('server.config.database.your_dbs')</h3>
|
||||||
@if(auth()->user()->root_admin)
|
|
||||||
<div class="box-tools">
|
|
||||||
<a href="{{ route('admin.servers.view.database', ['server' => $server->id]) }}" target="_blank" class="btn btn-sm btn-success">Create New</a>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
@if(count($databases) > 0)
|
@if(count($databases) > 0)
|
||||||
<div class="box-body table-responsive no-padding">
|
<div class="box-body table-responsive no-padding">
|
||||||
|
@ -69,17 +64,49 @@
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<div class="alert alert-info no-margin-bottom">
|
<div class="alert alert-info no-margin-bottom">
|
||||||
@lang('server.config.database.no_dbs')
|
@lang('server.config.database.no_dbs')
|
||||||
@if(Auth::user()->root_admin === 1)
|
|
||||||
<a href="{{ route('admin.servers.view', [
|
|
||||||
'id' => $server->id,
|
|
||||||
'tab' => 'tab_database'
|
|
||||||
]) }}" target="_blank">@lang('server.config.database.add_db')</a>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if($allowCreation)
|
||||||
|
<div class="col-xs-12 col-sm-4">
|
||||||
|
<div class="box box-success">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">Create New Database</h3>
|
||||||
|
</div>
|
||||||
|
@if($overLimit)
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="alert alert-danger no-margin">
|
||||||
|
You are currently using <strong>{{ count($databases) }}</strong> of your <strong>{{ $server->database_limit ?? '∞' }}</strong> allowed databases.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<form action="{{ route('server.databases.new', $server->uuidShort) }}" method="POST">
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="pDatabaseName" class="control-label">Database</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon">s{{ $server->id }}_</span>
|
||||||
|
<input id="pDatabaseName" type="text" name="database" class="form-control" placeholder="database" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="pRemote" class="control-label">Connections</label>
|
||||||
|
<input id="pRemote" type="text" name="remote" class="form-control" value="%" />
|
||||||
|
<p class="text-muted small">This should reflect the IP address that connections are allowed from. Uses standard MySQL notation. If unsure leave as <code>%</code>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{!! csrf_field() !!}
|
||||||
|
<p class="text-muted small">You are currently using <strong>{{ count($databases) }}</strong> of <strong>{{ $server->database_limit ?? '∞' }}</strong> databases. A username and password for this database will be randomly generated after form submission.</p>
|
||||||
|
<input type="submit" class="btn btn-sm btn-success pull-right" value="Create Database" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ Route::group(['prefix' => 'settings'], function () {
|
||||||
Route::group(['prefix' => 'databases'], function () {
|
Route::group(['prefix' => 'databases'], function () {
|
||||||
Route::get('/', 'DatabaseController@index')->name('server.databases.index');
|
Route::get('/', 'DatabaseController@index')->name('server.databases.index');
|
||||||
|
|
||||||
|
Route::post('/new', 'DatabaseController@store')->name('server.databases.new');
|
||||||
|
|
||||||
Route::patch('/password', 'DatabaseController@update')->middleware('server..database')->name('server.databases.password');
|
Route::patch('/password', 'DatabaseController@update')->middleware('server..database')->name('server.databases.password');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue