/** * Show list of roles. * * @since 2.0.0 * @access public */ public function index($roleID = null) { $this->_permission(); $this->addSideMenu('dashboard/role'); $this->addJsFile('jquery.tablednd.js'); $this->title(t('Roles & Permissions')); if (!$roleID) { $roles = $this->RoleModel->getWithRankPermissions()->resultArray(); // Check to see which roles can be modified. foreach ($roles as &$row) { $canModify = true; if (!Gdn::session()->checkPermission('Garden.Settings.Manage')) { foreach ($this->RoleModel->RankPermissions as $permission) { if ($row[$permission] && !Gdn::session()->checkPermission($permission)) { $canModify = false; break; } } } $row['CanModify'] = $canModify; } $this->setData('Roles', $roles); } elseif ($this->deliveryType() === DELIVERY_TYPE_DATA) { // This is an API request. Get the role in a nicer format. $role = $this->RoleModel->getID($roleID, DATASET_TYPE_ARRAY); // Get the global permissions. $permissions = Gdn::permissionModel()->getGlobalPermissions($roleID); unset($permissions['PermissionID']); // Get the per-category permissions. $permissions['Category'] = $this->RoleModel->getCategoryPermissions($roleID); $role['Permissions'] = $permissions; $this->setData('Role', $role); saveToConfig('Api.Clean', false, false); } else { $Role = $this->RoleModel->getID($roleID); $this->setData('Roles', [$Role]); } $this->render(); }
/** * Get the active {@link PermissionModel}. * * @return PermissionModel */ public function getPermissionModel() { if ($this->_PermissionModel === null) { $this->_PermissionModel = Gdn::permissionModel(); } return $this->_PermissionModel; }
/** * Saves the category. * * @since 2.0.0 * @access public * * @param array $FormPostValue The values being posted back from the form. * @param array|false $Settings Additional settings to affect saving. * @return int ID of the saved category. */ public function save($FormPostValues, $Settings = false) { // Define the primary key in this model's table. $this->defineSchema(); // Get data from form $CategoryID = val('CategoryID', $FormPostValues); $NewName = val('Name', $FormPostValues, ''); $UrlCode = val('UrlCode', $FormPostValues, ''); $AllowDiscussions = val('AllowDiscussions', $FormPostValues, ''); $CustomPermissions = (bool) val('CustomPermissions', $FormPostValues) || is_array(val('Permissions', $FormPostValues)); $CustomPoints = val('CustomPoints', $FormPostValues, null); if (isset($FormPostValues['AllowedDiscussionTypes']) && is_array($FormPostValues['AllowedDiscussionTypes'])) { $FormPostValues['AllowedDiscussionTypes'] = dbencode($FormPostValues['AllowedDiscussionTypes']); } // Is this a new category? $Insert = $CategoryID > 0 ? false : true; if ($Insert) { $this->addInsertFields($FormPostValues); } $this->addUpdateFields($FormPostValues); // Add some extra validation to the url code if one is provided. if ($Insert || array_key_exists('UrlCode', $FormPostValues)) { $this->Validation->applyRule('UrlCode', 'Required'); $this->Validation->applyRule('UrlCode', 'UrlStringRelaxed'); // Url slugs cannot be the name of a CategoriesController method or fully numeric. $this->Validation->addRule('CategorySlug', 'regex:/^(?!(all|archives|discussions|index|table|[0-9]+)$).*/'); $this->Validation->applyRule('UrlCode', 'CategorySlug', 'Url code cannot be numeric or the name of an internal method.'); // Make sure that the UrlCode is unique among categories. $this->SQL->select('CategoryID')->from('Category')->where('UrlCode', $UrlCode); if ($CategoryID) { $this->SQL->where('CategoryID <>', $CategoryID); } if ($this->SQL->get()->numRows()) { $this->Validation->addValidationResult('UrlCode', 'The specified url code is already in use by another category.'); } } // Prep and fire event. $this->EventArguments['FormPostValues'] =& $FormPostValues; $this->EventArguments['CategoryID'] = $CategoryID; $this->fireEvent('BeforeSaveCategory'); // Validate the form posted values if ($this->validate($FormPostValues, $Insert)) { $Fields = $this->Validation->schemaValidationFields(); unset($Fields['CategoryID']); $AllowDiscussions = val('AllowDiscussions', $Fields) == '1' ? true : false; $Fields['AllowDiscussions'] = $AllowDiscussions ? '1' : '0'; if ($Insert === false) { $OldCategory = $this->getID($CategoryID, DATASET_TYPE_ARRAY); if (null === val('AllowDiscussions', $FormPostValues, null)) { $AllowDiscussions = $OldCategory['AllowDiscussions']; // Force the allowdiscussions property } $Fields['AllowDiscussions'] = $AllowDiscussions ? '1' : '0'; // Figure out custom points. if ($CustomPoints !== null) { if ($CustomPoints) { $Fields['PointsCategoryID'] = $CategoryID; } else { $Parent = self::categories(val('ParentCategoryID', $Fields, $OldCategory['ParentCategoryID'])); $Fields['PointsCategoryID'] = val('PointsCategoryID', $Parent, 0); } } $this->update($Fields, array('CategoryID' => $CategoryID)); // Check for a change in the parent category. if (isset($Fields['ParentCategoryID']) && $OldCategory['ParentCategoryID'] != $Fields['ParentCategoryID']) { $this->rebuildTree(); } else { $this->setCache($CategoryID, $Fields); } } else { $CategoryID = $this->insert($Fields); if ($CategoryID) { if ($CustomPermissions) { $this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('CategoryID' => $CategoryID)); } if ($CustomPoints) { $this->SQL->put('Category', array('PointsCategoryID' => $CategoryID), array('CategoryID' => $CategoryID)); } } $this->rebuildTree(); // Safeguard to make sure that treeleft and treeright cols are added } // Save the permissions if ($CategoryID) { // Check to see if this category uses custom permissions. if ($CustomPermissions) { $permissionModel = Gdn::permissionModel(); if (is_array(val('Permissions', $FormPostValues))) { // The permissions were posted in an API format provided by settings/getcategory $permissions = val('Permissions', $FormPostValues); foreach ($permissions as &$perm) { $perm['JunctionTable'] = 'Category'; $perm['JunctionColumn'] = 'PermissionCategoryID'; $perm['JunctionID'] = $CategoryID; } } else { // The permissions were posted in the web format provided by settings/addcategory and settings/editcategory $permissions = $permissionModel->pivotPermissions(val('Permission', $FormPostValues, array()), array('JunctionID' => $CategoryID)); } $permissionModel->saveAll($permissions, array('JunctionID' => $CategoryID, 'JunctionTable' => 'Category')); if (!$Insert) { // Figure out my last permission and tree info. $Data = $this->SQL->select('PermissionCategoryID, TreeLeft, TreeRight')->from('Category')->where('CategoryID', $CategoryID)->get()->firstRow(DATASET_TYPE_ARRAY); // Update this category's permission. $this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('CategoryID' => $CategoryID)); // Update all of my children that shared my last category permission. $this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('TreeLeft >' => $Data['TreeLeft'], 'TreeRight <' => $Data['TreeRight'], 'PermissionCategoryID' => $Data['PermissionCategoryID'])); self::clearCache(); } } elseif (!$Insert) { // Figure out my parent's permission. $NewPermissionID = $this->SQL->select('p.PermissionCategoryID')->from('Category c')->join('Category p', 'c.ParentCategoryID = p.CategoryID')->where('c.CategoryID', $CategoryID)->get()->value('PermissionCategoryID', 0); if ($NewPermissionID != $CategoryID) { // Update all of my children that shared my last permission. $this->SQL->put('Category', array('PermissionCategoryID' => $NewPermissionID), array('PermissionCategoryID' => $CategoryID)); self::clearCache(); } // Delete my custom permissions. $this->SQL->delete('Permission', array('JunctionTable' => 'Category', 'JunctionColumn' => 'PermissionCategoryID', 'JunctionID' => $CategoryID)); } } // Force the user permissions to refresh. Gdn::userModel()->clearPermissions(); // $this->RebuildTree(); } else { $CategoryID = false; } return $CategoryID; }
/** * Show list of roles. * * @since 2.0.0 * @access public */ public function index($roleID = null) { $this->_permission(); $this->setHighlightRoute('dashboard/role'); $this->addJsFile('jquery.tablednd.js'); $this->title(t('Roles & Permissions')); if (!$roleID) { $roles = $this->RoleModel->getWithRankPermissions()->resultArray(); // Check to see which roles can be modified. foreach ($roles as &$row) { $canModify = true; if (!Gdn::session()->checkPermission('Garden.Settings.Manage')) { foreach ($this->RoleModel->RankPermissions as $permission) { if ($row[$permission] && !Gdn::session()->checkPermission($permission)) { $canModify = false; break; } } } $row['CanModify'] = $canModify; } $this->setData('Roles', $roles); } elseif ($this->deliveryType() === DELIVERY_TYPE_DATA) { // This is an API request. Get the role in a nicer format. $role = $this->RoleModel->getID($roleID, DATASET_TYPE_ARRAY); // Get the global permissions. $permissions = Gdn::permissionModel()->getGlobalPermissions($roleID); unset($permissions['PermissionID']); // Get the per-category permissions. $permissions['Category'] = $this->RoleModel->getCategoryPermissions($roleID); $role['Permissions'] = $permissions; $this->setData('Role', $role); saveToConfig('Api.Clean', false, false); } else { $Role = $this->RoleModel->getID($roleID); $this->setData('Roles', [$Role]); } // Grab the total users for each role. if (is_array($this->data('Roles'))) { $pastThreshold = Gdn::userModel()->pastUserMegaThreshold(); $thresholdTypeExceptions = RoleModel::getDefaultTypes(); unset($thresholdTypeExceptions[RoleModel::TYPE_MEMBER]); $roles = $this->data('Roles'); foreach ($roles as &$role) { if ($pastThreshold && !in_array($role['Type'], $thresholdTypeExceptions)) { $countUsers = t('View'); } else { $countUsers = $this->RoleModel->getUserCount($role['RoleID']); } $role['CountUsers'] = $countUsers; } $this->setData('Roles', $roles); } $this->render(); }
/** * Run the structure for all addons. * * The structure runs the addons in priority order so that higher priority addons override lower priority ones. * * @param bool $captureOnly Run the structure or just capture the SQL changes. * @throws Exception Throws an exception if in debug mode and something goes wrong. */ public function runStructure($captureOnly = false) { $addons = array_reverse(Gdn::addonManager()->getEnabled()); // These variables are required for included structure files. $Database = Gdn::database(); $SQL = $this->SQL; $SQL->CaptureModifications = $captureOnly; $Structure = Gdn::structure(); $Structure->CaptureOnly = $captureOnly; /* @var Addon $addon */ foreach ($addons as $addon) { // Look for a structure file. if ($structure = $addon->getSpecial('structure')) { Logger::event('addon_structure', Logger::INFO, "Executing structure for {addonKey}.", ['addonKey' => $addon->getKey(), 'structureType' => 'file']); try { include $addon->path($structure); } catch (\Exception $ex) { if (debug()) { throw $ex; } } } // Look for a structure method on the plugin. if ($addon->getPluginClass()) { $plugin = Gdn::pluginManager()->getPluginInstance($addon->getPluginClass(), Gdn_PluginManager::ACCESS_CLASSNAME); if (is_object($plugin) && method_exists($plugin, 'structure')) { Logger::event('addon_structure', Logger::INFO, "Executing structure for {addonKey}.", ['addonKey' => $addon->getKey(), 'structureType' => 'method']); try { call_user_func([$plugin, 'structure']); } catch (\Exception $ex) { if (debug()) { throw $ex; } } } } // Register permissions. $permissions = $addon->getInfoValue('registerPermissions'); if (!empty($permissions)) { Logger::event('addon_permissions', Logger::INFO, "Defining permissions for {addonKey}.", ['addonKey' => $addon->getKey(), 'permissions' => $permissions]); Gdn::permissionModel()->define($permissions); } } $this->fireEvent('AfterStructure'); if ($captureOnly && property_exists($Structure->Database, 'CapturedSql')) { return $Structure->Database->CapturedSql; } return []; }
/** * Get a user's permissions. * * @param int $userID Unique ID of the user. * @return Vanilla\Permissions */ public function getPermissions($userID) { $permissions = new Vanilla\Permissions(); $permissionsKey = ''; if (Gdn::cache()->activeEnabled()) { $permissionsIncrement = $this->getPermissionsIncrement(); $permissionsKey = formatString(self::USERPERMISSIONS_KEY, ['UserID' => $userID, 'PermissionsIncrement' => $permissionsIncrement]); $cachedPermissions = Gdn::cache()->get($permissionsKey); if ($cachedPermissions !== Gdn_Cache::CACHEOP_FAILURE) { $permissions->setPermissions($cachedPermissions); return $permissions; } } $data = Gdn::permissionModel()->cachePermissions($userID); $permissions->compileAndLoad($data); $this->EventArguments['UserID'] = $userID; $this->EventArguments['Permissions'] = $permissions; $this->fireEvent('loadPermissions'); if (Gdn::cache()->activeEnabled()) { Gdn::cache()->store($permissionsKey, $permissions->getPermissions()); } else { // Save the permissions to the user table if ($userID > 0) { $this->SQL->put('User', ['Permissions' => dbencode($permissions->getPermissions())], ['UserID' => $userID]); } } return $permissions; }
/** * Define the permissions for an application. * * @param string $applicationName The name of the application. */ public function registerPermissions($applicationName) { $addon = $this->addonManager->lookupAddon($applicationName); if ($permissions = $addon->getInfoValue('registerPermissions')) { Gdn::permissionModel()->define($permissions); } }
/** * Reset permissions for all roles, based on the value in their Type column. * * @param string $Type Role type to limit the updates to. */ public static function resetAllRoles($Type = null) { // Retrieve an array containing all available roles. $RoleModel = new RoleModel(); if ($Type) { $Result = $RoleModel->getByType($Type)->resultArray(); $Roles = array_column($Result, 'Name', 'RoleID'); } else { $Roles = $RoleModel->getArray(); } // Iterate through our roles and reset their permissions. $Permissions = Gdn::permissionModel(); foreach ($Roles as $RoleID => $Role) { $Permissions->resetRole($RoleID); } }
/** * Joins the query to a permission junction table and limits the results accordingly. * * @param mixed $Permission The permission name (or array of names) to use when limiting the query. * @param string $ForeignAlias The alias of the table to join to (ie. Category). * @param string $ForeignColumn The primary key column name of $JunctionTable (ie. CategoryID). * @param string $JunctionTable * @param string $JunctionColumn * @return Gdn_SQLDriver $this */ public function permission($Permission, $ForeignAlias, $ForeignColumn, $JunctionTable = '', $JunctionColumn = '') { $PermissionModel = Gdn::permissionModel(); $PermissionModel->sqlPermission($this, $Permission, $ForeignAlias, $ForeignColumn, $JunctionTable, $JunctionColumn); return $this; }
/** * Editing a category. * * @since 2.0.0 * @access public * * @param int $CategoryID Unique ID of the category to be updated. */ public function editCategory($CategoryID = '') { // Check permission $this->permission('Garden.Community.Manage'); // Set up models $RoleModel = new RoleModel(); $PermissionModel = Gdn::permissionModel(); $this->Form->setModel($this->CategoryModel); if (!$CategoryID && $this->Form->authenticatedPostBack()) { if ($ID = $this->Form->getFormValue('CategoryID')) { $CategoryID = $ID; } } // Get category data $this->Category = $this->CategoryModel->getID($CategoryID); if (!$this->Category) { throw notFoundException('Category'); } $this->Category->CustomPermissions = $this->Category->CategoryID == $this->Category->PermissionCategoryID; // Set up head $this->addJsFile('jquery.alphanumeric.js'); $this->addJsFile('categories.js'); $this->addJsFile('jquery.gardencheckboxgrid.js'); $this->title(t('Edit Category')); $this->addSideMenu('vanilla/settings/managecategories'); // Make sure the form knows which item we are editing. $this->Form->addHidden('CategoryID', $CategoryID); $this->setData('CategoryID', $CategoryID); // Load all roles with editable permissions $this->RoleArray = $RoleModel->getArray(); $this->fireEvent('AddEditCategory'); if ($this->Form->authenticatedPostBack()) { $this->setupDiscussionTypes($this->Category); $Upload = new Gdn_Upload(); $TmpImage = $Upload->validateUpload('PhotoUpload', false); if ($TmpImage) { // Generate the target image name $TargetImage = $Upload->generateTargetName(PATH_UPLOADS); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); // Save the uploaded image $Parts = $Upload->saveAs($TmpImage, $ImageBaseName); $this->Form->setFormValue('Photo', $Parts['SaveName']); } $this->Form->setFormValue('CustomPoints', (bool) $this->Form->getFormValue('CustomPoints')); if ($this->Form->save()) { $Category = CategoryModel::categories($CategoryID); $this->setData('Category', $Category); if ($this->deliveryType() == DELIVERY_TYPE_ALL) { redirect('vanilla/settings/managecategories'); } } } else { $this->Form->setData($this->Category); $this->setupDiscussionTypes($this->Category); $this->Form->setValue('CustomPoints', $this->Category->PointsCategoryID == $this->Category->CategoryID); } // Get all of the currently selected role/permission combinations for this junction. $Permissions = $PermissionModel->getJunctionPermissions(array('JunctionID' => $CategoryID), 'Category', '', array('AddDefaults' => !$this->Category->CustomPermissions)); $Permissions = $PermissionModel->unpivotPermissions($Permissions, true); if ($this->deliveryType() == DELIVERY_TYPE_ALL) { $this->setData('PermissionData', $Permissions, true); } // Render default view $this->render(); }
/** * Saves the category. * * @since 2.0.0 * @access public * * @param array $FormPostValue The values being posted back from the form. * @return int ID of the saved category. */ public function save($FormPostValues) { // Define the primary key in this model's table. $this->defineSchema(); // Get data from form $CategoryID = arrayValue('CategoryID', $FormPostValues); $NewName = arrayValue('Name', $FormPostValues, ''); $UrlCode = arrayValue('UrlCode', $FormPostValues, ''); $AllowDiscussions = arrayValue('AllowDiscussions', $FormPostValues, ''); $CustomPermissions = (bool) GetValue('CustomPermissions', $FormPostValues); $CustomPoints = val('CustomPoints', $FormPostValues, null); if (isset($FormPostValues['AllowedDiscussionTypes']) && is_array($FormPostValues['AllowedDiscussionTypes'])) { $FormPostValues['AllowedDiscussionTypes'] = serialize($FormPostValues['AllowedDiscussionTypes']); } // Is this a new category? $Insert = $CategoryID > 0 ? false : true; if ($Insert) { $this->AddInsertFields($FormPostValues); } $this->AddUpdateFields($FormPostValues); $this->Validation->applyRule('UrlCode', 'Required'); $this->Validation->applyRule('UrlCode', 'UrlStringRelaxed'); // Make sure that the UrlCode is unique among categories. $this->SQL->select('CategoryID')->from('Category')->where('UrlCode', $UrlCode); if ($CategoryID) { $this->SQL->where('CategoryID <>', $CategoryID); } if ($this->SQL->get()->numRows()) { $this->Validation->addValidationResult('UrlCode', 'The specified url code is already in use by another category.'); } // Prep and fire event. $this->EventArguments['FormPostValues'] =& $FormPostValues; $this->EventArguments['CategoryID'] = $CategoryID; $this->fireEvent('BeforeSaveCategory'); // Validate the form posted values if ($this->validate($FormPostValues, $Insert)) { $Fields = $this->Validation->SchemaValidationFields(); $Fields = RemoveKeyFromArray($Fields, 'CategoryID'); $AllowDiscussions = arrayValue('AllowDiscussions', $Fields) == '1' ? true : false; $Fields['AllowDiscussions'] = $AllowDiscussions ? '1' : '0'; if ($Insert === false) { $OldCategory = $this->getID($CategoryID, DATASET_TYPE_ARRAY); if (null === val('AllowDiscussions', $FormPostValues, null)) { $AllowDiscussions = $OldCategory['AllowDiscussions']; // Force the allowdiscussions property } $Fields['AllowDiscussions'] = $AllowDiscussions ? '1' : '0'; // Figure out custom points. if ($CustomPoints !== null) { if ($CustomPoints) { $Fields['PointsCategoryID'] = $CategoryID; } else { $Parent = self::categories(val('ParentCategoryID', $Fields, $OldCategory['ParentCategoryID'])); $Fields['PointsCategoryID'] = val('PointsCategoryID', $Parent, 0); } } $this->update($Fields, array('CategoryID' => $CategoryID)); // Check for a change in the parent category. if (isset($Fields['ParentCategoryID']) && $OldCategory['ParentCategoryID'] != $Fields['ParentCategoryID']) { $this->RebuildTree(); } else { $this->SetCache($CategoryID, $Fields); } } else { $CategoryID = $this->insert($Fields); if ($CategoryID) { if ($CustomPermissions) { $this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('CategoryID' => $CategoryID)); } if ($CustomPoints) { $this->SQL->put('Category', array('PointsCategoryID' => $CategoryID), array('CategoryID' => $CategoryID)); } } $this->RebuildTree(); // Safeguard to make sure that treeleft and treeright cols are added } // Save the permissions if ($CategoryID) { // Check to see if this category uses custom permissions. if ($CustomPermissions) { $PermissionModel = Gdn::permissionModel(); $Permissions = $PermissionModel->PivotPermissions(val('Permission', $FormPostValues, array()), array('JunctionID' => $CategoryID)); $PermissionModel->SaveAll($Permissions, array('JunctionID' => $CategoryID, 'JunctionTable' => 'Category')); if (!$Insert) { // Figure out my last permission and tree info. $Data = $this->SQL->select('PermissionCategoryID, TreeLeft, TreeRight')->from('Category')->where('CategoryID', $CategoryID)->get()->firstRow(DATASET_TYPE_ARRAY); // Update this category's permission. $this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('CategoryID' => $CategoryID)); // Update all of my children that shared my last category permission. $this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('TreeLeft >' => $Data['TreeLeft'], 'TreeRight <' => $Data['TreeRight'], 'PermissionCategoryID' => $Data['PermissionCategoryID'])); self::ClearCache(); } } elseif (!$Insert) { // Figure out my parent's permission. $NewPermissionID = $this->SQL->select('p.PermissionCategoryID')->from('Category c')->join('Category p', 'c.ParentCategoryID = p.CategoryID')->where('c.CategoryID', $CategoryID)->get()->value('PermissionCategoryID', 0); if ($NewPermissionID != $CategoryID) { // Update all of my children that shared my last permission. $this->SQL->put('Category', array('PermissionCategoryID' => $NewPermissionID), array('PermissionCategoryID' => $CategoryID)); self::ClearCache(); } // Delete my custom permissions. $this->SQL->delete('Permission', array('JunctionTable' => 'Category', 'JunctionColumn' => 'PermissionCategoryID', 'JunctionID' => $CategoryID)); } } // Force the user permissions to refresh. Gdn::userModel()->ClearPermissions(); // $this->RebuildTree(); } else { $CategoryID = false; } return $CategoryID; }
/** * Editing a category. * * @since 2.0.0 * @param int|string $CategoryID Unique ID of the category to be updated. * @throws Exception when category cannot be found. */ public function editCategory($CategoryID = '') { // Check permission $this->permission(['Garden.Community.Manage', 'Garden.Settings.Manage'], false); // Set up models $RoleModel = new RoleModel(); $PermissionModel = Gdn::permissionModel(); $this->Form->setModel($this->CategoryModel); if (!$CategoryID && $this->Form->authenticatedPostBack()) { if ($ID = $this->Form->getFormValue('CategoryID')) { $CategoryID = $ID; } } // Get category data $this->Category = CategoryModel::categories($CategoryID); if (!$this->Category) { throw notFoundException('Category'); } // Category data is expected to be in the form of an object. $this->Category = (object) $this->Category; $this->Category->CustomPermissions = $this->Category->CategoryID == $this->Category->PermissionCategoryID; $displayAsOptions = categoryModel::getDisplayAsOptions(); // Restrict "Display As" types based on parent. $parentCategory = $this->CategoryModel->getID($this->Category->ParentCategoryID); $parentDisplay = val('DisplayAs', $parentCategory); if ($parentDisplay === 'Flat') { unset($displayAsOptions['Heading']); } // Set up head $this->addJsFile('jquery.alphanumeric.js'); $this->addJsFile('manage-categories.js'); $this->addJsFile('jquery.gardencheckboxgrid.js'); $this->title(t('Edit Category')); $this->setHighlightRoute('vanilla/settings/categories'); // Make sure the form knows which item we are editing. $this->Form->addHidden('CategoryID', $CategoryID); $this->setData('CategoryID', $CategoryID); // Load all roles with editable permissions $this->RoleArray = $RoleModel->getArray(); $this->fireAs('SettingsController'); $this->fireEvent('AddEditCategory'); if ($this->Form->authenticatedPostBack()) { $this->setupDiscussionTypes($this->Category); $Upload = new Gdn_Upload(); $TmpImage = $Upload->validateUpload('PhotoUpload', false); if ($TmpImage) { // Generate the target image name $TargetImage = $Upload->generateTargetName(PATH_UPLOADS); $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME); // Save the uploaded image $Parts = $Upload->saveAs($TmpImage, $ImageBaseName); $this->Form->setFormValue('Photo', $Parts['SaveName']); } $this->Form->setFormValue('CustomPoints', (bool) $this->Form->getFormValue('CustomPoints')); // Enforces tinyint values on boolean fields to comply with strict mode $this->Form->setFormValue('HideAllDiscussions', forceBool($this->Form->getFormValue('HideAllDiscussions'), '0', '1', '0')); $this->Form->setFormValue('Archived', forceBool($this->Form->getFormValue('Archived'), '0', '1', '0')); $this->Form->setFormValue('AllowFileUploads', forceBool($this->Form->getFormValue('AllowFileUploads'), '0', '1', '0')); if ($parentDisplay === 'Flat' && $this->Form->getFormValue('DisplayAs') === 'Heading') { $this->Form->addError('Cannot display as a heading when your parent category is displayed flat.', 'DisplayAs'); } if ($this->Form->save()) { $Category = CategoryModel::categories($CategoryID); $this->setData('Category', $Category); if ($this->deliveryType() == DELIVERY_TYPE_ALL) { $destination = $this->categoryPageByParent($parentCategory); redirect($destination); } elseif ($this->deliveryType() === DELIVERY_TYPE_DATA && method_exists($this, 'getCategory')) { $this->Data = []; $this->getCategory($CategoryID); return; } } } else { $this->Form->setData($this->Category); $this->setupDiscussionTypes($this->Category); $this->Form->setValue('CustomPoints', $this->Category->PointsCategoryID == $this->Category->CategoryID); } // Get all of the currently selected role/permission combinations for this junction. $Permissions = $PermissionModel->getJunctionPermissions(array('JunctionID' => $CategoryID), 'Category', '', array('AddDefaults' => !$this->Category->CustomPermissions)); $Permissions = $PermissionModel->unpivotPermissions($Permissions, true); if ($this->deliveryType() == DELIVERY_TYPE_ALL) { $this->setData('PermissionData', $Permissions, true); } // Render default view $this->setData('Operation', 'Edit'); $this->setData('DisplayAsOptions', $displayAsOptions); $this->render(); }
/** * Define the permissions for an application. * * @param string $applicationName The name of the application. */ public function registerPermissions($applicationName) { $ApplicationInfo = val($applicationName, $this->availableApplications(), array()); $PermissionName = val('RegisterPermissions', $ApplicationInfo, false); if ($PermissionName != false) { $PermissionModel = Gdn::permissionModel(); $PermissionModel->define($PermissionName); } }
/** * Enable an addon and do all the stuff that's entailed there. * * @param Addon $addon The addon to enable. * @param bool $setup Whether or not to set the plugin up. * @throws Exception Throws an exception if something goes bonkers during the process. */ private function enableAddon(Addon $addon, $setup) { if ($setup) { $this->addonManager->startAddon($addon); $this->pluginHook($addon->getRawKey(), self::ACTION_ENABLE, true); // If setup succeeded, register any specified permissions $permissions = $addon->getInfoValue('registerPermissions'); if (!empty($permissions)) { $PermissionModel = Gdn::permissionModel(); $PermissionModel->define($permissions); } // Write enabled state to config. saveToConfig("EnabledPlugins." . $addon->getRawKey(), true); Logger::event('addon_enabled', Logger::INFO, 'The {addonName} plugin was enabled.', array('addonName' => $addon->getRawKey())); } $pluginClassName = $addon->getPluginClass(); $this->registerPlugin($pluginClassName); }
/** * Test to see if a plugin throws fatal errors. */ public function testPlugin($PluginName, &$Validation, $Setup = false) { // Make sure that the plugin's requirements are met // Required Plugins $PluginInfo = $this->getPluginInfo($PluginName); $RequiredPlugins = val('RequiredPlugins', $PluginInfo, false); CheckRequirements($PluginName, $RequiredPlugins, $this->enabledPlugins(), 'plugin'); // Required Themes $EnabledThemes = Gdn::themeManager()->enabledThemeInfo(); $RequiredThemes = ArrayValue('RequiredTheme', $PluginInfo, false); CheckRequirements($PluginName, $RequiredThemes, $EnabledThemes, 'theme'); // Required Applications $EnabledApplications = Gdn::applicationManager()->enabledApplications(); $RequiredApplications = ArrayValue('RequiredApplications', $PluginInfo, false); CheckRequirements($PluginName, $RequiredApplications, $EnabledApplications, 'application'); // Include the plugin, instantiate it, and call its setup method $PluginClassName = ArrayValue('ClassName', $PluginInfo, false); $PluginFolder = ArrayValue('Folder', $PluginInfo, false); if ($PluginFolder == '') { throw new Exception(T('The plugin folder was not properly defined.')); } $this->pluginHook($PluginName, self::ACTION_ENABLE, $Setup); // If setup succeeded, register any specified permissions $PermissionName = val('RegisterPermissions', $PluginInfo, false); if ($PermissionName != false) { $PermissionModel = Gdn::permissionModel(); $PermissionModel->define($PermissionName); } return true; }
/** * Delete a role. * * @param string|unknown_type $RoleID * @param bool|unknown_type $ReplacementRoleID */ public function delete($RoleID, $ReplacementRoleID) { // First update users that will be orphaned if (is_numeric($ReplacementRoleID) && $ReplacementRoleID > 0) { $this->SQL->options('Ignore', true)->update('UserRole')->join('UserRole urs', 'UserRole.UserID = urs.UserID')->groupBy('urs.UserID')->having('count(urs.RoleID) =', '1', true, false)->set('UserRole.RoleID', $ReplacementRoleID)->where(array('UserRole.RoleID' => $RoleID))->put(); } else { $this->SQL->delete('UserRole', array('RoleID' => $RoleID)); } // Remove permissions for this role. $PermissionModel = Gdn::permissionModel(); $PermissionModel->delete($RoleID); // Remove the role $this->SQL->delete('Role', array('RoleID' => $RoleID)); }
/** * Load and compile user permissions * * @param integer $UserID * @param boolean $Serialize * @return array */ public function definePermissions($UserID, $Serialize = true) { if (Gdn::cache()->activeEnabled()) { $PermissionsIncrement = $this->GetPermissionsIncrement(); $UserPermissionsKey = formatString(self::USERPERMISSIONS_KEY, array('UserID' => $UserID, 'PermissionsIncrement' => $PermissionsIncrement)); $CachePermissions = Gdn::cache()->get($UserPermissionsKey); if ($CachePermissions !== Gdn_Cache::CACHEOP_FAILURE) { return $CachePermissions; } } $Data = Gdn::permissionModel()->cachePermissions($UserID); $Permissions = UserModel::compilePermissions($Data); $PermissionsSerialized = null; if (Gdn::cache()->activeEnabled()) { Gdn::cache()->store($UserPermissionsKey, $Permissions); } else { // Save the permissions to the user table $PermissionsSerialized = Gdn_Format::serialize($Permissions); if ($UserID > 0) { $this->SQL->put('User', array('Permissions' => $PermissionsSerialized), array('UserID' => $UserID)); } } if ($Serialize && is_null($PermissionsSerialized)) { $PermissionsSerialized = Gdn_Format::serialize($Permissions); } return $Serialize ? $PermissionsSerialized : $Permissions; }
/** * Edit a role. * * @since 2.0.0 * @access public */ public function edit($RoleID = false) { if (!$this->_permission($RoleID)) { return; } if ($this->Head && $this->Head->title() == '') { $this->Head->title(t('Edit Role')); } $this->addSideMenu('dashboard/role'); $PermissionModel = Gdn::permissionModel(); $this->Role = $this->RoleModel->getByRoleID($RoleID); // $this->EditablePermissions = is_object($this->Role) ? $this->Role->EditablePermissions : '1'; $this->addJsFile('jquery.gardencheckboxgrid.js'); // Set the model on the form. $this->Form->setModel($this->RoleModel); // Make sure the form knows which item we are editing. $this->Form->addHidden('RoleID', $RoleID); $LimitToSuffix = !$this->Role || $this->Role->CanSession == '1' ? '' : 'View'; // If seeing the form for the first time... if ($this->Form->authenticatedPostBack() === false) { // Get the role data for the requested $RoleID and put it into the form. $Permissions = $PermissionModel->getPermissionsEdit($RoleID ? $RoleID : 0, $LimitToSuffix); // Remove permissions the user doesn't have access to. if (!Gdn::session()->checkPermission('Garden.Settings.Manage')) { foreach ($this->RoleModel->RankPermissions as $Permission) { if (Gdn::session()->checkPermission($Permission)) { continue; } list($Px, $Sx) = explode('.', $Permission, 2); unset($Permissions['_' . $Px][$Sx]); } } $this->setData('PermissionData', $Permissions, true); $this->Form->setData($this->Role); } else { $this->removeRankPermissions(); // If the form has been posted back... // 2. Save the data (validation occurs within): if ($RoleID = $this->Form->save()) { $this->informMessage(t('Your changes have been saved.')); $this->RedirectUrl = url('dashboard/role'); // Reload the permission data. $this->setData('PermissionData', $PermissionModel->getPermissionsEdit($RoleID, $LimitToSuffix), true); } } $this->setData('_Types', $this->RoleModel->getDefaultTypes(true)); $this->render(); }
$Construct->table('UserMeta')->column('UserID', 'int', false, 'primary')->column('Name', 'varchar(100)', false, array('primary', 'index'))->column('Value', 'text', true)->set($Explicit, $Drop); // User Points Table $Construct->table('UserPoints')->column('SlotType', array('d', 'w', 'm', 'y', 'a'), false, 'primary')->column('TimeSlot', 'datetime', false, 'primary')->column('Source', 'varchar(10)', 'Total', 'primary')->column('CategoryID', 'int', 0, 'primary')->column('UserID', 'int', false, 'primary')->column('Points', 'int', 0)->set($Explicit, $Drop); // Create the authentication table. $Construct->table('UserAuthentication')->column('ForeignUserKey', 'varchar(100)', false, 'primary')->column('ProviderKey', 'varchar(64)', false, 'primary')->column('UserID', 'int', false, 'key')->set($Explicit, $Drop); $Construct->table('UserAuthenticationProvider')->column('AuthenticationKey', 'varchar(64)', false, 'primary')->column('AuthenticationSchemeAlias', 'varchar(32)', false)->column('Name', 'varchar(50)', true)->column('URL', 'varchar(255)', true)->column('AssociationSecret', 'text', true)->column('AssociationHashMethod', 'varchar(20)', true)->column('AuthenticateUrl', 'varchar(255)', true)->column('RegisterUrl', 'varchar(255)', true)->column('SignInUrl', 'varchar(255)', true)->column('SignOutUrl', 'varchar(255)', true)->column('PasswordUrl', 'varchar(255)', true)->column('ProfileUrl', 'varchar(255)', true)->column('Attributes', 'text', true)->column('Active', 'tinyint', '1')->column('IsDefault', 'tinyint', 0)->set($Explicit, $Drop); $Construct->table('UserAuthenticationNonce')->column('Nonce', 'varchar(100)', false, 'primary')->column('Token', 'varchar(128)', false)->column('Timestamp', 'timestamp', false)->set($Explicit, $Drop); $Construct->table('UserAuthenticationToken')->column('Token', 'varchar(128)', false, 'primary')->column('ProviderKey', 'varchar(64)', false, 'primary')->column('ForeignUserKey', 'varchar(100)', true)->column('TokenSecret', 'varchar(64)', false)->column('TokenType', array('request', 'access'), false)->column('Authorized', 'tinyint(1)', false)->column('Timestamp', 'timestamp', false)->column('Lifetime', 'int', false)->set($Explicit, $Drop); // Fix the sync roles config spelling mistake. if (c('Garden.SSO.SynchRoles')) { saveToConfig(array('Garden.SSO.SynchRoles' => '', 'Garden.SSO.SyncRoles' => c('Garden.SSO.SynchRoles')), '', array('RemoveEmpty' => true)); } $Construct->table('Session')->column('SessionID', 'char(32)', false, 'primary')->column('UserID', 'int', 0)->column('DateInserted', 'datetime', false)->column('DateUpdated', 'datetime', false)->column('TransientKey', 'varchar(12)', false)->column('Attributes', 'text', null)->set($Explicit, $Drop); $Construct->table('AnalyticsLocal')->engine('InnoDB')->column('TimeSlot', 'varchar(8)', false, 'unique')->column('Views', 'int', null)->column('EmbedViews', 'int', true)->set(false, false); // Only Create the permission table if we are using Garden's permission model. $PermissionModel = Gdn::permissionModel(); $PermissionModel->Database = $Database; $PermissionModel->SQL = $SQL; $PermissionTableExists = false; if ($PermissionModel instanceof PermissionModel) { $PermissionTableExists = $Construct->tableExists('Permission'); // Permission Table $Construct->table('Permission')->primaryKey('PermissionID')->column('RoleID', 'int', 0, 'key')->column('JunctionTable', 'varchar(100)', true)->column('JunctionColumn', 'varchar(100)', true)->column('JunctionID', 'int', true)->set($Explicit, $Drop); } // Define the set of permissions that Garden uses. $PermissionModel->define(array('Garden.Email.View' => 'Garden.SignIn.Allow', 'Garden.Settings.Manage', 'Garden.Settings.View', 'Garden.SignIn.Allow' => 1, 'Garden.Users.Add', 'Garden.Users.Edit', 'Garden.Users.Delete', 'Garden.Users.Approve', 'Garden.Activity.Delete', 'Garden.Activity.View' => 1, 'Garden.Profiles.View' => 1, 'Garden.Profiles.Edit' => 'Garden.SignIn.Allow', 'Garden.Curation.Manage' => 'Garden.Moderation.Manage', 'Garden.Moderation.Manage', 'Garden.PersonalInfo.View' => 'Garden.Moderation.Manage', 'Garden.AdvancedNotifications.Allow', 'Garden.Community.Manage' => 'Garden.Settings.Manage')); $PermissionModel->undefine(array('Garden.Applications.Manage', 'Garden.Email.Manage', 'Garden.Plugins.Manage', 'Garden.Registration.Manage', 'Garden.Routes.Manage', 'Garden.Themes.Manage', 'Garden.Messages.Manage')); // Invitation Table $Construct->table('Invitation')->primaryKey('InvitationID')->column('Email', 'varchar(100)', false, 'index')->column('Name', 'varchar(50)', true)->column('RoleIDs', 'text', true)->column('Code', 'varchar(50)', false, 'unique.code')->column('InsertUserID', 'int', true, 'index.userdate')->column('DateInserted', 'datetime', false, 'index.userdate')->column('AcceptedUserID', 'int', true)->column('DateExpires', 'datetime', true)->set($Explicit, $Drop); // Fix negative invitation expiry dates. $InviteExpiry = c('Garden.Registration.InviteExpiration');
/** * Runs on utility/update. * * @throws Exception */ public function structure() { // Pocket class isn't autoloaded on Enable. require_once 'library/class.pocket.php'; $St = Gdn::structure(); $St->table('Pocket')->primaryKey('PocketID')->column('Name', 'varchar(255)')->column('Page', 'varchar(50)', null)->column('Location', 'varchar(50)')->column('Sort', 'smallint')->column('Repeat', 'varchar(25)')->column('Body', 'text')->column('Format', 'varchar(20)')->column('Condition', 'varchar(500)', null)->column('Disabled', 'smallint', '0')->column('Attributes', 'text', null)->column('MobileOnly', 'tinyint', '0')->column('MobileNever', 'tinyint', '0')->column('EmbeddedNever', 'tinyint', '0')->column('ShowInDashboard', 'tinyint', '0')->column('Type', array(Pocket::TYPE_DEFAULT, Pocket::TYPE_AD), Pocket::TYPE_DEFAULT)->set(); $PermissionModel = Gdn::permissionModel(); $PermissionModel->define(array('Garden.NoAds.Allow' => 0)); }