User password reset form should use a more precise cache context

Created on 17 January 2025, 3 months ago

Problem/Motivation

This form declares it varies by the 'url.query_args' cache context. But when I look at the code, the only query arg (GET param) it relies on is "name". So the cache context should be 'url.query_args:name'.
See 🐛 "Taxonomy term ID from URL" default views argument should have url.path as cache context, not url Active or #2983187: Use more strict views url query argument caching for similar issues and why it matters.

Proposed resolution

MR is coming.

User interface changes

Possibly better performance.

API changes

None.

Data model changes

None.

🐛 Bug report
Status

Needs work

Version

11.1 🔥

Component

user.module

Created by

🇫🇷France GaëlG Lille, France

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @GaëlG
  • 🇫🇷France GaëlG Lille, France
  • Pipeline finished with Success
    3 months ago
    Total: 611s
    #398901
  • 🇺🇸United States smustgrave

    IS seems to be incomplete.

    Proposed solution is missing (MR coming isn't valid)
    User Interface mentions performance improvements, wrong section but how does this improve performance?

  • 🇫🇷France GaëlG Lille, France

    Thanks for the review, I updated the IS.

  • 🇫🇷France GaëlG Lille, France
  • 🇺🇸United States smustgrave

    MR actually needs to point to 11.x please

    If you are another contributor eager to jump in, please allow the previous poster at least 48 hours to respond to feedback first, so they have the opportunity to finish what they started!

  • Pipeline finished with Canceled
    3 months ago
    Total: 408s
    #414335
  • Pipeline finished with Failed
    3 months ago
    Total: 125s
    #414340
  • 🇫🇷France GaëlG Lille, France
  • Pipeline finished with Failed
    3 months ago
    Total: 556s
    #414343
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Hmm, looks like the original code (not your MR) is more broken than just what's reported here.

    The statement:

        // THIS CHECK MEANS WE NEED TO VARY BY user.roles:authenticated REGARDLESS OF OUTCOME
        if ($user->isAuthenticated()) {
    
        else {
    
        }
    

    First section of that statement:

          // THIS REQUIRES THE USER TO BE A CACHEABLE DEPENDENCY
          $form['name']['#value'] = $user->getEmail();
    

    Please note forms didn't used to be cacheable, but now they are (somewhat). So that might explain why this wasn't set in the past.

    Second section of that statement (goal of this issue):

         // THIS CHECK MEANS WE NEED TO VARY BY url.query_args REGARDLESS OF OUTCOME, BUT ONLY HERE. NOT REGARDLESS OF IF-STATEMENT OUTCOME.
          $form['name']['#default_value'] = $this->getRequest()->query->get('name');
    

    So the full code should probably look something like this:

        // Allow logged in users to request this also.
        $cacheability = (new CacheableMetadata())->addCacheContexts(['user.roles:authenticated']);
        $user = $this->currentUser();
        if ($user->isAuthenticated()) {
          $cacheability->addCacheableDependency($user);
          $form['name']['#type'] = 'value';
          $form['name']['#value'] = $user->getEmail();
          $form['mail'] = [
            '#prefix' => '<p>',
            '#markup' => $this->t('Password reset instructions will be mailed to %email. You must log out to use the password reset link in the email.', ['%email' => $user->getEmail()]),
            '#suffix' => '</p>',
          ];
        }
        else {
          $form['mail'] = [
            '#prefix' => '<p>',
            '#markup' => $this->t('Password reset instructions will be sent to your registered email address.'),
            '#suffix' => '</p>',
          ];
          $form['name']['#default_value'] = $this->getRequest()->query->get('name');
          $cacheability->addCacheContexts(['url.query_args']);
        }
        $cacheability->applyTo($form);
        $form['actions'] = ['#type' => 'actions'];
        $form['actions']['submit'] = ['#type' => 'submit', '#value' => $this->t('Submit')];
    
        return $form;
    
Production build 0.71.5 2024