From 2a5de20bd7f5f9ca73fe8117744b1bf9aa2bc8de Mon Sep 17 00:00:00 2001 From: Noah Miller Date: Tue, 5 Sep 2023 13:55:15 -0400 Subject: [PATCH] implement OAuthSessionToken, with tests --- .../Civi/Api4/OAuthSessionToken.php | 87 +++++++++++ .../Civi/OAuth/OAuthTokenFacade.php | 2 +- .../phpunit/api/v4/OAuthSessionTokenTest.php | 140 ++++++++++++++++++ 3 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 ext/oauth-client/Civi/Api4/OAuthSessionToken.php create mode 100644 ext/oauth-client/tests/phpunit/api/v4/OAuthSessionTokenTest.php diff --git a/ext/oauth-client/Civi/Api4/OAuthSessionToken.php b/ext/oauth-client/Civi/Api4/OAuthSessionToken.php new file mode 100644 index 0000000000..5c96d018ce --- /dev/null +++ b/ext/oauth-client/Civi/Api4/OAuthSessionToken.php @@ -0,0 +1,87 @@ +exchangeArray(OAuthSessionToken::get()); + \CRM_Core_Session::singleton()->set('OAuthSessionTokens'); + } + + })->setCheckPermissions($checkPermissions); + } + + /** + * @param bool $checkPermissions + * @return Generic\BasicGetAction + */ + public static function get($checkPermissions = TRUE): Generic\BasicGetAction { + $action = new Generic\BasicGetAction(self::ENTITY, __FUNCTION__, function () { + $session = \CRM_Core_Session::singleton(); + return $session->get('OAuthSessionTokens') ?? []; + }); + return $action->setCheckPermissions($checkPermissions); + } + + public static function create($checkPermissions = TRUE): Generic\BasicCreateAction { + $action = new Generic\BasicCreateAction( + self::ENTITY, + __FUNCTION__, + function ($item, $createAction) { + $session = \CRM_Core_Session::singleton(); + $all = $session->get('OAuthSessionTokens') ?? []; + $all[] = &$item; + $item['cardinal'] = array_key_last($all); + $session->set('OAuthSessionTokens', $all); + return $item; + }); + return $action->setCheckPermissions($checkPermissions); + } + + /** + * @param bool $checkPermissions + * @return Generic\BasicGetFieldsAction + */ + public static function getFields($checkPermissions = TRUE) { + $action = new Generic\BasicGetFieldsAction(self::ENTITY, __FUNCTION__, function () { + return [ + [ + 'name' => 'client_id', + 'required' => TRUE, + ], + ['name' => 'grant_type'], + ['name' => 'tag'], + ['name' => 'scopes'], + ['name' => 'token_type'], + ['name' => 'access_token'], + ['name' => 'refresh_token'], + ['name' => 'expires'], + ['name' => 'raw'], + ['name' => 'storage'], + ['name' => 'resource_owner_name'], + ['name' => 'resource_owner'], + ]; + }); + return $action->setCheckPermissions($checkPermissions); + } + + /** + * @return array + */ + public static function permissions() { + return [ + "meta" => ["access CiviCRM"], + "default" => ["administer CiviCRM data"], + ]; + } + +} diff --git a/ext/oauth-client/Civi/OAuth/OAuthTokenFacade.php b/ext/oauth-client/Civi/OAuth/OAuthTokenFacade.php index 679599c0e3..45718390e9 100644 --- a/ext/oauth-client/Civi/OAuth/OAuthTokenFacade.php +++ b/ext/oauth-client/Civi/OAuth/OAuthTokenFacade.php @@ -6,7 +6,7 @@ use League\OAuth2\Client\Provider\ResourceOwnerInterface; class OAuthTokenFacade { - const STORAGE_TYPES = ';^OAuth(Sys|Contact)Token$;'; + const STORAGE_TYPES = ';^OAuth(Sys|Contact|Session)Token$;'; /** * Request and store a token. diff --git a/ext/oauth-client/tests/phpunit/api/v4/OAuthSessionTokenTest.php b/ext/oauth-client/tests/phpunit/api/v4/OAuthSessionTokenTest.php new file mode 100644 index 0000000000..82431d04df --- /dev/null +++ b/ext/oauth-client/tests/phpunit/api/v4/OAuthSessionTokenTest.php @@ -0,0 +1,140 @@ +install('oauth-client')->apply(); + } + + public function setUp(): void { + parent::setUp(); + $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_oauth_client')); + $this->assertNull(CRM_Core_Session::singleton()->get('OAuthSessionTokens') ?? NULL); + } + + protected function tearDown(): void { + CRM_Core_Session::singleton()->reset(); + parent::tearDown(); + } + + private function createClient(): ?array { + $createClient = Civi\Api4\OAuthClient::create(FALSE)->setValues( + [ + 'provider' => 'test_example_1', + 'guid' => "example-client-guid", + 'secret' => "example-secret", + ] + )->execute(); + $client = $createClient->first(); + $this->assertTrue(is_numeric($client['id'])); + return $client; + } + + private function getTestTokenCreateValues($client, $secretPrefix) { + return [ + 'client_id' => $client['id'], + 'access_token' => "$secretPrefix-user-access-token", + 'refresh_token' => "$secretPrefix-user-refresh-token", + ]; + } + + public function testAnonymousSessionCanHoldToken() { + self::assertNull(CRM_Core_Session::getLoggedInContactID()); + + $client = $this->createClient(); + $tokenCreateValues = $this->getTestTokenCreateValues($client, 'anon'); + + Civi\Api4\OAuthSessionToken::create(FALSE) + ->setValues($tokenCreateValues) + ->execute(); + + $retrievedToken = \Civi\Api4\OAuthSessionToken::get(FALSE) + ->addWhere('client_id', '=', $client['id']) + ->execute() + ->first(); + + $this->assertEquals($client['id'], $retrievedToken['client_id']); + $this->assertEquals($tokenCreateValues['access_token'], $retrievedToken['access_token']); + $this->assertEquals($tokenCreateValues['refresh_token'], $retrievedToken['refresh_token']); + } + + public function testAnonymousSessionTokensCanBeDeleted() { + self::assertNull(CRM_Core_Session::getLoggedInContactID()); + + $client = $this->createClient(); + $tokenCreateValues = $this->getTestTokenCreateValues($client, 'anon'); + + Civi\Api4\OAuthSessionToken::create(FALSE) + ->setValues($tokenCreateValues) + ->execute(); + + \Civi\Api4\OAuthSessionToken::deleteAll(FALSE) + ->execute(); + + $retrievedTokens = \Civi\Api4\OAuthSessionToken::get(FALSE) + ->execute() + ->first(); + + $this->assertEmpty($retrievedTokens); + } + + public function testLoggedInSessionCanHoldToken() { + $this->createLoggedInUser(); + self::assertIsNumeric(CRM_Core_Session::getLoggedInContactID()); + + $client = $this->createClient(); + $tokenCreateValues = $this->getTestTokenCreateValues($client, 'loggedIn'); + + Civi\Api4\OAuthSessionToken::create(FALSE) + ->setValues($tokenCreateValues) + ->execute(); + + $retrievedToken = \Civi\Api4\OAuthSessionToken::get(FALSE) + ->addWhere('client_id', '=', $client['id']) + ->execute() + ->first(); + + $this->assertEquals($client['id'], $retrievedToken['client_id']); + $this->assertEquals($tokenCreateValues['access_token'], $retrievedToken['access_token']); + $this->assertEquals($tokenCreateValues['refresh_token'], $retrievedToken['refresh_token']); + } + + public function testLoggingOutDeletesTokens() { + $this->createLoggedInUser(); + self::assertIsNumeric(CRM_Core_Session::getLoggedInContactID()); + + $client = $this->createClient(); + $tokenCreateValues = $this->getTestTokenCreateValues($client, 'loggedIn'); + + Civi\Api4\OAuthSessionToken::create(FALSE) + ->setValues($tokenCreateValues) + ->execute(); + + // log out + CRM_Core_Session::singleton()->reset(); + self::assertNull(CRM_Core_Session::getLoggedInContactID()); + + $retrievedTokens = \Civi\Api4\OAuthSessionToken::get(FALSE) + ->execute() + ->first(); + + $this->assertEmpty($retrievedTokens); + } + +} -- 2.25.1