yii2-usuario
yii2-usuario copied to clipboard
usuario + AccessControl on Application throws User::identityClass must be set
I am trying to set global AccessControl on application. I have this in application configuration:
'components' => [ ... ],
'modules' => [
'user' => [
'class' => Da\User\Module::class,
]
],
'as beforeRequest' => [
'class' => \yii\filters\AccessControl::class,
'ruleConfig' => [
'class' => \Da\User\Filter\AccessRuleFilter::class,
],
'rules' => [
[ ... ],
],
],
],
It always throws User::identityClass must be set exception.
Is there any way to make it work?
'modules' => [
'user' => [
'class' => Da\User\Module::class,
'identityClass' => 'Da\User\Model\User'
]
],
Maybe, this help.
@aka-VoV It does not.
I've found that usuario overrides yii\web\User here: https://github.com/2amigos/yii2-usuario/blob/master/src/User/Bootstrap.php#L145
But looks like it happens later than AccessControl behavior is initialized. So there is no identityClass at that time.
I tried this in application configuration:
'container' => [
'definitions' => [
\yii\web\User::class => [
'enableAutoLogin' => true,
'loginUrl' => ['/user/security/login'],
'identityClass' => \Da\User\Model\User::class,
]
],
],
It works. But Da\User\Bootstrap has slighly more logic on this: it uses class map at initialization: 'identityClass' => $di->get(ClassMapHelper::class)->get(User::class), and I can't reproduce this logic in app's config. So I think I loose enhancement ability with this solution.
Can there be any better solution than overriding container definitions manually?
Have you set the user component of your application? I think the problem is the initialization process of your application (https://github.com/yiisoft/yii2/blob/03299e8870eaaeb2714e53452078ca3ba2c86800/framework/web/User.php#L158). You can do the class map to the module but set your web user to the overridden model or the User model provided by this module.
Have you set the user component of your application?
I haven't, because 1) usuario docs do not say to do it and 2) I see that usuario does this for me already.
You can do the class map to the module but set your web user to the overridden model
This is what I am doing now. I just hoped there was a way to make it all work automatically. Because "If you need to use AccessControl on Application with yii2-usuario, you must override yii\web\User manually" does not sound logical.
Maybe AccessControl initializes his $user just too early ? Should I file a bug report to yiisoft/yii2 on it? What do you think?
I haven't, because 1) usuario docs do not say to do it and 2) I see that usuario does this for me already.
I know, the issue is with the initialization process that requires you to set the identity class. Is required by Yii not usuario. The model provided by the module implements the IdentityInterface required.
Maybe AccessControl initializes his $user just too early ? Should I file a bug report to yiisoft/yii2 on it? What do you think?
I would try before to fire the bootstrap process by setting 'bootstrap' => ['user'],? Let's see, otherwise, the problem is not on the module but on the application configuration and initialization.
If it doesn't work, lets see... But I don't think placing the User model on the config, shouldn't be an issue. I think they won't listen.
I would try before to fire the bootstrap process by setting 'bootstrap' => ['user']
Currently it does not work. Here are the reasons:
yii\web\Applicationhas it's core componentuser: https://github.com/yiisoft/yii2/blob/master/framework/web/Application.php#L199yii\base\Application::bootstrap(), when looking for an object to initialize, first searches through components, and then through modules: https://github.com/yiisoft/yii2/blob/master/framework/base/Application.php#L312- Thus, yii's core
usercomponent is bootstraped instead ofusuario. - Could be solved by using another name for
usuariomodule, say'modules' => [ 'usuario' => [ ... ] ], but 'user' module name is hardcoded in usuario: https://github.com/2amigos/yii2-usuario/blob/master/src/User/Bootstrap.php#L263
So, no way to initialize 'user' module instead of 'user' component, no way no rename 'user' module to something else. Impasse.
@cronfy the components have nothing to do with the modules. Unfortunately, I just saw that the preInit() (https://github.com/yiisoft/yii2/blob/master/framework/base/Application.php#L258) is called prior the initialization (https://github.com/yiisoft/yii2/blob/master/framework/base/Application.php#L273) so, the only solution would be to set the 'components' => ['user' => ['class' => '\Da\User\Model\User']]
@tonydspaniard Ok, one more question. The hardcoded 'user' module name in Da\User\Bootstrap - what are reasons for this? If it would not be hardcoded, we could safely rename the module and bootstrap it.
How would you do it then? We require access to the module... would you add a loop? Feel free for a PR: https://github.com/2amigos/yii2-usuario/blob/master/src/User/Traits/ModuleAwareTrait.php#L27
@tonydspaniard I can give it a try, but first let's try some luck here: https://github.com/yiisoft/yii2/issues/14766