All users forced into Welcome to SuiteCRM wizard on every login

Thanks pgr, I have arrived at the same place, but I can’t find a column or field for ā€˜ut’ in the DB in the users or user preferences tables, or anywhere in Bean Land. I would be most interested to see the files field_arrays.php and vardefs.php from the …/modules/UserPreferences directory of a working 7.14.5 system. I may need to do a clean install of 7.14.5 if nobody can help.

You can find the original files in GitHub, start by going into the correct branch for your intended version, then navigate the directories to get to the file.

Some user preferences are stored inside a base64-encoded JSON field in user table.

Search these forums for base64decode to learn about this. It’s not too difficult to get and set those parameters manually, and it really helps troubleshooting.

Thanks pgr, much appreciated. I’m sure learning a lot!

1 Like

Was thinking I was the only one with that issue, but look like not,

Started with SuiteCRM 7.14.6

For now I just press next quickly to access to the CRM.

Bug reported here: Regression: Local users gets Profile wizard on each login Ā· Issue #10637 Ā· salesagility/SuiteCRM Ā· GitHub

There is also a fix proposal.

1 Like

Issue 1

The proposed fix suggested on Regression: Local users gets Profile wizard on each login Ā· Issue #10637 Ā· salesagility/SuiteCRM Ā· GitHub still won’t work, because in reloadPreferences() in the modules/UserPreferences/UserPreference.php that inner if

        if ($row) {
            if (!$GLOBALS['current_user']->id || $GLOBALS['current_user']->user_name === $user->user_name){
                $_SESSION[$user->user_name . '_PREFERENCES'][$category] = unserialize(base64_decode($row['contents']));
            }
            $user->user_preferences[$category] = unserialize(base64_decode($row['contents']));
            return true;
        } else {
            if (!$GLOBALS['current_user']->id || $GLOBALS['current_user']->user_name === $user->user_name){
                $_SESSION[$user->user_name . '_PREFERENCES'][$category] = array();
            }
            $user->user_preferences[$category] = array();
        }

will never be true for your Google‐Sync user when run under cron, since current_user is always the admin. As a result, the sync user’s session bucket never gets populated—instead it falls through to the ā€œelseā€ and gets reset to an empty array. That change was introduced in commit ea756b13f0ae606997c0ccb4382e1a72902a9207 (ā€œAdd check for current user on session preferencesā€) and has broken Google‐Sync users

Fix

Or remove the condition completely

if (!$GLOBALS['current_user']->id || $GLOBALS['current_user']->user_name === $user->user_name){

Or add an extra condition like

if (PHP_SAPI === 'cli' || $GLOBALS['current_user']->user_name === $user->user_name){

Whenever PHP is invoked from the command‐line (for example by your cron job), its ā€œServer APIā€ string (PHP_SAPI) is set to cli. In contrast, when PHP runs as an Apache module it might be apache2handler, or under PHP‐FPM it’s fpm‐cgi, etc.

This will always be true in the cron context, because you’re literally calling php -f cron.php (the CLI binary), not going through the web server. That guarantees your session‐reload logic fires under cron even though current_user is still ā€œadmin.

Issue 2

On the other hand, the function getGoogleClient in the file include/GoogleSync/GoogleSyncBase.php needs also a small fix for code optimization so it does not refresh the Google API token every minute. To fix this, pass the ā€œno-sessionā€ flag (0) as the third argument and the category as the fourth:

By changing from

                $this->workingUser->setPreference('GoogleApiToken', base64_encode(json_encode($client->getAccessToken())), 'GoogleSync');

to

$this->workingUser->setPreference('GoogleApiToken', base64_encode(json_encode($client->getAccessToken())), 0,'GoogleSync');

you are making sure that the generated GoogleApiToken is actually saved under the user preference GoogleSync and not Global

If you make this change the token is saved under the GoogleSync category, so subsequent runs will load the existing token and only refresh when it’s actually expired.

The current behaviour means that the function getGoogleClient always perceives the GoogleApiToken as expired and forces the token to be reloaded because it cannot find it in the GoogleSync preference.