If you can put the tar or zip online somehwere, you can place the link here (I will let you know when I've downloaded it so you can remove it again), send it to me via email (see previous post) or via PM on IRC.
When you save a user, a 'before_save' event kicks in inside the Warden user model, which calls _add_default_role().
This method runs an ORM query on the current user object. This will refresh the data in the object, which is a problem if you're saving permissions on the current user. That should be changed to a standard DB query to avoid ORM cache reload or update issues.
which will return the the first user (which normally is the admin user I guess) and it's roles. Which causes that user object to be updated.
Since ORM caches objects, if you are modifying the permissions of the first user, than that user will be updated too (since both objects will point to the same cached user object). Which is what is causing your problem.
>>which will return the the first user (which normally is the admin user I guess) and it's roles. Which causes that user object to be updated.
You mean first role?
Ok as far as I know about Warden _add_default_role() method checks if user has default role and if not it adds it. But this code inside _add_default_role() should never be executed in the first place, because all users in my case already have a default_role assigned... meaning first condition should not pass trough...
UPDATE: Just debugged this _add_default_role() method and it's correct what I said. Both conditions in first if sentence are false so this code is never executed, which means that your conclusion about static::query()->related('roles')->get_one() is not what causes this bug?
UDPATE2: Ah stupid me, but the query is still executed... sorry about this.
/** * Adds default role to a new user if enabled in config * * @see \Warden\Model_User::_event_before_save() */ private function _add_default_role() { // Make sure no roles exist already if (empty($this->roles) || !static::query()->related('roles')->get_one()) { // Check for default role if (($default_role = \Config::get('warden.default_role'))) { $role = \Model_Role::find('first', array( 'where' => array( 'name' => $default_role ) ));
if (!is_null($role)) { $this->roles[] = $role; } } } }
All I can say is that if you disable this call in the before_save() event, your problem is solved.
I didn't go into detail on what exactly is causing it, but the only logical cause is that static::query(). Nothing else in there would cause an update of the user object.
The query is run when there is something assigned to $this->roles, and it checks if a role is assigned to the user in the database.
This logic is flawed.You're saving the user object (which is $this), so if $this->roles is empty, either no roles where assigned, or all assigned roles were removed. Only in that case, the code should look into a default value. The OR in this if should not be there, it should be a nested if (so the query only runs when needed). And it should be a DB query, not an ORM query.
The more I look at this (Warden) code, the more rubbish it seems to me. Saving permissions in your application takes ages, and if I debug the model, I see tons of queries pass. I'd see it's in need of refactoring.