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
13 changes: 9 additions & 4 deletions src/Middleware/ValidateSignature.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Closure;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Uri;
use jdavidbakr\MailTracker\Events\ValidLinkEvent;
use jdavidbakr\MailTracker\Exceptions\BadUrlLink;
use jdavidbakr\MailTracker\MailTracker;
Expand All @@ -14,17 +15,21 @@ class ValidateSignature extends Middleware
{
public function handle($request, Closure $next, ...$args)
{
$hash = $request->get('h');
$url = $request->get('l');
$hash = $request->query('h');
$url = $request->query('l');

if (filter_var($url, FILTER_VALIDATE_URL) === false) {
$uri = Uri::of($url);

$validUriSchemes = ['http', 'https', 'tel', 'mailto'];

if (!in_array($uri->scheme(), $validUriSchemes)) {
throw new BadUrlLink('Mail hash: ' . $hash . ', URL: ' . $url);
}

[$relative, $ignore] = $this->parseArguments($args);

// If the signature is valid then we know that it has not been tampered with so continue
if ($request->hasValidSignatureWhileIgnoring($ignore, ! $relative)) {
if ($request->hasValidSignatureWhileIgnoring($ignore, !$relative)) {
return $next($request);
}

Expand Down
34 changes: 32 additions & 2 deletions tests/MailTrackerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace jdavidbakr\MailTracker\Tests;

use Faker\Factory;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Mail\Events\MessageSending;
Expand Down Expand Up @@ -32,7 +31,7 @@
use jdavidbakr\MailTracker\RecordLinkClickJob;
use jdavidbakr\MailTracker\RecordTrackingJob;
use Mockery;
use Orchestra\Testbench\Exceptions\Handler;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Header\Headers;
Expand All @@ -58,6 +57,7 @@ public function render($request, Throwable $e)
{
throw $e;
}

public function renderForConsole($output, Throwable $e)
{
throw $e;
Expand Down Expand Up @@ -486,6 +486,36 @@ public function random_string_in_link_does_not_crash()
$this->get($url);
}

public static function linkDataProvider()
{
return [
'Normal HTTP URL' => ['http://goodwebsite.com/test.html'],
'Normal HTTPS URL' => ['https://goodwebsite.com/test.html'],
'Normal Tel' => ['tel:+123456789'],
'Normal Mailto' => ['mailto:test@email.com'],
];
}

#[Test]
#[DataProvider('linkDataProvider')]
public function test_signed_link_redirects_to_valid_url(string $link)
{
$track = MailTracker::sentEmailModel()->newQuery()->create([
'hash' => Str::random(32),
'content' => 'This is some content with a link to <a href="' . $link . '">Good website</a>',
]);

$this->disableExceptionHandling();

$url = URL::signedRoute('mailTracker_n', [
'l' => $link,
'h' => $track->hash,
]);

$this->get($url)
->assertRedirect($link);
}

#[Test]
public function it_retrieves_the_message_id_from_laravel_mailer()
{
Expand Down