Improve logic for logging into the websocket of the target node
This commit is contained in:
parent
5c5e2e24f1
commit
01926e2896
6 changed files with 63 additions and 31 deletions
|
@ -61,18 +61,21 @@ class WebsocketController extends ClientApiController
|
|||
$permissions = $this->permissionsService->handle($server, $user);
|
||||
|
||||
$node = null;
|
||||
|
||||
// Check if there is a transfer query param asking to connect to the target node's websocket.
|
||||
if ($request->query('transfer', 'false') === 'true') {
|
||||
if ($server->transfer !== null) {
|
||||
// Check if the user has permissions to receive transfer logs.
|
||||
if (! in_array('admin.websocket.transfer', $permissions)) {
|
||||
throw new HttpException(Response::HTTP_FORBIDDEN, 'You do not have permission to get transfer logs');
|
||||
throw new HttpException(Response::HTTP_FORBIDDEN, 'You do not have permission to view transfer logs');
|
||||
}
|
||||
|
||||
// Redirect the websocket request to the new node if the server has been archived.
|
||||
if ($server->transfer->archived) {
|
||||
$node = $server->transfer->newNode;
|
||||
} else {
|
||||
$node = $server->node;
|
||||
}
|
||||
} else {
|
||||
$node = $server->node;
|
||||
}
|
||||
|
||||
$token = $this->jwtService
|
||||
->setExpiresAt(CarbonImmutable::now()->addMinutes(10))
|
||||
|
|
|
@ -112,7 +112,6 @@ class ServerTransferController extends Controller
|
|||
|
||||
// Unsuspend the server and don't continue the transfer.
|
||||
if (! $request->input('successful')) {
|
||||
//$this->suspensionService->toggle($server, 'unsuspend');
|
||||
$server->transfer->forceFill([
|
||||
'successful' => false,
|
||||
])->saveOrFail();
|
||||
|
@ -142,6 +141,12 @@ class ServerTransferController extends Controller
|
|||
->relatedTo($server->uuid, true)
|
||||
->getToken($signer, new Key($server->node->getDecryptedKey()));
|
||||
|
||||
// Update the archived field on the transfer to make clients connect to the websocket
|
||||
// on the new node to be able to receive transfer logs.
|
||||
$server->transfer->forceFill([
|
||||
'archived' => true,
|
||||
])->saveOrFail();
|
||||
|
||||
// On the daemon transfer repository, make sure to set the node after the server
|
||||
// because setServer() tells the repository to use the server's node and not the one
|
||||
// we want to specify.
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace Pterodactyl\Models;
|
|||
* @property string $old_additional_allocations
|
||||
* @property string $new_additional_allocations
|
||||
* @property bool|null $successful
|
||||
* @property bool $archived
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
*
|
||||
|
@ -55,6 +56,7 @@ class ServerTransfer extends Model
|
|||
'old_additional_allocations' => 'string',
|
||||
'new_additional_allocations' => 'string',
|
||||
'successful' => 'bool',
|
||||
'archived' => 'bool',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddArchivedFieldToServerTransfersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('server_transfers', function (Blueprint $table) {
|
||||
$table->boolean('archived')->default(0)->after('new_additional_allocations');
|
||||
});
|
||||
|
||||
// Update archived to all be true on existing transfers.
|
||||
Schema::table('server_transfers', function (Blueprint $table) {
|
||||
DB::statement('UPDATE `server_transfers` SET `archived` = 1 WHERE `successful` = 1');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('server_transfers', function (Blueprint $table) {
|
||||
$table->dropColumn('archived');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -5,13 +5,9 @@ interface Response {
|
|||
socket: string;
|
||||
}
|
||||
|
||||
export default (server: string, transfer: boolean): Promise<Response> => {
|
||||
export default (server: string): Promise<Response> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
http.get(`/api/client/servers/${server}/websocket`, {
|
||||
params: {
|
||||
transfer,
|
||||
},
|
||||
})
|
||||
http.get(`/api/client/servers/${server}/websocket`)
|
||||
.then(({ data }) => resolve({
|
||||
token: data.data.token,
|
||||
socket: data.data.socket,
|
||||
|
|
|
@ -15,15 +15,12 @@ const reconnectErrors = [
|
|||
export default () => {
|
||||
let updatingToken = false;
|
||||
const [ error, setError ] = useState<'connecting' | string>('');
|
||||
const [ transfer, setTransfer ] = useState<boolean>(false);
|
||||
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
|
||||
const uuid = ServerContext.useStoreState(state => state.server.data?.uuid);
|
||||
const setServerStatus = ServerContext.useStoreActions(actions => actions.status.setServerStatus);
|
||||
const { setInstance, setConnectionState } = ServerContext.useStoreActions(actions => actions.socket);
|
||||
|
||||
const connect = (uuid: string, transfer = false) => {
|
||||
setTransfer(transfer);
|
||||
|
||||
const connect = (uuid: string) => {
|
||||
const socket = new Websocket();
|
||||
|
||||
socket.on('auth success', () => setConnectionState(true));
|
||||
|
@ -52,21 +49,12 @@ export default () => {
|
|||
});
|
||||
|
||||
socket.on('transfer status', (status: string) => {
|
||||
if (status === 'success') {
|
||||
setTransfer(false);
|
||||
if (status === 'starting' || status === 'success') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === 'starting') {
|
||||
return;
|
||||
}
|
||||
|
||||
// This doesn't use the `setTransfer` hook as it doesn't want to work properly in this context,
|
||||
// and causes all kinds of fuckery with the websocket.
|
||||
let transfer = false;
|
||||
if (status === 'archived') {
|
||||
transfer = true;
|
||||
}
|
||||
// Force a reconnection to the websocket which will connect us
|
||||
// to the target node instead of the source node.
|
||||
|
||||
// Close the current websocket connection.
|
||||
socket.close();
|
||||
|
@ -75,10 +63,10 @@ export default () => {
|
|||
setConnectionState(false);
|
||||
setInstance(null);
|
||||
|
||||
connect(uuid, transfer);
|
||||
connect(uuid);
|
||||
});
|
||||
|
||||
getWebsocketToken(uuid, transfer)
|
||||
getWebsocketToken(uuid)
|
||||
.then(data => {
|
||||
// Connect and then set the authentication token.
|
||||
socket.setToken(data.token).connect(data.socket);
|
||||
|
@ -93,7 +81,7 @@ export default () => {
|
|||
if (updatingToken) return;
|
||||
|
||||
updatingToken = true;
|
||||
getWebsocketToken(uuid, transfer)
|
||||
getWebsocketToken(uuid)
|
||||
.then(data => socket.setToken(data.token, true))
|
||||
.catch(error => console.error(error))
|
||||
.then(() => {
|
||||
|
|
Loading…
Reference in a new issue