We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 3749
    • 24,544 Posts
    What is the code that creates the user?
      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
      • 38357
      • 178 Posts
      The plugin creates the user in modx if the user doesn't exist?

       
       /* Generate a random, 50 character password */
              $password = "";
              for($i=0;$i<50;$i++) {
                  $password .= chr( (mt_rand(1, 36) <= 26) ? mt_rand(97, 122) : mt_rand(48, 57 ));
              }
      
      /* Create the new user */
       
              $fields = array(
                  'username' => $username,
                  'password' => $password,
                  'blocked' => '0',
                  'email' => '[email protected]',
                  'passwordnotifymethod' => 'x',
              );
       
              $response = $modx->runProcessor('security/user/create', $fields);
      
              /* Log the error if the processor fails */
              if ($response->isError()) {
                  if ($response->hasFieldErrors()) {
                      $fieldErrors = $response->getAllErrors();
                      $errorMessage = implode("\n", $fieldErrors);
                  } else {
                      $errorMessage = $response->getMessage();
                  }
                  $modx->log(modX::LOG_LEVEL_ERROR, '[OnBeforeWebLogin] ' . $errorMessage);
                  $output = true; /* prevent login */
              } else {
                  $output = false;
              }
              break;
      
      [ed. note: bobd72 last edited this post 9 years, 10 months ago.]
        • 3749
        • 24,544 Posts
        First, be sure the users are not being created but inactive ('active' field set to false). I don't think that's the problem, but it's worth checking.

        I think the problem is that the processor wants the user to have the new_user permission, which an anonymous user won't have.

        One solution would be to give anonymous users that permission by adding it to their 'web' Context Access Policy. It seems risky, but offhand, I don't think it is. They won't have save_user permission, so they can't really create new users and I assume that they're not going to get into the Manager. Even if they will be in the Manager, their 'mgr' Policy will apply, not their 'web' Policy. I don't think the user/create processor will require save_user permission, but I could definitely be wrong about that.

        The alternative would be to create the User and the User Profile without calling the processor. That would look something like this:

        $user = $modx->newObject('modUser');
        $user->set('username', $userName);
        $user->set('password', $password);
        $user->set('active', false); /* or true */
        $user->set('blocked', false);
        $user->save();
        
        $user = $modx->getObject('modUser', array('username' => $username));
        
        if ($user) {
            $userId = $user->get('id');
            $profile = $modx->newObject('modUserProfile');
            $profile->set('email', $email);
            $profile->set('internalKey', $userId);
            $profile->save();
        } else {
            $modx->log(modX::LOG_LEVEL_ERROR, 'could not retrieve user -- USERNAME: ' . $username);
        }
        


        I don't think you'd run into the permission issues with this, but again, I could be wrong.

        A third solution would be to temporarily give the anonymous user the necessary permission(s), but offhand I can't think of an easy way to do that.


          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
          • 38357
          • 178 Posts
          I have most things working OK now, however, login only works if password is saved in Modx database.
          My lgnLogin.tpl gets the user's password in the form, but how do I capture it and transfer it to the plugin which will then save it to the Modx database? Should this be done with a Session and if so how?

          My lgnLogin.tpl
          <script>
          $(document).ready(function() {
              $("#myLogin").click(function() {
                  $.post($("#Login").attr("action"), $("#Login").serialize(),
                    function(data) {
                      $("#msg").append(data);
                      $.post($("#myclubLogin").attr("action"), $("#myclubLogin").serialize(),
                        function(data) {
                          $("#msg").append(data);
                        });
                    });
                });
            });
          </script>
           
           
          <div class="loginMessage">[[+errors]]</div>
                  <form id="Login" name="Login" class="loginLoginForm" action="[[~[[*id]]]]" method="post" >
                       
                      <fieldset class="loginLoginFieldset">
                           
                           <!-- Show Member Login message -->  <legend class="loginLegend"></legend> 
                          <label class="loginPasswordLabel" style="color: #AEE67A;"> Username:
                              <input class="loginUsername" type="txt" name="username" onblur="document.myclubLogin.user.value = this.value;" />
                            </label>
                           
                          <label class="loginPasswordLabel" style="color: #AEE67A;"> Password:
                              <input type="password" name="password" onblur="document.myclubLogin.password.value = this.value;"/>
                          </label>
                               <input class="returnUrl" type="hidden" name="returnUrl" value="[[+request_uri]]" />
           
                          [[+login.recaptcha_html]]
                           
                              <input class="loginLoginValue" type="hidden" name="service" value="login" />
                         
                          
                      </fieldset>
                  </form>
                   
          <div class="loginMessage">[[+errors]]</div>
                  <form name="myclubLogin" id="myclubLogin" method="post" action="url_to_log_in_to_remote_server" target="myClub"> 
           
                      <fieldset class="loginLoginFieldset" >
           
                          <input id="action" type="hidden" name="action" value="login" /> 
                          <input class="loginUsername" type="hidden" name="user" id="user"   />
                           
                          <input type="hidden" name="password"  />
                          <input id="action" type="hidden" name="action" value="password" /> 
           
                          <input class="loginLoginValue" type="hidden" name="service" value="login" />
                          <span class="loginLoginButton">
                          <input id="myLogin" name="myLogin" type="submit" value="[[+actionMsg]]" style="float: right;"/>
                          </span>
           
                      </fieldset>
                  </form> 
           
          <div> 
          <iframe id="myClub" name="myClub" style="width:0; height:0; border:0; border: none;"></iframe>
          </div>


          My Plugin code:

          <?php
          
          /* Get the event name */
          $eventName = $modx->event->name;
           
          /* Run the code appropriate to the event */
          switch($eventName) {
              case 'OnBeforeWebLogin':
           
                  /* Return if the user is already in the database */
                  /** @var $username string */
           
                  $existingUser = $modx->getObject('modUser', array ('username' => $username));
                  if ($existingUser) {
                     $modx->event->_output = false; /* allow login */
          
                     return;
                  }
                  
          
                  /* Retrieve password here
                  $password = "";
                 
                 
                  */
                  
                  /* Create the new user */
          
                  $fields = array(
                      'username' => $username,
                      'password' => $password,
                      'active' => '1',
                      'blocked' => '0',
                      'email' => '[email protected]',
                      'passwordnotifymethod' => 'x',
                  );
            
                  $response = $modx->runProcessor('security/user/create', $fields);
                  
                  /* Assign new user to User Group / Role    */  
                  $user = $modx->getObject('modUser', array('username' => $username));
                  if( $user ){
                   $user->save();
                      $user->joinGroup('Members','Members');}
              
                  /* Log the error if the processor fails */
                  if ($response->isError()) {
                      if ($response->hasFieldErrors()) {
                          $fieldErrors = $response->getAllErrors();
                          $errorMessage = implode("\n", $fieldErrors);
                      } else {
                          $errorMessage = $response->getMessage();
                      }
                      $modx->log(modX::LOG_LEVEL_ERROR, '[OnBeforeWebLogin] ' . $errorMessage);
                      $output = true; /* prevent login */
                  } else {
                      $output = false;
                  }
                  
          $eventName = $modx->event->name;
          $msg = 'Event: ' . $eventName . ' -- Line x of plugin executing';
          $modx->log(modX::LOG_LEVEL_ERROR, $msg);
                  break;
           
           
              case 'OnWebAuthentication':
                  $authenticated = false;
           
                  /* Your authentication code here sets $authenticated to true if the
                     user should be allowed to log in */
           
                  /* Set authentic user to active if not already active */
                  if ($authenticated) {
                      if (! $user->get('active')) {
                          $user->set('active', '1');
                          $user->save();
                      }
                  }
           
                  $output = (bool)$authenticated;
          
                  $eventName = $modx->event->name;
                  $msg = 'Event: ' . $eventName . ' -- Line x of plugin executing';
                  $modx->log(modX::LOG_LEVEL_ERROR, $msg);	
          
                  break;
          
          }
           
          $modx->event->_output = $output;
          return;
            • 3749
            • 24,544 Posts
            I'm not sure it's related to any issues you have, but this code will never execute since you've set $authenticated to false:

            /* Set authentic user to active if not already active */
                    if ($authenticated) {
                        if (! $user->get('active')) {
                            $user->set('active', '1');
                            $user->save();
                        }
                    }


            As a result, the return from OnWebAuthentication will always be false.
              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
              • 38357
              • 178 Posts
              Thanks Bob,
              Quote from: BobRay at Dec 06, 2016, 01:50 PM
              I'm not sure it's related to any issues you have, but this code will never execute since you've set $authenticated to false:

              /* Set authentic user to active if not already active */
                      if ($authenticated) {
                          if (! $user->get('active')) {
                              $user->set('active', '1');
                              $user->save();
                          }
                      }


              As a result, the return from OnWebAuthentication will always be false.

              That gave me a clue as to why the user is not logged on - changing $authentication to 'true' allows the login. However, the script above always runs even if is set to false as it only requires $authenticated to exist - how it is set isn't evaluated by the script and it sets the user as 'active' regardless of the parameter set.

              What I think I need is a conditional statement, something like:

              if( /*some condition set by successful login to remote site */){
                  $authenticated=true;
                  $user->set('active', '1');
                              $user->save();
              } else {
                  authenticated=false;
              }


              but what can I use as 'condition set by successful login to remote site'? I would think it would be something which needs to be set in
              <div class="loginMessage">[[+errors]]</div>
                      <form name="myclubLogin" id="myclubLogin" method="post" action="url_to_log_in_to_remote_server" target="myClub"> 
                
                          <fieldset class="loginLoginFieldset" >
                
                              <input id="action" type="hidden" name="action" value="login" /> 
                              <input class="loginUsername" type="hidden" name="user" id="user"   />
                                
                              <input type="hidden" name="password"  />
                              <input id="action" type="hidden" name="action" value="password" /> 
                
                              <input class="loginLoginValue" type="hidden" name="service" value="login" />
                              <span class="loginLoginButton">
                              <input id="myLogin" name="myLogin" type="submit" value="[[+actionMsg]]" style="float: right;"/>
                              </span>
                
                          </fieldset>
                      </form> 


              or some system event? [ed. note: bobd72 last edited this post 9 years, 9 months ago.]
                • 3749
                • 24,544 Posts
                You want the original code, but with the comment replaced by code that checks the user's authentication on the remote site:

                 case 'OnWebAuthentication':
                        $authenticated = false;
                  
                        /* Your authentication code here sets $authenticated to true if the
                           user should be allowed to log in */
                  
                        /* Set authentic user to active if not already active */
                        if ($authenticated) {
                            if (! $user->get('active')) {
                                $user->set('active', '1');
                                $user->save();
                            }
                        }


                How to authenticate the user on the remote site in code will depend on the remote site. Some sites will have an API, some have another method, and for some you actually need to use cURL to post the users credentials and any necessary hidden fields to the remote site's login form and check the returned page for signs that the login was successful.
                  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
                  • 38357
                  • 178 Posts
                  Thanks Bob,

                  How to authenticate the user on the remote site in code will depend on the remote site. Some sites will have an API, some have another method, and for some you actually need to use cURL to post the users credentials and any necessary hidden fields to the remote site's login form and check the returned page for signs that the login was successful.

                  I am successfully authenticating on the remote site when the form is submitted. I just need some sort of a flag to indicate that that has happened - true or false.
                    • 3749
                    • 24,544 Posts
                    If you can tell whether the user is successfully logged in to the remote site, you can set a $_SESSION variable and read it later in your plugin:


                    $_SESSION['successAtRemote'] = 1; // or 0 if it failed



                    Then in the plugin:

                    $authenticated = isset($_SESSION['successAtRemote']) && $_SESSION['successAtRemote'] === 1)'
                      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
                      • 38357
                      • 178 Posts
                      Quote from: BobRay at Dec 07, 2016, 04:23 PM
                      If you can tell whether the user is successfully logged in to the remote site,
                      Yes - herein lies the problem. I can see visually that the user is logged in as the URL changes but how do I turn that into a variable?

                      you can set a $_SESSION variable and read it later in your plugin:


                      $_SESSION['successAtRemote'] = 1; // or 0 if it failed
                      But can this be used in a .tpl file which is a chunk?

                      Then in the plugin:

                      $authenticated = isset($_SESSION['successAtRemote']) && $_SESSION['successAtRemote'] === 1)'

                      This is what I was looking for - how to set and then retrieve the session varialbe in the plugin smiley

                      Now all I need is how to recognise in code that the login to the remote server has been successful when I don't have access to it. Perhaps it sets a cookie I can read somehow?