jeroennoten / Laravel-AdminLTE

Easy AdminLTE integration with Laravel
MIT License
3.78k stars 1.08k forks source link

[BUG] Problem with DarkModeWasToggled event #1248

Closed Arametheus closed 3 months ago

Arametheus commented 5 months ago

So I set-up Persistent Dark mode to save to the DB. the issue I'm having is in the SetupDarkModePreference I get auth just fine but in StoreDarkModePreference Auth is null even though I'm logged in.

I'm running multi-tenacy not that should matter since thats taken care of way before this point.

I added in EventServiceProvider.

 // Listeners for the AdminLTE package events.
        ReadingDarkModePreference::class => [
            SetupDarkModePreference::class,
        ],

        DarkModeWasToggled::class => [
            StoreDarkModePreference::class,
        ],

my SetupDarkModePreference looks like

<?php

namespace App\Listeners;

use App\Helpers\AuthHelper;
use App\Models\Setting;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use JeroenNoten\LaravelAdminLte\Events\ReadingDarkModePreference;

class SetupDarkModePreference
{
    /**
     * The dark mode setting ID used on the database.
     *
     * @var string
     */
    protected $darkModeSettingId = 1;

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @return void
     */
    public function handle(ReadingDarkModePreference $event)
    {
        // Register listener for ReadingDarkModePreference event. We use this
        // event to setup dark mode initial status for AdminLTE package.

        $getCurrentAuth = (new AuthHelper())->getAuthClass();

        // Log::debug('Tenant ID: ' . tenant());
        // Log::debug('Handling event ReadingDarkModePreference ...');

        // First, check if user is authenticated.

        if (! $getCurrentAuth['check']) {
            // Log::debug('Can\'t get dark mode setting: user is not auth!');

            return;
        }

        // Now, get dark mode setting for the authenticated user.

        $darkModeCfg = $this->getDarkModeSetting();

        // When no setting available, skip the initial setup. It will fallback
        // to the one available on the AdminLTE configuration file.

        if (is_null($darkModeCfg)) {
            // Log::debug("Dark mode setting not available for user: " . $getCurrentAuth['user']->label);

            return;
        }

        // At this point, dark mode setting is available for the user.

        if ($darkModeCfg) {
            // Log::debug("Dark mode is enabled for user: " . $getCurrentAuth['user']->label);
            $event->darkMode->enable();
        } else {
            // Log::debug("Dark mode is disabled for user: " . $getCurrentAuth['user']->label);
            $event->darkMode->disable();
        }
    }

    /**
     * Get the dark mode setting for the current authenticated user.
     *
     * @return null|bool
     */
    protected function getDarkModeSetting()
    {
        $getCurrentAuth = (new AuthHelper())->getAuthClass();

        // Get the dark mode setting for the authenticated user.

        $darkModeSetting = $getCurrentAuth['user']->settings()
            ->where('setting_types_id', $this->darkModeSettingId)
            ->first();

        // Check if dark mode setting is available for the user.

        if (is_null($darkModeSetting)) {
            return null;
        }

        // Return the dark mode setting value for the user.
        // TODO: We should cast to the type described in database
        // (setting table) for the dark mode setting.

        return filter_var($darkModeSetting->active, FILTER_VALIDATE_BOOLEAN);
    }
}

my StoreDarkModePreference looks like

<?php

namespace App\Listeners;

use App\Helpers\AuthHelper;
use App\Models\SettingTypes;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use JeroenNoten\LaravelAdminLte\Events\DarkModeWasToggled;
use Session;

class StoreDarkModePreference
{
    /**
     * The dark mode setting ID used on the database.
     *
     * @var string
     */
    protected $darkModeSettingId = 1;

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @return void
     */
    public function handle(DarkModeWasToggled $event)
    {
        $getCurrentAuth = (new AuthHelper())->getAuthClass();
        Log::debug($getCurrentAuth['tenant']);

        // Register listener for DarkModeWasToggled AdminLTE event.

        Log::debug('Handling event DarkModeWasToggled ...');

        // First, check if user is authenticated.

        if (! $getCurrentAuth['check']) {
            Log::debug('Can\'t update dark mode setting: user is not auth!');

            return;
        }

        // Get the new dark mode setting for the authenticated user.
        $darkModeCfg = $event->darkMode->isEnabled();

        $status = $darkModeCfg ? 'enabled' : 'disabled';
        Log::debug('New dark mode setting for user '.$getCurrentAuth['user']->label.' is: '.$status);

        // Store the new dark mode setting for the authenticated user.

        $this->storeDarkModeSetting($darkModeCfg);
    }

    /**
     * Store the dark mode setting for the current authenticated user.
     *
     * @param  bool  $darkModeCfg
     * @return void
     */
    protected function storeDarkModeSetting($darkModeCfg)
    {
        $tmpTenantId = Session::get('tenant') == 'landlord' ? '' : Session::get('tenant');
        // Log::debug('Before initialization DB connection: ' . \DB::connection()->getName());
        Tenancy()->initialize($tmpTenantId);
        // Log::debug('After initialization DB connection: ' . \DB::connection()->getName());

        $tenantConnectionName = \DB::connection()->getName();
        // Log::debug('Set DB Name: ' . $tenantConnectionName);

        $getCurrentAuth = (new AuthHelper())->getAuthClass();

        // Check that dark mode setting is available on database.
        // Log::debug('store Tenant ID: ' . tenant());

        $setting = SettingTypes::on($tenantConnectionName)->where('id', $this->darkModeSettingId)->first();
        // Log::debug('Setting: ' . json_encode($setting));

        if (is_null($setting)) {
            // Log::warning('Dark mode setting is not available on database!');

            return;
        }

        $user = $getCurrentAuth['user'];
        $user->setConnection($tenantConnectionName);
        $user->settings()->updateOrCreate(['setting_types_id' => $this->darkModeSettingId], ['setting_types_id' => $this->darkModeSettingId, 'active' => ($darkModeCfg ? 1 : 0)]);
        // Log::debug('New dark mode setting is now stored on database!');
    }
}

and my AuthHelper looks like

<?php

namespace App\Helpers;

use App\Models\Locations;
use App\Models\Partners;
use App\Models\User;
use Auth;

class AuthHelper
{
    public function getAuthClass()
    {
        //Auth::login(User::find(4));

        $objAuth = [];
        $objAuth['user'] = Auth::user();
        $objAuth['class'] = User::class;
        $objAuth['check'] = Auth::check();
        $objAuth['tenant'] = tenant();

        if (Auth::guard('location')->check()) {
            $objAuth['user'] = Auth::guard('location')->user();
            $objAuth['class'] = Locations::class;
            $objAuth['check'] = Auth::guard('location')->check();
        }

        if (Auth::guard('partner')->check()) {
            $objAuth['user'] = Auth::user();
            $objAuth['class'] = Partners::class;
            $objAuth['check'] = Auth::guard('partner')->check();
        }

        return $objAuth;
    }

    public function getClassByTypeId($typeId)
    {
        $objAuth = [];
        $objAuth['user'] = Auth::user();
        $objAuth['class'] = User::class;

        if ($typeId == 2) {
            $objAuth['user'] = Auth::guard('location')->user();
            $objAuth['class'] = Locations::class;
        }

        if ($typeId == 3) {
            $objAuth['user'] = Auth::user();
            $objAuth['class'] = Partners::class;
        }

        return $objAuth;
    }

    public function getAuthId($id, $class)
    {
        $objAuth = [];
        $objAuth['user'] = (new $class)->find($id);
        $objAuth['class'] = $class;

        return $objAuth;
    }
}

its selecting the correct class since I'm signed in as a user.

I don't understand why the read is working fine but the store one is not..

Thanks for any help in advanced.

dfsmania commented 5 months ago

@Arametheus First, I need to mention that I shared this code previously on issue #1078 to exemplify how I was using persistent dark mode on my scenario, but that code also requires proper migrations to create a settings table and extensions on the user model to implement the relationship between those tables. I'm not sure if you have managed to figure out all those changes and how you implemented that in your system. In other words, that code won't work as a single copy+paste procedure...

Second, this isn't likely a bug in the package, but more like a custom integration of the feature. So, some questions:

1) How are you sure the SetupDarkModePreference handler is working fine?? Start debugging and tracing your logic so you know when the handle returns (in which step of the logic). Then share that information. Do the same for the other event handler.

2) Is the auth middleware correctly configured in the group of routes you are accessing? See https://laravel.com/docs/10.x/authentication#protecting-routes

Arametheus commented 4 months ago

@dfsmania Sorry took me so long to reply got slammed with a few other issues.

So I have a Settings table created and implemented the relationship for the user and that part is working.

  1. When I log or dump the Auth()->user() in SetupDarkModePreference I get my Logged in user. I also added logging to output to DebugBar which is also logging correctly.

  2. I have 3 types of auths (web, locations, partners) set correctly. which is why I created the helper I mentioned since I need to figure out who you are so I correctly use the correct auth's and Classes.

but even with out the helper and logged in as a web(user) if I log or dump out the auth object its null in storeDarkModeSetting

I guess I'm trying to figure out why auth is working fine in SetupDarkModePreference but in storeDarkModeSetting its not and they are 1 line away from each other.

dfsmania commented 4 months ago

Hi @Arametheus , please backup your StoreDarkModePreference listener and use the next one instead. I have the next code working on a Laravel 8.x system without any problems. I just want to check what trace do you get when toggling the dark mode button.

<?php

namespace App\Listeners;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use JeroenNoten\LaravelAdminLte\Events\DarkModeWasToggled;

class StoreDarkModePreference
{
    /**
     * The dark mode setting ID used on the database.
     *
     * @var string
     */
    protected $darkModeSettingId = 1;

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  DarkModeWasToggled  $event
     * @return void
     */
    public function handle(DarkModeWasToggled $event)
    {
        Log::debug('Handling event DarkModeWasToggled ...');

        // First, check if user is authenticated.

        if (! Auth::check()) {
            Log::debug('Can\'t update dark mode setting: user is not auth!');
            return;
        }

        // Get the new dark mode setting for the authenticated user.

        $darkModeCfg = $event->darkMode->isEnabled();

        $user = Auth::user()->name;
        $status = $darkModeCfg ? 'enabled' : 'disabled';
        Log::debug("New dark mode setting for user {$user} is: {$status}");

        // Store the new dark mode setting for the authenticated user.

        //$this->storeDarkModeSetting($darkModeCfg);

        //Log::debug("New dark mode setting is now stored on database!");
    }
}

Then, share the trace you're getting, and your Laravel version also...

dfsmania commented 4 months ago

@Arametheus Have you found any solution for your problem, or tested the previous suggestions?

Arametheus commented 4 months ago

@dfsmania sorry I got slammed again I will get that tested this week and let you know.

dfsmania commented 3 months ago

Closed, no more feedback, can't reproduce.