Adds possibility to send new password to users
authorMatthias Schmidt <gravatronics@live.com>
Mon, 24 Mar 2014 21:28:41 +0000 (22:28 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Mon, 24 Mar 2014 21:28:41 +0000 (22:28 +0100)
com.woltlab.wcf/clipboardAction.xml
wcfsetup/install/files/acp/js/WCF.ACP.js
wcfsetup/install/files/acp/templates/userList.tpl
wcfsetup/install/files/lib/system/clipboard/action/UserClipboardAction.class.php
wcfsetup/install/files/lib/system/worker/SendNewPasswordWorker.class.php [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index df5d5b74b10dbd5805bae9f07e63027feca211b8..f8970230842580b406061500b6a7d6587bc71d90 100644 (file)
                        </pages>
                </action>
                
-               <action name="sendMail">
-                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserClipboardAction]]></actionclassname>
+               <action name="merge">
+                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserExtendedClipboardAction]]></actionclassname>
+                       <showorder>4</showorder>
+                       <pages>
+                               <page><![CDATA[wcf\acp\page\UserListPage]]></page>
+                       </pages>
+               </action>
+               
+               <action name="enable">
+                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserExtendedClipboardAction]]></actionclassname>
                        <showorder>5</showorder>
                        <pages>
                                <page><![CDATA[wcf\acp\page\UserListPage]]></page>
                        </pages>
                </action>
                
-               <action name="exportMailAddress">
+               <action name="sendMail">
                        <actionclassname><![CDATA[wcf\system\clipboard\action\UserClipboardAction]]></actionclassname>
                        <showorder>6</showorder>
                        <pages>
                        </pages>
                </action>
                
-               <action name="merge">
-                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserExtendedClipboardAction]]></actionclassname>
-                       <showorder>4</showorder>
+               <action name="exportMailAddress">
+                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserClipboardAction]]></actionclassname>
+                       <showorder>7</showorder>
                        <pages>
                                <page><![CDATA[wcf\acp\page\UserListPage]]></page>
                        </pages>
                </action>
-               <action name="enable">
-                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserExtendedClipboardAction]]></actionclassname>
-                       <showorder>5</showorder>
+               
+               <action name="sendNewPassword">
+                       <actionclassname><![CDATA[wcf\system\clipboard\action\UserClipboardAction]]></actionclassname>
+                       <showorder>8</showorder>
                        <pages>
                                <page><![CDATA[wcf\acp\page\UserListPage]]></page>
                        </pages>
index 66ef32bfaac4648aaea4b46d28bb599b132edb7e..d581072bbd54a99a1f71fefd0d183ecac1e9b901 100644 (file)
@@ -9,7 +9,7 @@
 /**
  * Initialize WCF.ACP namespace
  */
-WCF.ACP = {};
+WCF.ACP = { };
 
 /**
  * Namespace for ACP application management.
@@ -613,7 +613,7 @@ WCF.ACP.Package.Installation = Class.extend({
                this._setIcon('spinner');
                
                // collect form values
-               var $additionalData = {};
+               var $additionalData = { };
                $('#packageInstallationInnerContent input').each(function(index, inputElement) {
                        var $inputElement = $(inputElement);
                        var $type = $inputElement.attr('type');
@@ -677,7 +677,7 @@ WCF.ACP.Package.Installation = Class.extend({
         * @param       object          additionalData
         */
        _executeStep: function(step, node, additionalData) {
-               if (!additionalData) additionalData = {};
+               if (!additionalData) additionalData = { };
                
                var $data = $.extend({
                        node: node,
@@ -1725,7 +1725,7 @@ WCF.ACP.Worker = Class.extend({
 /**
  * Namespace for category-related functions.
  */
-WCF.ACP.Category = {};
+WCF.ACP.Category = { };
 
 /**
  * Handles collapsing categories.
@@ -1775,8 +1775,8 @@ WCF.ACP.Category.Collapsible = WCF.Collapsible.SimpleRemote.extend({
                $('.collapsibleButton').remove();
                
                // reinit containers
-               this._containers = {};
-               this._containerData = {};
+               this._containers = { };
+               this._containerData = { };
                
                var $containers = this._getContainers();
                if ($containers.length == 0) {
@@ -2101,6 +2101,56 @@ WCF.ACP.User.EnableHandler = {
        }
 };
 
+/**
+ * Handles the send new password clipboard action.
+ */
+WCF.ACP.User.SendNewPasswordHandler = {
+       /**
+        * action proxy
+        * @var WCF.Action.Proxy
+        */
+       _proxy: null,
+       
+       /**
+        * Initializes WCF.ACP.User.SendNewPasswordHandler on first use.
+        */
+       init: function() {
+               this._proxy = new WCF.Action.Proxy({
+                       success: $.proxy(this._success, this)
+               });
+               
+               // bind clipboard event listener
+               $('.jsClipboardEditor').each($.proxy(function(index, container) {
+                       var $container = $(container);
+                       var $types = eval($container.data('types'));
+                       if (WCF.inArray('com.woltlab.wcf.user', $types)) {
+                               $container.on('clipboardAction', $.proxy(this._execute, this));
+                               return false;
+                       }
+               }, this));
+       },
+       
+       /**
+        * Handles clipboard actions.
+        * 
+        * @param       object          event
+        * @param       string          type
+        * @param       string          actionName
+        * @param       object          parameters
+        */
+       _execute: function(event, type, actionName, parameters) {
+               if (actionName == 'com.woltlab.wcf.user.sendNewPassword') {
+                       WCF.System.Confirmation.show(parameters.confirmMessage, function(action) {
+                               if (action === 'confirm') {
+                                       new WCF.ACP.Worker('sendingNewPasswords', 'wcf\\system\\worker\\SendNewPasswordWorker', WCF.Language.get('wcf.acp.user.sendNewPassword.workerTitle'), {
+                                               userIDs: parameters.objectIDs
+                                       });
+                               }
+                       });
+               }
+       }
+};
+
 /**
  * Namespace for import-related classes.
  */
index 2246eb450baf5a773f1e3780d146a97b9748922b..63e35de881b67c11a145aeb33365a28edeeb3d2f 100644 (file)
                WCF.Language.addObject({
                        'wcf.acp.user.banReason': '{lang}wcf.acp.user.banReason{/lang}',
                        'wcf.acp.user.banReason.description': '{lang}wcf.acp.user.banReason.description{/lang}',
-                       'wcf.acp.user.ban.sure': '{lang}wcf.acp.user.ban.sure{/lang}'
+                       'wcf.acp.user.ban.sure': '{lang}wcf.acp.user.ban.sure{/lang}',
+                       'wcf.acp.user.sendNewPassword.workerTitle': '{lang}wcf.acp.user.sendNewPassword.workerTitle{/lang}',
+                       'wcf.acp.worker.abort.confirmMessage': '{lang}wcf.acp.worker.abort.confirmMessage{/lang}'
                });
                WCF.ACP.User.BanHandler.init();
-               {if $__wcf->session->getPermission('admin.user.canEnableUser')}WCF.ACP.User.EnableHandler.init();{/if}
+               
+               {if $__wcf->session->getPermission('admin.user.canEnableUser')}
+                       WCF.ACP.User.EnableHandler.init();
+               {/if}
+               
+               {if $__wcf->session->getPermission('admin.user.canEditPassword')}
+                       WCF.ACP.User.SendNewPasswordHandler.init();
+               {/if}
                
                {event name='javascriptInit'}
        });
index be41c6ef92c65c51cefe76fba14629e7d7c95cbe..bf79d25c7bba49a85a0499ecd857540a6bb953b1 100644 (file)
@@ -25,7 +25,7 @@ class UserClipboardAction extends AbstractClipboardAction {
        /**
         * @see \wcf\system\clipboard\action\AbstractClipboardAction::$supportedActions
         */
-       protected $supportedActions = array('assignToGroup', 'ban', 'delete', 'exportMailAddress', 'sendMail');
+       protected $supportedActions = array('assignToGroup', 'ban', 'delete', 'exportMailAddress', 'sendMail', 'sendNewPassword');
        
        /**
         * @see \wcf\system\clipboard\action\IClipboardAction::execute()
@@ -56,6 +56,12 @@ class UserClipboardAction extends AbstractClipboardAction {
                        case 'sendMail':
                                $item->setURL(LinkHandler::getInstance()->getLink('UserMail'));
                        break;
+                       
+                       case 'sendNewPassword':
+                               $item->addParameter('confirmMessage', WCF::getLanguage()->getDynamicVariable('wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword.confirmMessage', array(
+                                       'count' => $item->getCount()
+                               )));
+                       break;
                }
                
                return $item;
@@ -135,7 +141,7 @@ class UserClipboardAction extends AbstractClipboardAction {
                        if (!isset($userToGroup[$row['userID']])) {
                                $userToGroup[$row['userID']] = array();
                        }
-                               
+                       
                        $userToGroup[$row['userID']][] = $row['groupID'];
                }
                
@@ -148,4 +154,18 @@ class UserClipboardAction extends AbstractClipboardAction {
                
                return $userIDs;
        }
+       
+       /**
+        * Returns the ids of the users which can be sent new passwords.
+        * 
+        * @return      array<integer>
+        */
+       public function validateSendNewPassword() {
+               // check permissions
+               if (!WCF::getSession()->getPermission('admin.user.canEditPassword')) {
+                       return array();
+               }
+               
+               return $this->__validateAccessibleGroups(array_keys($this->objects));
+       }
 }
diff --git a/wcfsetup/install/files/lib/system/worker/SendNewPasswordWorker.class.php b/wcfsetup/install/files/lib/system/worker/SendNewPasswordWorker.class.php
new file mode 100644 (file)
index 0000000..fb054e1
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+namespace wcf\system\worker;
+use wcf\data\user\UserAction;
+use wcf\data\user\UserEditor;
+use wcf\data\user\UserList;
+use wcf\system\clipboard\ClipboardHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\mail\Mail;
+use wcf\system\request\LinkHandler;
+use wcf\system\WCF;
+use wcf\util\PasswordUtil;
+
+/**
+ * Worker implementation for sending new passwords.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2014 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.worker
+ * @category   Community Framework
+ */
+class SendNewPasswordWorker extends AbstractWorker {
+       /**
+        * @see \wcf\system\worker\AbstractWorker::$limit
+        */
+       protected $limit = 50;
+       
+       /**
+        * @see \wcf\system\worker\IWorker::countObjects()
+        */
+       public function countObjects() {
+               $userList = new UserList();
+               $userList->getConditionBuilder()->add('user_table.userID IN (?)', array($this->parameters['userIDs']));
+               
+               return $userList->countObjects();
+       }
+       
+       /**
+        * @see \wcf\system\worker\IWorker::execute()
+        */
+       public function execute() {
+               $userList = new UserList();
+               $userList->decoratorClassName = 'wcf\data\user\UserEditor';
+               $userList->getConditionBuilder()->add('user_table.userID IN (?)', array($this->parameters['userIDs']));
+               $userList->sqlLimit = $this->limit;
+               $userList->sqlOffset = $this->limit * $this->loopCount;
+               $userList->readObjects();
+               
+               foreach ($userList as $userEditor) {
+                       $this->sendNewPassword($userEditor);
+               }
+       }
+       
+       /**
+        * @see \wcf\system\worker\IWorker::getProceedURL()
+        */
+       public function getProceedURL() {
+               return LinkHandler::getInstance()->getLink('UserList');
+       }
+       
+       /**
+        * @see \wcf\system\worker\IWorker::getProgress()
+        */
+       public function getProgress() {
+               $progress = parent::getProgress();
+               
+               if ($progress == 100) {
+                       // unmark users
+                       ClipboardHandler::getInstance()->unmark($this->parameters['userIDs'], ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.user'));
+               }
+               
+               return $progress;
+       }
+       
+       /**
+        * Sends a new password to the given user.
+        * 
+        * @param       \wcf\data\user\UserEditor       $userEditor
+        */
+       protected function sendNewPassword(UserEditor $userEditor) {
+               $newPassword = PasswordUtil::getRandomPassword();
+               
+               $userAction = new UserAction(array($userEditor), 'update', array(
+                       'data' => array(
+                               'password' => $newPassword
+                       )
+               ));
+               $userAction->executeAction();
+               
+               // send mail
+               $mail = new Mail(array($userEditor->username => $userEditor->email), $userEditor->getLanguage()->getDynamicVariable('wcf.acp.user.sendNewPassword.mail.subject'), $userEditor->getLanguage()->getDynamicVariable('wcf.acp.user.sendNewPassword.mail', array(
+                       'password' => $newPassword,
+                       'username' => $userEditor->username,
+               )));
+               $mail->send();
+       }
+       
+       /**
+        * @see \wcf\system\worker\IWorker::validate()
+        */
+       public function validate() {
+               WCF::getSession()->checkPermissions(array('admin.user.canEditPassword'));
+               
+               if (!isset($this->parameters['userIDs']) || !is_array($this->parameters['userIDs']) || empty($this->parameters['userIDs'])) {
+                       throw new SystemException("'userIDs' parameter is missing or invalid");
+               }
+       }
+}
index dadecac8676b70f7c40a32035c72bf1b53282825..c748be832a7603cadfa1d8768d004bbd6fa6dd41 100644 (file)
@@ -1372,6 +1372,14 @@ Wenn Sie unter <em>System -&gt; Optionen -&gt; Allgemein -&gt; E-Mails</em> alle
                <item name="wcf.acp.user.usersAwaitingApprovalInfo"><![CDATA[<a href="{link controller='UserQuickSearch'}mode=disabled{/link}">{#$usersAwaitingApproval} Benutzer</a> {if $usersAwaitingApproval == 1}wartet auf seine{else}warten auf ihre{/if} Aktivierung.]]></item>
                <item name="wcf.acp.user.search.conditions.state.enabled"><![CDATA[Aktiviert]]></item>
                <item name="wcf.acp.user.search.conditions.state.disabled"><![CDATA[Nicht aktiviert]]></item>
+               <item name="wcf.acp.user.sendNewPassword.mail"><![CDATA[Hallo {@$username},
+
+Ihr Kennwort wurde von einem Administrator geändert.
+Ihr neues Kennwort lautet: {$password}
+
+Klicken Sie hier, um sich mit Ihrem neuen Kennwort anzumelden: {link controller='Login' isEmail=true}{/link}]]></item>
+               <item name="wcf.acp.user.sendNewPassword.mail.subject"><![CDATA[Neues Kennwort für Ihr Benutzerkonto auf der Website: {@PAGE_TITLE|language}]]></item>
+               <item name="wcf.acp.user.sendNewPassword.workerTitle"><![CDATA[Neue Passwörter zusenden]]></item>
        </category>
        
        <category name="wcf.acp.worker">
@@ -1489,6 +1497,8 @@ Fehler sind beispielsweise:
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.delete.confirmMessage"><![CDATA[{if $count == 1}Einen{else}{#$count}{/if} Benutzer löschen?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.exportMailAddress"><![CDATA[E-Mail-Adressen exportieren]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendMail"><![CDATA[E-Mail senden]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword"><![CDATA[Neues Kennwort senden ({#$count})]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword.confirmMessage"><![CDATA[Wollen Sie wirklich {if $count == 1}einem{else}{#$count}{/if} Benutzer ein neues Kennwort zusenden?]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.user.marked"><![CDATA[{if $count == 1}Ein{else}{#$count}{/if} Benutzer markiert]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.merge"><![CDATA[Zusammenfügen]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.enable"><![CDATA[Aktivieren]]></item>
@@ -2094,7 +2104,7 @@ Fehler sind beispielsweise:
                <item name="wcf.user.lostPassword.mail"><![CDATA[Hallo {@$username},
 
 wenn Sie Ihr Kennwort vergessen haben, können Sie über folgenden Link ein neues Kennwort anfordern.
-Klicken Sie hier, um ein neues Kennwort anzufordern: {link controller='NewPassword' isEmail=true}u={@$userID}&k={@$key}{/link}  
+Klicken Sie hier, um ein neues Kennwort anzufordern: {link controller='NewPassword' isEmail=true}u={@$userID}&k={@$key}{/link}
 
 Falls Sie Ihr Kennwort nicht vergessen haben, können Sie diese E-Mail ignorieren.]]></item>
                <item name="wcf.user.lostPassword.mail.sent"><![CDATA[Sie erhalten in Kürze eine E-Mail mit weiteren Informationen.]]></item>
index 8dd5711fae956f30640d914e6520089788a435d3..6c137eeb9741d2036a62a1101403c26ef0fec561 100644 (file)
@@ -1372,6 +1372,14 @@ You can define the default sender in <em>System -&gt; Options -&gt; General -&gt
                <item name="wcf.acp.user.usersAwaitingApprovalInfo"><![CDATA[<a href="{link controller='UserQuickSearch'}mode=disabled{/link}">{#$usersAwaitingApproval} User{if $usersAwaitingApproval != 1}s{/if}</a> {if $usersAwaitingApproval == 1}is{else}are{/if} awaiting your approval.]]></item>
                <item name="wcf.acp.user.search.conditions.state.enabled"><![CDATA[Approved]]></item>
                <item name="wcf.acp.user.search.conditions.state.disabled"><![CDATA[Awaiting approval]]></item>
+               <item name="wcf.acp.user.sendNewPassword.mail"><![CDATA[Dear {@$username},
+
+Your password has been changed by an administrator.
+Your new password is: {$password}
+
+Login with your new password: {link controller='Login' isEmail=true}{/link}]]></item>
+               <item name="wcf.acp.user.sendNewPassword.mail.subject"><![CDATA[New Password for your Account for Website: {@PAGE_TITLE|language}]]></item>
+               <item name="wcf.acp.user.sendNewPassword.workerTitle"><![CDATA[Sending New Passwords]]></item>
        </category>
        
        <category name="wcf.acp.worker">
@@ -1488,6 +1496,8 @@ Errors are:
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.delete.confirmMessage"><![CDATA[Do you really want to delete {#$count} user{if $count != 1}s{/if}?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.exportMailAddress"><![CDATA[Export Email addresses]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendMail"><![CDATA[Send Email]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword"><![CDATA[Send New Password ({#$count})]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword.confirmMessage"><![CDATA[Do you really want to send a new password to {#$count} user{if $count != 1}s{/if}?]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.user.marked"><![CDATA[{#$count} User{if $count != 1}s{/if} marked]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.merge"><![CDATA[Merge]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.enable"><![CDATA[Approve]]></item>
@@ -2093,7 +2103,7 @@ Errors are:
                <item name="wcf.user.lostPassword.mail"><![CDATA[Dear {@$username},
 
 if you have lost your password you can request a new one using the link below.
-Request a new password: {link controller='NewPassword' isEmail=true}u={@$userID}&k={@$key}{/link}  
+Request a new password: {link controller='NewPassword' isEmail=true}u={@$userID}&k={@$key}{/link}
 
 If you have not lost your password, you can safely ignore this email.]]></item>
                <item name="wcf.user.lostPassword.mail.sent"><![CDATA[You should receive an email shortly.]]></item>