Skip to content

Commit

Permalink
Merge pull request #588 from therecluse26/therecluse26-encrypted-job-…
Browse files Browse the repository at this point in the history
…bugfix

Allow for encrypted command data
  • Loading branch information
khepin authored Apr 26, 2024
2 parents 30cc317 + 9bd427a commit 3d58891
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 0 deletions.
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<env name="PORT" value="5672"/>
<env name="PORT_SSL" value="5671"/>
<env name="RABBITMQ_SSL_CAFILE" value="./tests/files/rootCA.pem"/>
<env name="APP_KEY" value="12345678901234567890123456789012"/>
</php>
<logging/>
</phpunit>
7 changes: 7 additions & 0 deletions src/Queue/RabbitMQQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use ErrorException;
use Exception;
use Illuminate\Contracts\Queue\Queue as QueueContract;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Queue\Queue;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Str;
use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Connection\AbstractConnection;
Expand Down Expand Up @@ -525,6 +527,11 @@ protected function createMessage($payload, int $attempts = 0): array
}

if (isset($currentPayload['data']['command'])) {
// If the command data is encrypted, decrypt it first before attempting to unserialize
if (is_subclass_of($currentPayload['data']['commandName'], ShouldBeEncrypted::class)) {
$currentPayload['data']['command'] = Crypt::decrypt($currentPayload['data']['command']);
}

$commandData = unserialize($currentPayload['data']['command']);
if (property_exists($commandData, 'priority')) {
$properties['priority'] = $commandData->priority;
Expand Down
98 changes: 98 additions & 0 deletions tests/Feature/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PhpAmqpLib\Exception\AMQPProtocolChannelException;
use RuntimeException;
use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob;
use VladimirYuldashev\LaravelQueueRabbitMQ\Tests\Mocks\TestEncryptedJob;
use VladimirYuldashev\LaravelQueueRabbitMQ\Tests\Mocks\TestJob;
use VladimirYuldashev\LaravelQueueRabbitMQ\Tests\TestCase as BaseTestCase;

Expand Down Expand Up @@ -194,6 +195,103 @@ public function testBulk(): void
$this->assertSame($count, Queue::size());
}

public function testPushEncrypted(): void
{
Queue::push(new TestEncryptedJob());

sleep(1);

$this->assertSame(1, Queue::size());
$this->assertNotNull($job = Queue::pop());
$this->assertSame(1, $job->attempts());
$this->assertInstanceOf(RabbitMQJob::class, $job);
$this->assertSame(TestEncryptedJob::class, $job->resolveName());
$this->assertNotNull($job->getJobId());

$payload = $job->payload();

$this->assertSame(TestEncryptedJob::class, $payload['displayName']);
$this->assertSame('Illuminate\Queue\CallQueuedHandler@call', $payload['job']);
$this->assertNull($payload['maxTries']);
$this->assertNull($payload['backoff']);
$this->assertNull($payload['timeout']);
$this->assertNull($payload['retryUntil']);
$this->assertSame($job->getJobId(), $payload['id']);

$job->delete();
$this->assertSame(0, Queue::size());
}

public function testPushEncryptedAfterCommit(): void
{
$transaction = new DatabaseTransactionsManager;

$this->app->singleton('db.transactions', function ($app) use ($transaction) {
$transaction->begin('FakeDBConnection', 1);

return $transaction;
});

TestEncryptedJob::dispatch()->afterCommit();

sleep(1);
$this->assertSame(0, Queue::size());
$this->assertNull(Queue::pop());

$transaction->commit('FakeDBConnection', 1, 0);

sleep(1);

$this->assertSame(1, Queue::size());
$this->assertNotNull($job = Queue::pop());

$job->delete();
$this->assertSame(0, Queue::size());
}

public function testEncryptedLater(): void
{
Queue::later(3, new TestEncryptedJob());

sleep(1);

$this->assertSame(0, Queue::size());
$this->assertNull(Queue::pop());

sleep(3);

$this->assertSame(1, Queue::size());
$this->assertNotNull($job = Queue::pop());

$this->assertInstanceOf(RabbitMQJob::class, $job);

$body = json_decode($job->getRawBody(), true);

$this->assertSame(TestEncryptedJob::class, $body['displayName']);
$this->assertSame('Illuminate\Queue\CallQueuedHandler@call', $body['job']);
$this->assertSame(TestEncryptedJob::class, $body['data']['commandName']);
$this->assertNotNull($job->getJobId());

$job->delete();
$this->assertSame(0, Queue::size());
}

public function testEncryptedBulk(): void
{
$count = 100;
$jobs = [];

for ($i = 0; $i < $count; $i++) {
$jobs[$i] = new TestEncryptedJob($i);
}

Queue::bulk($jobs);

sleep(1);

$this->assertSame($count, Queue::size());
}

public function testReleaseRaw(): void
{
Queue::pushRaw($payload = Str::random());
Expand Down
25 changes: 25 additions & 0 deletions tests/Mocks/TestEncryptedJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace VladimirYuldashev\LaravelQueueRabbitMQ\Tests\Mocks;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class TestEncryptedJob implements ShouldBeEncrypted, ShouldQueue
{
use Dispatchable, Queueable;

public $i;

public function __construct($i = 0)
{
$this->i = $i;
}

public function handle(): void
{
//
}
}

0 comments on commit 3d58891

Please sign in to comment.