diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index dd3fce9..d4b75c8 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -8,6 +8,5 @@ jobs: with: enable_backend_testing: true enable_phpstan: true - php_versions: '["8.0", "8.1", "8.2", "8.3"]' backend_directory: . diff --git a/src/Api/UserResourceDeleteEndpoint.php b/src/Api/UserResourceDeleteEndpoint.php index a2c2d6f..da22bff 100644 --- a/src/Api/UserResourceDeleteEndpoint.php +++ b/src/Api/UserResourceDeleteEndpoint.php @@ -32,7 +32,7 @@ public function __construct( public function __invoke(Endpoint\Delete $endpoint): Endpoint\Delete { - return $endpoint->action(function (User $user, Context $context) use ($endpoint) { + return $endpoint->action(function (Context $context) use ($endpoint) { $model = $context->model; /** @var AbstractResource $resource */ diff --git a/src/Extend/UserData.php b/src/Extend/UserData.php index 1187710..95d50cb 100644 --- a/src/Extend/UserData.php +++ b/src/Extend/UserData.php @@ -20,7 +20,7 @@ class UserData implements ExtenderInterface protected array $removeTypes = []; protected array $removeUserColumns = []; - public function extend(Container $container, Extension $extension = null): void + public function extend(Container $container, ?Extension $extension = null): void { foreach ($this->types as $type) { DataProcessor::addType($type, $extension?->getId()); diff --git a/tests/integration/api/CancelErasureTest.php b/tests/integration/api/CancelErasureTest.php index 1d967aa..17392cf 100644 --- a/tests/integration/api/CancelErasureTest.php +++ b/tests/integration/api/CancelErasureTest.php @@ -18,6 +18,7 @@ use Flarum\Testing\integration\TestCase; use Flarum\User\User; use PHPUnit\Framework\Attributes\Test; +use Psr\Http\Message\ResponseInterface; class CancelErasureTest extends TestCase { @@ -58,12 +59,19 @@ public function setUp(): void $this->extension('flarum-gdpr'); } + public function cancelErasureRequest(int $userId, ?int $actorId): ResponseInterface + { + return $this->send( + $this->request('POST', "/api/user-erasure-requests/{$userId}/cancel", [ + 'authenticatedAs' => $actorId, + ]) + ); + } + #[Test] public function guest_cannot_cancel_unconfirmed_erasure_request() { - $response = $this->send( - $this->request('DELETE', '/api/user-erasure-requests/1') - ); + $response = $this->cancelErasureRequest(1, null); $this->assertEquals(401, $response->getStatusCode()); } @@ -71,9 +79,7 @@ public function guest_cannot_cancel_unconfirmed_erasure_request() #[Test] public function guest_cannot_cancel_confirmed_erasure_request() { - $response = $this->send( - $this->request('DELETE', '/api/user-erasure-requests/2') - ); + $response = $this->cancelErasureRequest(2, null); $this->assertEquals(401, $response->getStatusCode()); } @@ -81,11 +87,7 @@ public function guest_cannot_cancel_confirmed_erasure_request() #[Test] public function user_can_cancel_own_unconfirmed_erasure_request() { - $response = $this->send( - $this->request('DELETE', '/api/user-erasure-requests/1', [ - 'authenticatedAs' => 4, - ]) - ); + $response = $this->cancelErasureRequest(1, 4); $this->assertEquals(204, $response->getStatusCode()); @@ -102,11 +104,7 @@ public function user_can_cancel_own_unconfirmed_erasure_request() #[Test] public function user_can_cancel_own_confirmed_erasure_request() { - $response = $this->send( - $this->request('DELETE', '/api/user-erasure-requests/2', [ - 'authenticatedAs' => 5, - ]) - ); + $response = $this->cancelErasureRequest(2, 5); $this->assertEquals(204, $response->getStatusCode()); @@ -123,11 +121,7 @@ public function user_can_cancel_own_confirmed_erasure_request() #[Test] public function user_cannot_cancel_others_erasure_request() { - $response = $this->send( - $this->request('DELETE', '/api/user-erasure-requests/1', [ - 'authenticatedAs' => 5, - ]) - ); + $response = $this->cancelErasureRequest(1, 5); $this->assertEquals(403, $response->getStatusCode()); } @@ -135,11 +129,7 @@ public function user_cannot_cancel_others_erasure_request() #[Test] public function moderator_can_cancel_others_erasure_request() { - $response = $this->send( - $this->request('DELETE', '/api/user-erasure-requests/1', [ - 'authenticatedAs' => 3, - ]) - ); + $response = $this->cancelErasureRequest(1, 3); $this->assertEquals(204, $response->getStatusCode()); diff --git a/tests/integration/api/DeleteUserTest.php b/tests/integration/api/DeleteUserTest.php index ee18ad2..bcc1058 100644 --- a/tests/integration/api/DeleteUserTest.php +++ b/tests/integration/api/DeleteUserTest.php @@ -53,15 +53,40 @@ public function delete_user_endpoint_is_processed_by_this_extension() $this->assertEquals(ErasureRequest::STATUS_MANUAL, $user->erasureRequest->status); } + #[Test] + public function delete_user_endpoint_uses_default_when_no_mode_provided() + { + $response = $this->send( + $this->request( + 'DELETE', + '/api/users/2', + [ + 'authenticatedAs' => 1, + 'json' => [], + ] + ) + ); + + $this->assertEquals(204, $response->getStatusCode()); + + $user = User::query()->where('id', 2)->with('erasureRequest')->first(); + $this->assertNotNull($user); + $this->assertEquals("Anonymous{$user->erasureRequest->id}", $user->username); + $this->assertEquals(ErasureRequest::STATUS_MANUAL, $user->erasureRequest->status); + } + #[Test] public function delete_user_endpoint_can_be_called_with_anonymization_mode() { $response = $this->send( $this->request( 'DELETE', - '/api/users/2/gdpr/'.ErasureRequest::MODE_ANONYMIZATION, + '/api/users/2', [ 'authenticatedAs' => 1, + 'json' => [ + 'gdprMode' => ErasureRequest::MODE_ANONYMIZATION, + ], ] ) ); @@ -80,9 +105,12 @@ public function delete_user_endpoint_with_deletion_mode_not_enabled_by_default() $response = $this->send( $this->request( 'DELETE', - '/api/users/2/gdpr/'.ErasureRequest::MODE_DELETION, + '/api/users/2', [ 'authenticatedAs' => 1, + 'json' => [ + 'gdprMode' => ErasureRequest::MODE_DELETION, + ], ] ) ); @@ -103,9 +131,12 @@ public function delete_user_endpoint_can_be_called_with_deletion_mode_enabled() $response = $this->send( $this->request( 'DELETE', - '/api/users/2/gdpr/'.ErasureRequest::MODE_DELETION, + '/api/users/2', [ 'authenticatedAs' => 1, + 'json' => [ + 'gdprMode' => ErasureRequest::MODE_DELETION, + ], ] ) ); @@ -122,9 +153,12 @@ public function invalid_erasure_mode_throws_validation_error() $response = $this->send( $this->request( 'DELETE', - '/api/users/2/gdpr/invalid-mode', + '/api/users/2', [ 'authenticatedAs' => 1, + 'json' => [ + 'gdprMode' => 'invalid-mode', + ], ] ) ); diff --git a/tests/integration/api/ListDataTypesControllerTest.php b/tests/integration/api/ListDataTypesControllerTest.php index 15d0d3c..c03899d 100644 --- a/tests/integration/api/ListDataTypesControllerTest.php +++ b/tests/integration/api/ListDataTypesControllerTest.php @@ -36,7 +36,7 @@ public function setUp(): void public function non_admin_cannot_list_types() { $response = $this->send( - $this->request('GET', '/api/gdpr/datatypes', ['authenticatedAs' => 2]) + $this->request('GET', '/api/gdpr-datatypes', ['authenticatedAs' => 2]) ); $this->assertEquals(403, $response->getStatusCode()); @@ -46,7 +46,7 @@ public function non_admin_cannot_list_types() public function admin_can_list_types() { $response = $this->send( - $this->request('GET', '/api/gdpr/datatypes', ['authenticatedAs' => 1]) + $this->request('GET', '/api/gdpr-datatypes', ['authenticatedAs' => 1]) ); $this->assertEquals(200, $response->getStatusCode()); diff --git a/tests/integration/api/ProcessErasureTest.php b/tests/integration/api/ProcessErasureTest.php index 39ad097..89a92b1 100644 --- a/tests/integration/api/ProcessErasureTest.php +++ b/tests/integration/api/ProcessErasureTest.php @@ -115,17 +115,15 @@ public function authorized_user_cannot_process_unconfirmed_request() 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I am trying to process this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_DELETION, - ], + 'processorComment' => 'I am trying to process this request', + 'processedMode' => ErasureRequest::MODE_DELETION, ], ], ], ]) ); - $this->assertEquals(422, $response->getStatusCode()); + $this->assertEquals(403, $response->getStatusCode()); } #[Test] @@ -139,10 +137,8 @@ public function authorized_user_can_process_confirmed_erasure_request_in_deletio 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_DELETION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_DELETION, ], ], ], @@ -169,10 +165,8 @@ public function authorized_user_can_process_confirmed_erasure_request_in_anonymi 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_ANONYMIZATION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_ANONYMIZATION, ], ], ], @@ -208,10 +202,8 @@ public function anonymization_with_custom_username_works() 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_ANONYMIZATION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_ANONYMIZATION, ], ], ], @@ -236,10 +228,8 @@ public function authorized_user_cannot_process_confirmed_erasure_request_in_anon 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_ANONYMIZATION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_ANONYMIZATION, ], ], ], @@ -260,10 +250,8 @@ public function authorized_user_cannot_process_confirmed_erasure_request_in_dele 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_DELETION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_DELETION, ], ], ], @@ -291,10 +279,8 @@ public function user_is_anonymized_when_nicknames_is_enabled() 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_ANONYMIZATION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_ANONYMIZATION, ], ], ], @@ -320,20 +306,14 @@ public function cancelled_erasure_requests_are_not_processed() 'json' => [ 'data' => [ 'attributes' => [ - 'processor_comment' => 'I have processed this request', - 'meta' => [ - 'mode' => ErasureRequest::MODE_DELETION, - ], + 'processorComment' => 'I have processed this request', + 'processedMode' => ErasureRequest::MODE_DELETION, ], ], ], ]) ); - $this->assertEquals(422, $response->getStatusCode()); - - $data = json_decode($response->getBody()->getContents(), true); - - $this->assertEquals('Erasure request is cancelled.', $data['errors'][0]['detail']); + $this->assertEquals(403, $response->getStatusCode()); } } diff --git a/tests/integration/api/RequestErasureTest.php b/tests/integration/api/RequestErasureTest.php index d433b1b..877f612 100644 --- a/tests/integration/api/RequestErasureTest.php +++ b/tests/integration/api/RequestErasureTest.php @@ -141,9 +141,7 @@ public function normal_user_can_request_erasure_and_recieves_notification_to_con $this->assertNull($erasureRequest->processed_at); $this->assertNull($erasureRequest->processed_mode); - $notification = Notification::query()->where('user_id', 2)->where('type', 'gdpr_erasure_confirm')->orderBy('id', 'desc')->first(); - - $this->assertNotNull($notification); + // TODO: Check that email was sent } #[Test] @@ -191,9 +189,7 @@ public function user_can_request_erasure_without_giving_reason() $this->assertNull($erasureRequest->processed_at); $this->assertNull($erasureRequest->processed_mode); - $notification = Notification::query()->where('user_id', 2)->where('type', 'gdpr_erasure_confirm')->orderBy('id', 'desc')->first(); - - $this->assertNotNull($notification); + // TODO: Check that email was sent } #[Test]