Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Feature/Controller/CompanionAppsTest.php
<?php | <?php | ||||
namespace Tests\Feature\Controller; | namespace Tests\Feature\Controller; | ||||
use App\User; | use App\User; | ||||
use App\CompanionApp; | use App\CompanionApp; | ||||
use Laravel\Passport\Token; | use Laravel\Passport\Token; | ||||
use Laravel\Passport\Passport; | |||||
use Laravel\Passport\TokenRepository; | use Laravel\Passport\TokenRepository; | ||||
use Tests\TestCase; | use Tests\TestCase; | ||||
class CompanionAppsTest extends TestCase | class CompanionAppsTest extends TestCase | ||||
{ | { | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
Show All 14 Lines | public function tearDown(): void | ||||
$this->deleteTestUser('CompanionAppsTest1@userscontroller.com'); | $this->deleteTestUser('CompanionAppsTest1@userscontroller.com'); | ||||
$this->deleteTestUser('CompanionAppsTest2@userscontroller.com'); | $this->deleteTestUser('CompanionAppsTest2@userscontroller.com'); | ||||
$this->deleteTestCompanionApp('testdevice'); | $this->deleteTestCompanionApp('testdevice'); | ||||
parent::tearDown(); | parent::tearDown(); | ||||
} | } | ||||
/** | /** | ||||
* Test registering the app | * Test creating the app | ||||
*/ | */ | ||||
public function testRegister(): void | public function testStore(): void | ||||
{ | { | ||||
$user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | $user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | ||||
$notificationToken = "notificationToken"; | |||||
$deviceId = "deviceId"; | |||||
$name = "testname"; | $name = "testname"; | ||||
$response = $this->actingAs($user)->post( | $post = ['name' => $name]; | ||||
"api/v4/companion/register", | $response = $this->actingAs($user)->post("api/v4/companions", $post); | ||||
['notificationToken' => $notificationToken, 'deviceId' => $deviceId, 'name' => $name] | |||||
); | |||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$companionApp = \App\CompanionApp::where('device_id', $deviceId)->first(); | $json = $response->json(); | ||||
$this->assertCount(3, $json); | |||||
$this->assertSame('success', $json['status']); | |||||
$this->assertSame("Companion app has been created.", $json['message']); | |||||
$companionApp = \App\CompanionApp::where('name', $name)->first(); | |||||
$this->assertTrue($companionApp != null); | $this->assertTrue($companionApp != null); | ||||
$this->assertEquals($deviceId, $companionApp->device_id); | |||||
$this->assertEquals($name, $companionApp->name); | $this->assertEquals($name, $companionApp->name); | ||||
$this->assertEquals($notificationToken, $companionApp->notification_token); | $this->assertFalse((bool)$companionApp->mfa_enabled); | ||||
} | |||||
// Test a token update | /** | ||||
$notificationToken = "notificationToken2"; | * Test destroying the app | ||||
$response = $this->actingAs($user)->post( | */ | ||||
"api/v4/companion/register", | public function testDestroy(): void | ||||
['notificationToken' => $notificationToken, 'deviceId' => $deviceId, 'name' => $name] | { | ||||
$user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | |||||
$user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | |||||
$response = $this->actingAs($user)->delete("api/v4/companions/foobar"); | |||||
$response->assertStatus(404); | |||||
$companionApp = $this->getTestCompanionApp( | |||||
'testdevice', | |||||
$user, | |||||
[ | |||||
'notification_token' => 'notificationtoken', | |||||
'mfa_enabled' => 1, | |||||
'name' => 'testname', | |||||
] | |||||
); | ); | ||||
$response->assertStatus(200); | $client = Passport::client()->forceFill([ | ||||
'user_id' => $user->id, | |||||
'name' => "CompanionApp Password Grant Client", | |||||
'secret' => "VerySecret", | |||||
'provider' => 'users', | |||||
'redirect' => 'https://' . \config('app.website_domain'), | |||||
'personal_access_client' => 0, | |||||
'password_client' => 1, | |||||
'revoked' => false, | |||||
'allowed_scopes' => ["mfa"] | |||||
]); | |||||
print(var_export($client, true)); | |||||
$client->save(); | |||||
$companionApp->oauth_client_id = $client->id; | |||||
$companionApp->save(); | |||||
$companionApp->refresh(); | $tokenRepository = app(TokenRepository::class); | ||||
$this->assertEquals($notificationToken, $companionApp->notification_token); | $tokenRepository->create([ | ||||
'id' => 'testtoken', | |||||
'revoked' => false, | |||||
'user_id' => $user->id, | |||||
'client_id' => $client->id | |||||
]); | |||||
// Failing input valdiation | //Make sure we have a token to revoke | ||||
$response = $this->actingAs($user)->post( | $tokenCount = Token::where('user_id', $user->id)->where('client_id', $client->id)->count(); | ||||
"api/v4/companion/register", | $this->assertTrue($tokenCount > 0); | ||||
[] | |||||
); | |||||
$response->assertStatus(422); | |||||
// Other users device | |||||
$user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | $response = $this->actingAs($user2)->delete("api/v4/companions/{$companionApp->id}"); | ||||
$response = $this->actingAs($user2)->post( | |||||
"api/v4/companion/register", | |||||
['notificationToken' => $notificationToken, 'deviceId' => $deviceId, 'name' => $name] | |||||
); | |||||
$response->assertStatus(403); | $response->assertStatus(403); | ||||
$response = $this->actingAs($user)->delete("api/v4/companions/{$companionApp->id}"); | |||||
$response->assertStatus(200); | |||||
$json = $response->json(); | |||||
$this->assertCount(2, $json); | |||||
$this->assertSame('success', $json['status']); | |||||
$this->assertSame("Companion app has been removed.", $json['message']); | |||||
$client->refresh(); | |||||
$this->assertSame((bool)$client->revoked, true); | |||||
$companionApp = \App\CompanionApp::where('device_id', 'testdevice')->first(); | |||||
$this->assertTrue($companionApp == null); | |||||
$tokenCount = Token::where('user_id', $user->id) | |||||
->where('client_id', $client->id) | |||||
->where('revoked', false)->count(); | |||||
$this->assertSame(0, $tokenCount); | |||||
} | } | ||||
/** | |||||
* Test listing apps | |||||
*/ | |||||
public function testIndex(): void | public function testIndex(): void | ||||
{ | { | ||||
$response = $this->get("api/v4/companion"); | $response = $this->get("api/v4/companions"); | ||||
$response->assertStatus(401); | $response->assertStatus(401); | ||||
$user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | $user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | ||||
$companionApp = $this->getTestCompanionApp( | $companionApp = $this->getTestCompanionApp( | ||||
'testdevice', | 'testdevice', | ||||
$user, | $user, | ||||
[ | [ | ||||
'notification_token' => 'notificationtoken', | 'notification_token' => 'notificationtoken', | ||||
'mfa_enabled' => 1, | 'mfa_enabled' => 1, | ||||
'name' => 'testname', | 'name' => 'testname', | ||||
] | ] | ||||
); | ); | ||||
$response = $this->actingAs($user)->get("api/v4/companion"); | $response = $this->actingAs($user)->get("api/v4/companions"); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$this->assertSame(1, $json['count']); | $this->assertSame(1, $json['count']); | ||||
$this->assertCount(1, $json['list']); | $this->assertCount(1, $json['list']); | ||||
$this->assertSame($user->id, $json['list'][0]['user_id']); | $this->assertSame($user->id, $json['list'][0]['user_id']); | ||||
$this->assertSame($companionApp['device_id'], $json['list'][0]['device_id']); | $this->assertSame($companionApp['device_id'], $json['list'][0]['device_id']); | ||||
$this->assertSame($companionApp['name'], $json['list'][0]['name']); | $this->assertSame($companionApp['name'], $json['list'][0]['name']); | ||||
$this->assertSame($companionApp['notification_token'], $json['list'][0]['notification_token']); | $this->assertSame($companionApp['notification_token'], $json['list'][0]['notification_token']); | ||||
$this->assertSame($companionApp['mfa_enabled'], $json['list'][0]['mfa_enabled']); | $this->assertSame($companionApp['mfa_enabled'], $json['list'][0]['mfa_enabled']); | ||||
$user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | $user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | ||||
$response = $this->actingAs($user2)->get( | $response = $this->actingAs($user2)->get( | ||||
"api/v4/companion" | "api/v4/companions" | ||||
); | ); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$this->assertSame(0, $json['count']); | $this->assertSame(0, $json['count']); | ||||
$this->assertCount(0, $json['list']); | $this->assertCount(0, $json['list']); | ||||
} | } | ||||
/** | |||||
* Test showing the app | |||||
*/ | |||||
public function testShow(): void | public function testShow(): void | ||||
{ | { | ||||
$user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | $user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | ||||
$companionApp = $this->getTestCompanionApp('testdevice', $user); | $companionApp = $this->getTestCompanionApp('testdevice', $user); | ||||
$response = $this->get("api/v4/companion/{$companionApp->id}"); | $response = $this->get("api/v4/companions/{$companionApp->id}"); | ||||
$response->assertStatus(401); | $response->assertStatus(401); | ||||
$response = $this->actingAs($user)->get("api/v4/companion/aaa"); | $response = $this->actingAs($user)->get("api/v4/companions/aaa"); | ||||
$response->assertStatus(404); | $response->assertStatus(404); | ||||
$response = $this->actingAs($user)->get("api/v4/companion/{$companionApp->id}"); | $response = $this->actingAs($user)->get("api/v4/companions/{$companionApp->id}"); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$this->assertSame($companionApp->id, $json['id']); | $this->assertSame($companionApp->id, $json['id']); | ||||
$user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | $user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | ||||
$response = $this->actingAs($user2)->get("api/v4/companion/{$companionApp->id}"); | $response = $this->actingAs($user2)->get("api/v4/companions/{$companionApp->id}"); | ||||
$response->assertStatus(403); | $response->assertStatus(403); | ||||
} | } | ||||
public function testPairing(): void | |||||
{ | |||||
$response = $this->get("api/v4/companion/pairing"); | |||||
$response->assertStatus(401); | |||||
/** | |||||
* Test registering the app | |||||
*/ | |||||
public function testRegister(): void | |||||
{ | |||||
$user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | $user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | ||||
$response = $this->actingAs($user)->get("api/v4/companion/pairing"); | |||||
$companionApp = $this->getTestCompanionApp( | |||||
'testdevice', | |||||
$user, | |||||
[ | |||||
'notification_token' => 'notificationtoken', | |||||
'mfa_enabled' => 0, | |||||
'name' => 'testname', | |||||
] | |||||
); | |||||
$notificationToken = "notificationToken"; | |||||
$deviceId = "deviceId"; | |||||
$name = "testname"; | |||||
$response = $this->actingAs($user)->post( | |||||
"api/v4/companion/register", | |||||
[ | |||||
'notificationToken' => $notificationToken, | |||||
'deviceId' => $deviceId, | |||||
'name' => $name, | |||||
'companionId' => $companionApp->id | |||||
] | |||||
); | |||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $companionApp->refresh(); | ||||
$this->assertArrayHasKey('qrcode', $json); | $this->assertTrue($companionApp != null); | ||||
$this->assertSame('data:image/svg+xml;base64,', substr($json['qrcode'], 0, 26)); | $this->assertEquals($deviceId, $companionApp->device_id); | ||||
$this->assertEquals($name, $companionApp->name); | |||||
$this->assertEquals($notificationToken, $companionApp->notification_token); | |||||
$this->assertTrue((bool)$companionApp->mfa_enabled); | |||||
// Companion id required | |||||
$response = $this->actingAs($user)->post( | |||||
"api/v4/companion/register", | |||||
['notificationToken' => $notificationToken, 'deviceId' => $deviceId, 'name' => $name] | |||||
); | |||||
$response->assertStatus(422); | |||||
// Test a token update | |||||
$notificationToken = "notificationToken2"; | |||||
$response = $this->actingAs($user)->post( | |||||
"api/v4/companion/register", | |||||
[ | |||||
'notificationToken' => $notificationToken, | |||||
'deviceId' => $deviceId, | |||||
'name' => $name, | |||||
'companionId' => $companionApp->id | |||||
] | |||||
); | |||||
$response->assertStatus(200); | |||||
$companionApp->refresh(); | |||||
$this->assertEquals($notificationToken, $companionApp->notification_token); | |||||
// Failing input valdiation | |||||
$response = $this->actingAs($user)->post( | |||||
"api/v4/companion/register", | |||||
[] | |||||
); | |||||
$response->assertStatus(422); | |||||
// Other users device | |||||
$user2 = $this->getTestUser('CompanionAppsTest2@userscontroller.com'); | |||||
$response = $this->actingAs($user2)->post( | |||||
"api/v4/companion/register", | |||||
[ | |||||
'notificationToken' => $notificationToken, | |||||
'deviceId' => $deviceId, | |||||
'name' => $name, | |||||
'companionId' => $companionApp->id | |||||
] | |||||
); | |||||
$response->assertStatus(403); | |||||
} | } | ||||
public function testRevoke(): void | |||||
/** | |||||
* Test getting the pairing info | |||||
*/ | |||||
public function testPairing(): void | |||||
{ | { | ||||
$user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | $user = $this->getTestUser('CompanionAppsTest1@userscontroller.com'); | ||||
$companionApp = $this->getTestCompanionApp('testdevice', $user); | |||||
$clientIdentifier = \App\Tenant::getConfig($user->tenant_id, 'auth.companion_app.client_id'); | |||||
$tokenRepository = app(TokenRepository::class); | $companionApp = $this->getTestCompanionApp( | ||||
$tokenRepository->create([ | 'testdevice', | ||||
'id' => 'testtoken', | $user, | ||||
'revoked' => false, | [ | ||||
'user_id' => $user->id, | 'notification_token' => 'notificationtoken', | ||||
'client_id' => $clientIdentifier | 'mfa_enabled' => 0, | ||||
]); | 'name' => 'testname', | ||||
] | |||||
//Make sure we have a token to revoke | ); | ||||
$tokenCount = Token::where('user_id', $user->id)->where('client_id', $clientIdentifier)->count(); | |||||
$this->assertTrue($tokenCount > 0); | |||||
$response = $this->post("api/v4/companion/revoke"); | $response = $this->get("api/v4/companions/{$companionApp->id}/pairing"); | ||||
$response->assertStatus(401); | $response->assertStatus(401); | ||||
$response = $this->actingAs($user)->post("api/v4/companion/revoke"); | $response = $this->actingAs($user)->get("api/v4/companions/{$companionApp->id}/pairing"); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | |||||
$this->assertSame('success', $json['status']); | |||||
$this->assertArrayHasKey('message', $json); | |||||
$companionApp = \App\CompanionApp::where('device_id', 'testdevice')->first(); | $companionApp->refresh(); | ||||
$this->assertTrue($companionApp == null); | $this->assertTrue($companionApp->oauth_client_id != null); | ||||
$tokenCount = Token::where('user_id', $user->id) | $json = $response->json(); | ||||
->where('client_id', $clientIdentifier) | $this->assertArrayHasKey('qrcode', $json); | ||||
->where('revoked', false)->count(); | $this->assertSame('data:image/svg+xml;base64,', substr($json['qrcode'], 0, 26)); | ||||
$this->assertSame(0, $tokenCount); | |||||
} | } | ||||
} | } |