Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Many to many relation not saved for current user
  • 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.
  • HarroHarro
    Accepted Answer
    Thanks for the files.

    Bug found, and Warden is to blame.

    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.
  • Hmm thanks for digging into this. I will report bug and make a pull request?

    But a question arises here why this only applies to first user in users table?
  • It's not related to the first user, it's related to the current user, i.e. the user that is loaded by Warden.

    It should be fixed in Warden (that static::query() has to go), I leave it up to you how you handle that.
  • Correction. It runs

    static::query()->related('roles')->get_one()

    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.
  • Yes correct. Thanks a lot, I really appreciate it. I will fill a bug report for this.
  • No problem. Happy Easter (or what's left of it ;)).

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion