Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/Http/Requests/CreateReplyRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
];
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/ThreadRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

use App\Rules\DoesNotContainUrlRule;
use App\Rules\HttpImageRule;
use App\Rules\InvalidMentionRule;

class ThreadRequest extends Request
{
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',
];
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/UpdateReplyRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()],
];
}

Expand Down
21 changes: 21 additions & 0 deletions app/Rules/InvalidMentionRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

/**
* This rule validates links are not diguised as mentions.
*/
final class InvalidMentionRule implements Rule
{
public function passes($attribute, $value): bool
{
return ! preg_match('/\[@.*\]\(http.*\)/', $value);
}

public function message(): string
{
return 'The :attribute field contains an invalid mention.';
}
}
13 changes: 13 additions & 0 deletions tests/Feature/ForumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,16 @@

Notification::assertNothingSent();
});

test('cannot fake a mention', function () {
$this->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.']);
});
28 changes: 28 additions & 0 deletions tests/Feature/ReplyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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]);
});
51 changes: 51 additions & 0 deletions tests/Unit/Rules/InvalidMentionRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

use App\Rules\InvalidMentionRule;

it('passes when no invalid mentions are detected', function ($body) {
expect((new InvalidMentionRule())->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)",
]);