Add permission to restrict hiding online status (#3363)
authorMatthias Schmidt <gravatronics@live.com>
Thu, 11 Jun 2020 13:44:32 +0000 (15:44 +0200)
committerGitHub <noreply@github.com>
Thu, 11 Jun 2020 13:44:32 +0000 (15:44 +0200)
Close #3248

com.woltlab.wcf/userGroupOption.xml
com.woltlab.wcf/userOption.xml
wcfsetup/install/files/lib/data/user/UserProfile.class.php
wcfsetup/install/files/lib/data/user/online/UserOnline.class.php
wcfsetup/install/files/lib/data/user/online/UsersOnlineList.class.php
wcfsetup/install/files/lib/system/box/WhoWasOnlineBoxController.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 9fd4679bf1ecf7aef2cdb489f4b91b870b1d8e72..81f26c995cfb48842df58e47ddc60210cbb709cc 100644 (file)
@@ -743,6 +743,12 @@ pdf</defaultvalue>
                                <defaultvalue>1</defaultvalue>
                                <usersonly>1</usersonly>
                        </option>
+                       <option name="user.profile.canHideOnlineStatus">
+                               <categoryname>user.profile</categoryname>
+                               <optiontype>boolean</optiontype>
+                               <defaultvalue>1</defaultvalue>
+                               <usersonly>1</usersonly>
+                       </option>
                        <option name="user.profile.avatar.canSeeAvatars">
                                <categoryname>user.profile.avatar</categoryname>
                                <optiontype>boolean</optiontype>
index 769aade42c8018b5e6ee95a3622ba71a49dcc62e..e8503fc1e73e06ac7077b320ce43cd5bf90f864c 100644 (file)
 2:wcf.user.access.following
 3:wcf.user.access.nobody</selectoptions>
                                <editable>3</editable>
+                               <permissions>user.profile.canHideOnlineStatus</permissions>
                        </option>
                        <option name="canViewProfile">
                                <categoryname>settings.privacy.content</categoryname>
index 4ec1b523d9997ae3abff7de0de2be57323000883..88240858bb051e5b4c276cc49dabffdc92e1537a 100644 (file)
@@ -406,7 +406,10 @@ class UserProfile extends DatabaseObjectDecorator implements ITitledLinkObject {
         * @return      boolean
         */
        public function canViewOnlineStatus() {
-               return (WCF::getUser()->userID == $this->userID || WCF::getSession()->getPermission('admin.user.canViewInvisible') || $this->isAccessible('canViewOnlineStatus'));
+               return WCF::getUser()->userID == $this->userID
+                       || WCF::getSession()->getPermission('admin.user.canViewInvisible')
+                       || !$this->getPermission('user.profile.canHideOnlineStatus')
+                       || $this->isAccessible('canViewOnlineStatus');
        }
        
        /**
index 154127a43796d61e53f1b86139ae79ff1c2a9de9..6cdcad3610d49107a1656bc0e78286900855cf3f 100644 (file)
@@ -48,7 +48,10 @@ class UserOnline extends UserProfile {
                        $username = str_replace('%s', $username, $this->userOnlineMarking);
                }
                
-               if ($this->canViewOnlineStatus == 3) {
+               if (
+                       $this->getPermission('user.profile.canHideOnlineStatus')
+                       && $this->canViewOnlineStatus == UserProfile::ACCESS_NOBODY
+               ) {
                        $username .= WCF::getLanguage()->get('wcf.user.usersOnline.invisible');
                }
                
index 1069985dd710511df8a2a344550c1a44c07fc88c..af400413a804837367149a1948cc07027ed41db2 100644 (file)
@@ -4,7 +4,9 @@ use wcf\data\option\OptionAction;
 use wcf\data\session\SessionList;
 use wcf\data\user\group\UserGroup;
 use wcf\data\user\User;
+use wcf\data\user\UserProfile;
 use wcf\system\event\EventHandler;
+use wcf\system\user\storage\UserStorageHandler;
 use wcf\system\WCF;
 use wcf\util\StringUtil;
 
@@ -70,9 +72,11 @@ class UsersOnlineList extends SessionList {
                $objects = $this->objects;
                $this->indexToObject = $this->objects = [];
                
+               UserStorageHandler::getInstance()->loadStorage($this->objectIDs);
+               
                foreach ($objects as $object) {
                        $object = new UserOnline(new User(null, null, $object));
-                       if (!$object->userID || self::isVisible($object->userID, $object->canViewOnlineStatus)) {
+                       if (!$object->userID || self::isVisibleUser($object)) {
                                $this->objects[$object->sessionID] = $object;
                                $this->indexToObject[] = $object->sessionID;
                        }
@@ -96,11 +100,13 @@ class UsersOnlineList extends SessionList {
                $statement = WCF::getDB()->prepareStatement($sql);
                $statement->execute($conditionBuilder->getParameters());
                while ($row = $statement->fetchArray()) {
+                       $user = new UserOnline(new User(null, $row));
+                       
                        $this->stats['total']++;
-                       if ($row['userID']) {
+                       if ($user->userID) {
                                $this->stats['members']++;
                                
-                               if ($row['canViewOnlineStatus'] && !self::isVisible($row['userID'], $row['canViewOnlineStatus'])) {
+                               if ($user->canViewOnlineStatus && !self::isVisibleUser($user)) {
                                        $this->stats['invisible']++;
                                }
                        }
@@ -155,20 +161,29 @@ class UsersOnlineList extends SessionList {
         * @param       integer         $userID
         * @param       integer         $canViewOnlineStatus
         * @return      boolean
+        * @deprecated  5.3             Use `isVisibleUser` instead
         */
        public static function isVisible($userID, $canViewOnlineStatus) {
-               if (WCF::getSession()->getPermission('admin.user.canViewInvisible') || $userID == WCF::getUser()->userID) return true;
-
-               $data = ['result' => false, 'userID' => $userID, 'canViewOnlineStatus' => $canViewOnlineStatus];
+               if (WCF::getSession()->getPermission('admin.user.canViewInvisible') || $userID == WCF::getUser()->userID) {
+                       return true;
+               }
+               
+               $data = [
+                       'result' => false,
+                       'userID' => $userID,
+                       'canViewOnlineStatus' => $canViewOnlineStatus,
+               ];
                
                switch ($canViewOnlineStatus) {
-                       case 0: // everyone
+                       case UserProfile::ACCESS_EVERYONE:
                                $data['result'] = true;
                                break;
-                       case 1: // registered
+                               
+                       case UserProfile::ACCESS_REGISTERED:
                                if (WCF::getUser()->userID) $data['result'] = true;
                                break;
-                       case 2: // following
+                               
+                       case UserProfile::ACCESS_FOLLOWING:
                                /** @noinspection PhpUndefinedMethodInspection */
                                if (WCF::getUserProfileHandler()->isFollower($userID)) $data['result'] = true;
                                break;
@@ -178,4 +193,46 @@ class UsersOnlineList extends SessionList {
                
                return $data['result'];
        }
+       
+       /**
+        * Checks the 'canViewOnlineStatus' setting for the given user.
+        * 
+        * @param       UserOnline      $userOnline
+        * @return      boolean
+        * @since       5.3
+        */
+       public static function isVisibleUser(UserOnline $userOnline) {
+               if (WCF::getSession()->getPermission('admin.user.canViewInvisible') || $userOnline->userID == WCF::getUser()->userID) {
+                       return true;
+               }
+               
+               $data = [
+                       'result' => false,
+                       'userOnline' => $userOnline,
+               ];
+               
+               if ($userOnline->getPermission('user.profile.canHideOnlineStatus')) {
+                       switch ($userOnline->canViewOnlineStatus) {
+                               case UserProfile::ACCESS_EVERYONE:
+                                       $data['result'] = true;
+                                       break;
+                               
+                               case UserProfile::ACCESS_REGISTERED:
+                                       if (WCF::getUser()->userID) $data['result'] = true;
+                                       break;
+                               
+                               case UserProfile::ACCESS_FOLLOWING:
+                                       /** @noinspection PhpUndefinedMethodInspection */
+                                       if (WCF::getUserProfileHandler()->isFollower($userID)) $data['result'] = true;
+                                       break;
+                       }
+               }
+               else {
+                       $data['result'] = true;
+               }
+               
+               EventHandler::getInstance()->fireAction(get_called_class(), 'isVisibleUser', $data);
+               
+               return $data['result'];
+       }
 }
index 495c02975349a33d878aef9dc5df5c24dea935ff..5682de6b02942ba2b3c79c7a5c12fdae674fa996 100644 (file)
@@ -102,7 +102,7 @@ class WhoWasOnlineBoxController extends AbstractDatabaseObjectListBoxController
                        });
                        foreach ($this->users as $key => $user) {
                                // remove invisible users
-                               if (!UsersOnlineList::isVisible($user->userID, $user->canViewOnlineStatus)) {
+                               if (!UsersOnlineList::isVisibleUser($user)) {
                                        unset($this->users[$key]);
                                }
                        }
index d7e287dd91061257f202539d44645ec451bb53e7..b3ba3bb06330d143b4237df9a8d1808c0652fe7a 100644 (file)
@@ -891,6 +891,7 @@ ACHTUNG: Die oben genannten Meldungen sind stark gekürzt. Sie können Details z
                <item name="wcf.acp.group.option.user.contactForm.attachment.allowedExtensions.description"><![CDATA[Eine Dateiendung pro Zeile]]></item>
                <item name="wcf.acp.group.option.user.contactForm.attachment.maxCount"><![CDATA[Maximale Dateianhänge pro Nachricht]]></item>
                <item name="wcf.acp.group.option.user.profile.canEditUserProfile"><![CDATA[Kann eigenes Profil bearbeiten]]></item>
+               <item name="wcf.acp.group.option.user.profile.canHideOnlineStatus"><![CDATA[Kann Online-Status verbergen]]></item>
                <item name="wcf.acp.group.allowMention"><![CDATA[Benutzergruppe kann erwähnt werden]]></item>
                <item name="wcf.acp.group.type.owner"><![CDATA[Besitzer]]></item>
                <item name="wcf.acp.group.type.owner.description"><![CDATA[Die Besitzer-Gruppe verfügt über nicht entziehbare Berechtigungen und kann von anderen Gruppen nicht bearbeitet werden, diese Gruppe kann nur durch die Besitzer-Gruppe selbst bearbeitet werden. Mitglieder dieser Gruppe können andere Benutzer zu dieser Gruppe hinzufügen, sich aber selbst nicht daraus entfernen.]]></item>
index b30d0f59d68fba6a0afe9a5c8c970fc93aff1950..ada3909315d94a57b6e7d939506f4c966263d3e8 100644 (file)
@@ -868,6 +868,7 @@ ATTENTION: The messages listed above are greatly shortened. You can view details
                <item name="wcf.acp.group.option.user.contactForm.attachment.allowedExtensions.description"><![CDATA[Enter one extension per line.]]></item>
                <item name="wcf.acp.group.option.user.contactForm.attachment.maxCount"><![CDATA[Maximum Attachments per Message]]></item>
                <item name="wcf.acp.group.option.user.profile.canEditUserProfile"><![CDATA[Can edit their profile]]></item>
+               <item name="wcf.acp.group.option.user.profile.canHideOnlineStatus"><![CDATA[Can hide their online status]]></item>
                <item name="wcf.acp.group.allowMention"><![CDATA[User group can be mentioned]]></item>
                <item name="wcf.acp.group.type.owner"><![CDATA[Owner]]></item>
                <item name="wcf.acp.group.type.owner.description"><![CDATA[The owner group features a few irrevocable permissions and is protected from edits by other groups, only the owner group can edit itself. Members of this group can add other users to this group, but cannot remove themselves.]]></item>