Limit desktop notifications to a single domain for multi-domain environments
authorAlexander Ebert <ebert@woltlab.com>
Wed, 6 Sep 2017 09:39:28 +0000 (11:39 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 6 Sep 2017 09:39:36 +0000 (11:39 +0200)
Closes #2411

12 files changed:
com.woltlab.wcf/option.xml
com.woltlab.wcf/templates/headIncludeJavaScript.tpl
com.woltlab.wcf/templates/login.tpl
constants.php
wcfsetup/install/files/acp/templates/desktopNotificationApplicationSelectOptionType.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/rescueMode.tpl
wcfsetup/install/files/lib/system/WCF.class.php
wcfsetup/install/files/lib/system/application/ApplicationHandler.class.php
wcfsetup/install/files/lib/system/option/DesktopNotificationApplicationSelectOptionType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/OptionACPSearchResultProvider.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 325202450ac6b00fb0276f46611214d600ecd81d..5568748776f6f73975f416729992598d241518f4 100644 (file)
                                <categoryname>general.page</categoryname>
                                <optiontype>boolean</optiontype>
                                <defaultvalue>1</defaultvalue>
-                               <enableoptions>enable_desktop_notifications</enableoptions>
+                               <enableoptions>enable_desktop_notifications,desktop_notification_package_id</enableoptions>
                        </option>
                        <option name="enable_desktop_notifications">
                                <categoryname>general.page</categoryname>
                                <optiontype>boolean</optiontype>
                                <defaultvalue>1</defaultvalue>
+                               <enableoptions>desktop_notification_package_id</enableoptions>
+                       </option>
+                       <option name="desktop_notification_package_id">
+                               <categoryname>general.page</categoryname>
+                               <optiontype>desktopNotificationApplicationSelect</optiontype>
+                               <defaultvalue>1</defaultvalue>
                        </option>
                        <option name="head_code">
                                <categoryname>general.page</categoryname>
index 1fca4b96b2cfd1f6b0196d35d4fade953eb2d6fc..553f36eafd2ff3e581f09b78dfc997108a06f7f2 100644 (file)
@@ -212,7 +212,7 @@ requirejs.config({
                        {if ENABLE_POLLING && $__wcf->user->userID}
                                require(['WoltLabSuite/Core/Notification/Handler'], function(NotificationHandler) {
                                        NotificationHandler.setup({
-                                               enableNotifications: {if ENABLE_DESKTOP_NOTIFICATIONS}true{else}false{/if},
+                                               enableNotifications: {if $__wcf->useDesktopNotifications()}true{else}false{/if},
                                                icon: '{$__wcf->getStyleHandler()->getStyle()->getFaviconAppleTouchIcon()}',
                                                sessionKeepAlive: {@$__sessionKeepAlive}
                                        });
index b82690cfc6c14e82eeceb3145eef83f0f32a6d35..4b31acac7fcf1b83c192ef62b830f1c52f11738f 100644 (file)
@@ -8,7 +8,7 @@
        {include file='formError'}
 {/if}
 
-<div id="loginForm" class="loginForm{if REGISTER_DISABLED} loginFormLoginOnly{/if}">
+<div id="loginForm" class="section loginForm{if REGISTER_DISABLED} loginFormLoginOnly{/if}">
        <form method="post" action="{@$loginController}">
                <section class="section loginFormLogin">
                        <h2 class="sectionTitle">{lang}wcf.user.login.login{/lang}</h2>
index dac81c311b32161fdb4d82d76dacf358af220547..5e5ef776bf1ad43234b19ff874ed873b86d8fdf3 100644 (file)
@@ -229,3 +229,4 @@ define('SITEMAP_INDEX_TIME_FRAME', 365);
 define('MODULE_TROPHY', 1);
 define('ENABLE_DEVELOPER_TOOLS', 0);
 define('FORCE_LOGIN', 0);
+define('DESKTOP_NOTIFICATION_PACKAGE_ID', 1);
diff --git a/wcfsetup/install/files/acp/templates/desktopNotificationApplicationSelectOptionType.tpl b/wcfsetup/install/files/acp/templates/desktopNotificationApplicationSelectOptionType.tpl
new file mode 100644 (file)
index 0000000..9aeef09
--- /dev/null
@@ -0,0 +1,19 @@
+{if $isMultiDomainSetup}
+       <select name="values[{$option->optionName}]" id="{$option->optionName}">
+               {foreach from=$applications item=application}
+                       <option value="{@$application->packageID}"{if $application->packageID == $value} selected{/if}>{$application->getPackage()}</option>
+               {/foreach}
+       </select>
+{else}
+       {* TODO: hide *}
+       <input type="hidden" name="values[{$option->optionName}]" value="1">
+       <script>
+               (function() {
+                       {* pretend that this option does not exist *}
+                       var container = elBySel('.{$option->optionName}Input');
+                       container.style.setProperty('margin', '0', 'important');
+                       container.style.setProperty('max-height', '0', 'important');
+                       container.style.setProperty('overflow', 'hidden', 'important');
+               })();
+       </script>
+{/if}
index 541526d3502a87f25272630078f7888bc73e30e0..c1eee62c6687539f3779ab88cc816a9b83186b41 100644 (file)
@@ -12,7 +12,7 @@
 <body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}" class="wcfAcp">
 <a id="top"></a>
 
-<div id="pageContainer" class="pageContainer">
+<div id="pageContainer" class="pageContainer acpPageHiddenMenu">
        <div class="pageHeaderContainer">
                <header id="pageHeaderFacade" class="pageHeaderFacade">
                        <div class="layoutBoundary">
index 2d25440016350a6bb326b6bcbfb409c78de43d87..6733947b351ff8a5ab4973f54616df64faca072b 100644 (file)
@@ -1004,6 +1004,30 @@ class WCF {
                return self::getPath() . $favicon;
        }
        
+       /**
+        * Returns true if the desktop notifications should be enabled.
+        * 
+        * @return      boolean
+        */
+       public function useDesktopNotifications() {
+               if (!ENABLE_DESKTOP_NOTIFICATIONS) {
+                       return false;
+               }
+               else if (ApplicationHandler::getInstance()->isMultiDomainSetup()) {
+                       $application = ApplicationHandler::getInstance()->getApplicationByID(DESKTOP_NOTIFICATION_PACKAGE_ID);
+                       // mismatch, default to Core
+                       if ($application === null) $application = ApplicationHandler::getInstance()->getApplicationByID(1);
+                       
+                       $currentApplication = ApplicationHandler::getInstance()->getActiveApplication();
+                       if ($currentApplication->domainName != $application->domainName) {
+                               // different domain
+                               return false;
+                       }
+               }
+               
+               return true;
+       }
+       
        /**
         * Returns true if currently active request represents the landing page.
         * 
index 5ad414e490ad32511a1700fa3336f8b325cc8bd6..2c9e5a548ecfc7ab8fbfb9bc692d7655055251e3 100644 (file)
@@ -24,6 +24,12 @@ class ApplicationHandler extends SingletonFactory {
         */
        protected $cache;
        
+       /**
+        * true for multi-domain setups
+        * @var boolean
+        */
+       protected $isMultiDomain;
+       
        /**
         * list of page URLs
         * @var string[]
@@ -200,6 +206,28 @@ class ApplicationHandler extends SingletonFactory {
                return false;
        }
        
+       /**
+        * Returns true if this is a multi-domain setup.
+        * 
+        * @return      boolean
+        * @since       3.1
+        */
+       public function isMultiDomainSetup() {
+               if ($this->isMultiDomain === null) {
+                       $this->isMultiDomain = false;
+                       
+                       $domainName = $this->getApplicationByID(1)->domainName;
+                       foreach ($this->getApplications() as $application) {
+                               if ($application->domainName !== $domainName) {
+                                       $this->isMultiDomain = true;
+                                       break;
+                               }
+                       }
+               }
+               
+               return $this->isMultiDomain;
+       }
+       
        /**
         * Rebuilds cookie domain/path for all applications.
         */
diff --git a/wcfsetup/install/files/lib/system/option/DesktopNotificationApplicationSelectOptionType.class.php b/wcfsetup/install/files/lib/system/option/DesktopNotificationApplicationSelectOptionType.class.php
new file mode 100644 (file)
index 0000000..305f119
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+namespace wcf\system\option;
+use wcf\data\option\Option;
+use wcf\system\application\ApplicationHandler;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Option type implementation for the desktop notification application selection. This
+ * option is intentionally designed to be invisible at most times.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2017 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Option
+ */
+class DesktopNotificationApplicationSelectOptionType extends AbstractOptionType {
+       /**
+        * @inheritDoc
+        */
+       public function getFormElement(Option $option, $value) {
+               return WCF::getTPL()->fetch('desktopNotificationApplicationSelectOptionType', 'wcf', [
+                       'applications' => ApplicationHandler::getInstance()->getApplications(),
+                       'isMultiDomainSetup' => ApplicationHandler::getInstance()->isMultiDomainSetup(),
+                       'option' => $option,
+                       'value' => $value
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function validate(Option $option, $newValue) {
+               if (ApplicationHandler::getInstance()->isMultiDomainSetup()) {
+                       if (ApplicationHandler::getInstance()->getApplicationByID($newValue) === null) {
+                               throw new UserInputException($option->optionName, 'validationFailed');
+                       }
+               }
+       }
+}
index 26e885b19d31c71afbd2613cb746b1f77aeac53a..337939b85f940be325ce9ae6d110728258b3454e 100644 (file)
@@ -2,6 +2,7 @@
 namespace wcf\system\search\acp;
 use wcf\data\option\category\OptionCategoryList;
 use wcf\data\option\Option;
+use wcf\system\application\ApplicationHandler;
 use wcf\system\cache\builder\OptionCacheBuilder;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\request\LinkHandler;
@@ -72,6 +73,7 @@ class OptionACPSearchResultProvider extends AbstractCategorizedACPSearchResultPr
                
                $optionCategories = OptionCacheBuilder::getInstance()->getData([], 'categories');
                
+               /** @var Option $option */
                while ($option = $statement->fetchObject(Option::class)) {
                        // category is not accessible
                        if (!$this->isValid($option->categoryName)) {
@@ -83,6 +85,11 @@ class OptionACPSearchResultProvider extends AbstractCategorizedACPSearchResultPr
                                continue;
                        }
                        
+                       // hide special option for multi-domain setups if not applicable
+                       if ($option->optionName === 'desktop_notification_package_id' && !ApplicationHandler::getInstance()->isMultiDomainSetup()) {
+                               continue;
+                       }
+                       
                        $link = LinkHandler::getInstance()->getLink('Option', [
                                'id' => $this->getCategoryID($this->getTopCategory($option->categoryName)->parentCategoryName)
                        ], 'optionName='.$option->optionName.'#category_'.$this->getCategoryName($option->categoryName));
index 76a68eb3cf07e0cbd73b64110282b59578349e5a..29139b93e68540cd3746239ddf01cceb4450ad56 100644 (file)
@@ -1412,6 +1412,8 @@ Als Benachrichtigungs-URL in der Konfiguration der sofortigen Zahlungsbestätigu
                <item name="wcf.acp.option.enable_developer_tools.description"><![CDATA[Aktiviert spezielle Werkzeuge die für die Plugin-Entwicklung verwendet werden. Diese Option sollte im Live-Betrieb abgeschaltet werden.]]></item>
                <item name="wcf.acp.option.force_login"><![CDATA[Anmeldung erzwingen]]></item>
                <item name="wcf.acp.option.force_login.description"><![CDATA[Besucher werden aufgefordert sich anzumelden, um auf die Inhalte zugreifen zu können.]]></item>
+               <item name="wcf.acp.option.desktop_notification_package_id"><![CDATA[Primäre Domain für Desktop-Benachrichtigungen]]></item>
+               <item name="wcf.acp.option.desktop_notification_package_id.description"><![CDATA[Desktop-Benachrichtigungen werden nur für die ausgewählte App aktiviert, einschließlich aller anderen Apps die auf der identischen Domain laufen.]]></item>
        </category>
        
        <category name="wcf.acp.customOption">
index 9b8397b7033da2b5898414ee085319cf225d98d6..9c928baccb7c9312b2861903200e405ffbe787e0 100644 (file)
@@ -1406,6 +1406,8 @@ When prompted for the notification URL for the instant payment notifications, pl
                <item name="wcf.acp.option.enable_developer_tools.description"><![CDATA[Enables a set of specialized tools that are used for plugin development. Should always be disabled in production environments.]]></item>
                <item name="wcf.acp.option.force_login"><![CDATA[Force login]]></item>
                <item name="wcf.acp.option.force_login.description"><![CDATA[Visitors are required to log-in themselves to access the page.]]></item>
+               <item name="wcf.acp.option.desktop_notification_package_id"><![CDATA[Primary Domain for Desktop Notifications]]></item>
+               <item name="wcf.acp.option.desktop_notification_package_id.description"><![CDATA[Desktop Notifications will be enabled for the selected app only, including all other apps that use the exact same domain.]]></item>
        </category>
        
        <category name="wcf.acp.customOption">