silverstripe / silverstripe-staticpublishqueue

This module allows you to build static HTML caches of every page (for increased security and performance)
BSD 3-Clause "New" or "Revised" License
46 stars 57 forks source link

Running StaticCacheFullBuildTask via QueuedJobs admin logs user out #171

Open emteknetnz opened 1 year ago

emteknetnz commented 1 year ago

From https://github.com/silverstripe/silverstripe-staticpublishqueue/pull/168#pullrequestreview-1575939203

6.0.0

1) Run vendor/bin/sake dev/tasks/SilverStripe-StaticPublishQueue-Task-StaticCacheFullBuildTask from CLI - this create a queuedjob 2) Run it via the QueuedJobsAdmin it times out after 30 seconds and logs me out. 3) It did create files in the public/cache directory though messages for the job showed [ALERT] Fatal Error (E_ERROR): Maximum execution time of 30 seconds exceeded {"code":1,"message":"Maximum execution time of 30 seconds exceeded","file":"/var/www/vendor/silverstripe/framework/src/ORM/FieldType /DBDate.php","line":87,"trace":null} [] Tried reverting framework to 5.0.0, same issue.

joelgrondrup commented 2 months ago

Hi guys,

I had a similar problem, but in the CMS. After starting a job which should generate some static pages for caching I was always logged out. I thought it was a memory issue, but it wasn't.

After investigating I found the problem in the end of a function called runJob($jobId) in the class QueuedJobService in the SilverStripe Queued Jobs module.

There is a call to $this->unsetRunAsUser($runAsUser, $originalUser), but if the runAsUser is null, Security will never log in a user again after the job has been running in a new Kernel.

To fix the problem I injected a custom class on top of QueuedJobService and made a few changes to the protected function unsetRunAsUser:

/**
     * @param Member|null $runAsUser
     * @param Member|null $originalUser
     */
    protected function unsetRunAsUser(Member $runAsUser = null, Member $originalUser = null)
    {
        // No runAsUser was set, so we don't need to do anything.
        //This fixes the problem
        if ($runAsUser === null **&& $originalUser === null**) {
            return;
        }

        // There was no originalUser, so we should make sure that we set the user back to null.
        if (!$originalUser) {

            if (Controller::has_curr()) {
                Security::setCurrentUser(null);
            } else {
                $_SESSION['loggedInAs'] = null;
            }

            return;
        }

        // Okay let's reset our user.
        if (Controller::has_curr()) {
            Security::setCurrentUser($originalUser);
            **//This fixes the problem
            $identityStore = Injector::inst()->get(IdentityStore::class);
            $identityStore->logIn($originalUser, true);**
        } else {
            $_SESSION['loggedInAs'] = $originalUser->ID;
        }
    }

Now, I'm still logged into the cms after creating the static pages. This is probably not best practice, but it fixed my problem.

Summary.

  1. Create a yml with this content:

SilverStripe\Core\Injector\Injector: Symbiote\QueuedJobs\Services\QueuedJobService: class: CustomQueuedJobService

  1. Copy the class QueuedJobService from the SilverStripe Queued Jobs module and make a custom class and change the function as described above: CustomQueuedJobService.txt

Voila.

Hope it's useful for someone. And that maybe @symbiote can have a look at this.