From 092bdf829787acc8e66c4e01cc52a04077fc327d Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 31 Dec 2012 03:33:22 +0100 Subject: [PATCH] Merged com.woltlab.wcf.acl into WCF --- com.woltlab.wcf/objectTypeDefinition.xml | 4 + com.woltlab.wcf/packageInstallationPlugin.xml | 1 + .../template/aclPermissionJavaScript.tpl | 63 ++ com.woltlab.wcf/template/aclPermissions.tpl | 19 + .../acp/templates/aclPermissionJavaScript.tpl | 63 ++ .../files/acp/templates/aclPermissions.tpl | 19 + .../files/acp/templates/categoryAdd.tpl | 157 +++++ .../files/acp/templates/categoryList.tpl | 164 +++++ wcfsetup/install/files/js/WCF.ACL.js | 574 ++++++++++++++++++ .../form/AbstractCategoryAddForm.class.php | 348 +++++++++++ .../form/AbstractCategoryEditForm.class.php | 171 ++++++ .../page/AbstractCategoryListPage.class.php | 155 +++++ .../lib/data/acl/option/ACLOption.class.php | 40 ++ .../data/acl/option/ACLOptionAction.class.php | 43 ++ .../data/acl/option/ACLOptionEditor.class.php | 20 + .../data/acl/option/ACLOptionList.class.php | 20 + .../category/ACLOptionCategory.class.php | 25 + .../ACLOptionCategoryAction.class.php | 20 + .../ACLOptionCategoryEditor.class.php | 20 + .../category/ACLOptionCategoryList.class.php | 20 + .../data/category/ViewableCategory.class.php | 61 ++ .../category/ViewableCategoryNode.class.php | 21 + .../ViewableCategoryNodeList.class.php | 19 + .../files/lib/system/acl/ACLHandler.class.php | 413 +++++++++++++ .../ACLOptionCategoryCacheBuilder.class.php | 35 ++ .../CategoryACLOptionCacheBuilder.class.php | 55 ++ .../CategoryPermissionHandler.class.php | 83 +++ ...LOptionPackageInstallationPlugin.class.php | 202 ++++++ wcfsetup/install/files/style/acl.less | 80 +++ wcfsetup/install/lang/de.xml | 7 + wcfsetup/install/lang/en.xml | 7 + wcfsetup/setup/db/install.sql | 49 ++ 32 files changed, 2978 insertions(+) create mode 100644 com.woltlab.wcf/template/aclPermissionJavaScript.tpl create mode 100644 com.woltlab.wcf/template/aclPermissions.tpl create mode 100644 wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl create mode 100644 wcfsetup/install/files/acp/templates/aclPermissions.tpl create mode 100644 wcfsetup/install/files/acp/templates/categoryAdd.tpl create mode 100644 wcfsetup/install/files/acp/templates/categoryList.tpl create mode 100644 wcfsetup/install/files/js/WCF.ACL.js create mode 100644 wcfsetup/install/files/lib/acp/form/AbstractCategoryAddForm.class.php create mode 100644 wcfsetup/install/files/lib/acp/form/AbstractCategoryEditForm.class.php create mode 100644 wcfsetup/install/files/lib/acp/page/AbstractCategoryListPage.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/ACLOption.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/ACLOptionAction.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/ACLOptionEditor.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/ACLOptionList.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/category/ACLOptionCategory.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/category/ACLOptionCategoryAction.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/category/ACLOptionCategoryEditor.class.php create mode 100644 wcfsetup/install/files/lib/data/acl/option/category/ACLOptionCategoryList.class.php create mode 100644 wcfsetup/install/files/lib/data/category/ViewableCategory.class.php create mode 100644 wcfsetup/install/files/lib/data/category/ViewableCategoryNode.class.php create mode 100644 wcfsetup/install/files/lib/data/category/ViewableCategoryNodeList.class.php create mode 100644 wcfsetup/install/files/lib/system/acl/ACLHandler.class.php create mode 100644 wcfsetup/install/files/lib/system/cache/builder/ACLOptionCategoryCacheBuilder.class.php create mode 100644 wcfsetup/install/files/lib/system/cache/builder/CategoryACLOptionCacheBuilder.class.php create mode 100644 wcfsetup/install/files/lib/system/category/CategoryPermissionHandler.class.php create mode 100644 wcfsetup/install/files/lib/system/package/plugin/ACLOptionPackageInstallationPlugin.class.php create mode 100644 wcfsetup/install/files/style/acl.less diff --git a/com.woltlab.wcf/objectTypeDefinition.xml b/com.woltlab.wcf/objectTypeDefinition.xml index dac9532485..ed67be9398 100644 --- a/com.woltlab.wcf/objectTypeDefinition.xml +++ b/com.woltlab.wcf/objectTypeDefinition.xml @@ -1,6 +1,10 @@ + + com.woltlab.wcf.acl + + com.woltlab.wcf.collapsibleContent diff --git a/com.woltlab.wcf/packageInstallationPlugin.xml b/com.woltlab.wcf/packageInstallationPlugin.xml index 8c576bec14..140fd6b14e 100644 --- a/com.woltlab.wcf/packageInstallationPlugin.xml +++ b/com.woltlab.wcf/packageInstallationPlugin.xml @@ -1,6 +1,7 @@ + wcf\system\package\plugin\ACLOptionPackageInstallationPlugin wcf\system\package\plugin\ACPMenuPackageInstallationPlugin wcf\system\package\plugin\ACPTemplatePackageInstallationPlugin wcf\system\package\plugin\ClipboardActionPackageInstallationPlugin diff --git a/com.woltlab.wcf/template/aclPermissionJavaScript.tpl b/com.woltlab.wcf/template/aclPermissionJavaScript.tpl new file mode 100644 index 0000000000..897fd83d67 --- /dev/null +++ b/com.woltlab.wcf/template/aclPermissionJavaScript.tpl @@ -0,0 +1,63 @@ + \ No newline at end of file diff --git a/com.woltlab.wcf/template/aclPermissions.tpl b/com.woltlab.wcf/template/aclPermissions.tpl new file mode 100644 index 0000000000..3e44ddd725 --- /dev/null +++ b/com.woltlab.wcf/template/aclPermissions.tpl @@ -0,0 +1,19 @@ + + \ No newline at end of file diff --git a/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl b/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl new file mode 100644 index 0000000000..897fd83d67 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl @@ -0,0 +1,63 @@ + \ No newline at end of file diff --git a/wcfsetup/install/files/acp/templates/aclPermissions.tpl b/wcfsetup/install/files/acp/templates/aclPermissions.tpl new file mode 100644 index 0000000000..f0db0ede23 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/aclPermissions.tpl @@ -0,0 +1,19 @@ + + \ No newline at end of file diff --git a/wcfsetup/install/files/acp/templates/categoryAdd.tpl b/wcfsetup/install/files/acp/templates/categoryAdd.tpl new file mode 100644 index 0000000000..0f499bef80 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/categoryAdd.tpl @@ -0,0 +1,157 @@ +{include file='header'} + +{if $aclObjectTypeID} + {include file='aclPermissions'} + + {if !$category|isset} + {include file='aclPermissionJavaScript' containerID='groupPermissions' objectTypeID=$aclObjectTypeID} + {else} + {include file='aclPermissionJavaScript' containerID='groupPermissions' objectTypeID=$aclObjectTypeID objectID=$category->categoryID} + {/if} +{/if} + +{include file='multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=false} +{if $objectType->getProcessor()->hasDescription()} + {include file='multipleLanguageInputJavascript' elementIdentifier='description' forceSelection=false} +{/if} + +
+
+

{@$objectType->getProcessor()->getLanguageVariable($action)}

+
+
+ +{if $errorField} +

{lang}wcf.global.form.error{/lang}

+{/if} + +{if $success|isset} +

{lang}wcf.global.form.{@$action}.success{/lang}

+{/if} + +{hascontent} +
+ +
+{/hascontent} + +
+
+
+ {lang}wcf.global.form.data{/lang} + + {if $objectType->getProcessor()->getMaximumNestingLevel() && $categoryNodeList|count} + +
+
+ + {if $errorField == 'parentCategoryID'} + + {assign var=__languageVariable value='parentCategoryID.error.'|concat:$errorType} + {@$objectType->getProcessor()->getLanguageVariable($__languageVariable)} + + {/if} + {hascontent}{content}{@$objectType->getProcessor()->getLanguageVariable('parentCategoryID.description', true)}{/content}{/hascontent} +
+ + {/if} + + +
+
+ + {if $errorField == 'title'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {assign var=__languageVariable value='title.error.'|concat:$errorType} + {@$objectType->getProcessor()->getLanguageVariable($__languageVariable)} + {/if} + + {/if} + {hascontent}{content}{@$objectType->getProcessor()->getLanguageVariable('title.description', true)}{/content}{/hascontent} +
+ + + {if $objectType->getProcessor()->hasDescription()} + +
+
+ + {if $errorField == 'description'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {assign var=__languageVariable value='description.error.'|concat:$errorType} + {@$objectType->getProcessor()->getLanguageVariable($__languageVariable)} + {/if} + + {/if} + {hascontent}{content}{@$objectType->getProcessor()->getLanguageVariable('description.description', true)}{/content}{/hascontent} +
+ + {/if} + + +
+
+ + {hascontent}{content}{@$objectType->getProcessor()->getLanguageVariable('isDisabled.description', true)}{/content}{/hascontent} +
+ + + +
+
+ + {if $errorField == 'showOrder'} + + {assign var=__languageVariable value='showOrder.error.'|concat:$errorType} + {@$objectType->getProcessor()->getLanguageVariable($__languageVariable)} + + {/if} + {hascontent}{content}{@$objectType->getProcessor()->getLanguageVariable('showOrder.description', true)}{/content}{/hascontent} +
+ + + {event name='dataFields'} +
+ + {if $aclObjectTypeID} +
+ {lang}wcf.acp.acl.permissions{/lang} + +
+
{lang}wcf.acp.acl.permissions{/lang}
+
+
+ + {event name='permissionFields'} +
+ {/if} + + {event name='fieldsets'} +
+ +
+ + +
+
+ +{include file='footer'} \ No newline at end of file diff --git a/wcfsetup/install/files/acp/templates/categoryList.tpl b/wcfsetup/install/files/acp/templates/categoryList.tpl new file mode 100644 index 0000000000..42d68764d6 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/categoryList.tpl @@ -0,0 +1,164 @@ +{include file='header'} + +{if $categoryNodeList|count} + +{/if} + +
+
+

{@$objectType->getProcessor()->getLanguageVariable('list')}

+
+
+ +{hascontent} +
+ +
+{/hascontent} + +{if $categoryNodeList|count} +
+
    + {assign var=oldDepth value=0} + {foreach from=$categoryNodeList item=category} + {section name=i loop=$oldDepth-$categoryNodeList->getDepth()}
{/section} + +
  • + + + {if $objectType->getProcessor()->canEditCategory()} + + {else} + + {/if} + + {if $objectType->getProcessor()->canDeleteCategory()} + + {else} + + {/if} + + {if $objectType->getProcessor()->canEditCategory()} + {* todo: toggle icons aren't clickable *} + + {else} + + {/if} + + {event name='buttons'} + + + + {$category->getTitle()} + + + +
      + {if !$categoryNodeList->current()->hasChildren()} +
  • + {/if} + {assign var=oldDepth value=$categoryNodeList->getDepth()} + {/foreach} + {section name=i loop=$oldDepth}{/section} + + + {if $objectType->getProcessor()->canEditCategory() && $categoryNodeList|count > 1} +
    + +
    + {/if} +
    + + {hascontent} +
    + +
    + {/hascontent} +{else} +

    {@$objectType->getProcessor()->getLanguageVariable('noneAvailable')}

    +{/if} + +{include file='footer'} \ No newline at end of file diff --git a/wcfsetup/install/files/js/WCF.ACL.js b/wcfsetup/install/files/js/WCF.ACL.js new file mode 100644 index 0000000000..078ae0ac59 --- /dev/null +++ b/wcfsetup/install/files/js/WCF.ACL.js @@ -0,0 +1,574 @@ +/** + * Namespace for ACL + */ +WCF.ACL = {}; + +/** + * ACL support for WCF + * + * @author Alexander Ebert + * @copyright 2001-2011 WoltLab GmbH + * @license GNU Lesser General Public License + */ +WCF.ACL.List = Class.extend({ + /** + * name of the category the acl options belong to + * @var string + */ + _categoryName: '', + + /** + * ACL container + * @var jQuery + */ + _container: null, + + /** + * list of ACL container elements + * @var object + */ + _containerElements: { }, + + /** + * object id + * @var integer + */ + _objectID: 0, + + /** + * object type id + * @var integer + */ + _objectTypeID: null, + + /** + * list of available ACL options + * @var object + */ + _options: { }, + + /** + * action proxy + * @var WCF.Action.Proxy + */ + _proxy: null, + + /** + * user search handler + * @var WCF.Search.User + */ + _search: null, + + /** + * list of ACL settings + * @var object + */ + _values: { + group: { }, + user: { } + }, + + /** + * Initializes the ACL configuration. + * + * @param string containerSelector + * @param integer objectTypeID + * @param string categoryName + * @param integer objectID + * @param boolean includeUserGroups + */ + init: function(containerSelector, objectTypeID, categoryName, objectID, includeUserGroups, initialPermissions) { + this._objectID = objectID; + this._objectTypeID = objectTypeID; + this._categoryName = categoryName; + if (includeUserGroups === undefined) { + includeUserGroups = true; + } + + this._proxy = new WCF.Action.Proxy({ + showLoadingOverlay: false, + success: $.proxy(this._success, this) + }); + + // bind hidden container + this._container = $(containerSelector).hide().addClass('aclContainer'); + + // insert container elements + var $elementContainer = this._container.children('dd'); + var $aclList = $('
      ').appendTo($elementContainer); + var $searchInput = $('').appendTo($elementContainer); + var $permissionList = $('
        ').hide().appendTo($elementContainer); + + // set elements + this._containerElements = { + aclList: $aclList, + denyAll: null, + grantAll: null, + permissionList: $permissionList, + searchInput: $searchInput + }; + + // prepare search input + this._search = new WCF.Search.User($searchInput, $.proxy(this.addObject, this), includeUserGroups); + + // bind event listener for submit + var $form = this._container.parents('form:eq(0)'); + $form.submit($.proxy(this.submit, this)); + + // reset ACL on click + var $resetButton = $form.find('input[type=reset]:eq(0)'); + if ($resetButton.length) { + $resetButton.click($.proxy(this._reset, this)); + } + + if (initialPermissions) { + this._success(initialPermissions); + } + else { + this._loadACL(); + } + }, + + /** + * Restores the original ACL state. + */ + _reset: function() { + // reset stored values + this._values = { + group: { }, + user: { } + }; + + // remove entries + this._containerElements.aclList.empty(); + this._containerElements.searchInput.val(''); + + // deselect all input elements + this._containerElements.permissionList.hide().find('input[type=checkbox]').removeAttr('checked'); + }, + + /** + * Loads current ACL configuration. + */ + _loadACL: function() { + this._proxy.setOption('data', { + actionName: 'loadAll', + className: 'wcf\\data\\acl\\option\\ACLOptionAction', + parameters: { + data: { + categoryName: this._categoryName, + objectID: this._objectID, + objectTypeID: this._objectTypeID + } + } + }); + this._proxy.sendRequest(); + }, + + /** + * Adds a new object to acl list. + * + * @param object data + */ + addObject: function(data) { + var $listItem = $('
      • ' + data.label + '
      • ').appendTo(this._containerElements.aclList); + $listItem.data('objectID', data.objectID).data('type', data.type).click($.proxy(this._click, this)); + $('').click($.proxy(this._removeItem, this)).appendTo($listItem); + + // toggle element + this._savePermissions(); + this._containerElements.aclList.children('li').removeClass('active'); + $listItem.addClass('active'); + + this._search.addExcludedSearchValue(data.label); + + // uncheck all option values + this._containerElements.permissionList.find('input[type=checkbox]').removeAttr('checked'); + + // clear search input + this._containerElements.searchInput.val(''); + + // show permissions + this._containerElements.permissionList.show(); + }, + + /** + * Removes an item from list. + * + * @param object event + */ + _removeItem: function(event) { + var $listItem = $(event.currentTarget).parent(); + var $type = $listItem.data('type'); + var $objectID = $listItem.data('objectID'); + + this._search.removeExcludedSearchValue($listItem.children('span:eq(0)').text()); + $listItem.remove(); + + // remove stored data + if (this._values[$type][$objectID]) { + delete this._values[$type][$objectID]; + } + + // try to select something else + this._selectFirstEntry(); + }, + + /** + * Selects the first available entry. + */ + _selectFirstEntry: function() { + var $listItem = this._containerElements.aclList.children('li:eq(0)'); + if ($listItem.length) { + this._select($listItem, false); + } + else { + this._reset(); + } + }, + + /** + * Parses current ACL configuration. + * + * @param object data + * @param string textStatus + * @param jQuery jqXHR + */ + _success: function(data, textStatus, jqXHR) { + if (!$.getLength(data.returnValues.options)) { + return; + } + + // prepare options + var $count = 0; + var $structure = { }; + for (var $optionID in data.returnValues.options) { + var $option = data.returnValues.options[$optionID]; + + var $listItem = $('
      • ' + $option.label + '
      • ').data('optionID', $optionID).data('optionName', $option.optionName); + var $grantPermission = $('').appendTo($listItem).wrap('