</type>
<!-- /box controllers -->
+ <!-- pages -->
+ <type>
+ <name>com.woltlab.wcf.page</name>
+ <definitionname>com.woltlab.wcf.acl.simple</definitionname>
+ </type>
+ <!-- /pages -->
+
<!-- deprecated -->
<type>
<name>com.woltlab.wcf.page.controller</name>
<name>com.woltlab.wcf.acl</name>
</definition>
+ <definition>
+ <name>com.woltlab.wcf.acl.simple</name>
+ </definition>
+
<definition>
<name>com.woltlab.wcf.collapsibleContent</name>
</definition>
--- /dev/null
+<div class="section">
+ <dl>
+ <dt><label for="aclAllowAll">{lang}wcf.acl.allowAll{/lang}</label></dt>
+ <dd>
+ <ol class="flexibleButtonGroup">
+ <li>
+ <input type="radio" id="aclAllowAll" name="aclValues[allowAll]" value="1"{if $aclValues[allowAll]} checked{/if}>
+ <label for="aclAllowAll" class="green"><span class="icon icon16 fa-check"></span> {lang}wcf.acp.option.type.boolean.yes{/lang}</label>
+ </li>
+ <li>
+ <input type="radio" id="aclAllowAll_no" name="aclValues[allowAll]" value="0"{if !$aclValues[allowAll]} checked{/if}>
+ <label for="aclAllowAll_no" class="red"><span class="icon icon16 fa-times"></span> {lang}wcf.acp.option.type.boolean.no{/lang}</label>
+ </li>
+ </ol>
+ </dd>
+ </dl>
+</div>
+
+<section class="section" id="aclInputContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
+ <h2 class="sectionTitle">{lang}wcf.acl.access{/lang}</h2>
+ <dl>
+ <dt><label for="aclSearchInput">{lang}wcf.acl.access.grant{/lang}</label></dt>
+ <dd>
+ <input type="text" id="aclSearchInput" class="long" placeholder="{lang}wcf.acl.search.description{/lang}">
+ </dd>
+ </dl>
+
+ <dl id="aclListContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
+ <dt>{lang}wcf.acl.access.granted{/lang}</dt>
+ <dd>
+ <ul id="aclAccessList" class="aclList containerList">
+ {foreach from=$aclValues[group] item=aclGroup}
+ <li>
+ <span class="icon icon16 fa-users"></span>
+ <span class="aclLabel">{$aclGroup}</span>
+ <span class="icon icon16 fa-times pointer jsTooltip" title="{lang}wcf.global.button.delete{/lang}"></span>
+ <input type="hidden" name="aclValues[group][]" value="{@$aclGroup->groupID}">
+ </li>
+ {/foreach}
+ {foreach from=$aclValues[user] item=aclUser}
+ <li>
+ <span class="icon icon16 fa-user"></span>
+ <span class="aclLabel">{$aclUser}</span>
+ <span class="icon icon16 fa-times pointer jsTooltip" title="{lang}wcf.global.button.delete{/lang}"></span>
+ <input type="hidden" name="aclValues[user][]" value="{@$aclUser->userID}">
+ </li>
+ {/foreach}
+ </ul>
+ </dd>
+ </dl>
+</section>
+
+<script data-relocate="true">
+ require(['WoltLab/WCF/Ui/Acl/Simple'], function(UiAclSimple) {
+ new UiAclSimple();
+ });
+</script>
</div>
<div id="acl" class="tabMenuContent">
+ {include file='aclSimple'}
</div>
</div>
--- /dev/null
+define(['Language', 'Dom/ChangeListener', 'WoltLab/WCF/Ui/User/Search/Input'], function(Language, DomChangeListener, UiUserSearchInput) {
+ "use strict";
+
+ function UiAclSimple() { this.init(); }
+ UiAclSimple.prototype = {
+ init: function() {
+ this._build();
+ },
+
+ _build: function () {
+ var container = elById('aclInputContainer');
+
+ elById('aclAllowAll').addEventListener('change', (function() {
+ elHide(container);
+ }));
+ elById('aclAllowAll_no').addEventListener('change', (function() {
+ elShow(container);
+ }));
+
+ new UiUserSearchInput(elById('aclSearchInput'), {
+ callbackSelect: this._select.bind(this),
+ includeUserGroups: true,
+ preventSubmit: true
+ });
+
+ this._aclListContainer = elById('aclListContainer');
+
+ this._list = elById('aclAccessList');
+ this._list.addEventListener(WCF_CLICK_EVENT, this._removeItem.bind(this));
+
+ DomChangeListener.trigger();
+ },
+
+ _select: function(listItem) {
+ var type = elData(listItem, 'type');
+
+ var html = '<span class="icon icon16 fa-' + (type === 'group' ? 'users' : 'user') + '"></span>';
+ html += '<span class="aclLabel">' + elData(listItem, 'label') + '</span>';
+ html += '<span class="icon icon16 fa-times pointer jsTooltip" title="' + Language.get('wcf.global.button.delete') + '"></span>';
+ html += '<input type="hidden" name="aclValues[' + type + '][]" value="' + elData(listItem, 'object-id') + '">';
+
+ var item = elCreate('li');
+ item.innerHTML = html;
+
+ var firstUser = elBySel('.fa-user', this._list);
+ if (firstUser === null) {
+ this._list.appendChild(item);
+ }
+ else {
+ this._list.insertBefore(item, firstUser.parentNode);
+ }
+
+ elShow(this._aclListContainer);
+
+ DomChangeListener.trigger();
+
+ return false;
+ },
+
+ _removeItem: function (event) {
+ if (event.target.classList.contains('fa-times')) {
+ elRemove(event.target.parentNode);
+
+ if (this._list.childElementCount === 0) {
+ elHide(this._aclListContainer);
+ }
+ }
+ }
+ };
+
+ return UiAclSimple;
+});
_createListItem: function(item) {
var listItem = UiUserSearchInput._super.prototype._createListItem.call(this, item);
+ elData(listItem, 'type', item.type);
var box = elCreate('div');
box.className = 'box16';
use wcf\data\page\PageEditor;
use wcf\data\page\PageNodeTree;
use wcf\form\AbstractForm;
+use wcf\system\acl\simple\SimpleAclHandler;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\UserInputException;
use wcf\system\html\input\HtmlInputProcessor;
*/
public $boxIDs = [];
+ /**
+ * acl values
+ * @var array
+ */
+ public $aclValues = [];
+
/**
* @inheritDoc
*/
if (isset($_POST['metaDescription']) && is_array($_POST['metaDescription'])) $this->metaDescription = ArrayUtil::trim($_POST['metaDescription']);
if (isset($_POST['metaKeywords']) && is_array($_POST['metaKeywords'])) $this->metaKeywords = ArrayUtil::trim($_POST['metaKeywords']);
if (isset($_POST['boxIDs']) && is_array($_POST['boxIDs'])) $this->boxIDs = ArrayUtil::toIntegerArray($_POST['boxIDs']);
+
+ if (isset($_POST['aclValues']) && is_array($_POST['aclValues'])) $this->aclValues = $_POST['aclValues'];
}
/**
$parseHTML = function($content) {
if ($this->pageType == 'text') {
$htmlInputProcessor = new HtmlInputProcessor();
- $content = $htmlInputProcessor->process($content);
+ $htmlInputProcessor->process($content);
+ $content = $htmlInputProcessor->getHtml();
}
return $content;
// set generic page identifier
$pageEditor = new PageEditor($page);
$pageEditor->update([
- 'identifier' => 'com.woltlab.wcf.generic'.$pageEditor->pageID
+ 'identifier' => 'com.woltlab.wcf.generic'.$page->pageID
]);
if ($this->isLandingPage) {
$page->setAsLandingPage();
}
+ // save acl
+ SimpleAclHandler::getInstance()->setValues('com.woltlab.wcf.page', $page->pageID, $_POST);
+
// call saved event
$this->saved();
'availableApplications' => $this->availableApplications,
'availableLanguages' => $this->availableLanguages,
'availableBoxes' => $this->availableBoxes,
- 'pageNodeList' => (new PageNodeTree())->getNodeList()
+ 'pageNodeList' => (new PageNodeTree())->getNodeList(),
+ 'aclValues' => (empty($_POST) ? $this->aclValues : SimpleAclHandler::getInstance()->getOutputValues($this->aclValues))
]);
}
}
use wcf\data\page\Page;
use wcf\data\page\PageAction;
use wcf\form\AbstractForm;
+use wcf\system\acl\simple\SimpleAclHandler;
use wcf\system\exception\IllegalLinkException;
use wcf\system\language\LanguageFactory;
use wcf\system\WCF;
$this->page->setAsLandingPage();
}
+ // save acl
+ SimpleAclHandler::getInstance()->setValues('com.woltlab.wcf.page', $this->page->pageID, $this->aclValues);
+
// call saved event
$this->saved();
}
}
}
+
+ $this->aclValues = SimpleAclHandler::getInstance()->getValues('com.woltlab.wcf.page', $this->page->pageID);
}
}
* exists.
*
* @param integer $groupID
- * @return \wcf\data\user\group\UserGroup
+ * @return UserGroup|null
*/
public static function getGroupByID($groupID) {
self::getCache();
return null;
}
+ /**
+ * Returns a list of groups by group id.
+ *
+ * @param integer[] $groupIDs list of group ids
+ * @return UserGroup[]
+ */
+ public static function getGroupsByIDs(array $groupIDs) {
+ $groups = [];
+ foreach ($groupIDs as $groupID) {
+ $group = self::getGroupByID($groupID);
+ if ($group !== null) $groups[$groupID] = $group;
+ }
+
+ return $groups;
+ }
+
/**
* Returns true if the given user is member of the group. If no user is
* given, the active user is used.
*
- * @param \wcf\data\user\User $user
+ * @param User $user user object or current user if null
* @return boolean
*/
public function isMember(User $user = null) {
--- /dev/null
+<?php
+namespace wcf\system\acl\simple;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\data\user\group\UserGroup;
+use wcf\system\cache\runtime\UserRuntimeCache;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
+
+/**
+ * Simplified ACL handlers that stores access data for objects requiring
+ * just a simple yes/no instead of a set of different permissions.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Acl\Simple
+ */
+class SimpleAclHandler extends SingletonFactory {
+ /**
+ * list of registered object types
+ * @var ObjectType[]
+ */
+ protected $objectTypes = [];
+
+ /**
+ * @inheritDoc
+ */
+ protected function init() {
+ $this->objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.acl.simple');
+ }
+
+ /**
+ * Returns the object type id by object type.
+ *
+ * @param string $objectType object type name
+ * @return integer object type id
+ * @throws SystemException
+ */
+ public function getObjectTypeID($objectType) {
+ if (!isset($this->objectTypes[$objectType])) {
+ throw new SystemException("Unknown object type '" . $objectType . "'");
+ }
+
+ return $this->objectTypes[$objectType]->objectTypeID;
+ }
+
+ /**
+ * Returns the user and group values for provided object type and object id.
+ *
+ * @param string $objectType object type name
+ * @param integer $objectID object id
+ * @return array array containing the keys `allowAll`, `user` and `group`
+ */
+ public function getValues($objectType, $objectID) {
+ $objectTypeID = $this->getObjectTypeID($objectType);
+
+ $data = [
+ 'allowAll' => true,
+ 'user' => [],
+ 'group' => []
+ ];
+
+ $sql = "SELECT userID
+ FROM wcf".WCF_N."_acl_simple_to_user
+ WHERE objectTypeID = ?
+ AND objectID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $objectTypeID,
+ $objectID
+ ]);
+ $userIDs = [];
+ while ($row = $statement->fetchArray()) {
+ $userIDs[] = $row['userID'];
+ }
+
+ $sql = "SELECT groupID
+ FROM wcf".WCF_N."_acl_simple_to_group
+ WHERE objectTypeID = ?
+ AND objectID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $objectTypeID,
+ $objectID
+ ]);
+ $groupIDs = [];
+ while ($row = $statement->fetchArray()) {
+ $groupIDs[] = $row['groupID'];
+ }
+
+ if (!empty($userIDs) || !empty($groupIDs)) {
+ $data['allowAll'] = false;
+
+ if (!empty($userIDs)) {
+ $data['user'] = UserRuntimeCache::getInstance()->getObjects($userIDs);
+ }
+
+ if (!empty($groupIDs)) {
+ $data['group'] = UserGroup::getGroupsByIDs($groupIDs);
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Sets the user and group values for provided object type and object id.
+ *
+ * @param string $objectType object type name
+ * @param integer $objectID object id
+ * @param array $values list of user and group ids
+ */
+ public function setValues($objectType, $objectID, array $values) {
+ $objectTypeID = $this->getObjectTypeID($objectType);
+
+ // validate data of `$values`
+ if (empty($values['user']) && empty($values['group']) && !isset($values['allowAll'])) {
+ throw new SystemException("Missing ACL configuration values.");
+ }
+
+ // users
+ $sql = "DELETE FROM wcf".WCF_N."_acl_simple_to_user
+ WHERE objectTypeID = ?
+ AND objectID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $objectTypeID,
+ $objectID
+ ]);
+
+ if ($values['allowAll'] == 0 && !empty($values['user'])) {
+ $values['user'] = ArrayUtil::toIntegerArray($values['user']);
+ if (!empty($values['user'])) {
+ $sql = "INSERT INTO wcf" . WCF_N . "_acl_simple_to_user
+ (objectTypeID, objectID, userID)
+ VALUES (?, ?, ?)";
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($values['user'] as $userID) {
+ $statement->execute([
+ $objectTypeID,
+ $objectID,
+ $userID
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+ }
+ }
+
+ // groups
+ $sql = "DELETE FROM wcf".WCF_N."_acl_simple_to_group
+ WHERE objectTypeID = ?
+ AND objectID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $objectTypeID,
+ $objectID
+ ]);
+
+ if ($values['allowAll'] == 0 && !empty($values['group'])) {
+ $values['group'] = ArrayUtil::toIntegerArray($values['group']);
+ if (!empty($values['group'])) {
+ $sql = "INSERT INTO wcf" . WCF_N . "_acl_simple_to_group
+ (objectTypeID, objectID, groupID)
+ VALUES (?, ?, ?)";
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($values['group'] as $groupID) {
+ $statement->execute([
+ $objectTypeID,
+ $objectID,
+ $groupID
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+ }
+ }
+
+ // reset cache for object type
+ SimpleAclResolver::getInstance()->resetCache($objectType);
+ }
+
+ /**
+ * Processes the provided values and returns the final
+ * values for template assignment.
+ *
+ * @param array $rawValues acl values as provided (by the user input)
+ * @return array final values for template assignment
+ */
+ public function getOutputValues(array $rawValues) {
+ $aclValues = [
+ 'allowAll' => true,
+ 'user' => [],
+ 'group' => []
+ ];
+
+ if ($rawValues['allowAll'] == 0) {
+ if (!empty($rawValues['user'])) {
+ $aclValues['user'] = UserRuntimeCache::getInstance()->getObjects($rawValues['user']);
+ }
+
+ if (!empty($rawValues['group'])) {
+ $aclValues['group'] = UserGroup::getGroupsByIDs($rawValues['group']);
+ }
+
+ if (!empty($aclValues['user']) || !empty($aclValues['group'])) {
+ $aclValues['allowAll'] = false;
+ }
+ }
+
+ return $aclValues;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\acl\simple;
+use wcf\data\user\User;
+use wcf\system\cache\builder\SimpleAclCacheBuilder;
+use wcf\system\SingletonFactory;
+use wcf\system\WCF;
+
+/**
+ * Simplified ACL handlers that stores access data for objects requiring
+ * just a simple yes/no instead of a set of different permissions.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Acl\Simple
+ */
+class SimpleAclResolver extends SingletonFactory {
+ /**
+ * cached permissions per object type
+ * @var array
+ */
+ protected $cache = [];
+
+ /**
+ * Returns true if there are no ACL settings, the user is allowed or
+ * one of its group is allowed.
+ *
+ * @param string $objectType object type name
+ * @param integer $objectID object id
+ * @param User|null $user user object, if `null` uses current user
+ * @return boolean false if user is not allowed
+ */
+ public function canAccess($objectType, $objectID, User $user = null) {
+ if ($user === null) $user = WCF::getUser();
+
+ $this->loadCache($objectType);
+
+ // allow all
+ if (!isset($this->cache[$objectType][$objectID])) {
+ return true;
+ }
+
+ if ($user->userID) {
+ // user is explicitly allowed
+ if (in_array($user->userID, $this->cache[$objectType][$objectID]['user'])) {
+ return true;
+ }
+ }
+
+ // check for user groups
+ $groupIDs = $user->getGroupIDs();
+ foreach ($groupIDs as $groupID) {
+ // group is explicitly allowed
+ if (in_array($groupID, $this->cache[$objectType][$objectID]['group'])) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Resets the cache for provided object type.
+ *
+ * @param string $objectType object type name
+ */
+ public function resetCache($objectType) {
+ SimpleAclCacheBuilder::getInstance()->reset(['objectType' => $objectType]);
+ }
+
+ /**
+ * Attempts to load the cache for provided object type.
+ *
+ * @param string $objectType object type name
+ */
+ protected function loadCache($objectType) {
+ if (!isset($this->cache[$objectType])) {
+ $this->cache[$objectType] = SimpleAclCacheBuilder::getInstance()->getData(['objectType' => $objectType]);
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\cache\builder;
+use wcf\system\acl\simple\SimpleAclHandler;
+use wcf\system\WCF;
+
+/**
+ * Caches the simple ACL settings per object type.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Cache\Builder
+ */
+class SimpleAclCacheBuilder extends AbstractCacheBuilder {
+ /**
+ * @inheritDoc
+ */
+ public function rebuild(array $parameters) {
+ $data = [];
+
+ $objectTypeID = SimpleAclHandler::getInstance()->getObjectTypeID($parameters['objectType']);
+
+ $sql = "SELECT objectID, userID
+ FROM wcf".WCF_N."_acl_simple_to_user
+ WHERE objectTypeID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$objectTypeID]);
+ while ($row = $statement->fetchArray()) {
+ $objectID = $row['objectID'];
+
+ if (!isset($data[$objectID])) {
+ $data[$objectID] = [
+ 'group' => [],
+ 'user' => []
+ ];
+ }
+
+ $data[$objectID]['user'][] = $row['userID'];
+ }
+
+ $sql = "SELECT objectID, groupID
+ FROM wcf".WCF_N."_acl_simple_to_group
+ WHERE objectTypeID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$objectTypeID]);
+ while ($row = $statement->fetchArray()) {
+ $objectID = $row['objectID'];
+
+ if (!isset($data[$objectID])) {
+ $data[$objectID] = [
+ 'group' => [],
+ 'user' => []
+ ];
+ }
+
+ $data[$objectID]['group'][] = $row['groupID'];
+ }
+
+ return $data;
+ }
+}
<?xml version="1.0" encoding="UTF-8"?>
<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/language.xsd" languagecode="de" languagename="Deutsch" countrycode="de">
<category name="wcf.acl">
+ <item name="wcf.acl.access"><![CDATA[Zugangsbeschränkung]]></item>
+ <item name="wcf.acl.access.grant"><![CDATA[Zugang gewähren]]></item>
+ <item name="wcf.acl.access.granted"><![CDATA[Erlaubte Benutzer und Benutzergruppen]]></item>
+ <item name="wcf.acl.allowAll"><![CDATA[Inhalt ist für alle Benutzer sichtbar]]></item>
+
<item name="wcf.acl.option.deny"><![CDATA[Verweigern]]></item>
<item name="wcf.acl.option.fullAccess"><![CDATA[Vollzugriff]]></item>
<item name="wcf.acl.option.grant"><![CDATA[Erlauben]]></item>
<?xml version="1.0" encoding="UTF-8"?>
<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/language.xsd" languagecode="en" languagename="English" countrycode="gb">
<category name="wcf.acl">
+ <item name="wcf.acl.access"><![CDATA[Restricted Access]]></item>
+ <item name="wcf.acl.access.grant"><![CDATA[Allow Access]]></item>
+ <item name="wcf.acl.access.granted"><![CDATA[Granted Access for Users and User-Groups]]></item>
+ <item name="wcf.acl.allowAll"><![CDATA[Content Can be Accessed by Everyone]]></item>
+
<item name="wcf.acl.option.deny"><![CDATA[Deny]]></item>
<item name="wcf.acl.option.fullAccess"><![CDATA[Full Access]]></item>
<item name="wcf.acl.option.grant"><![CDATA[Grant]]></item>
UNIQUE KEY groupID (groupID, objectID, optionID)
);
+DROP TABLE IF EXISTS wcf1_acl_simple_to_user;
+CREATE TABLE wcf1_acl_simple_to_user (
+ objectTypeID INT(10) NOT NULL,
+ objectID INT(10) NOT NULL,
+ userID INT(10) NOT NULL,
+ UNIQUE KEY userKey (objectTypeID, objectID, userID)
+);
+
+DROP TABLE IF EXISTS wcf1_acl_simple_to_group;
+CREATE TABLE wcf1_acl_simple_to_group (
+ objectTypeID INT(10) NOT NULL,
+ objectID INT(10) NOT NULL,
+ groupID INT(10) NOT NULL,
+ UNIQUE KEY groupKey (objectTypeID, objectID, groupID)
+);
+
DROP TABLE IF EXISTS wcf1_acp_menu_item;
CREATE TABLE wcf1_acp_menu_item (
menuItemID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
ALTER TABLE wcf1_acl_option_to_group ADD FOREIGN KEY (optionID) REFERENCES wcf1_acl_option (optionID) ON DELETE CASCADE;
ALTER TABLE wcf1_acl_option_to_group ADD FOREIGN KEY (groupID) REFERENCES wcf1_user_group (groupID) ON DELETE CASCADE;
+ALTER TABLE wcf1_acl_simple_to_user ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
+ALTER TABLE wcf1_acl_simple_to_user ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
+
+ALTER TABLE wcf1_acl_simple_to_group ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
+ALTER TABLE wcf1_acl_simple_to_group ADD FOREIGN KEY (groupID) REFERENCES wcf1_user_group (groupID) ON DELETE CASCADE;
+
ALTER TABLE wcf1_acp_menu_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
ALTER TABLE wcf1_acp_search_provider ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;