Authentication - how to get associated data & tests error

Hi there

I am currently developing on cakephp 4.0.x and I am using the new cakephp/authentication (v2.0). Works so far soo good.

I have two issues, I do not know how to solve…

First issue. In AppController I am checking if the user is logged in. If so, I want to pass the users data (with related hasOne Profile) to the template. I saw in the authentication book following section: IdentityInterface on User class.

Now I managed to get the users’ profile by using the ConnectionManager, but this seems not like a good solution. Is there a better way to go, to use the Profile entity by cake?

// src/Model/Entity/User.php
use Authentication\IdentityInterface;
class User extends Entity implements IdentityInterface {
// ...
public function getOriginalData()
{
    $conn = ConnectionManager::get('default');
    $stmt = $conn->execute('SELECT * FROM profiles WHERE user_id = ' . $this->id);
    $results = $stmt ->fetchAll('assoc');

    $this->profile = $results[0];
    debug($this); exit;
    return $this;
}

The second issue. Since I installed the authentication plugin, my phpunit tests are failing. The PagesControllerTest.php file fails with 5 failures, but I did not change anything on the test files. I even let the PagesControllerTest.php use the default cakephp home file (Pages/home.php) with its original layout and content, but still.

Here are the errors:

There were 5 failures:

1) App\Test\TestCase\ApplicationTest::testBootstrap
Failed asserting that actual size 5 matches expected size 3.

/var/www/my_app/tests/TestCase/ApplicationTest.php:43

2) App\Test\TestCase\Controller\PagesControllerTest::testMissingTemplate
Failed asserting that 302 is between 400 and 429.

/var/www/my_app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestTrait.php:797
/var/www/my_app/tests/TestCase/Controller/PagesControllerTest.php:68

3) App\Test\TestCase\Controller\PagesControllerTest::testMissingTemplateInDebug
Failed asserting that 302 is between 500 and 505.

/var/www/my_app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestTrait.php:808
/var/www/my_app/tests/TestCase/Controller/PagesControllerTest.php:82

4) App\Test\TestCase\Controller\PagesControllerTest::testDirectoryTraversalProtection
Failed asserting that `403` matches response status code `302`.

/var/www/my_app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestTrait.php:820
/var/www/my_app/tests/TestCase/Controller/PagesControllerTest.php:96

5) App\Test\TestCase\Controller\PagesControllerTest::testCsrfAppliedError
Failed asserting that `403` matches response status code `302`.

/var/www/my_app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestTrait.php:820
/var/www/my_app/tests/TestCase/Controller/PagesControllerTest.php:109

FAILURES!
Tests: 59, Assertions: 16, Failures: 5, Incomplete: 49.

The errorcodes tell me that the authentication plugin is making issues here, because the PagesControllerTest.php wants to get its own error codes, but only gets 302 (unauthenticated). How can I turn that plugin off for testing purposes?

Second issue: With the authentication middleware active in your application you’ll need to simulate authentication credentials in your integration tests. You can read here: https://github.com/cakephp/authentication/blob/master/docs/en/testing.rst

1 Like

Thank you. Don’t know how I didn’t see that in the docs :slight_smile: .
Now I just need to fix the part with the associated data… Any idea?

You can try that…

public function getOriginalData()
{
$profile = TableRegistry::getTableLocator()->get(‘Profiles’);
$profile = $profile->find … //Query here
$this->profile = $profile;
debug($this); exit;
return $this;
}

1 Like

Thank you!
Works like a charm. Don’t know how I didn’t came up with that solution. But thank you.

You can add things (like your profile) to the Identity object (which is available after login) by setting a custom finder to use in your Identifier. In the Authentication configuration in Application.php do something like this:

        $service->loadIdentifier('Authentication.Password', [
            'fields' => $fields,
            'resolver' => [
                'className' => 'Authentication.Orm',
                'userModel' => 'Users',
                'finder' => 'AuthRecord',
            ],
        ]);

The finder key is where you name the finder you want.

1 Like