From 198a021a9748b2cff5b290b712abb1c7cb1b2400 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 16 Mar 2017 19:35:29 -0400 Subject: [PATCH] Add database host management to panel. --- CHANGELOG.md | 2 + .../Controllers/Admin/DatabaseController.php | 130 ++++++++------ .../Controllers/Admin/ServersController.php | 2 +- app/Http/Routes/AdminRoutes.php | 23 +++ app/Models/Database.php | 10 +- .../{DatabaseServer.php => DatabaseHost.php} | 18 +- app/Repositories/DatabaseRepository.php | 163 ++++++++++++------ ...eOrganizeDatabaseServersToDatabaseHost.php | 48 ++++++ ..._03_16_181515_CleanupDatabasesDatabase.php | 40 +++++ .../admin/databases/index.blade.php | 149 ++++++++++++++++ .../admin/databases/view.blade.php | 143 +++++++++++++++ .../pterodactyl/layouts/admin.blade.php | 2 +- 12 files changed, 605 insertions(+), 125 deletions(-) rename app/Models/{DatabaseServer.php => DatabaseHost.php} (84%) create mode 100644 database/migrations/2017_03_16_181109_ReOrganizeDatabaseServersToDatabaseHost.php create mode 100644 database/migrations/2017_03_16_181515_CleanupDatabasesDatabase.php create mode 100644 resources/themes/pterodactyl/admin/databases/index.blade.php create mode 100644 resources/themes/pterodactyl/admin/databases/view.blade.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aaf6b6dc..c6de40f1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines. * Table seeders for services now can be run during upgrades and will attempt to locate and update, or create new if not found in the database. * Many structural changes to the database and `Pterodactyl\Models` classes that would flood this changelog if they were all included. All required migrations included to handle database changes. * `[pre.4]` — Service pack files are now stored in the database rather than on the host system to make updates easier. +* Clarified details for database hosts to prevent users entering invalid account details, as well as renamed tables and columns relating to it to keep things clearer. ### Fixed * Fixes potential bug with invalid CIDR notation (ex: `192.168.1.1/z`) when adding allocations that could cause over 4 million records to be created at once. @@ -22,6 +23,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines. ### Added * Ability to assign multiple allocations at once when creating a new server. * New `humanReadable` macro on `File` facade that accepts a file path and returns a human readable size. (`File::humanReadable(path, precision)`) +* Added ability to edit database host details after creation on the system. ### Deprecated * Old API calls to `Server::create` will fail due to changed data structure. diff --git a/app/Http/Controllers/Admin/DatabaseController.php b/app/Http/Controllers/Admin/DatabaseController.php index 7014c321b..e41575458 100644 --- a/app/Http/Controllers/Admin/DatabaseController.php +++ b/app/Http/Controllers/Admin/DatabaseController.php @@ -26,8 +26,10 @@ namespace Pterodactyl\Http\Controllers\Admin; use Log; use Alert; -use Pterodactyl\Models; use Illuminate\Http\Request; +use Pterodactyl\Models\Database; +use Pterodactyl\Models\Location; +use Pterodactyl\Models\DatabaseHost; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Repositories\DatabaseRepository; @@ -36,82 +38,98 @@ use Pterodactyl\Exceptions\DisplayValidationException; class DatabaseController extends Controller { /** - * Controller Constructor. + * Display database host index. + * + * @param Request $request + * @return \Illuminate\View\View */ - public function __construct() - { - // - } - - public function getIndex(Request $request) + public function index(Request $request) { return view('admin.databases.index', [ - 'databases' => Models\Database::with('server')->paginate(50), - 'hosts' => Models\DatabaseServer::withCount('databases')->with('node')->paginate(20), + 'locations' => Location::with('nodes')->get(), + 'hosts' => DatabaseHost::withCount('databases')->with('node')->get(), ]); } - public function getNew(Request $request) + /** + * Display database host to user. + * + * @param Request $request + * @param int $id + * @return \Illuminate\View\View + */ + public function view(Request $request, $id) { - return view('admin.databases.new', [ - 'nodes' => Models\Node::all()->load('location'), + return view('admin.databases.view', [ + 'locations' => Location::with('nodes')->get(), + 'host' => DatabaseHost::with('databases.server')->findOrFail($id), ]); } - public function postNew(Request $request) + /** + * Handle post request to create database host. + * + * @param Request $request + * @return \Illuminate\Response\RedirectResponse + */ + public function create(Request $request) { + $repo = new DatabaseRepository; + try { - $repo = new DatabaseRepository; - $repo->add($request->only([ - 'name', - 'host', - 'port', - 'username', - 'password', - 'linked_node', + $host = $repo->add($request->intersect([ + 'name', 'username', 'password', + 'host', 'port', 'node_id', ])); - Alert::success('Successfully added a new database server to the system.')->flash(); + Alert::success('Successfully created new database host on the system.')->flash(); - return redirect()->route('admin.databases', ['tab' => 'tab_dbservers']); + return redirect()->route('admin.databases.view', $host->id); + } catch (\PDOException $ex) { + Alert::danger($ex->getMessage())->flash(); } catch (DisplayValidationException $ex) { - return redirect()->route('admin.databases.new')->withErrors(json_decode($ex->getMessage()))->withInput(); + return redirect()->route('admin.databases')->withErrors(json_decode($ex->getMessage())); } catch (\Exception $ex) { - if ($ex instanceof DisplayException || $ex instanceof \PDOException) { - Alert::danger($ex->getMessage())->flash(); + Log::error($ex); + Alert::danger('An error was encountered while trying to process this request. This error has been logged.')->flash(); + } + + return redirect()->route('admin.databases'); + } + + /** + * Handle post request to update a database host. + * + * @param Request $request + * @param int $id + * @return \Illuminate\Response\RedirectResponse + */ + public function update(Request $request, $id) + { + $repo = new DatabaseRepository; + + try { + if ($request->input('action') !== 'delete') { + $host = $repo->update($id, $request->intersect([ + 'name', 'username', 'password', + 'host', 'port', 'node_id', + ])); + Alert::success('Database host was updated successfully.')->flash(); } else { - Log::error($ex); - Alert::danger('An error occurred while attempting to delete this database server from the system.')->flash(); + $repo->delete($id); + + return redirect()->route('admin.databases'); } - - return redirect()->route('admin.databases.new')->withInput(); - } - } - - public function deleteDatabase(Request $request, $id) - { - try { - $repo = new DatabaseRepository; - $repo->drop($id); + } catch (\PDOException $ex) { + Alert::danger($ex->getMessage())->flash(); + } catch (DisplayException $ex) { + Alert::danger($ex->getMessage())->flash(); + } catch (DisplayValidationException $ex) { + return redirect()->route('admin.databases.view', $id)->withErrors(json_decode($ex->getMessage())); } catch (\Exception $ex) { Log::error($ex); - - return response()->json([ - 'error' => ($ex instanceof DisplayException) ? $ex->getMessage() : 'An error occurred while attempting to delete this database from the system.', - ], 500); + Alert::danger('An error was encountered while trying to process this request. This error has been logged.')->flash(); } - } - public function deleteServer(Request $request, $id) - { - try { - $repo = new DatabaseRepository; - $repo->delete($id); - } catch (\Exception $ex) { - Log::error($ex); - - return response()->json([ - 'error' => ($ex instanceof DisplayException) ? $ex->getMessage() : 'An error occurred while attempting to delete this database server from the system.', - ], 500); - } + return redirect()->route('admin.databases.view', $id); } } diff --git a/app/Http/Controllers/Admin/ServersController.php b/app/Http/Controllers/Admin/ServersController.php index 56dfdbad3..5ac430865 100644 --- a/app/Http/Controllers/Admin/ServersController.php +++ b/app/Http/Controllers/Admin/ServersController.php @@ -212,7 +212,7 @@ class ServersController extends Controller $server = Models\Server::where('installed', 1)->with('databases.host')->findOrFail($id); return view('admin.servers.view.database', [ - 'hosts' => Models\DatabaseServer::all(), + 'hosts' => Models\DatabaseHost::all(), 'server' => $server, ]); } diff --git a/app/Http/Routes/AdminRoutes.php b/app/Http/Routes/AdminRoutes.php index 8649e789f..41ab22482 100644 --- a/app/Http/Routes/AdminRoutes.php +++ b/app/Http/Routes/AdminRoutes.php @@ -43,6 +43,29 @@ class AdminRoutes 'uses' => 'Admin\BaseController@getIndex', ]); + $router->group([ + 'prefix' => 'admin/databases', + 'middleware' => [ + 'auth', + 'admin', + 'csrf', + ], + ], function () use ($router) { + $router->get('/', [ + 'as' => 'admin.databases', + 'uses' => 'Admin\DatabaseController@index', + ]); + + $router->post('/', 'Admin\DatabaseController@create'); + + $router->get('/view/{id}', [ + 'as' => 'admin.databases.view', + 'uses' => 'Admin\DatabaseController@view', + ]); + + $router->post('/view/{id}', 'Admin\DatabaseController@update'); + }); + $router->group([ 'prefix' => 'admin/locations', 'middleware' => [ diff --git a/app/Models/Database.php b/app/Models/Database.php index b5e9d39ad..e7f543466 100644 --- a/app/Models/Database.php +++ b/app/Models/Database.php @@ -43,11 +43,13 @@ class Database extends Model protected $hidden = ['password']; /** - * Fields that are not mass assignable. + * Fields that are mass assignable. * * @var array */ - protected $guarded = ['id', 'created_at', 'updated_at']; + protected $fillable = [ + 'server_id', 'database_host_id', 'database', 'username', 'remote', + ]; /** * Cast values to correct type. @@ -56,7 +58,7 @@ class Database extends Model */ protected $casts = [ 'server_id' => 'integer', - 'db_server' => 'integer', + 'database_host_id' => 'integer', ]; /** @@ -66,7 +68,7 @@ class Database extends Model */ public function host() { - return $this->belongsTo(DatabaseServer::class, 'db_server'); + return $this->belongsTo(DatabaseHost::class); } /** diff --git a/app/Models/DatabaseServer.php b/app/Models/DatabaseHost.php similarity index 84% rename from app/Models/DatabaseServer.php rename to app/Models/DatabaseHost.php index 1ebb7546f..0d5eaf30a 100644 --- a/app/Models/DatabaseServer.php +++ b/app/Models/DatabaseHost.php @@ -26,14 +26,14 @@ namespace Pterodactyl\Models; use Illuminate\Database\Eloquent\Model; -class DatabaseServer extends Model +class DatabaseHost extends Model { /** * The table associated with the model. * * @var string */ - protected $table = 'database_servers'; + protected $table = 'database_hosts'; /** * The attributes excluded from the model's JSON form. @@ -43,11 +43,13 @@ class DatabaseServer extends Model protected $hidden = ['password']; /** - * Fields that are not mass assignable. + * Fields that are mass assignable. * * @var array */ - protected $guarded = ['id', 'created_at', 'updated_at']; + protected $fillable = [ + 'name', 'host', 'port', 'username', 'max_databases', 'node_id', + ]; /** * Cast values to correct type. @@ -56,8 +58,8 @@ class DatabaseServer extends Model */ protected $casts = [ 'id' => 'integer', - 'server_id' => 'integer', - 'db_server' => 'integer', + 'max_databases' => 'integer', + 'node_id' => 'integer', ]; /** @@ -67,7 +69,7 @@ class DatabaseServer extends Model */ public function node() { - return $this->belongsTo(Node::class, 'linked_node'); + return $this->belongsTo(Node::class); } /** @@ -77,6 +79,6 @@ class DatabaseServer extends Model */ public function databases() { - return $this->hasMany(Database::class, 'db_server'); + return $this->hasMany(Database::class); } } diff --git a/app/Repositories/DatabaseRepository.php b/app/Repositories/DatabaseRepository.php index 5397fc5c7..7e1760b63 100644 --- a/app/Repositories/DatabaseRepository.php +++ b/app/Repositories/DatabaseRepository.php @@ -28,7 +28,9 @@ use DB; use Crypt; use Config; use Validator; -use Pterodactyl\Models; +use Pterodactyl\Models\Server; +use Pterodactyl\Models\Database; +use Pterodactyl\Models\DatabaseHost; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayValidationException; @@ -37,17 +39,16 @@ class DatabaseRepository /** * Adds a new database to a specified database host server. * - * @param int $server Id of the server to add a database for. - * @param array $options Array of options for creating that database. + * @param int $id + * @param array $data + * @return \Pterodactyl\Models\Database * * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\DisplayValidationException - * @throws \Exception - * @return void */ - public function create($server, $data) + public function create($id, array $data) { - $server = Models\Server::findOrFail($server); + $server = Server::findOrFail($server); $validator = Validator::make($data, [ 'host' => 'required|exists:database_servers,id', @@ -56,16 +57,16 @@ class DatabaseRepository ]); if ($validator->fails()) { - throw new DisplayValidationException($validator->errors()); + throw new DisplayValidationException(json_encode($validator->errors())); } - $host = Models\DatabaseServer::findOrFail($data['host']); + $host = DatabaseHost::findOrFail($data['host']); DB::beginTransaction(); try { $database = Models\Database::firstOrNew([ 'server_id' => $server->id, - 'db_server' => $data['host'], + 'database_host_id' => $data['host'], 'database' => sprintf('s%d_%s', $server->id, $data['database']), ]); @@ -109,6 +110,8 @@ class DatabaseRepository // Save Everything DB::commit(); + + return $database; } catch (\Exception $ex) { try { DB::connection('dynamic')->statement(sprintf('DROP DATABASE IF EXISTS `%s`', $database->database)); @@ -124,18 +127,17 @@ class DatabaseRepository /** * Updates the password for a given database. - * @param int $id The ID of the database to modify. - * @param string $password The new password to use for the database. - * @return bool + * + * @param int $id + * @param string $password + * @return void */ public function password($id, $password) { $database = Models\Database::with('host')->findOrFail($id); - DB::beginTransaction(); - try { + DB::transaction(function () use ($database, $password) { $database->password = Crypt::encrypt($password); - $database->save(); Config::set('database.connections.dynamic', [ 'driver' => 'mysql', @@ -153,24 +155,21 @@ class DatabaseRepository $database->username, $database->remote, $password )); - DB::commit(); - } catch (\Exception $ex) { - DB::rollBack(); - throw $ex; - } + $database->save(); + }); } /** - * Drops a database from the associated MySQL Server. - * @param int $id The ID of the database to drop. - * @return bool + * Drops a database from the associated database host. + * + * @param int $id + * @return void */ public function drop($id) { - $database = Models\Database::with('host')->findOrFail($id); + $database = Database::with('host')->findOrFail($id); - DB::beginTransaction(); - try { + DB::transaction(function () use ($database) { Config::set('database.connections.dynamic', [ 'driver' => 'mysql', 'host' => $database->host->host, @@ -187,34 +186,35 @@ class DatabaseRepository DB::connection('dynamic')->statement('FLUSH PRIVILEGES'); $database->delete(); - - DB::commit(); - } catch (\Exception $ex) { - DB::rollback(); - throw $ex; - } + }); } /** - * Deletes a database server from the system if it is empty. + * Deletes a database host from the system if it has no associated databases. * - * @param int $server The ID of the Database Server. - * @return bool + * @param int $server + * @return void + * + * @throws \Pterodactyl\Exceptions\DisplayException */ - public function delete($server) + public function delete($id) { - $host = Models\DatabaseServer::withCount('databases')->findOrFail($server); + $host = DatabaseHost::withCount('databases')->findOrFail($id); if ($host->databases_count > 0) { - throw new DisplayException('You cannot delete a database server that has active databases attached to it.'); + throw new DisplayException('You cannot delete a database host that has active databases attached to it.'); } - return $host->delete(); + $host->delete(); } /** - * Adds a new Database Server to the system. - * @param array $data + * Adds a new Database Host to the system. + * + * @param array $data + * @return \Pterodactyl\Models\DatabaseHost + * + * @throws \Pterodactyl\Exceptions\DisplayValidationException */ public function add(array $data) { @@ -224,19 +224,18 @@ class DatabaseRepository $validator = Validator::make($data, [ 'name' => 'required|string|max:255', - 'host' => 'required|ip|unique:database_servers,host', + 'host' => 'required|ip|unique:database_hosts,host', 'port' => 'required|numeric|between:1,65535', 'username' => 'required|string|max:32', 'password' => 'required|string', - 'linked_node' => 'sometimes', + 'node_id' => 'sometimes|required|exists:nodes,id', ]); if ($validator->fails()) { - throw new DisplayValidationException($validator->errors()); + throw new DisplayValidationException(json_encode($validator->errors())); } - DB::beginTransaction(); - try { + return DB::transaction(function () use ($data) { Config::set('database.connections.dynamic', [ 'driver' => 'mysql', 'host' => $data['host'], @@ -251,20 +250,74 @@ class DatabaseRepository // Allows us to check that we can connect to things. DB::connection('dynamic')->select('SELECT 1 FROM dual'); - Models\DatabaseServer::create([ + $host = new DatabaseHost; + $host->password = Crypt::encrypt($data['password']); + + $host->fill([ 'name' => $data['name'], 'host' => $data['host'], 'port' => $data['port'], 'username' => $data['username'], - 'password' => Crypt::encrypt($data['password']), 'max_databases' => null, - 'linked_node' => (! empty($data['linked_node']) && $data['linked_node'] > 0) ? $data['linked_node'] : null, + 'node_id' => (isset($data['node_id'])) ? $data['node_id'] : null, + ])->save(); + + return $host; + }); + } + + /** + * Updates a Database Host on the system. + * + * @param int $id + * @param array $data + * @return \Pterodactyl\Models\DatabaseHost + * + * @throws \Pterodactyl\Exceptions\DisplayValidationException + */ + public function update($id, array $data) + { + $host = DatabaseHost::findOrFail($id); + + if (isset($data['host'])) { + $data['host'] = gethostbyname($data['host']); + } + + $validator = Validator::make($data, [ + 'name' => 'sometimes|required|string|max:255', + 'host' => 'sometimes|required|ip|unique:database_hosts,host,' . $host->id, + 'port' => 'sometimes|required|numeric|between:1,65535', + 'username' => 'sometimes|required|string|max:32', + 'password' => 'sometimes|required|string', + 'node_id' => 'sometimes|required|exists:nodes,id', + ]); + + if ($validator->fails()) { + throw new DisplayValidationException(json_encode($validator->errors())); + } + + return DB::transaction(function () use ($data, $host) { + if (isset($data['password'])) { + $host->password = Crypt::encrypt($data['password']); + } + $host->fill($data)->save(); + + // Check that we can still connect with these details. + Config::set('database.connections.dynamic', [ + 'driver' => 'mysql', + 'host' => $host->host, + 'port' => $host->port, + 'database' => 'mysql', + 'username' => $host->username, + 'password' => Crypt::decrypt($host->password), + 'charset' => 'utf8', + 'collation' => 'utf8_unicode_ci', ]); - DB::commit(); - } catch (\Exception $ex) { - DB::rollBack(); - throw $ex; - } + // Allows us to check that we can connect to things. + DB::connection('dynamic')->select('SELECT 1 FROM dual'); + + return $host; + }); } } diff --git a/database/migrations/2017_03_16_181109_ReOrganizeDatabaseServersToDatabaseHost.php b/database/migrations/2017_03_16_181109_ReOrganizeDatabaseServersToDatabaseHost.php new file mode 100644 index 000000000..50699a688 --- /dev/null +++ b/database/migrations/2017_03_16_181109_ReOrganizeDatabaseServersToDatabaseHost.php @@ -0,0 +1,48 @@ +dropForeign(['linked_node']); + }); + + Schema::rename('database_servers', 'database_hosts'); + + Schema::table('database_hosts', function (Blueprint $table) { + $table->renameColumn('linked_node', 'node_id'); + + $table->foreign('node_id')->references('id')->on('nodes'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('database_hosts', function (Blueprint $table) { + $table->dropForeign(['node_id']); + }); + + Schema::rename('database_hosts', 'database_servers'); + + Schema::table('database_servers', function (Blueprint $table) { + $table->renameColumn('node_id', 'linked_node'); + + $table->foreign('linked_node')->references('id')->on('nodes'); + }); + } +} diff --git a/database/migrations/2017_03_16_181515_CleanupDatabasesDatabase.php b/database/migrations/2017_03_16_181515_CleanupDatabasesDatabase.php new file mode 100644 index 000000000..07192f898 --- /dev/null +++ b/database/migrations/2017_03_16_181515_CleanupDatabasesDatabase.php @@ -0,0 +1,40 @@ +dropForeign(['db_server']); + + $table->renameColumn('db_server', 'database_host_id'); + + $table->foreign('database_host_id')->references('id')->on('database_hosts'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('databases', function (Blueprint $table) { + $table->dropForeign(['database_host_id']); + + $table->renameColumn('database_host_id', 'db_server'); + + $table->foreign('db_server')->references('id')->on('database_hosts'); + }); + } +} diff --git a/resources/themes/pterodactyl/admin/databases/index.blade.php b/resources/themes/pterodactyl/admin/databases/index.blade.php new file mode 100644 index 000000000..b2735849a --- /dev/null +++ b/resources/themes/pterodactyl/admin/databases/index.blade.php @@ -0,0 +1,149 @@ +{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} +@extends('layouts.admin') + +@section('title') + Database Hosts +@endsection + +@section('content-header') +

Database HostsDatabase hosts that servers can have databases created on.

+ +@endsection + +@section('content') +
+
+
+
+

Host List

+
+
+ + + + + + + + + + + + @foreach ($hosts as $host) + + + + + + + + + + @endforeach + +
IDNameHostPortUsernameDatabasesNode
{{ $host->id }}{{ $host->name }}{{ $host->host }}{{ $host->port }}{{ $host->username }}{{ $host->databases_count }} + @if(! is_null($host->node)) + {{ $host->node->name }} + @else + None + @endif +
+
+ +
+
+
+ +@endsection + +@section('footer-scripts') + @parent + +@endsection diff --git a/resources/themes/pterodactyl/admin/databases/view.blade.php b/resources/themes/pterodactyl/admin/databases/view.blade.php new file mode 100644 index 000000000..ab331921c --- /dev/null +++ b/resources/themes/pterodactyl/admin/databases/view.blade.php @@ -0,0 +1,143 @@ +{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} +@extends('layouts.admin') + +@section('title') + Database Hosts → View → {{ $host->name }} +@endsection + +@section('content-header') +

{{ $host->name }}Viewing associated databases and details for this database host.

+ +@endsection + +@section('content') +
+
+
+
+
+

Host Details

+
+
+
+ + +
+
+ + +

The IP address or FQDN that should be used when attempting to connect to this MySQL host from the panel to add new databases.

+
+
+ + +

The port that MySQL is running on for this host.

+
+
+ + +

This setting does nothing other than default to this database host when adding a database to a server on the selected node.

+
+
+
+
+
+
+
+

User Details

+
+
+
+ + +

The username of an account that has enough permissions to create new users and databases on the system.

+
+
+ + +

The password to the account defined. Leave blank to continue using the assigned password.

+
+
+

The account defined for this database host must have the WITH GRANT OPTION permission. If the defined account does not have this permission requests to create databases will fail. Do not use the same account details for MySQL that you have defined for this panel.

+
+ +
+
+
+
+
+
+
+
+

Databases

+
+
+ + + + + + + + + @foreach($host->databases as $database) + + + + + + + + @endforeach +
ServerDatabase NameUsernameConnections From
{{ $database->server->name }}{{ $database->database }}{{ $database->username }}{{ $database->remote }} + + + +
+
+
+
+
+@endsection + +@section('footer-scripts') + @parent + +@endsection diff --git a/resources/themes/pterodactyl/layouts/admin.blade.php b/resources/themes/pterodactyl/layouts/admin.blade.php index 85ac74160..9a17d3119 100644 --- a/resources/themes/pterodactyl/layouts/admin.blade.php +++ b/resources/themes/pterodactyl/layouts/admin.blade.php @@ -92,7 +92,7 @@
  • MANAGEMENT
  • - + Databases