We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 50631
    • 5 Posts
    I have a plugin that I created that gets all contexts except the mgr context and displays it on the mgr login page inside a combo box under the password field. The content writers can select a website context to work on when they login. How can I dynamically change either the ACL's access permissions to "load_only" for all contexts except the one chosen from the combo box when they login? This way they only see the context in the tree they selected when they logged in. Basically removing them from the mgr tree in the manager so they don't accidentally add content to the wrong website context by having too many contexts displaying in the tree causing them to loose their place of reference. What part of the API can I use to remove contexts from the tree or set them to load_only upon login? Hope I am explaining this clearly. Here is a sample of my plugin so far. Thanks for any help!!

    switch ($modx->event->name) {
        case 'OnManagerLoginFormPrerender': /* if you want to add custom scripts, css, etc, register them here */
    
      		$results  = $modx->query("SELECT * FROM modx_context WHERE modx_context.key NOT IN ('mgr')");
    		$numItems = $modx->getCount('modContext', array('key:NOT IN' => array('mgr')));
    		$i        = 0;
    
    		while ($r = $results->fetch(PDO::FETCH_ASSOC)){
    		  if(++$i === $numItems){
    			$listContext .= "['" . $r['key'] . "', '" . $r['name'] . "']"; // NO comma at the end of the array.
    		  }else{
    		  	$listContext .= "['" . $r['key'] . "', '" . $r['name'] . "'],";
    		  }
    		}
    
    		// Define the model for website
    		$script = "<script type='text/javascript'>
    		  Ext.onReady(function() {
    
    			  /* disable shadows for the combo-list globally, saves a few dom nodes as it's not used anyways */
    			  Ext.form.ComboBox.prototype.shadow = false;
    			  /* replaces the default img tag for the combo trigger with a div to make the use of iconfonts with :before possible */
    			  Ext.override(Ext.form.TriggerField, {
    				  // this is the exact method from the source code, just the triggerConfig is modified to not use an img tag
    				  // We cannot override the prototype Ext.form.TriggerField.prototype.triggerConfig because we loose the option to add a custom triggerClass
    				  onRender: function(ct, position){
    					  this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
    					  Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
    			  
    					  this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
    					  this.trigger = this.wrap.createChild(this.triggerConfig ||
    							  {tag: 'div', cls: 'x-form-trigger ' + (this.triggerClass || '')});
    					  this.initTrigger();
    					  if(!this.width){
    						  this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
    					  }
    					  this.resizeEl = this.positionEl = this.wrap;
    				  }
    			  });
    
    			  Ext.namespace('Ext.websitedata');
    		  
    			  Ext.websitedata.websites = [" . $listContext . "];
    
    				  // simple array store
    				  var store = new Ext.data.ArrayStore({
    					  fields: ['context', 'name'],
    					  data : Ext.websitedata.websites // from namespace data
    				  });
    
    				  var combo = new Ext.form.ComboBox({
    					  store: store,
    					  displayField:'name',
    					  typeAhead: true,
    					  mode: 'local',
    					  forceSelection: true,
    					  triggerAction: 'all',
    					  emptyText:'Select a website...',
    					  selectOnFocus:true,
    					  hiddenName: 'cntxwebsite',
    					  valueField: 'context',
    					  applyTo: 'local-websites'
    				  });
    			});
    		</script>";
    
    		$modx->event->output($script);
    
    	break;
    	case 'OnManagerLoginFormRender':
    
     		$fields = '<div class="x-form-item login-form-item" style="padding-top: 17px;">
    					<label for="local-websites">Website</label>
    					  	<input type="text" id="local-websites" value="" readonly="" style="width: 368px;"/>
            		   </div>';
    
    		$modx->event->output($fields);
    
    	break;
    	case 'OnManagerLogin':
    
    		$profile = $user->getOne('Profile');
    
    		$modx->log(modX::LOG_LEVEL_ERROR, "You have logged in with: " . $_POST['cntxwebsite'] . " Your user name is: " . $_POST['username'] . " Session contexts: " . print_r($user->toArray()));
    
      		$results  = $modx->query("SELECT * FROM modx_context WHERE modx_context.key NOT IN ('" . $_POST['cntxwebsite'] . "','mgr')");
    
    		while ($r = $results->fetch(PDO::FETCH_ASSOC)){
    
              $resource =  $modx->getObject('modResource',array('context_key' => $r['key']));
    
    		  $user->removeSessionContext($r['key']);
    		}
    
    
    		/*$script = '<script type="text/javascript">
    					  var tree = null;
    					  Ext.onReady(function() {
    						var tree = Ext.getCmp("modx-resource-tree");
    						if (tree && tree.rendered) {
    							tree.refresh();
    						}
    					  });
    				  </script>';*/
    
    
    	break;
    }
    [ed. note: exceedinteractive last edited this post 11 years, 4 months ago.]
      • 50631
      • 5 Posts
      No one wants to take a stab at this? I didn't think that this would be that complex to do.
        • 28042 ☆ A M B ☆
        • 24,524 Posts
        Actually it would be that complex. The code to generate the lists would need to be modified, or else the Javascript would have to hide everything, then only show the one selected. Ether way, I don't think it'll be trivial.
          Studying MODX in the desert - http://sottwell.com
          Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
          Join the Slack Community - http://modx.org
          • 50631
          • 5 Posts
          Thanks for the reply sottwell, I'm thinking that there might be a way to either interject when the object is creating the tree nodes in PHP and setting has permissions to false for each node it tries to create that doesn't match the context chosen at login. The other way would be to get in front of the class that builds the tree nodes and tweak the ACL's so that they are all "load only" but the context chosen at login. Just not sure yet what the firing order is for all objects and what's available to me at what point. I've only started working with Modx in the last two weeks.
            • 3749
            • 24,544 Posts
            It's a really interesting question.

            I'm pretty sure there's no System Event for creating a tree node, so you wouldn't be able to intervene there without hacking the core code (definitely not recommended). Messing with ACLs is fairly complex, as Susan suggests. Messing with ACLs on the fly is not only difficult, but fraught with peril (and would affect other concurrent users). I wouldn't attempt it.

            It might be possible to accomplish what you want with a set of User Groups, each with access to one context in the Manager. Your plugin (I think connected to OnManagerAuthentication) could first remove the user from all of them, then add them back selectively based on their context selections. You would have to call reloadContext() to invalidate the cache. I'm not sure it would work, but I think there's a good chance that it would.

            Another possibility would be to hide contexts with JavaScript. That would mean learning ExtJS/modExt, and the Manager code is generally created on the fly and stuff tends not to be there when you're trying to modify it, so I have less confidence that this could work without a whole lot of frustrating work.








              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting
              • 50631
              • 5 Posts
              thanks for your input Bob. Can you help me undstand what's going on with Modx permissions. Users are assined to groups. Those groups contain the ACL's that are set for all users in that group. Do individual users in that group have workspaces that can be altered so they do not affect others in that same group when they are logged in? Can a workspace override the ACL's while that user is logged in without affecting other users in that group. I don't want to disturb the core in anyway. The idea is to preserve the core files.
                • 50631
                • 5 Posts
                Ah! I see the trap I'm in now... User have settings (which are not permissions) that can override context and sys settings. UserGroups have permissions and no settings but their group permissions can override context and sys permissions. I think I got it now. I will update this post for others to use in the future with a hack that I come up with. Wish me luck!
                  • 3749
                  • 24,544 Posts
                  You're correct. AFAIK, there are no user-specific permissions. All Revo permissions are given to user groups and every member of the user group that has the minimum authority gets the permission. I would advise against using authority levels to do what you want. Using separate user groups is much cleaner and easier.

                  Good luck!!! smiley

                  Once you've finished, you can start figuring out how to control what specific users can do with regard to creating other users and setting the capabilities of other users -- right now, it's all or nothing. IOW, any user that can create other users can make him or herself a super user and take away any other user's super user status (including you). wink
                    Did I help you? Buy me a beer
                    Get my Book: MODX:The Official Guide
                    MODX info for everyone: http://bobsguides.com/modx.html
                    My MODX Extras
                    Bob's Guides is now hosted at A2 MODX Hosting
                    • 28042 ☆ A M B ☆
                    • 24,524 Posts
                    Well, you can take away my SuperUser status, but I can take it right back, and take away yours! So there!!!
                      Studying MODX in the desert - http://sottwell.com
                      Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                      Join the Slack Community - http://modx.org
                      • 28042 ☆ A M B ☆
                      • 24,524 Posts
                      With that out of the way, yes. What would be nice is to be able to restrict users to working with users in specified groups, and only to be able to bestow permissions he himself has. At the very least, a non-superuser should not be able to remove or give superuser status. In fact, a non-superuser shouldn't be able to even see that checkbox.
                        Studying MODX in the desert - http://sottwell.com
                        Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                        Join the Slack Community - http://modx.org