Cms: Handle independent Statamic users in existing project not working

Created on 9 Sep 2020  路  12Comments  路  Source: statamic/cms

Bug Description

I am trying to install Statamic into an existing project with lot of users. The project is using eloquent as driver for the users.
I would like to use the file driver for Statamic having only 1 user.

I get the error:

 Argument 1 passed to Statamic\Stache\Query\Builder::__construct() must be an instance of Statamic\Stache\Stores\Store, null given, called in /vendor/statamic/cms/src/Stache/Repositories/UserRepository.php on line 52

How to Reproduce

Add Statamic via composer to one existing project with several users.

There is two ways to reproduce:
Run
php please make:user
or after manually creating the user file, login into the control panel.

Extra Detail

I have tried several things guided by @damcclean , like adding a new provider for users in the config/auth, generating manually the [email protected] file etc. In every case, I get the error after login in the control panel or is not possible to login (shaking login dialog).

Statamic version: 3.0.7

PHP version: 7.2

Install method (choose one):

  • Existing Laravel app
custom stache

Most helpful comment

In 3.1 you will be able to define separate user guards, eg: one for the Statamic CP and another for the rest of your Laravel app. See #3143.

All 12 comments

You can't have separate sets of users for Statamic vs the rest of your app.

What's wrong with continuing to use the regular eloquent driver for that one Statamic user?

I have several users in the database. If I setup the eloquent driver, I can not use the "Solo" plan. In this case I get the error "Statamic Pro is required".

I want to use Statamic to create the marketing web using the same project of my SAAS. I think this should be possible with the Solo plan.

In this Twitter thread with @statamic I was also told this was looking like a bug.

I would have to agree with @stuartcusackie on his #1470 ticket regarding the new columns added to the main users table.

Just in relation to the comments above and following two tickets:

https://github.com/statamic/ideas/issues/345
https://github.com/statamic/cms/issues/1470

Could we resolve the above by adding config options for the users / role_user / group_user tables and allowing config of the auth provider used in UserRepositoryManager:
e.g.

public function createEloquentDriver(array $config)
{
    $config['model'] = $this->app['config']['auth.providers.users.model'];
...

If my assumptions are correct we should be able to swap out the User model and database tables and database without having to reimplement the entire custom statamic user provider.

I would be happy to do up a pull request for the config settings outlined above if that would be of benefit and seems like it check outs on paper.

Before I do that though you mention:

You can't have separate sets of users for Statamic vs the rest of your app.

If I went through with the above do you still see issues with having some notion of separate 'admin' user for Statamic and admins only? If so is that related to the 'Protect Content' functionality?

I think a good test for your implementation would be to see if both Statamic and Nova (and possibly the spatie roles package) still work together afterwards. You'll see @chrisbjr had a few problems with PasswordBrokers and other things here.

I also struggle implementing a separate authentication for Statamic inside an existing Laravel app.
For me it would be sufficient if Statamic let's us define a custom guard.

In the Statamic src-directory I see a lot of occurences of Auth::guard().
Statamic seems to be always accessing the default guard. Afaik Laravel let's you specify the guard to use, e.g Auth::guard('statamic')

It should be possible to have a config/auth.php like this:

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

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

    'statamic' => [
        'driver' => 'session',
        'provider' => 'statamic_users',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],

    'statamic_users' => [
        'driver' => 'statamic',
    ],
],

This should provides麓 a statamic-guard with the statamic_users provider which uses the statamic-driver. The current Laravel default eloquent-guard will stay in place.

The interesting thing is that this is already available for the password broker in config/statamic/users.php

Would be cool to have some feedback here @jasonvarga
Thank you!

We have absolutely no objection to having this feature.

We agree that the "multiple users required for pro mode" means "statamic control panel users", in terms of licensing. It's just that there's currently no separation at the moment. A user is a user.

We haven't tackled this yet because of the number of devs who would need it vs. the effort for us to implement it.

I don't want to introduce additional steps to getting Statamic working on existing Laravel apps (like having to configure a dedicated auth guard).

I think a solution would be to have config/statamic/users.php have a guard option that defaults to web. You guys that want separate guards can make one for Statamic and then tell Statamic to use it there. Of course that means anywhere in our code base we're relying on something like request()->user() or auth()->user(), we'd need to pass along the guard.

Sounds like @damcclean might take a stab at it.

You could also use a middleware, could save some time and leave the code base as it is, e.g.

public function handle(Request $request, Closure $next)
{
    Auth::shouldUse(config('statamic.users.guard'));

    return $next($request);
}

When applied,Auth::user() and $request->user() will then always use the configured guard. If there's no return value from config('statamic.users.guard') the Auth::shouldUse() falls back to the default-guard.

Ah, that's a good idea, certainly a quicker way of implementing.

fyi, I was able to work around this with the current version by extending the AddonServiceProvider and push a middleware containing Auth::shouldUse().

class StatamicServiceProvider extends AddonServiceProvider
{
    protected $middlewareGroups = [
        'statamic.cp' => [
            UseStatamicGuard::class,
        ],
    ];

    public function boot()
    {
        parent::bootMiddleware();
    }
}

@ajnsn Looks promising. 馃憤馃徏 Just to fully understand what this does: using your workaround we'd be able to have different sets of users? So I won't see the "customer" users in my Statamic CP?

@MrMooky Yes, excactly. The UseStatamicGuard::class contains the above mentiond handle-method which points to your custom guard implementation.

Note that there's also an open PR which introduces multiple guard support.

In 3.1 you will be able to define separate user guards, eg: one for the Statamic CP and another for the rest of your Laravel app. See #3143.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

skoontastic picture skoontastic  路  4Comments

andrewying picture andrewying  路  4Comments

sandervanh picture sandervanh  路  4Comments

wm-simon picture wm-simon  路  3Comments

riasvdv picture riasvdv  路  4Comments