We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
  • If you add Contexts with ACLs attached in code, you have to have some way to refresh user sessions and the cache. Access policies are cached (for obvious performance reasons) both on the target object caches (i.e. Resources, Elements, etc.) and in the user session. This worked previously because of a bug that was bypassing the security checks for loading a Context. Now that this is fixed, you have to make sure users have permission to work with the Context before you can add Resources or even access the Context, this requires that there session be either flushed OR each user will need to have their policies refreshed when they access the site, via plugin perhaps, using the following API method for the current user:
    <?php
    $modx->user->getAttributes(array(), '', true);
    

    This forces the current user’s session to be reloaded with the latest access policy data.
      • 577
      • 132 Posts
      If I am understanding your solution correctly this still does not work. I tried calling the reload after the creation of the Admin Resource Policy but that seemed to have no effect on the situation. I actually just got a hack solution to work which in itself contradicts the idea that the user needs to be reloaded after the policy. There seems to be something happening at the context level because the hack is placed before I ever create the policy in the first place

      ### THIS DOES NOT WORK (reloading current user permissions after policy before resource) ###
      
      $modx = new modX();
          $modx->initialize('mgr');
      
          $modx->setDebug(true);
          $modx->setLogLevel(modX::LOG_LEVEL_INFO);
          echo '<pre>'; $modx->setLogTarget('ECHO');
          
          $context_key = 'MigrationTest11';
      
          /*
           * Set Context
           */
      
          $context = $modx->newObject('modContext');
          $context->fromArray(array(
          'key'         => $context_key,
          'description' => ''
          ), '', true);
      
          $context->save();
          
          // Administrator "Resource Policy"
          $access = $modx->newObject('modAccessContext');
          $access->fromArray(array(
          'target'          => $context_key,
          'principal_class' => 'modUserGroup',
          'principal'       => 1,
          'authority'       => 9999,
          'policy'          => 1
          ), '', true);
      
          $access->save();
          
          $modx->user->getAttributes(array(), '', true);
      
          /*
           * Resource "_config"
           * Build _config container
           */
      
          $resource = $modx->newObject('modResource');
          $resource->fromArray(array(
          'type'        => 'document',
          'contentType' => 'text/html',
          'pagetitle'   => '_config',
          'template'    => 0,
          'isfolder'    => 1,
          'context_key' => $context_key,
          'hidemenu'    => 1,
          'alias'       => 'config'
          ), '', true);
      
          $resource->save();
      

      ### THIS DOES WORK BUT IS A HACK (reloading modx object and initializing mgr again) ###
      
      $modx = new modX();
          $modx->initialize('mgr');
      
          $modx->setDebug(true);
          $modx->setLogLevel(modX::LOG_LEVEL_INFO);
          echo '<pre>'; $modx->setLogTarget('ECHO');
          
          $context_key = 'MigrationTest11';
      
          /*
           * Set Context
           */
      
          $context = $modx->newObject('modContext');
          $context->fromArray(array(
          'key'         => $context_key,
          'description' => ''
          ), '', true);
      
          $context->save();
          
          $modx = new modX();
          $modx->initialize('mgr');
          
          // Administrator "Resource Policy"
          $access = $modx->newObject('modAccessContext');
          $access->fromArray(array(
          'target'          => $context_key,
          'principal_class' => 'modUserGroup',
          'principal'       => 1,
          'authority'       => 9999,
          'policy'          => 1
          ), '', true);
      
          $access->save();
      
          /*
           * Resource "_config"
           * Build _config container
           */
      
          $resource = $modx->newObject('modResource');
          $resource->fromArray(array(
          'type'        => 'document',
          'contentType' => 'text/html',
          'pagetitle'   => '_config',
          'template'    => 0,
          'isfolder'    => 1,
          'context_key' => $context_key,
          'hidemenu'    => 1,
          'alias'       => 'config'
          ), '', true);
      
          $resource->save();
      



        "One of these days I will get around to my own website... Its only been about 12 years... maybe tomorrow smiley"
      • A context is not available for use until the request after it is saved and the cache is refreshed. This is why it is working when you get a new modX instance and reinitialize the context.
          • 577
          • 132 Posts
          Ok then this simply comes down to the fact that I am trying to do to much in the single requests.

          So my options are to reinitialize as I have shown that to work or break this logic into two separate requests?

          Since this is an internal migration script and will never see the real word or be used after migration I don’t care if I have to reinitialize. Just wanting to get a clear answer as to what would be best in general to wrap up this post and leave others with a meaningful solution to my post
            "One of these days I will get around to my own website... Its only been about 12 years... maybe tomorrow smiley"
          • Maybe you can sidestep from the refreshing issue, by creating the resources you need in arrays, and adding that to the resource before calling save?

            Ie:
            $context = $modx->newObject('modContext');
            $context->fromArray(array(
            'context_key' => 'testing',
            'description' => 'Just for tests.'));
            
            $ress = array();
            $res = $modx->newObject('modResource');
            $res->fromArray($resourcedata);
            $ress[] = $res;
            $res = $modx->newObject('modResource');
            $res->fromArray($resourcedata);
            $ress[] = $res;
            // .. etc ..
            
            $context->addMany($ress);
            $context->save();


            Not sure on specific syntaxes, but you get the idea.
              Mark Hamstra • Developer spending his days working on Premium Extras and a MODX Site Dashboard with the ability to remotely upgrade MODX and extras to make the MODX world a little better.

              Tweet me @mark_hamstra, check my infrequent blog at markhamstra.com, my slightly more frequent ramblings at MODX.today or see code at Github.
              • 577
              • 132 Posts
              @Mark

              Thanks for the suggestion and something I will keep in mind for other things. In this situation it will not work because many resources play off other resources. Like creating a container getting the id then adding docs under that container and then taking that container id and adding it to the context settings as _%container%_id so that I have the id stored for future access.
                "One of these days I will get around to my own website... Its only been about 12 years... maybe tomorrow smiley"
              • It would be IMO better to create the Context( s ) and any ACLs in one script/request (I would still flush sessions and refresh the cache) and then use a second script to add things to that Context.
                  • 577
                  • 132 Posts
                  I have decided to go with the reinitialize for now and my script is back in business and working. Just to share this is a screen shot of the end result of the full script. What you see here along with hundreds of TV’s , System - Context - User Settings, Users, User Groups, Admin Policies are all created in the click of a button.

                  Thank You Jason and Mark for helping me get things figured out.

                  Adam
                    "One of these days I will get around to my own website... Its only been about 12 years... maybe tomorrow smiley"
                    • 577
                    • 132 Posts
                    @ Jason,

                    Understood and I think I will revisit that when I take this logic out of being a migration script and hopefully roll it into a "Site Setup Wizard"

                    Thanks Again
                      "One of these days I will get around to my own website... Its only been about 12 years... maybe tomorrow smiley"