v2-hub icon indicating copy to clipboard operation
v2-hub copied to clipboard

Use auto-incrementing IDs with Eloquent users instead of UUIDs

Open rdarcy1 opened this issue 7 years ago • 3 comments

Describe the bug Applies when using the Eloquent user driver.

When creating a new user, if the generated UUID can be cast to integer it will be written to the database instead of the database's auto-increment value. This pushes up the auto-increment value and has led to issues where the maximum integer value is reached in MySQL.

Affected UUIDs are those which start with integers (as PHP will cast these to a non-zero integer), e.g. 7336336d-6f3b-4f1f-9eff-b1dfa4a148a1.

To Reproduce This is difficult to reproduce 'naturally' as it only happens with a specific subset of UUIDs. We can simulate it happening by manually setting the UUID when creating a user.

In Statamic\CP\Publish\Publisher add the following $this->id assignment to line 111.

 public function publish()
    {
        // ...

        // Add the fieldset to the data if it was specified on the fly.
        $this->appendFieldset();

        // Commit any changes made by the user and/or the fieldtype processors back to the content object.
        $this->id = "7336336d-6f3b-4f1f-9eff-b1dfa4a148a1";
        $this->updateContent();

        // Save the file and any run any supplementary tasks like updating the cache, firing events, etc.
        $this->save();

        return $this->content;
    }

Save a user. See it has the ID 7336336 (the first part of the UUID).

Expected behavior The ID should not be set for Eloquent users, instead they should be assigned one by the database.

Fix We can check to see if the content is an eloquent user when updating the content in Statamic\CP\Publish\Publisher.

protected function updateContent()
    {
        if (! $this->content instanceof \Statamic\Data\Users\Eloquent\User) {
            $this->fields['id'] = $this->id;
        }

        // ...
    }

Environment details

  • Statamic Version 2.10.4
  • Fresh Install or Upgrade: Upgrade
  • PHP Version: 7.1

rdarcy1 avatar Oct 09 '18 10:10 rdarcy1

@jackmcdade This has been labelled as a feature request but I'd say it's more of a bug – it's causing the integer ID column in the database to reach its max value very quickly (due to the auto incremement value being pushed up unecessarily).

For a site with only a few thousand users I've had to manually re-assign IDs above a threshold and reset the auto-incr value on the table three times because it hit its limit.

rdarcy1 avatar Oct 29 '18 10:10 rdarcy1

I think our original intentions with the feature was for new sites, but yeah I guess you're right on that one.

jackmcdade avatar Oct 29 '18 14:10 jackmcdade

I don't know if this helps anyone but I was able to solve my issue by validating and adding to the database beforehand to get the ID. Seems to be working locally. I changed line 41 of Statamic\CP\Publish\UserPublisher from:

$this->id = Helper::makeUuid();

to:

if(Config::get('users.driver') === 'eloquent') {
    //validate the submission before adding user to DB 
    $this->addUserValidation('new');
    $submission = array_merge($this->request->all(), ['fields' => $this->fields]);
    $this->validateSubmission($submission);

    //add user to database to get the id
    $user = $user->save();
    $this->id = $user->id();
    $this->content = User::find($this->id);
} else {
    $this->id = Helper::makeUuid();
}

EDIT:

And also changing line 50 from:

$this->addUserValidation('new');

to:

if(Config::get('users.driver') === 'eloquent') {
    $this->addUserValidation('existing');
} else {
    $this->addUserValidation('new');
}

michaelb332 avatar Mar 03 '20 11:03 michaelb332