DirectoryTree / LdapRecord-Laravel

Multi-domain LDAP Authentication & Management for Laravel.
https://ldaprecord.com/docs/laravel/v3
MIT License
496 stars 52 forks source link

Call to undefined method LdapRecord\Query\Model\ActiveDirectoryBuilder::getKeyName()[Bug] #480

Closed miquelangeld closed 1 year ago

miquelangeld commented 1 year ago

Environment:

Describe the bug:

First of all I don't know if its a LdapRecord-Laravel issue, please forgive me if it's not.

I'm using Laravel with Backpack and the permission plugin (which is Spatie/Permissions). I'm able to log using ldaprecord, and all it's working perfectly, I can use Spatie roles and permissions correctly, but when I access to one route in order to admin the roles (it's just a backpack crud) I get this error: Call to undefined method LdapRecord\Query\Model\ActiveDirectoryBuilder::getKeyName() this crud it's just the same as other cruds that I have, I can use all the cruds but this.

The full stack is here: https://flareapp.io/share/oPRjyGdP#F63

stevebauman commented 1 year ago

Hi @miquelangeld,

Can you post your config/auth.php file?

miquelangeld commented 1 year ago

Hi Steve. Of course:

<?php

return [

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'ldap',
            'model' => LdapRecord\Models\ActiveDirectory\User::class,
            'rules' => [],
            'database' => [
                'model' => App\Models\User::class,
                'sync_passwords' => false,
                'sync_attributes' => [
                    'name' => 'cn',
                    'email' => 'mail',
                    'username' =>'samaccountname',
                    'rrhhId' => 'employeeID'
                ],
                'sync_existing' => [
                    'email' => 'mail',
                ],
            ],
        ]
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    'password_timeout' => 10800,

];
stevebauman commented 1 year ago

Thanks @miquelangeld.

Unfortunately Spatie Permission is not compatible with LdapRecord-Laravel (see https://github.com/DirectoryTree/LdapRecord-Laravel/issues/101, and https://github.com/DirectoryTree/LdapRecord-Laravel/issues/150).

Spatie Permission does not allow you to configure the configuration key that retrieves the authentication model.

For example, LdapRecord-Laravel's configuration structure is:

'providers' => [
    'users' => [
        'driver' => 'ldap',
        'model' => LdapRecord\Models\ActiveDirectory\User::class,
        // ...
    ],
],

Spatie Permission has hard-coded this configuration path here:

https://github.com/spatie/laravel-permission/blob/2ec9befb33d2110d9d354bb65a41b3b962280eb1/src/helpers.php#L17

Which means, an LdapRecord model instance will be instantiated instead of your Eloquent model leading to the exception you have posted above.

Since authentication drivers can have their own unique configuration with unique array keys, Spatie Permission should allow you to override this hard-coded path, but unfortunately that is not the case.

stevebauman commented 1 year ago

You may be able to override this method that is provided by Spatie (getModelForGuard(string $guard)) with your own version for it to function correctly:

// app/helpers.php

function getModelForGuard(string $guard)
{
    return collect(config('auth.guards'))
        ->map(function ($guard) {
            if (! isset($guard['provider'])) {
                return;
            }

            return config("auth.providers.{$guard['provider']}.database.model"); // <-- Notice the "database" key.
        })->get($guard);
}
miquelangeld commented 1 year ago

What strikes me is that everything seems to work correctly, the ad loggin and even the permissions for AD logged users are correctly applied. Except for this path

In any case, thank you very much, I will try it.