Change record status: 
Project: 
Introduced in branch: 
10.1.x
Introduced in version: 
10.1.0
Description: 

Before:

As per the original report at #3311563: Safeguarding against UnblockUser::execute()'s method unblocking the anonymous user, a User object could potentially be unconditionally activated by simply calling the User::activate() method on the object at hand, even if the User object would be the anonymous user.

In relation to that, the method User::isAnonymous() was not as strict as one would expect.
It would return respectively TRUE for entities that would not have an id set, as in, not yet persisted to the database. This is semantically equivalent to interacting with newly created entities and the codes in core reflected that as is the case in the following example:

    // Check for new account.
    $register = $account->isAnonymous();

(from https://git.drupalcode.org/project/drupal/-/blob/efda42f2fca0684e4b84580...)

or even

        // Allow view access to anyone with access to the entity.
        // The username field is editable during the registration process.
        if ($operation == 'view' || ($items && $items->getEntity()->isAnonymous())) {
          return AccessResult::allowed()->cachePerPermissions();
        }

(from https://git.drupalcode.org/project/drupal/-/blob/efda42f2fca0684e4b84580...)

After:

The User::activate() now makes sure that the User object it operates on is not the anonymous user as this unique User object should never be activated. This method will now throw a logical exception in that case.

Note for developers:
The method User::isAnonymous() is now more strict and will return FALSE for entities that do not have an id set, as in, new unpersisted entities.

Impacts: 
Module developers