Use a post request to delete SSH keys, some hashes use slashes which cause 404 errors; closes #4100

This commit is contained in:
DaneEveritt 2022-05-30 17:28:42 -04:00
parent 5143faa4b1
commit 03a497fb8a
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
5 changed files with 24 additions and 17 deletions

View file

@ -45,16 +45,22 @@ class SSHKeyController extends ClientApiController
/** /**
* Deletes an SSH key from the user's account. * Deletes an SSH key from the user's account.
*/ */
public function delete(ClientApiRequest $request, string $identifier): JsonResponse public function delete(ClientApiRequest $request): JsonResponse
{ {
$key = $request->user()->sshKeys()->where('fingerprint', $identifier)->firstOrFail(); $this->validate($request, ['fingerprint' => ['required', 'string']]);
$key = $request->user()->sshKeys()
->where('fingerprint', $request->input('fingerprint'))
->first();
if (!is_null($key)) {
$key->delete(); $key->delete();
Activity::event('user:ssh-key.delete') Activity::event('user:ssh-key.delete')
->subject($key) ->subject($key)
->property('fingerprint', $key->fingerprint) ->property('fingerprint', $key->fingerprint)
->log(); ->log();
}
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT); return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
} }

View file

@ -23,6 +23,6 @@ const createSSHKey = async (name: string, publicKey: string): Promise<SSHKey> =>
}; };
const deleteSSHKey = async (fingerprint: string): Promise<void> => const deleteSSHKey = async (fingerprint: string): Promise<void> =>
await http.delete(`/api/client/account/ssh-keys/${fingerprint}`); await http.post('/api/client/account/ssh-keys/remove', { fingerprint });
export { useSSHKeys, createSSHKey, deleteSSHKey }; export { useSSHKeys, createSSHKey, deleteSSHKey };

View file

@ -39,7 +39,7 @@ Route::prefix('/account')->middleware(AccountActivitySubject::class)->group(func
Route::prefix('/ssh-keys')->group(function () { Route::prefix('/ssh-keys')->group(function () {
Route::get('/', [Client\SSHKeyController::class, 'index']); Route::get('/', [Client\SSHKeyController::class, 'index']);
Route::post('/', [Client\SSHKeyController::class, 'store']); Route::post('/', [Client\SSHKeyController::class, 'store']);
Route::delete('/{identifier}', [Client\SSHKeyController::class, 'delete']); Route::post('/remove', [Client\SSHKeyController::class, 'delete']);
}); });
}); });

View file

@ -14,7 +14,6 @@ use Pterodactyl\Models\Location;
use Pterodactyl\Models\Schedule; use Pterodactyl\Models\Schedule;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Pterodactyl\Models\Allocation; use Pterodactyl\Models\Allocation;
use Pterodactyl\Models\UserSSHKey;
use Pterodactyl\Models\DatabaseHost; use Pterodactyl\Models\DatabaseHost;
use Pterodactyl\Tests\Integration\TestResponse; use Pterodactyl\Tests\Integration\TestResponse;
use Pterodactyl\Tests\Integration\IntegrationTestCase; use Pterodactyl\Tests\Integration\IntegrationTestCase;
@ -60,7 +59,6 @@ abstract class ClientApiIntegrationTestCase extends IntegrationTestCase
*/ */
protected function link($model, $append = null): string protected function link($model, $append = null): string
{ {
$link = '';
switch (get_class($model)) { switch (get_class($model)) {
case Server::class: case Server::class:
$link = "/api/client/servers/{$model->uuid}"; $link = "/api/client/servers/{$model->uuid}";
@ -77,9 +75,6 @@ abstract class ClientApiIntegrationTestCase extends IntegrationTestCase
case Backup::class: case Backup::class:
$link = "/api/client/servers/{$model->server->uuid}/backups/{$model->uuid}"; $link = "/api/client/servers/{$model->server->uuid}/backups/{$model->uuid}";
break; break;
case UserSSHKey::class:
$link = "/api/client/account/ssh-keys/$model->fingerprint";
break;
default: default:
throw new InvalidArgumentException(sprintf('Cannot create link for Model of type %s', class_basename($model))); throw new InvalidArgumentException(sprintf('Cannot create link for Model of type %s', class_basename($model)));
} }

View file

@ -40,14 +40,20 @@ class SSHKeyControllerTest extends ClientApiIntegrationTestCase
$key = UserSSHKey::factory()->for($user)->create(); $key = UserSSHKey::factory()->for($user)->create();
$key2 = UserSSHKey::factory()->for($user2)->create(); $key2 = UserSSHKey::factory()->for($user2)->create();
$endpoint = '/api/client/account/ssh-keys/remove';
$this->actingAs($user); $this->actingAs($user);
$this->deleteJson($this->link($key))->assertNoContent(); $this->postJson($endpoint)
->assertUnprocessable()
->assertJsonPath('errors.0.meta', ['source_field' => 'fingerprint', 'rule' => 'required']);
$this->postJson($endpoint, ['fingerprint' => $key->fingerprint])->assertNoContent();
$this->assertSoftDeleted($key); $this->assertSoftDeleted($key);
$this->assertNotSoftDeleted($key2); $this->assertNotSoftDeleted($key2);
$this->deleteJson($this->link($key))->assertNotFound(); $this->postJson($endpoint, ['fingerprint' => $key->fingerprint])->assertNoContent();
$this->deleteJson($this->link($key2))->assertNotFound(); $this->postJson($endpoint, ['fingerprint' => $key2->fingerprint])->assertNoContent();
$this->assertNotSoftDeleted($key2); $this->assertNotSoftDeleted($key2);
} }