Skip to content

Commit

Permalink
Limit desktop notifications to a single domain for multi-domain envir…
Browse files Browse the repository at this point in the history
…onments

Closes #2411
  • Loading branch information
dtdesign committed Sep 6, 2017
1 parent 4aa9249 commit 6e4aa12
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 4 deletions.
8 changes: 7 additions & 1 deletion com.woltlab.wcf/option.xml
Expand Up @@ -499,12 +499,18 @@
<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>
Expand Down
2 changes: 1 addition & 1 deletion com.woltlab.wcf/templates/headIncludeJavaScript.tpl
Expand Up @@ -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}
});
Expand Down
2 changes: 1 addition & 1 deletion com.woltlab.wcf/templates/login.tpl
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions constants.php
Expand Up @@ -229,3 +229,4 @@
define('MODULE_TROPHY', 1);
define('ENABLE_DEVELOPER_TOOLS', 0);
define('FORCE_LOGIN', 0);
define('DESKTOP_NOTIFICATION_PACKAGE_ID', 1);
@@ -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}
2 changes: 1 addition & 1 deletion wcfsetup/install/files/acp/templates/rescueMode.tpl
Expand Up @@ -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">
Expand Down
24 changes: 24 additions & 0 deletions wcfsetup/install/files/lib/system/WCF.class.php
Expand Up @@ -1004,6 +1004,30 @@ public function getFavicon() {
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.
*
Expand Down
Expand Up @@ -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[]
Expand Down Expand Up @@ -200,6 +206,28 @@ public function isInternalURL($url) {
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.
*/
Expand Down
@@ -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');
}
}
}
}
Expand Up @@ -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;
Expand Down Expand Up @@ -72,6 +73,7 @@ public function search($query) {

$optionCategories = OptionCacheBuilder::getInstance()->getData([], 'categories');

/** @var Option $option */
while ($option = $statement->fetchObject(Option::class)) {
// category is not accessible
if (!$this->isValid($option->categoryName)) {
Expand All @@ -83,6 +85,11 @@ public function search($query) {
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));
Expand Down
2 changes: 2 additions & 0 deletions wcfsetup/install/lang/de.xml
Expand Up @@ -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">
Expand Down
2 changes: 2 additions & 0 deletions wcfsetup/install/lang/en.xml
Expand Up @@ -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">
Expand Down

0 comments on commit 6e4aa12

Please sign in to comment.