Preventing deletion of delivered BBCodes, Page Menu Items and User Options
authorAlexander Ebert <ebert@woltlab.com>
Fri, 27 Jun 2014 12:36:39 +0000 (14:36 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 27 Jun 2014 12:36:39 +0000 (14:36 +0200)
All three types are either complex objects or have data or implicit properties associated with them which are not alterable through the ACP. For example user-created menu items will be assigned a generic name which cannot be used as a replacement for pre-defined items with a specific name (e.g. highliting the active menu item).

In order to prevent users from accidentially breaking stuff, we disallow deletion. In return all three types support disabling of items, therefore they can be safely turned off which in return results in the same behavior compared to deleting them.

12 files changed:
wcfsetup/install/files/acp/templates/bbcodeList.tpl
wcfsetup/install/files/acp/templates/userOptionList.tpl
wcfsetup/install/files/lib/data/bbcode/BBCode.class.php
wcfsetup/install/files/lib/data/bbcode/BBCodeAction.class.php
wcfsetup/install/files/lib/data/page/menu/item/PageMenuItem.class.php
wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemAction.class.php
wcfsetup/install/files/lib/data/user/option/UserOption.class.php
wcfsetup/install/files/lib/data/user/option/UserOptionAction.class.php
wcfsetup/install/files/lib/system/package/plugin/BBCodePackageInstallationPlugin.class.php
wcfsetup/install/files/lib/system/package/plugin/PageMenuPackageInstallationPlugin.class.php
wcfsetup/install/files/lib/system/package/plugin/UserOptionPackageInstallationPlugin.class.php
wcfsetup/setup/db/install.sql

index 2f7e5793ad06e6e869db730fb562b737f0d7c7ba..57836e9cb3aae82103853cb4c48eb0c95984f0b3 100644 (file)
                                                <td class="columnIcon">
                                                        <span class="icon icon16 icon-check{if $bbcode->isDisabled}-empty{/if} jsToggleButton jsTooltip pointer" title="{lang}wcf.global.button.{if $bbcode->isDisabled}enable{else}disable{/if}{/lang}" data-object-id="{@$bbcode->bbcodeID}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}"></span>
                                                        <a href="{link controller='BBCodeEdit' object=$bbcode}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 icon-pencil"></span></a>
-                                                       <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$bbcode->bbcodeID}" data-confirm-message="{lang}wcf.acp.bbcode.delete.sure{/lang}"></span>
+                                                       {if $bbcode->canDelete()}
+                                                               <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$bbcode->bbcodeID}" data-confirm-message="{lang}wcf.acp.bbcode.delete.sure{/lang}"></span>
+                                                       {else}
+                                                               <span class="icon icon16 fa-times disabled"></span>
+                                                       {/if}
                                                        
                                                        {event name='rowButtons'}
                                                </td>
index b9edb5bb4ed28373f323da98b57803b64790aad5..e252f5b9bd4771dad07dbdb5e712c6602feb9abf 100644 (file)
                                                <td class="columnIcon">
                                                        <span class="icon icon16 icon-check{if $option->isDisabled}-empty{/if} jsToggleButton jsTooltip pointer" title="{lang}wcf.global.button.{if $option->isDisabled}enable{else}disable{/if}{/lang}" data-object-id="{@$option->optionID}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}"></span>
                                                        <a href="{link controller='UserOptionEdit' id=$option->optionID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 icon-pencil"></span></a>
-                                                       <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$option->optionID}" data-confirm-message="{lang}wcf.acp.user.option.delete.sure{/lang}"></span>
+                                                       {if $option->canDelete()}
+                                                               <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$option->optionID}" data-confirm-message="{lang}wcf.acp.user.option.delete.sure{/lang}"></span>
+                                                       {else}
+                                                               <span class="icon icon16 fa-times disabled"></span>
+                                                       {/if}
                                                        
                                                        {event name='rowButtons'}
                                                </td>
index 9de8da71972dad7452151793e25cb2a19cbb5fae..485fbabd06eb5203141d102df4541ad2565192f4 100644 (file)
@@ -95,4 +95,17 @@ class BBCode extends ProcessibleDatabaseObject implements IRouteController {
                
                return in_array($bbcodeTag, $allowedBBCodeTags);
        }
+       
+       /**
+        * Returns true if this BBCode can be deleted.
+        * 
+        * @return      boolean
+        */
+       public function canDelete() {
+               if ($this->originIsSystem) {
+                       return false;
+               }
+               
+               return true;
+       }
 }
index 75ea5b974a1d7eba51303ff282a7f3d60b3c9878..6b6beda622d4cba73ad1d2305fc205a795aa6f15 100644 (file)
@@ -5,6 +5,7 @@ use wcf\data\user\group\UserGroupEditor;
 use wcf\data\AbstractDatabaseObjectAction;
 use wcf\data\IToggleAction;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\PermissionDeniedException;
 use wcf\system\WCF;
 
 /**
@@ -98,6 +99,19 @@ class BBCodeAction extends AbstractDatabaseObjectAction implements IToggleAction
                return $bbCode;
        }
        
+       /**
+        * @see \wcf\data\AbstractDatabaseObjectAction::validateDelete()
+        */
+       public function validateDelete() {
+               parent::validateDelete();
+               
+               foreach ($this->objects as $bbcode) {
+                       if (!$bbcode->canDelete()) {
+                               throw new PermissionDeniedException();
+                       }
+               }
+       }
+       
        /**
         * @see \wcf\data\IToggleAction::validateToggle()
         */
index 6d737974205febf2bd5d12a4f9c75e598367a4aa..3edcb522d2e912286696758032219dc3845f2e4f 100644 (file)
@@ -104,7 +104,11 @@ class PageMenuItem extends ProcessibleDatabaseObject implements ITreeMenuItem {
         * @return      boolean
         */
        public function canDelete() {
-               return ($this->isLandingPage ? false : true);
+               if ($this->originIsSystem || $this->isLandingPage) {
+                       return false;
+               }
+               
+               return true;
        }
        
        /**
index 68d3173f2e39ccb5f385fe4dccdf22135d7f63b2..a26b1b743ee9d89ed86e1ff28d2b9acb2932105a 100644 (file)
@@ -160,6 +160,19 @@ class PageMenuItemAction extends AbstractDatabaseObjectAction implements ISortab
                }
        }
        
+       /**
+        * @see \wcf\data\AbstractDatabaseObjectAction::validateDelete()
+        */
+       public function validateDelete() {
+               parent::validateDelete();
+               
+               foreach ($this->objects as $pageMenuItem) {
+                       if (!$pageMenuItem->canDelete()) {
+                               throw new PermissionDeniedException();
+                       }
+               }
+       }
+       
        /**
         * @see \wcf\data\IToggleAction::validateToggle()
         */
index 3cedf2db317f101b8be7700019ee96b4281bfc13..9d1cafd91ae370a97417da68791cc196b0219733 100644 (file)
@@ -159,4 +159,17 @@ class UserOption extends Option {
                
                return false;
        }
+       
+       /**
+        * Returns true if this user option can be deleted.
+        *
+        * @return      boolean
+        */
+       public function canDelete() {
+               if ($this->originIsSystem) {
+                       return false;
+               }
+               
+               return true;
+       }
 }
index 858b6e5175f1dbe9b15725acbf8a12f6b8b7a6e2..fc05ed9d83e3f0819c7e38b836f3eb76d7adb612 100644 (file)
@@ -2,6 +2,7 @@
 namespace wcf\data\user\option;
 use wcf\data\AbstractDatabaseObjectAction;
 use wcf\data\IToggleAction;
+use wcf\system\exception\PermissionDeniedException;
 
 /**
  * Executes user option-related actions.
@@ -39,6 +40,19 @@ class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAc
         */
        protected $requireACP = array('create', 'delete', 'toggle', 'update');
        
+       /**
+        * @see \wcf\data\AbstractDatabaseObjectAction::validateDelete()
+        */
+       public function validateDelete() {
+               parent::validateDelete();
+               
+               foreach ($this->objects as $userOption) {
+                       if (!$userOption->canDelete()) {
+                               throw new PermissionDeniedException();
+                       }
+               }
+       }
+       
        /**
         * @see \wcf\data\IToggleAction::toggle()
         */
index 69cf4e399ba4c3adeaabfbb4f89e39c1183c7def..94cf103bd1e07f1d34b1630ee7da64f408e2d32b 100644 (file)
@@ -91,7 +91,8 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
                        'attributes' => (isset($data['elements']['attributes']) ? $data['elements']['attributes'] : array()),
                        'className' => (!empty($data['elements']['classname']) ? $data['elements']['classname'] : ''),
                        'isSourceCode' => (!empty($data['elements']['sourcecode']) ? 1 : 0),
-                       'buttonLabel' => (isset($data['elements']['buttonlabel']) ? $data['elements']['buttonlabel'] : '')
+                       'buttonLabel' => (isset($data['elements']['buttonlabel']) ? $data['elements']['buttonlabel'] : ''),
+                       'originIsSystem' => 1
                );
                
                if ($data['wysiwygIcon'] && $data['buttonLabel']) {
index dc918b6746ca428cba0ff508fe9cb280c6eb7ef1..cff138fe4d39a61b11cbf38142cdae1bdb3c6854 100644 (file)
@@ -40,6 +40,8 @@ class PageMenuPackageInstallationPlugin extends AbstractMenuPackageInstallationP
                        throw new SystemException("Menu item '".$result['menuItem']."' neither has a link nor a controller given");
                }
                
+               $result['originIsSystem'] = 1;
+               
                return $result;
        }
        
index 9954d6c58a5f8e823ebbfd62054c7da5d67c6011..757cf1d44605dc30c1c1b91fcf938ce1cf1d65da 100644 (file)
@@ -124,7 +124,8 @@ class UserOptionPackageInstallationPlugin extends AbstractOptionPackageInstallat
                        'isDisabled' => $isDisabled,
                        'permissions' => $permissions,
                        'options' => $options,
-                       'additionalData' => serialize($additionalData)
+                       'additionalData' => serialize($additionalData),
+                       'originIsSystem' => 1
                );
                
                // update option
index 448703ccc8bd274b23fed51abeaaf98842ba8711..8b0dfc1b7fcbc8c5e4623335083a1304de1da0c6 100644 (file)
@@ -180,6 +180,7 @@ CREATE TABLE wcf1_bbcode (
        isSourceCode TINYINT(1) NOT NULL DEFAULT 0,
        isDisabled TINYINT(1) NOT NULL DEFAULT 0,
        showButton TINYINT(1) NOT NULL DEFAULT 0,
+       originIsSystem TINYINT(1) NOT NULL DEFAULT 0,
        UNIQUE KEY bbcodeTag (bbcodeTag)
 );
 
@@ -761,6 +762,7 @@ CREATE TABLE wcf1_page_menu_item (
        isDisabled TINYINT(1) NOT NULL DEFAULT 0,
        className VARCHAR(255) NOT NULL DEFAULT '',
        isLandingPage TINYINT(1) NOT NULL DEFAULT 0,
+       originIsSystem TINYINT(1) NOT NULL DEFAULT 0,
        UNIQUE KEY (packageID, menuItem)
 );
 
@@ -1312,6 +1314,7 @@ CREATE TABLE wcf1_user_option (
        permissions TEXT,
        options TEXT,
        additionalData MEDIUMTEXT,
+       originIsSystem TINYINT(1) NOT NULL DEFAULT 0,
        UNIQUE KEY optionName (optionName, packageID),
        KEY categoryName (categoryName)
 );