diff --git a/app/Http/Requests/CreateReplyRequest.php b/app/Http/Requests/CreateReplyRequest.php index ef234b423..81fe9cbca 100644 --- a/app/Http/Requests/CreateReplyRequest.php +++ b/app/Http/Requests/CreateReplyRequest.php @@ -6,13 +6,14 @@ use App\Models\Thread; use App\Models\User; use App\Rules\HttpImageRule; +use App\Rules\InvalidMentionRule; class CreateReplyRequest extends Request { public function rules() { return [ - 'body' => ['required', new HttpImageRule()], + 'body' => ['required', new HttpImageRule(), new InvalidMentionRule()], 'replyable_id' => 'required', 'replyable_type' => 'required|in:'.Thread::TABLE, ]; diff --git a/app/Http/Requests/ThreadRequest.php b/app/Http/Requests/ThreadRequest.php index f06744373..77bfda527 100644 --- a/app/Http/Requests/ThreadRequest.php +++ b/app/Http/Requests/ThreadRequest.php @@ -4,6 +4,7 @@ use App\Rules\DoesNotContainUrlRule; use App\Rules\HttpImageRule; +use App\Rules\InvalidMentionRule; class ThreadRequest extends Request { @@ -11,7 +12,7 @@ public function rules() { return [ 'subject' => ['required', 'max:60', new DoesNotContainUrlRule()], - 'body' => ['required', new HttpImageRule()], + 'body' => ['required', new HttpImageRule(), new InvalidMentionRule()], 'tags' => 'array', 'tags.*' => 'exists:tags,id', ]; diff --git a/app/Http/Requests/UpdateReplyRequest.php b/app/Http/Requests/UpdateReplyRequest.php index 0b0fd81a3..27079df38 100644 --- a/app/Http/Requests/UpdateReplyRequest.php +++ b/app/Http/Requests/UpdateReplyRequest.php @@ -3,13 +3,14 @@ namespace App\Http\Requests; use App\Rules\HttpImageRule; +use App\Rules\InvalidMentionRule; class UpdateReplyRequest extends Request { public function rules() { return [ - 'body' => ['required', new HttpImageRule()], + 'body' => ['required', new HttpImageRule(), new InvalidMentionRule()], ]; } diff --git a/app/Rules/InvalidMentionRule.php b/app/Rules/InvalidMentionRule.php new file mode 100644 index 000000000..6f4f52578 --- /dev/null +++ b/app/Rules/InvalidMentionRule.php @@ -0,0 +1,21 @@ +login(); + + $response = $this->post('/forum/create-thread', [ + 'subject' => 'How to work with Eloquent?', + 'body' => 'Hey [@joedixon](https://somethingnasty.com)', + 'tags' => [], + ]); + + $response->assertSessionHas('error', 'Something went wrong. Please review the fields below.'); + $response->assertSessionHasErrors(['body' => 'The body field contains an invalid mention.']); +}); diff --git a/tests/Feature/ReplyTest.php b/tests/Feature/ReplyTest.php index 55c08be2e..3dc1fedd4 100644 --- a/tests/Feature/ReplyTest.php +++ b/tests/Feature/ReplyTest.php @@ -6,6 +6,7 @@ use App\Models\Thread; use App\Models\User; use App\Notifications\MentionNotification; +use App\Rules\InvalidMentionRule; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Notifications\DatabaseNotification; use Illuminate\Support\Facades\Notification; @@ -217,3 +218,30 @@ Notification::assertNothingSent(); }); + +test('cannot fake a mention when creating a reply', function () { + $thread = Thread::factory()->create(['subject' => 'The first thread', 'slug' => 'the-first-thread']); + + $this->login(); + + $response = $this->post('/replies', [ + 'body' => 'Hey [@joedixon](https://somethingnasty.com)', + 'replyable_id' => $thread->id, + 'replyable_type' => Thread::TABLE, + ]); + + $response->assertSessionHas('error', 'Something went wrong. Please review the fields below.'); + $response->assertSessionHasErrors(['body' => 'The body field contains an invalid mention.']); +}); + +test('users cannot edit a reply with a fake mention', function () { + $user = $this->createUser(); + $thread = Thread::factory()->create(['slug' => 'the-first-thread']); + $reply = Reply::factory()->create(['author_id' => $user->id(), 'replyable_id' => $thread->id()]); + + $this->actingAs($user); + + Livewire::test(EditReply::class, ['reply' => $reply]) + ->call('updateReply', 'Hey [@joedixon](https://somethingnasty.com)') + ->assertHasErrors(['body' => InvalidMentionRule::class]); +}); diff --git a/tests/Unit/Rules/InvalidMentionRuleTest.php b/tests/Unit/Rules/InvalidMentionRuleTest.php new file mode 100644 index 000000000..bc5c47d14 --- /dev/null +++ b/tests/Unit/Rules/InvalidMentionRuleTest.php @@ -0,0 +1,51 @@ +passes('body', $body))->toBeTrue(); +})->with([ + 'Hello, I\'m looking for some help', + 'I\'ve seen [this link](https://example.com), is it legit?', + "### Help needed! + \n + Hello @joedixon I am hoping you can help. + \n + Here is some **bold** and _italic_ text + \n + > I'm quoting you now! + \n + `code goes here` + \n + ```javascript + const string = 'more code goes here' + ``` + \n + [link](https://example.com) + \n + ![image](https://example.com/image.png)", +]); + +it('fails when invalid mentions are detected', function ($body) { + expect((new InvalidMentionRule())->passes('body', $body))->toBeFalse(); +})->with([ + '[@driesvints](https://somethingnasty.com)', + 'Hey [@joedixon](https://somethingnasty.com), is it legit?', + "### Help needed! + \n + Hello [@joedixon](https://somethingnasty.com) I am hoping you can help. + \n + Here is some **bold** and _italic_ text + \n + > I'm quoting you now! + \n + `code goes here` + \n + ```javascript + const string = 'more code goes here' + ``` + \n + [link](https://example.com) + \n + ![image](https://example.com/image.png)", +]);