diff --git a/.config/.filestorage/.gitignore b/.config/.filestorage/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/.config/.filestorage/.gitignore @@ -0,0 +1 @@ +* diff --git a/examples/OAuthExampleProviderFactory.php b/examples/OAuthExampleProviderFactory.php index 05d0592..16dc2e9 100644 --- a/examples/OAuthExampleProviderFactory.php +++ b/examples/OAuthExampleProviderFactory.php @@ -9,15 +9,16 @@ */ declare(strict_types=1); -require_once __DIR__.'/OAuthExampleSessionStorage.php'; - use chillerlan\DotEnv\DotEnv; use chillerlan\OAuth\Core\OAuth1Interface; use chillerlan\OAuth\Core\OAuth2Interface; use chillerlan\OAuth\Core\OAuthInterface; use chillerlan\OAuth\OAuthOptions; use chillerlan\OAuth\OAuthProviderFactory; +use chillerlan\OAuth\Storage\FileStorage; use chillerlan\OAuth\Storage\MemoryStorage; +use chillerlan\OAuth\Storage\OAuthStorageInterface; +use chillerlan\OAuth\Storage\SessionStorage; use chillerlan\Settings\SettingsContainerInterface; use Monolog\Formatter\LineFormatter; use Monolog\Handler\NullHandler; @@ -82,12 +83,20 @@ public function getProvider( $storage = new MemoryStorage; if($sessionStorage === true){ - $storage = new OAuthExampleSessionStorage(options: $options, storagepath: $this->cfgDir); + $storage = new SessionStorage(options: $options); } return $this->factory->getProvider($providerFQN, $options, $storage); } + public function getFileStorage():OAuthStorageInterface{ + $options = new OAuthOptions; + + $options->fileStoragePath = $this->cfgDir.'/.filestorage'; + + return new FileStorage('oauth-example', $options, $this->logger); + } + public function getEnvVar(string $var):mixed{ return $this->dotEnv->get($var); } diff --git a/examples/OAuthExampleSessionStorage.php b/examples/OAuthExampleSessionStorage.php deleted file mode 100644 index 9cd4380..0000000 --- a/examples/OAuthExampleSessionStorage.php +++ /dev/null @@ -1,86 +0,0 @@ - - * @copyright 2019 smiley - * @license MIT - */ -declare(strict_types=1); - -use chillerlan\OAuth\Core\AccessToken; -use chillerlan\OAuth\OAuthOptions; -use chillerlan\OAuth\Storage\{OAuthStorageException, SessionStorage}; -use chillerlan\Settings\SettingsContainerInterface; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; - -class OAuthExampleSessionStorage extends SessionStorage{ - - protected string|null $storagepath; - - /** - * OAuthExampleSessionStorage constructor. - * - * @throws \chillerlan\OAuth\Storage\OAuthStorageException - */ - public function __construct( - OAuthOptions|SettingsContainerInterface $options = new OAuthOptions, - LoggerInterface $logger = new NullLogger, - string|null $storagepath = null, - ){ - parent::__construct($options, $logger); - - if($storagepath !== null){ - $storagepath = trim($storagepath); - - if(!is_dir($storagepath) || !is_writable($storagepath)){ - throw new OAuthStorageException('invalid storage path'); - } - - $storagepath = realpath($storagepath); - } - - $this->storagepath = $storagepath; - } - - /** - * @inheritDoc - */ - public function storeAccessToken(AccessToken $token, string $provider):static{ - parent::storeAccessToken($token, $provider); - - if($this->storagepath !== null){ - $tokenfile = sprintf('%s/%s.token.json', $this->storagepath, $this->getProviderName($provider)); - - if(file_put_contents($tokenfile, $token->toJSON()) === false){ - throw new OAuthStorageException('unable to access file storage'); - } - } - - return $this; - } - - /** - * @inheritDoc - */ - public function getAccessToken(string $provider):AccessToken{ - $provider = $this->getProviderName($provider); - - if($this->hasAccessToken($provider)){ - return (new AccessToken)->fromJSON($_SESSION[$this->tokenVar][$provider]); - } - - if($this->storagepath !== null){ - $tokenfile = sprintf('%s/%s.token.json', $this->storagepath, $provider); - - if(file_exists($tokenfile)){ - return (new AccessToken)->fromJSON(file_get_contents($tokenfile)); - } - } - - throw new OAuthStorageException(sprintf('token for provider "%s" not found', $provider)); - } - -} diff --git a/tests/Providers/ProviderLiveTestAbstract.php b/tests/Providers/ProviderLiveTestAbstract.php index 9506bda..248cb28 100644 --- a/tests/Providers/ProviderLiveTestAbstract.php +++ b/tests/Providers/ProviderLiveTestAbstract.php @@ -13,13 +13,10 @@ use chillerlan\DotEnv\DotEnv; use chillerlan\OAuth\OAuthOptions; +use chillerlan\OAuth\Storage\FileStorage; use chillerlan\OAuth\Storage\OAuthStorageInterface; -use InvalidArgumentException; use function constant; use function defined; -use function ltrim; -use function realpath; -use function sprintf; /** * @@ -30,7 +27,6 @@ abstract class ProviderLiveTestAbstract extends ProviderUnitTestAbstract{ protected DotEnv $dotEnv; protected string $ENV_PREFIX; - protected string $CFG_DIR; /** a test username for live API tests, defined in .env as {ENV-PREFIX}_TESTUSER*/ protected string $TEST_USER = ''; @@ -40,16 +36,11 @@ abstract class ProviderLiveTestAbstract extends ProviderUnitTestAbstract{ */ protected function setUp():void{ - // are we running on CI? (initializing this here too, so we can back out before initializing the provider) - $this->ENV_IS_CI = defined('TEST_IS_CI') && constant('TEST_IS_CI') === true; - - if($this->ENV_IS_CI){ + // are we running on CI? (checking this here, so we can back out before initializing the provider) + if(defined('TEST_IS_CI') && constant('TEST_IS_CI') === true){ $this->markTestSkipped('not on CI (set TEST_IS_CI in phpunit.xml to "false" if you want to run live API tests)'); } - // set the config dir and .env config before initializing the provider - $this->initEnvConfig(); - // init provider etc. parent::setUp(); } @@ -59,30 +50,18 @@ protected function setUp():void{ */ abstract protected function getEnvPrefix():string; - protected function initEnvConfig():void{ - - foreach(['TEST_CFGDIR', 'TEST_ENVFILE'] as $constant){ - if(!defined($constant)){ - throw new InvalidArgumentException(sprintf('constant "%s" not set -> see phpunit.xml', $constant)); - } - } - - $cfgdir = constant('TEST_CFGDIR'); - $this->CFG_DIR = realpath($this::PROJECT_ROOT.ltrim($cfgdir, '/\\')); - - if($this->CFG_DIR === false){ - throw new InvalidArgumentException(sprintf('invalid config dir "%s" (relative from project root)', $cfgdir)); - } + protected function initConfig():void{ + parent::initConfig(); $this->dotEnv = (new DotEnv($this->CFG_DIR, constant('TEST_ENVFILE'), false))->load(); $this->ENV_PREFIX = $this->getEnvPrefix(); - $this->TEST_USER = (string)$this->dotEnv->get($this->ENV_PREFIX.'_TESTUSER'); - + $this->TEST_USER = (string)$this->dotEnv->get($this->ENV_PREFIX.'_TESTUSER'); } protected function initOptions():OAuthOptions{ $options = new OAuthOptions; $options->tokenAutoRefresh = true; + $options->fileStoragePath = $this->CFG_DIR.'/.filestorage'; if(!empty($this->ENV_PREFIX)){ $options->key = ($this->dotEnv->get($this->ENV_PREFIX.'_KEY') ?? ''); @@ -93,7 +72,7 @@ protected function initOptions():OAuthOptions{ } protected function initStorage(OAuthOptions $options):OAuthStorageInterface{ - return new ProviderLiveTestMemoryStorage($options, $this->CFG_DIR); + return new FileStorage('oauth-example', $options); } } diff --git a/tests/Providers/ProviderLiveTestMemoryStorage.php b/tests/Providers/ProviderLiveTestMemoryStorage.php deleted file mode 100644 index 21883a1..0000000 --- a/tests/Providers/ProviderLiveTestMemoryStorage.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @copyright 2019 smiley - * @license MIT - */ -declare(strict_types = 1); - -namespace chillerlan\OAuthTest\Providers; - -use chillerlan\OAuth\Core\AccessToken; -use chillerlan\OAuth\OAuthOptions; -use chillerlan\OAuth\Storage\{MemoryStorage, OAuthStorageException}; -use chillerlan\Settings\SettingsContainerInterface; -use InvalidArgumentException; -use function file_exists; -use function file_get_contents; -use function file_put_contents; -use function is_dir; -use function is_writable; -use function realpath; -use function sprintf; - -/** - * Extends the standard memory storage so that it also saves tokens as JSON in the given path - */ -final class ProviderLiveTestMemoryStorage extends MemoryStorage{ - - protected string $storagePath; - - public function __construct(OAuthOptions|SettingsContainerInterface $options = null, string $storagePath = null){ - parent::__construct($options); - - $storagePath = realpath($storagePath ?? ''); - - if($storagePath === false || !is_dir($storagePath) || !is_writable($storagePath)){ - throw new InvalidArgumentException('invalid storage path'); - } - - $this->storagePath = $storagePath; - } - - /** - * @inheritDoc - */ - public function storeAccessToken(AccessToken $token, string $provider = null):static{ - parent::storeAccessToken($token, $provider); - - $tokenFile = sprintf('%s/%s.token.json', $this->storagePath, $this->getProviderName($provider)); - - if(file_put_contents($tokenFile, $token->toJSON()) === false){ - throw new OAuthStorageException('unable to access file storage'); - } - - return $this; - } - - /** - * @inheritDoc - */ - public function getAccessToken(string $provider = null):AccessToken{ - $providerName = $this->getProviderName($provider); - - if($this->hasAccessToken($provider)){ - return $this->tokens[$providerName]; - } - - $tokenFile = sprintf('%s/%s.token.json', $this->storagePath, $providerName); - - if(file_exists($tokenFile)){ - return (new AccessToken)->fromJSON(file_get_contents($tokenFile)); - } - - throw new OAuthStorageException('token not found'); - } - -} diff --git a/tests/Providers/ProviderUnitTestAbstract.php b/tests/Providers/ProviderUnitTestAbstract.php index 7e43749..6370064 100644 --- a/tests/Providers/ProviderUnitTestAbstract.php +++ b/tests/Providers/ProviderUnitTestAbstract.php @@ -17,6 +17,7 @@ use chillerlan\OAuth\Storage\MemoryStorage; use chillerlan\OAuth\Storage\OAuthStorageInterface; use chillerlan\PHPUnitHttp\HttpFactoryTrait; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; @@ -28,6 +29,7 @@ use function constant; use function defined; use function ini_set; +use function ltrim; use function realpath; use function sprintf; @@ -46,7 +48,8 @@ abstract class ProviderUnitTestAbstract extends TestCase{ protected string $HTTP_CLIENT_FACTORY = ProviderUnitTestHttpClientFactory::class; - protected bool $ENV_IS_CI; + protected string $CFG_DIR; + protected bool $ENV_IS_CI; protected const PROJECT_ROOT = __DIR__.'/../../'; protected const CACERT = __DIR__.'/../cacert.pem'; @@ -58,6 +61,7 @@ protected function setUp():void{ $this->ENV_IS_CI = defined('TEST_IS_CI') && constant('TEST_IS_CI') === true; try{ + $this->initConfig(); $this->initFactories(realpath($this::CACERT)); $this->logger = (new ProviderTestLoggerFactory)->getLogger($this->ENV_IS_CI); // PSR-3 logger @@ -96,13 +100,32 @@ abstract protected function getProviderFQCN():string; * init dependencies */ + protected function initConfig():void{ + + foreach(['TEST_CFGDIR', 'TEST_ENVFILE'] as $constant){ + if(!defined($constant)){ + throw new InvalidArgumentException(sprintf('constant "%s" not set -> see phpunit.xml', $constant)); + } + } + + $cfgdir = constant('TEST_CFGDIR'); + $this->CFG_DIR = realpath($this::PROJECT_ROOT.ltrim($cfgdir, '/\\')); + + if($this->CFG_DIR === false){ + throw new InvalidArgumentException(sprintf('invalid config dir "%s" (relative from project root)', $cfgdir)); + } + + } + protected function initOptions():OAuthOptions{ - return new OAuthOptions([ - 'key' => 'testclient', - 'secret' => 'testsecret', - 'callbackURL' => 'https://localhost/callback', - 'tokenAutoRefresh' => true, - ]); + $options = new OAuthOptions; + + $options->key = 'testclient'; + $options->secret = 'testsecret'; + $options->callbackURL = 'https://localhost/callback'; + $options->tokenAutoRefresh = true; + + return $options; } protected function initStorage(OAuthOptions $options):OAuthStorageInterface{