Add database password change support and fix column name
This commit is contained in:
parent
0d61c50dcc
commit
5233d6e87b
11 changed files with 188 additions and 9 deletions
|
@ -56,7 +56,7 @@ class DatabaseController extends Controller
|
||||||
'servers.id as a_serverId',
|
'servers.id as a_serverId',
|
||||||
'servers.name as a_serverName'
|
'servers.name as a_serverName'
|
||||||
)->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
|
)->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
|
||||||
->join('servers', 'databases.server', '=', 'servers.id')
|
->join('servers', 'databases.server_id', '=', 'servers.id')
|
||||||
->paginate(20),
|
->paginate(20),
|
||||||
'dbh' => Models\DatabaseServer::select(
|
'dbh' => Models\DatabaseServer::select(
|
||||||
'database_servers.*',
|
'database_servers.*',
|
||||||
|
|
|
@ -99,7 +99,7 @@ class ServersController extends Controller
|
||||||
->where('server_variables.server_id', $server->id)
|
->where('server_variables.server_id', $server->id)
|
||||||
->get(),
|
->get(),
|
||||||
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
|
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
|
||||||
->where('server', $server->id)
|
->where('server_id', $server->id)
|
||||||
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
|
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
|
||||||
->get(),
|
->get(),
|
||||||
'db_servers' => Models\DatabaseServer::all()
|
'db_servers' => Models\DatabaseServer::all()
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Pterodactyl\Http\Controllers\Server;
|
||||||
|
|
||||||
use Log;
|
use Log;
|
||||||
use Debugbar;
|
use Debugbar;
|
||||||
|
use Pterodactyl\Models;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use Pterodactyl\Models\Node;
|
use Pterodactyl\Models\Node;
|
||||||
|
|
||||||
|
@ -223,4 +224,28 @@ class AjaxController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function postResetDatabasePassword(Request $request, $uuid)
|
||||||
|
{
|
||||||
|
$server = Models\Server::getByUUID($uuid);
|
||||||
|
$database = Models\Database::where('id', $request->input('database'))->where('server_id', $server->id)->firstOrFail();
|
||||||
|
|
||||||
|
$this->authorize('reset-db-password', $server);
|
||||||
|
try {
|
||||||
|
|
||||||
|
$repo = new Repositories\DatabaseRepository;
|
||||||
|
$password = str_random(16);
|
||||||
|
$repo->modifyPassword($request->input('database'), $password);
|
||||||
|
return response($password);
|
||||||
|
} catch (\Pterodactyl\Exceptions\DisplayException $ex) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => $ex->getMessage(),
|
||||||
|
], 503);
|
||||||
|
} catch(\Exception $ex) {
|
||||||
|
Log::error($ex);
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'An unhandled error occured while attempting to modify this database\'s password.'
|
||||||
|
], 503);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,7 @@ class ServerController extends Controller
|
||||||
return view('server.settings', [
|
return view('server.settings', [
|
||||||
'server' => $server,
|
'server' => $server,
|
||||||
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
|
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
|
||||||
->where('server', $server->id)
|
->where('server_id', $server->id)
|
||||||
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
|
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
|
||||||
->get(),
|
->get(),
|
||||||
'node' => Models\Node::find($server->node),
|
'node' => Models\Node::find($server->node),
|
||||||
|
|
|
@ -152,6 +152,11 @@ class ServerRoutes {
|
||||||
$router->post('set-connection', [
|
$router->post('set-connection', [
|
||||||
'uses' => 'Server\AjaxController@postSetConnection'
|
'uses' => 'Server\AjaxController@postSetConnection'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$router->post('settings/reset-database-password', [
|
||||||
|
'as' => 'server.ajax.reset-database-password',
|
||||||
|
'uses' => 'Server\AjaxController@postResetDatabasePassword'
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assorted AJAX Routes
|
// Assorted AJAX Routes
|
||||||
|
|
|
@ -56,6 +56,8 @@ class DatabaseServer extends Model
|
||||||
*/
|
*/
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
|
'server_id' => 'integer',
|
||||||
|
'db_server' => 'integer'
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -546,4 +546,13 @@ class ServerPolicy
|
||||||
return $user->permissions()->server($server)->permission('create-task')->exists();
|
return $user->permissions()->server($server)->permission('create-task')->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function resetDbPassword(User $user, Server $server)
|
||||||
|
{
|
||||||
|
if ($this->isOwner($user, $server)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user->permissions()->server($server)->permission('create-task')->exists();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ class DatabaseRepository {
|
||||||
try {
|
try {
|
||||||
$db = new Models\Database;
|
$db = new Models\Database;
|
||||||
$db->fill([
|
$db->fill([
|
||||||
'server' => $server->id,
|
'server_id' => $server->id,
|
||||||
'db_server' => $options['db_server'],
|
'db_server' => $options['db_server'],
|
||||||
'database' => $server->uuidShort . '_' . $options['database'],
|
'database' => $server->uuidShort . '_' . $options['database'],
|
||||||
'username' => $server->uuidShort . '_' . str_random(7),
|
'username' => $server->uuidShort . '_' . str_random(7),
|
||||||
|
@ -103,6 +103,54 @@ class DatabaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the password for a given database.
|
||||||
|
* @param int $database The ID of the database to modify.
|
||||||
|
* @param string $password The new password to use for the database.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function modifyPassword($database, $password)
|
||||||
|
{
|
||||||
|
$db = Models\Database::findOrFail($database);
|
||||||
|
$dbr = Models\DatabaseServer::findOrFail($db->db_server);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
try {
|
||||||
|
|
||||||
|
$db->password = Crypt::encrypt($password);
|
||||||
|
$db->save();
|
||||||
|
|
||||||
|
$capsule = new Capsule;
|
||||||
|
$capsule->addConnection([
|
||||||
|
'driver' => 'mysql',
|
||||||
|
'host' => $dbr->host,
|
||||||
|
'port' => $dbr->port,
|
||||||
|
'database' => 'mysql',
|
||||||
|
'username' => $dbr->username,
|
||||||
|
'password' => Crypt::decrypt($dbr->password),
|
||||||
|
'charset' => 'utf8',
|
||||||
|
'collation' => 'utf8_unicode_ci',
|
||||||
|
'prefix' => '',
|
||||||
|
'options' => [
|
||||||
|
\PDO::ATTR_TIMEOUT => 3,
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$capsule->setAsGlobal();
|
||||||
|
Capsule::statement(sprintf(
|
||||||
|
'ALTER USER \'%s\'@\'%s\' IDENTIFIED BY \'%s\'',
|
||||||
|
$db->username,
|
||||||
|
$db->remote,
|
||||||
|
$password
|
||||||
|
));
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
} catch(\Exception $ex) {
|
||||||
|
DB::rollback();
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drops a database from the associated MySQL Server
|
* Drops a database from the associated MySQL Server
|
||||||
* @param int $database The ID of the database to drop.
|
* @param int $database The ID of the database to drop.
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class FixColumnNameForDatabases extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('databases', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('server', 'server_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('databases', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('server_id', 'server');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -363,7 +363,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $database->database }}</td>
|
<td>{{ $database->database }}</td>
|
||||||
<td>{{ $database->username }} ({{ $database->remote }})</td>
|
<td>{{ $database->username }} ({{ $database->remote }})</td>
|
||||||
<td><code>{{ Crypt::decrypt($database->password) }}</code></td>
|
<td><code>{{ Crypt::decrypt($database->password) }}</code> <a href="#" data-action="reset-database-password" data-id="{{ $database->id }}"><i class="fa fa-refresh pull-right"></i></a></td>
|
||||||
<td><code>{{ $database->a_host }}:{{ $database->a_port }}</code></td>
|
<td><code>{{ $database->a_host }}:{{ $database->a_port }}</code></td>
|
||||||
<td class="text-center"><a href="#delete" data-action="delete_database" data-database="{{ $database->id }}" class="text-danger"><i class="fa fa-trash-o"></i></a></td>
|
<td class="text-center"><a href="#delete" data-action="delete_database" data-database="{{ $database->id }}" class="text-danger"><i class="fa fa-trash-o"></i></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -530,6 +530,36 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
$('[data-action="reset-database-password"]').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var block = $(this);
|
||||||
|
$(this).find('i').addClass('fa-spin');
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '{{ route('server.ajax.reset-database-password', $server->uuidShort) }}',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
'database': $(this).data('id')
|
||||||
|
}
|
||||||
|
}).done(function (data) {
|
||||||
|
block.parent().find('code').html(data);
|
||||||
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||||
|
console.error(jqXHR);
|
||||||
|
var error = 'An error occured while trying to process this request.';
|
||||||
|
if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {
|
||||||
|
error = jqXHR.responseJSON.error;
|
||||||
|
}
|
||||||
|
swal({
|
||||||
|
type: 'error',
|
||||||
|
title: 'Whoops!',
|
||||||
|
text: error
|
||||||
|
});
|
||||||
|
}).always(function () {
|
||||||
|
block.find('i').removeClass('fa-spin');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -142,7 +142,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Database</th>
|
<th>Database</th>
|
||||||
<th>User (Connections From)</th>
|
<th>Username</th>
|
||||||
<th>Password</th>
|
<th>Password</th>
|
||||||
<th>DB Server</th>
|
<th>DB Server</th>
|
||||||
</th>
|
</th>
|
||||||
|
@ -151,8 +151,8 @@
|
||||||
@foreach($databases as $database)
|
@foreach($databases as $database)
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $database->database }}</td>
|
<td>{{ $database->database }}</td>
|
||||||
<td>{{ $database->username }} ({{ $database->remote }})</td>
|
<td>{{ $database->username }}</td>
|
||||||
<td><code>{{ Crypt::decrypt($database->password) }}</code></td>
|
<td><code>{{ Crypt::decrypt($database->password) }}</code> <a href="#" data-action="reset-database-password" data-id="{{ $database->id }}"><i class="fa fa-refresh pull-right"></i></a></td>
|
||||||
<td><code>{{ $database->a_host }}:{{ $database->a_port }}</code></td>
|
<td><code>{{ $database->a_host }}:{{ $database->a_port }}</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -206,7 +206,36 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
$('[data-action="reset-database-password"]').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var block = $(this);
|
||||||
|
$(this).find('i').addClass('fa-spin');
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '{{ route('server.ajax.reset-database-password', $server->uuidShort) }}',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
'database': $(this).data('id')
|
||||||
|
}
|
||||||
|
}).done(function (data) {
|
||||||
|
block.parent().find('code').html(data);
|
||||||
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||||
|
console.error(jqXHR);
|
||||||
|
var error = 'An error occured while trying to process this request.';
|
||||||
|
if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {
|
||||||
|
error = jqXHR.responseJSON.error;
|
||||||
|
}
|
||||||
|
swal({
|
||||||
|
type: 'error',
|
||||||
|
title: 'Whoops!',
|
||||||
|
text: error
|
||||||
|
});
|
||||||
|
}).always(function () {
|
||||||
|
block.find('i').removeClass('fa-spin');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
Loading…
Reference in a new issue