Skip to content

Commit

Permalink
Merge pull request #614 from cakephp/3.x-merge
Browse files Browse the repository at this point in the history
2.x => 3.x merge and fix tests
  • Loading branch information
ADmad authored May 1, 2023
2 parents 6ed2925 + 254edbe commit b79691e
Show file tree
Hide file tree
Showing 20 changed files with 93 additions and 218 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/stale@v6
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open for 120 days with no activity. Remove the `stale` label or comment or this will be closed in 15 days'
Expand Down
1 change: 1 addition & 0 deletions docs/en/contents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Contents
/middleware
/authentication-component
/testing
/impersonation
/url-checkers
/view-helper
/migration-from-the-authcomponent
4 changes: 2 additions & 2 deletions docs/en/impersonation.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
User Impersonation
##################

.. versionadded:: 3.0.0
.. versionadded:: 2.10.0
User impersonation was added.

After deploying your application, you may occasionally need to
Expand All @@ -15,7 +15,7 @@ To impersonate another user you can use the ``impersonate()`` method on the
``AuthenticationComponent``. To impersonate a user you first need to load that
user from your application's database::

// In a controller
// In a controller
public function impersonate()
{
$this->request->allowMethod(['POST']);
Expand Down
5 changes: 3 additions & 2 deletions docs/en/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Project's ROOT directory (where the **composer.json** file is located)

.. code-block:: bash
php composer.phar require "cakephp/authentication:^2.0"
php composer.phar require cakephp/authentication
Version 2 of the Authentication Plugin is compatible with CakePHP 4.

Expand Down Expand Up @@ -149,7 +149,7 @@ Building a Login Action
=======================

Once you have the middleware applied to your application you'll need a way for
users to login. First generate a Users model and controller with bake:
users to login. Please ensure your database has been created with the Users table structure used in :doc:`tutorial </tutorials-and-examples/cms/database>`. First generate a Users model and controller with bake:

.. code-block:: shell
Expand Down Expand Up @@ -244,6 +244,7 @@ Further Reading
* :doc:`/identifiers`
* :doc:`/password-hashers`
* :doc:`/identity-object`
* :doc:`/middleware`
* :doc:`/authentication-component`
* :doc:`/impersonation`
* :doc:`/url-checkers`
Expand Down
7 changes: 7 additions & 0 deletions docs/en/migration-from-the-authcomponent.rst
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ present::
Each call to ``allowUnauthenticated()`` will overwrite the current
action list.

To mimic ``$this->Auth->deny(['register']);`` you can do::

$action = $this->getRequest()->getParam('action');
if ($action !== 'register') {
$this->Authentication->allowUnauthenticated([$action]);
}

Migrating Unauthenticated Redirects
===================================

Expand Down
15 changes: 1 addition & 14 deletions src/Authenticator/CookieAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,23 +235,10 @@ protected function _createCookie(mixed $value): CookieInterface
$name = $options['name'];
unset($options['name']);

if (array_key_exists('expire', $options)) {
deprecationWarning('2.x', 'Config key `expire` is deprecated, use `expires` instead.');
$options['expires'] = $options['expire'];
unset($options['expire']);
}
if (array_key_exists('httpOnly', $options)) {
deprecationWarning('2.x', 'Config key `httpOnly` is deprecated, use `httponly` instead.');
$options['httponly'] = $options['httpOnly'];
unset($options['httpOnly']);
}

$cookie = Cookie::create(
return Cookie::create(
$name,
$value,
$options
);

return $cookie;
}
}
7 changes: 6 additions & 1 deletion src/Controller/Component/AuthenticationComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace Authentication\Controller\Component;

use ArrayAccess;
use ArrayObject;
use Authentication\AuthenticationServiceInterface;
use Authentication\Authenticator\ImpersonationInterface;
use Authentication\Authenticator\PersistenceInterface;
Expand Down Expand Up @@ -375,12 +376,16 @@ public function impersonate(ArrayAccess $impersonated)
if (!$identity) {
throw new UnauthenticatedException('You must be logged in before impersonating a user.');
}
$impersonator = $identity->getOriginalData();
if (!($impersonator instanceof ArrayAccess)) {
$impersonator = new ArrayObject($impersonator);
}
$controller = $this->getController();
/** @psalm-var array{request: \Cake\Http\ServerRequest, response: \Cake\Http\Response} $result */
$result = $service->impersonate(
$controller->getRequest(),
$controller->getResponse(),
$identity,
$impersonator,
$impersonated
);

Expand Down
4 changes: 2 additions & 2 deletions src/Identifier/Resolver/OrmResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function __construct(array $config = [])
/**
* @inheritDoc
*/
public function find(array $conditions, $type = self::TYPE_AND): ArrayAccess|array|null
public function find(array $conditions, string $type = self::TYPE_AND): ArrayAccess|array|null
{
$table = $this->getTableLocator()->get($this->_config['userModel']);

Expand All @@ -63,7 +63,7 @@ public function find(array $conditions, $type = self::TYPE_AND): ArrayAccess|arr
if (is_string($options)) {
$query->find($options);
} else {
$query->find($finder, $options);
$query->find($finder, ...$options);
}
}

Expand Down
45 changes: 1 addition & 44 deletions src/Middleware/AuthenticationMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,24 @@
*/
namespace Authentication\Middleware;

use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Authenticator\AuthenticationRequiredException;
use Authentication\Authenticator\StatelessInterface;
use Authentication\Authenticator\UnauthenticatedException;
use Cake\Core\InstanceConfigTrait;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\Response\RedirectResponse;
use Laminas\Diactoros\Stream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;

/**
* Authentication Middleware
*/
class AuthenticationMiddleware implements MiddlewareInterface
{
use InstanceConfigTrait;

/**
* Configuration options
*
* The following keys are deprecated and should instead be set on the AuthenticationService
*
* - `identityAttribute` - The request attribute to store the identity in.
* - `unauthenticatedRedirect` - The URL to redirect unauthenticated errors to. See
* AuthenticationComponent::allowUnauthenticated()
* - `queryParam` - The name of the query string parameter containing the previously blocked
* URL in case of unauthenticated redirect, or null to disable appending the denied URL.
*
* @var array
*/
protected array $_defaultConfig = [];

/**
* Authentication service or application instance.
*
Expand All @@ -65,15 +45,12 @@ class AuthenticationMiddleware implements MiddlewareInterface
* Constructor
*
* @param \Authentication\AuthenticationServiceInterface|\Authentication\AuthenticationServiceProviderInterface $subject Authentication service or application instance.
* @param array $config Array of configuration settings.
* @throws \InvalidArgumentException When invalid subject has been passed.
*/
public function __construct(
AuthenticationServiceInterface|AuthenticationServiceProviderInterface $subject,
array $config = []
AuthenticationServiceInterface|AuthenticationServiceProviderInterface $subject
) {
$this->subject = $subject;
$this->setConfig($config);
}

/**
Expand Down Expand Up @@ -144,26 +121,6 @@ protected function getAuthenticationService(ServerRequestInterface $request): Au
$subject = $subject->getAuthenticationService($request);
}

$forwardKeys = ['identityAttribute', 'unauthenticatedRedirect', 'queryParam'];
foreach ($forwardKeys as $key) {
$value = $this->getConfig($key);
if ($value) {
deprecationWarning(
'2.x',
"The `{$key}` configuration key on AuthenticationMiddleware is deprecated. " .
"Instead set the `{$key}` on your AuthenticationService instance."
);
if ($subject instanceof AuthenticationService) {
$subject->setConfig($key, $value);
} else {
throw new RuntimeException(
'Could not forward configuration to authentication service as ' .
'it does not implement `getConfig()`'
);
}
}
}

return $subject;
}
}
2 changes: 1 addition & 1 deletion src/UrlChecker/DefaultUrlChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function check(ServerRequestInterface $request, $loginUrls, array $option
*/
protected function _mergeDefaultOptions(array $options): array
{
return $options += $this->_defaultOptions;
return $options + $this->_defaultOptions;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion tests/TestCase/Authenticator/CookieAuthenticatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ public function testClearIdentity()
$this->assertInstanceOf(RequestInterface::class, $result['request']);
$this->assertInstanceOf(ResponseInterface::class, $result['response']);

$this->assertSame('CookieAuth=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/', $result['response']->getHeaderLine('Set-Cookie'));
$cookieHeader = $result['response']->getHeaderLine('Set-Cookie');
$this->assertStringContainsString('CookieAuth=; expires=Thu, 01-Jan-1970 00:00:01', $cookieHeader);
$this->assertStringContainsString('; path=/', $cookieHeader);
}
}
3 changes: 2 additions & 1 deletion tests/TestCase/Authenticator/HttpDigestAuthenticatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;
use PHPUnit\Framework\Constraint\RegularExpression;
use function Cake\Core\env;

/**
* Test case for HttpDigestAuthentication
Expand Down Expand Up @@ -300,7 +301,7 @@ public function testUnauthorizedFailReChallenge()
{
$this->auth->setConfig('scope.username', 'nate');

$nonce = $this->generateNonce();
$this->generateNonce();
$digest = <<<DIGEST
Digest username="mariano",
realm="localhost",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,11 +561,47 @@ public function testImpersonate()
$controller = new Controller($request, $this->response);
$registry = new ComponentRegistry($controller);
$component = new AuthenticationComponent($registry);

$this->assertEquals($impersonator, $controller->getRequest()->getSession()->read('Auth'));
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->impersonate($impersonated);
$this->assertEquals($impersonated, $controller->getRequest()->getSession()->read('Auth'));
$this->assertEquals($identity, $controller->getRequest()->getSession()->read('AuthImpersonate'));
$this->assertEquals($impersonator, $controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->stopImpersonating();
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));
}

/**
* test that impersonate() can handle identities with array data within them.
*
* @return void
*/
public function testImpersonateDecoratorIgnored()
{
$impersonator = ['username' => 'mariano'];
$impersonated = new ArrayObject(['username' => 'larry']);

$this->request->getSession()->write('Auth', $impersonator);
$this->service->authenticate($this->request);
$identity = new Identity($impersonator);
$request = $this->request
->withAttribute('identity', $identity)
->withAttribute('authentication', $this->service);
$controller = new Controller($request, $this->response);
$registry = new ComponentRegistry($controller);
$component = new AuthenticationComponent($registry);

$this->assertEquals($impersonator, $controller->getRequest()->getSession()->read('Auth'));
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->impersonate($impersonated);
$this->assertEquals($impersonated, $controller->getRequest()->getSession()->read('Auth'));
$this->assertEquals(new ArrayObject($impersonator), $controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->stopImpersonating();
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Identifier/IdentifierCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function testIdentify()
$this->assertInstanceOf('\ArrayAccess', $result);
$this->assertInstanceOf(PasswordIdentifier::class, $collection->getIdentificationProvider());

$result = $collection->identify([
$collection->identify([
'username' => 'mariano',
'password' => 'invalid password',
]);
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Identifier/Resolver/OrmResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function testFindConfig()
'userModel' => 'AuthUsers',
'finder' => [
'all',
'auth' => ['return_created' => true],
'auth' => ['returnCreated' => true],
],
]);

Expand Down
Loading

0 comments on commit b79691e

Please sign in to comment.