CakeDC / users

Users Plugin for CakePHP
https://www.cakedc.com
Other
521 stars 296 forks source link

Cake\Routing\Exception\MissingRouteException for url's generated by Url helper in layout #983

Closed C8Robin closed 2 years ago

C8Robin commented 2 years ago

Navigation in my layout builds urls using the Url builder.

958 and #935 seem similar, but not exactly, although #935 mentions also view building links seems to cause the issue.

When attempting to render a page as a non logged-in user, I get a MissingRouteException for those urls that the layout is asking the Url helper to build.

I noticed that the routes being requested include 'plugin'=> 'CakeDC/Users' ; I assume this is the case because the user is not yet logged in. See example below, no route requested with plugin reference.

Would expect a Url->build(...) request to work in a layout, as I am not asking to execute that request yet, just build the link. Tried the AuthLink helper, but the result is the same.

Reproduce

CakeDC/Users: 11.0.0 CakePHP: 4.3.5

Layout extract

<main class="main">
    <div class="container">
        <?= $this->Url->build(['controller' => 'Books']);?>
        <?= $this->Flash->render() ?>
        <?= $this->fetch('content') ?>
    </div>
</main>

Application.php

public function bootstrap(): void
    {
        // Call parent to load bootstrap from files.
        parent::bootstrap();

        if (PHP_SAPI === 'cli') {
            $this->bootstrapCli();
        } else {
            FactoryLocator::add(
                'Table',
                (new TableLocator())->allowFallbackClass(false)
            );
        }

        /*
         * Only try to load DebugKit in development mode
         * Debug Kit should not be installed on a production system
         */
        if (Configure::read('debug')) {
            $this->addPlugin('DebugKit');
        }

        // Load more plugins here
        $this->addPlugin('CakeDC/Users');
    }
C8Robin commented 2 years ago

After some more testing, I noticed that providing a url as a string, does not lead to this problem. This exception only manifests when requesting Url to build a url.

e.g. <?= $this->Html->link('Books', ['controller' => 'Books'])?> will raise that exception, when user is not logged in while <?= $this->Html->link('Books','/books/')?> will not.

I notice that HTML helper requests Url helper to build a url, without altering the url that was given:

if ($url !== null) {
    $url = $this->Url->build($url, $options);
    unset($options['fullBase']);
} else {
...
}

Inspecting Url helper's argument 'url' in Url::build, I notice that these are the values of that url (checked via DebugKit, in my browser):

[
    'controller' => 'Books',
    'plugin' => 'CakeDC/Users',
    'action' => 'index',
    '_ext' => null,
]

I don't know how or why 'plugin' => 'CakeDC/Users' got in there, maybe some middleware is inserting this?

In the list of available routes (DebugKit again), I see that this route exists:

/{controller} =>

[
  'plugin' => null,
  'action' => 'index',
]

Workaround for now is probably to use strings as urls in my layout (i.e. the site navigation), but that might break in the future I guess.

Am still puzzled...

C8Robin commented 2 years ago

Maybe a better workaround for now, is to generate my site nav urls like this:

<?= $this->Html->link('Books', ['plugin' => false, 'controller' => 'Books'])?>

This link works, and when not logged in I am redirected to the login page.

Doesn't solve the root cause, and if I would have to do this throughout my application, it would not be very elegant.

inlandsailor commented 2 years ago

I am getting the same error on a site using CakeDC/users plugin. The site worked fine on Saturday. I first became aware of the issue on Sunday.

Prior to this, attempting to access a valid url when not authenticated would redirect to a login page.

inlandsailor commented 2 years ago

Confirmed C8Robin's workaround using HTML helper and including 'plugin' => false works for my situation also. The issue appeared recently for me due to adding HTML helper code on the home.php page.

rochamarcelo commented 2 years ago

That's how HtmlHelper and UrlHelper works. They will create url based on current request, if you are accessing a plugin or prefix url they will use the current plugin|prefix. To use a non plugin|prefix url you must do what you did <?= $this->Html->link('Books', ['plugin' => false, 'controller' => 'Books'])?> or <?= $this->Html->link('Books', ['plugin' => false, 'prefix' => false, 'controller' => 'Books'])?>