Skip to content

Commit

Permalink
Expand Configuration Properties (and Refactor Config Builder) (#381)
Browse files Browse the repository at this point in the history
  • Loading branch information
evansims authored Apr 26, 2023
1 parent 6f23b16 commit 29fbb0a
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 35 deletions.
184 changes: 149 additions & 35 deletions src/Auth0.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
use Auth0\SDK\Auth0 as SDK;
use Auth0\SDK\Configuration\SdkConfiguration as Configuration;
use Auth0\SDK\Contract\API\ManagementInterface;
use Auth0\SDK\Contract\Auth0Interface as SDKContract;
use Auth0\SDK\Contract\{Auth0Interface as SDKContract, StoreInterface};
use Auth0\SDK\Utility\HttpTelemetry;
use Psr\Cache\CacheItemPoolInterface;

use function in_array;
use function is_string;

/**
* Service that provides access to the Auth0 SDK.
Expand All @@ -31,9 +33,144 @@ final class Auth0 implements ServiceContract
public function __construct(
private ?SDKContract $sdk = null,
private ?Configuration $configuration = null,
private ?CacheItemPoolInterface $tokenCachePool = null,
private ?CacheItemPoolInterface $managementTokenCachePool = null,
) {
}

private function bootManagementTokenCache(array $config): array
{
$managementTokenCache = $config['managementTokenCache'] ?? null;

if (false === $managementTokenCache) {
unset($config['managementTokenCache']);

return $config;
}

if (null === $managementTokenCache) {
$managementTokenCache = $this->getManagementTokenCachePool();
}

if (is_string($managementTokenCache)) {
$managementTokenCache = app(trim($managementTokenCache));
}

$config['managementTokenCache'] = $managementTokenCache instanceof CacheItemPoolInterface ? $managementTokenCache : null;

return $config;
}

private function bootSessionStorage(array $config): array
{
$sessionStorage = $config['sessionStorage'] ?? null;
$sessionStorageId = $config['sessionStorageId'] ?? 'auth0_session';

if (false === $sessionStorage) {
unset($config['sessionStorage']);

return $config;
}

if (null === $sessionStorage) {
$sessionStorage = app(LaravelSession::class, [
'prefix' => $sessionStorageId,
]);
}

if (is_string($sessionStorage)) {
$sessionStorage = app(trim($sessionStorage), [
'prefix' => $sessionStorageId,
]);
}

$config['sessionStorage'] = $sessionStorage instanceof StoreInterface ? $sessionStorage : null;

return $config;
}

private function bootStrategy(array $config): array
{
$strategy = $config['strategy'] ?? Configuration::STRATEGY_REGULAR;

if (! is_string($strategy)) {
$strategy = Configuration::STRATEGY_REGULAR;
}

$config['strategy'] = $strategy;

return $config;
}

private function bootTokenCache(array $config): array
{
$tokenCache = $config['tokenCache'] ?? null;

if (false === $tokenCache) {
unset($config['tokenCache']);

return $config;
}

if (null === $tokenCache) {
$tokenCache = $this->getTokenCachePool();
}

if (is_string($tokenCache)) {
$tokenCache = app(trim($tokenCache));
}

$config['tokenCache'] = $tokenCache instanceof CacheItemPoolInterface ? $tokenCache : null;

return $config;
}

private function bootTransientStorage(array $config): array
{
$transientStorage = $config['transientStorage'] ?? null;
$transientStorageId = $config['transientStorageId'] ?? 'auth0_transient';

if (false === $transientStorage) {
unset($config['transientStorage']);

return $config;
}

if (null === $transientStorage) {
$transientStorage = app(LaravelSession::class, [
'prefix' => $transientStorageId,
]);
}

if (is_string($transientStorage)) {
$transientStorage = app(trim($transientStorage), [
'prefix' => $transientStorageId,
]);
}

$config['transientStorage'] = $transientStorage instanceof StoreInterface ? $transientStorage : null;

return $config;
}

private function getManagementTokenCachePool(): CacheItemPoolInterface
{
if (! $this->managementTokenCachePool instanceof CacheItemPoolInterface) {
$this->managementTokenCachePool = app(LaravelCachePool::class);
}

return $this->managementTokenCachePool;
}

private function getTokenCachePool(): CacheItemPoolInterface
{
if (! $this->tokenCachePool instanceof CacheItemPoolInterface) {
$this->tokenCachePool = app(LaravelCachePool::class);
}

return $this->tokenCachePool;
}

/**
* Updates the Auth0 PHP SDK's telemetry to include the correct Laravel markers.
*/
Expand All @@ -53,49 +190,26 @@ public function getConfiguration(): Configuration
/**
* @var array<mixed> $config
*/
if (! isset($config['tokenCache']) || ! isset($config['managementTokenCache'])) {
$cache = new LaravelCachePool();

if (! isset($config['tokenCache'])) {
$config['tokenCache'] = $cache;
}

if (! isset($config['managementTokenCache'])) {
$config['managementTokenCache'] = $cache;
}
}

// Give host application an opportunity to update the configuration before assigning defaults.
$event = new Building($config);
event($event);
$config = $event->getConfiguration();

$configuration = new Configuration($event->getConfiguration());
$config = $this->bootStrategy($config);
$config = $this->bootTokenCache($config);
$config = $this->bootManagementTokenCache($config);

if (! in_array($configuration->getStrategy(), [Configuration::STRATEGY_API, Configuration::STRATEGY_MANAGEMENT_API], true)) {
// If no sessionStorage is defined, use an LaravelSession store instance.
if (! isset($config['sessionStorage'])) {
$sessionStore = app(LaravelSession::class, [
'prefix' => $configuration->getSessionStorageId(),
]);

$configuration->setSessionStorage(sessionStorage: $sessionStore);
}

// If no transientStorage is defined, use an LaravelSession store instance.
if (! isset($config['transientStorage'])) {
$transientStore = app(LaravelSession::class, [
'prefix' => $configuration->getTransientStorageId(),
]);

$configuration->setTransientStorage(transientStorage: $transientStore);
}
if (in_array($config['strategy'], Configuration::STRATEGIES_USING_SESSIONS, true)) {
$config = $this->bootSessionStorage($config);
$config = $this->bootTransientStorage($config);
}

$this->configuration = $configuration;
$config = new Configuration($config);

// Give apps an opportunity to mutate the configuration before applying it.
$event = new Built($configuration);
// Give host application an opportunity to update the configuration before applying it.
$event = new Built($config);
event($event);

$this->configuration = $event->getConfiguration();
}

Expand Down
104 changes: 104 additions & 0 deletions tests/Unit/Auth0Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,107 @@
$updated = spl_object_id($laravel->getSdk());
expect($cache)->not->toBe($updated);
});

test('bootStrategy() rejects non-string values', function (): void {
$method = new ReflectionMethod(Auth0::class, 'bootStrategy');
$method->setAccessible(true);

expect($method->invoke($this->laravel, ['strategy' => 123]))
->toMatchArray(['strategy' => SdkConfiguration::STRATEGY_REGULAR]);
});

test('bootSessionStorage() behaves as expected', function (): void {
$method = new ReflectionMethod(Auth0::class, 'bootSessionStorage');
$method->setAccessible(true);

expect($method->invoke($this->laravel, []))
->sessionStorage->toBeInstanceOf(LaravelSession::class);

expect($method->invoke($this->laravel, ['sessionStorage' => null]))
->sessionStorage->toBeInstanceOf(LaravelSession::class);

expect($method->invoke($this->laravel, ['sessionStorage' => false]))
->sessionStorage->toBeNull();

expect($method->invoke($this->laravel, ['sessionStorage' => LaravelCachePool::class]))
->sessionStorage->toBeNull();

expect($method->invoke($this->laravel, ['sessionStorage' => MemoryStore::class]))
->sessionStorage->toBeInstanceOf(MemoryStore::class);

$this->app->singleton('testStore', static fn (): MemoryStore => app(MemoryStore::class));

expect($method->invoke($this->laravel, ['sessionStorage' => 'testStore']))
->sessionStorage->toBeInstanceOf(MemoryStore::class);
});

test('bootTransientStorage() behaves as expected', function (): void {
$method = new ReflectionMethod(Auth0::class, 'bootTransientStorage');
$method->setAccessible(true);

expect($method->invoke($this->laravel, []))
->transientStorage->toBeInstanceOf(LaravelSession::class);

expect($method->invoke($this->laravel, ['transientStorage' => null]))
->transientStorage->toBeInstanceOf(LaravelSession::class);

expect($method->invoke($this->laravel, ['transientStorage' => false]))
->transientStorage->toBeNull();

expect($method->invoke($this->laravel, ['transientStorage' => LaravelCachePool::class]))
->transientStorage->toBeNull();

expect($method->invoke($this->laravel, ['transientStorage' => MemoryStore::class]))
->transientStorage->toBeInstanceOf(MemoryStore::class);

$this->app->singleton('testStore', static fn (): MemoryStore => app(MemoryStore::class));

expect($method->invoke($this->laravel, ['transientStorage' => 'testStore']))
->transientStorage->toBeInstanceOf(MemoryStore::class);
});

test('bootTokenCache() behaves as expected', function (): void {
$method = new ReflectionMethod(Auth0::class, 'bootTokenCache');
$method->setAccessible(true);

expect($method->invoke($this->laravel, []))
->tokenCache->toBeInstanceOf(LaravelCachePool::class);

expect($method->invoke($this->laravel, ['tokenCache' => null]))
->tokenCache->toBeInstanceOf(LaravelCachePool::class);

expect($method->invoke($this->laravel, ['tokenCache' => LaravelCachePool::class]))
->tokenCache->toBeInstanceOf(LaravelCachePool::class);

expect($method->invoke($this->laravel, ['tokenCache' => false]))
->tokenCache->toBeNull();

expect($method->invoke($this->laravel, ['tokenCache' => MemoryStore::class]))
->tokenCache->toBeNull();

expect($method->invoke($this->laravel, ['tokenCache' => 'cache.psr6']))
->tokenCache->toBeInstanceOf(CacheItemPoolInterface::class);
});

test('bootManagementTokenCache() behaves as expected', function (): void {
$method = new ReflectionMethod(Auth0::class, 'bootManagementTokenCache');
$method->setAccessible(true);

expect($method->invoke($this->laravel, []))
->managementTokenCache->toBeInstanceOf(LaravelCachePool::class);

expect($method->invoke($this->laravel, ['managementTokenCache' => null]))
->managementTokenCache->toBeInstanceOf(LaravelCachePool::class);

expect($method->invoke($this->laravel, ['managementTokenCache' => LaravelCachePool::class]))
->managementTokenCache->toBeInstanceOf(LaravelCachePool::class);

expect($method->invoke($this->laravel, ['managementTokenCache' => false]))
->managementTokenCache->toBeNull();

expect($method->invoke($this->laravel, ['managementTokenCache' => MemoryStore::class]))
->managementTokenCache->toBeNull();

expect($method->invoke($this->laravel, ['managementTokenCache' => 'cache.psr6']))
->managementTokenCache->toBeInstanceOf(CacheItemPoolInterface::class);
});

0 comments on commit 29fbb0a

Please sign in to comment.