55use Firebase \JWT \JWT ;
66use Google \Cloud \Tasks \V2 \CloudTasksClient ;
77use GuzzleHttp \Client ;
8+ use Illuminate \Support \Facades \Cache ;
89use Illuminate \Support \Facades \Mail ;
10+ use Mockery ;
11+ use phpseclib \Crypt \RSA ;
912use Stackkit \LaravelGoogleCloudTasksQueue \CloudTasksException ;
13+ use Stackkit \LaravelGoogleCloudTasksQueue \GooglePublicKey ;
1014use Stackkit \LaravelGoogleCloudTasksQueue \TaskHandler ;
1115use Tests \Support \TestMailable ;
1216
@@ -17,54 +21,116 @@ class TaskHandlerTest extends TestCase
1721 */
1822 private $ handler ;
1923
20- private $ client ;
21-
2224 private $ jwt ;
2325
26+ private $ request ;
27+
2428 protected function setUp (): void
2529 {
2630 parent ::setUp ();
2731
28- $ this ->client = \Mockery:: mock (CloudTasksClient::class)-> makePartial ();
32+ $ this ->request = request ();
2933
30- $ this ->jwt = \Mockery::mock (JWT ::class)->makePartial ();
34+ // We don't have a valid token to test with, so for now act as if its always valid
35+ $ this ->app ->instance (JWT ::class, ($ this ->jwt = Mockery::mock (new JWT ())->byDefault ()->makePartial ()));
36+ $ this ->jwt ->shouldReceive ('decode ' )->andReturn ((object ) [
37+ 'iss ' => 'accounts.google.com ' ,
38+ 'aud ' => 'https://localhost/my-handler ' ,
39+ 'exp ' => time () + 10
40+ ])->byDefault ();
3141
32- $ this ->handler = \Mockery::mock (new TaskHandler (
33- $ this ->client ,
42+ // Ensure we don't fetch the Google public key each test...
43+ $ googlePublicKey = Mockery::mock (app (GooglePublicKey::class));
44+ $ googlePublicKey ->shouldReceive ('get ' )->andReturnNull ();
45+
46+ $ this ->handler = new TaskHandler (
47+ new CloudTasksClient ([
48+ 'credentials ' => __DIR__ . '/Support/gcloud-key-valid.json '
49+ ]),
3450 request (),
35- new Client (),
36- $ this ->jwt
37- ))->shouldAllowMockingProtectedMethods ();
38- $ this ->app ->instance (TaskHandler::class, $ this ->handler );
51+ $ this ->jwt ,
52+ $ googlePublicKey
53+ );
3954
40- $ this ->jwt ->shouldReceive ('decode ' )->andReturnNull ();
41- $ this ->handler ->shouldReceive ('authorizeRequest ' )->andReturnNull ();
55+ $ this ->request ->headers ->add (['Authorization ' => 'Bearer 123 ' ]);
4256 }
4357
4458 /** @test */
4559 public function it_needs_an_authorization_header ()
4660 {
61+ $ this ->request ->headers ->remove ('Authorization ' );
62+
4763 $ this ->expectException (CloudTasksException::class);
4864 $ this ->expectExceptionMessage ('Missing [Authorization] header ' );
4965
50- request ()->headers ->add (['X-Cloudtasks-Taskname ' => 'test ' ]);
51- request ()->headers ->add (['X-Cloudtasks-Queuename ' => 'test ' ]);
5266 $ this ->handler ->handle ();
5367 }
5468
69+ /** @test */
70+ public function the_authorization_header_must_contain_a_valid_gcloud_token ()
71+ {
72+ request ()->headers ->add ([
73+ 'Authorization ' => 'Bearer 123 ' ,
74+ ]);
75+
76+ $ this ->expectException (CloudTasksException::class);
77+ $ this ->expectExceptionMessage ('Could not decode incoming task ' );
78+
79+ $ this ->handler ->handle ();
80+
81+ // @todo - test with a valid token, not sure how to do that right now
82+ }
83+
84+ /** @test */
85+ public function it_will_validate_the_token_iss ()
86+ {
87+ $ this ->jwt ->shouldReceive ('decode ' )->andReturn ((object ) [
88+ 'iss ' => 'test ' ,
89+ ]);
90+ $ this ->expectException (CloudTasksException::class);
91+ $ this ->expectExceptionMessage ('The given OpenID token is not valid ' );
92+ $ this ->handler ->handle ($ this ->simpleJob ());
93+ }
94+
95+ /** @test */
96+ public function it_will_validate_the_token_handler ()
97+ {
98+ $ this ->jwt ->shouldReceive ('decode ' )->andReturn ((object ) [
99+ 'iss ' => 'accounts.google.com ' ,
100+ 'aud ' => '__incorrect_aud__ '
101+ ]);
102+ $ this ->expectException (CloudTasksException::class);
103+ $ this ->expectExceptionMessage ('The given OpenID token is not valid ' );
104+ $ this ->handler ->handle ($ this ->simpleJob ());
105+ }
106+
107+ /** @test */
108+ public function it_will_validate_the_token_expiration ()
109+ {
110+ $ this ->jwt ->shouldReceive ('decode ' )->andReturn ((object ) [
111+ 'iss ' => 'accounts.google.com ' ,
112+ 'aud ' => 'https://localhost/my-handler ' ,
113+ 'exp ' => time () - 1
114+ ]);
115+ $ this ->expectException (CloudTasksException::class);
116+ $ this ->expectExceptionMessage ('The given OpenID token has expired ' );
117+ $ this ->handler ->handle ($ this ->simpleJob ());
118+ }
119+
55120 /** @test */
56121 public function it_runs_the_incoming_job ()
57122 {
58123 Mail::fake ();
59124
60- request ()->headers ->add (['X-Cloudtasks-Taskname ' => 'test ' ]);
61- request ()->headers ->add (['X-Cloudtasks-Queuename ' => 'test ' ]);
62125 request ()->headers ->add (['Authorization ' => 'Bearer 123 ' ]);
63126
64- $ this ->client ->shouldReceive ('getTask ' )->andReturnNull ();
65-
66- $ this ->handler ->handle (json_decode (file_get_contents (__DIR__ . '/Support/test-job-payload.json ' ), true ));
127+ $ this ->handler ->handle ($ this ->simpleJob ());
67128
68129 Mail::assertSent (TestMailable::class);
69130 }
131+
132+ private function simpleJob ()
133+ {
134+ return json_decode (file_get_contents (__DIR__ . '/Support/test-job-payload.json ' ), true );
135+ }
70136}
0 commit comments