Alexander 5 anni fa
parent
commit
28346a3b9b

+ 3 - 2
inc/classes/BxDol.php

@@ -230,11 +230,12 @@ interface iBxDolProfileService
     public function serviceCheckAllowedProfileContact($iContentId);
     
     /**
-     * Check if posting in profile is allowed, for example posting in profile's timeline
+     * Check if posting of a certain type of content in profile is allowed, for example posting in profile's timeline
      * @param $iContentId content ID
+     * @param $sPostModule type of content to be posted
      * @return message on error, or CHECK_ACTION_RESULT_ALLOWED when allowed
      */    
-    public function serviceCheckAllowedPostInProfile($iContentId);
+    public function serviceCheckAllowedPostInProfile($iContentId, $sPostModule = '');
 
     /**
      * Get profiles, current profile have relation with, like friends, joined groups and events

+ 11 - 0
inc/classes/BxDolPrivacy.php

@@ -418,10 +418,21 @@ class BxDolPrivacy extends BxDolFactory implements iBxDolFactoryObject
             $oModule = BxDolModule::getInstance($aModule['name']);
             
             $a = BxDolService::call($aModule['name'], 'get_participating_profiles', array($oProfile->id()));
+
+            // for an organization we should treat the organization profile itself as a participant of itself
+            // to be able to post into an organization's context while being logged as that organization
+            if ($aModule['name'] == 'bx_organizations' && $oProfile->getModule() == 'bx_organizations') $a = array_merge($a, [$oProfile->id()]);
+
             $aSpaces = array();       
             foreach ($a as $iProfileId) {
                 if (!($o = BxDolProfile::getInstance($iProfileId)))
                     continue;
+
+                // check whether a profile is allowed to post this type of content to a context
+                $oConnectedProfile = BxDolProfile::getInstance($iProfileId);
+                if (bx_srv($aModule['name'], 'check_allowed_post_in_profile', array($oConnectedProfile->getContentId(), $this->_aObject['module'])) !== CHECK_ACTION_RESULT_ALLOWED)
+                    continue;
+
                 $aSpaces[-$iProfileId] = array('key' => -$iProfileId, 'value' => $o->getDisplayName());
             }
 

+ 10 - 0
install/sql/system.sql

@@ -4341,6 +4341,7 @@ INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `fie
 
 ('sys_studio_labels', 'Sql', 'SELECT * FROM `sys_labels` WHERE 1 ', 'sys_labels', 'id', 'order', '', '', 1000, NULL, 'start', '', 'value', '', 'like', 'value', '', 'BxTemplStudioFormsLabels', ''),
 ('sys_studio_categories', 'Sql', 'SELECT * FROM `sys_categories` WHERE 1 ', 'sys_categories', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'value', '', 'like', '', '', 'BxTemplStudioFormsCategories', ''),
+('sys_studio_groups_roles', 'Sql', 'SELECT * FROM `sys_form_pre_values` WHERE 1 ', 'sys_form_pre_values', 'id', 'Order', '', '', 20, NULL, 'start', '', '', 'LKey', 'like', '', '', 'BxTemplStudioFormsGroupsRoles', ''),
 
 ('sys_audit_administration', 'Sql', 'SELECT * FROM `sys_audit` WHERE 1 ', 'sys_audit', 'id', 'added', '', '', 20, NULL, 'start', '', 'value', '', 'like', 'content_module,profile_id,content_id,context_profile_id,added', 'action_lang_key', 'BxTemplAuditGrid', ''),
 
@@ -4484,6 +4485,11 @@ INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable
 ('sys_studio_categories', 'added', '_adm_form_txt_categories_added', '15%', 1, 25, '', 6),
 ('sys_studio_categories', 'actions', '', '20%', 0, 0, '', 7),
 
+('sys_studio_groups_roles', 'order', '', '2%', 0, 0, '', 1),
+('sys_studio_groups_roles', 'LKey', '_adm_rl_txt_title', '40%', 1, 0, '', 2),
+('sys_studio_groups_roles', 'actions_list', '_adm_rl_txt_actions', '10%', 0, 35, '', 3),
+('sys_studio_groups_roles', 'actions', '', '48%', 0, 0, '', 4),
+
 ('sys_audit_administration', 'added', '_adm_form_txt_audit_added', '15%', 1, 25, '', 1),
 ('sys_audit_administration', 'profile_id', '_adm_form_txt_audit_profile', '15%', 1, 25, '', 2),
 ('sys_audit_administration', 'content_id', '_adm_form_txt_audit_content', '20%', 1, 25, '', 3),
@@ -4588,6 +4594,10 @@ INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `conf
 ('sys_studio_categories', 'single', 'delete', '', 'remove', 1, 2),
 ('sys_studio_categories', 'independent', 'add', '_adm_form_btn_categories_add', '', 0, 1),
 
+('sys_studio_groups_roles', 'independent', 'add', '_adm_rl_btn_role_add', '', 0, 1),
+('sys_studio_groups_roles', 'single', 'edit', '_adm_rl_btn_role_edit', 'pencil-alt', 0, 1),
+('sys_studio_groups_roles', 'single', 'delete', '_adm_rl_btn_role_delete', 'remove', 1, 3),
+
 ('sys_badges_administration', 'bulk', 'delete', '_adm_form_btn_badges_delete', '', 1, 1),
 ('sys_badges_administration', 'single', 'edit', '', 'pencil-alt', 0, 1),
 ('sys_badges_administration', 'single', 'delete', '', 'remove', 1, 2),

+ 23 - 6
modules/base/general/classes/BxBaseModGeneralModule.php

@@ -851,7 +851,7 @@ class BxBaseModGeneralModule extends BxDolModule
                     }
 
                     //--- Show a default privacy groups in Profile (for Owner) post form.
-                    if($bContextOwner && (int)$aValue['key'] >= 0) {
+                    if($bContextOwner && ((int)$aValue['key'] >= 0 || $mixedContextId == $aValue['key'])) {
                         $iGc += 1;
                         continue;
                     }
@@ -876,6 +876,8 @@ class BxBaseModGeneralModule extends BxDolModule
     }
 
     /**
+     *
+     *
      * Create entry form
      * @return HTML string
      */
@@ -2221,15 +2223,22 @@ class BxBaseModGeneralModule extends BxDolModule
             if ($oProfile){
                 $sModule = $oProfile->getModule();
                 $aEntity = BxDolRequest::serviceExists($sModule, 'get_all') ? BxDolService::call($sModule, 'get_all', array(array('type' => 'id', 'id' => $oProfile->getContentId()))) : array();
-                
+
                 $oModule = BxDolModule::getInstance($sModule);
+
+                // check for context's extra roles with rights
+                if (method_exists($oModule, 'isAllowedModuleActionByProfile')) {
+                    $bResult = $oModule->isAllowedModuleActionByProfile($oProfile->getContentId(), $this->getName(), 'edit_any');
+                    if ($bResult !== NULL) return $bResult;
+                }
+
+                // if allowed edit a group then allowed to edit anything inside its context
                 if(isset($aEntity) && $oModule->checkAllowedEdit($aEntity) === CHECK_ACTION_RESULT_ALLOWED){
                     return CHECK_ACTION_RESULT_ALLOWED;
                 }
             }
         }
-     
-        
+
         return _t('_sys_txt_access_denied');
     }
 
@@ -2246,15 +2255,23 @@ class BxBaseModGeneralModule extends BxDolModule
         $aCheck = checkActionModule($this->_iProfileId, 'delete entry', $this->getName(), $isPerformAction);
         if (($aDataEntry[$this->_oConfig->CNF['FIELD_AUTHOR']] == $this->_iProfileId || -$aDataEntry[$this->_oConfig->CNF['FIELD_AUTHOR']] == $this->_iProfileId) && $aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED)
             return CHECK_ACTION_RESULT_ALLOWED;
-        
+
         // check for context's admins 
         if (isset($this->_oConfig->CNF['FIELD_ALLOW_VIEW_TO']) && (int)$aDataEntry[$this->_oConfig->CNF['FIELD_ALLOW_VIEW_TO']] < 0){
             $oProfile = BxDolProfile::getInstance(-(int)$aDataEntry[$this->_oConfig->CNF['FIELD_ALLOW_VIEW_TO']]);
             if ($oProfile){
                 $sModule = $oProfile->getModule();
                 $aEntity = BxDolRequest::serviceExists($sModule, 'get_all') ? BxDolService::call($sModule, 'get_all', array(array('type' => 'id', 'id' => $oProfile->getContentId()))) : array();
-                
+
                 $oModule = BxDolModule::getInstance($sModule);
+
+                // check for context's extra roles with rights
+                if (method_exists($oModule, 'isAllowedModuleActionByProfile')) {
+                    $bResult = $oModule->isAllowedModuleActionByProfile($oProfile->getContentId(), $this->getName(), 'delete_any');
+                    if ($bResult !== NULL) return $bResult;
+                }
+
+                // if allowed delete a group then allowed to delete anything inside its context
                 if(isset($aEntity) && $oModule->checkAllowedDelete($aEntity) === CHECK_ACTION_RESULT_ALLOWED){
                     return CHECK_ACTION_RESULT_ALLOWED;
                 }

+ 74 - 10
modules/base/groups/classes/BxBaseModGroupsModule.php

@@ -22,6 +22,8 @@ define('BX_BASE_MOD_GROUPS_ACTION_INVITE', 'invite');
 define('BX_BASE_MOD_GROUPS_ACTION_MANAGE_FANS', 'manage_fans');
 define('BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES', 'manage_roles');
 define('BX_BASE_MOD_GROUPS_ACTION_DELETE', 'delete');
+define('BX_BASE_MOD_GROUPS_ACTION_EDIT_CONTENT', 'edit_any');
+define('BX_BASE_MOD_GROUPS_ACTION_DELETE_CONTENT', 'delete_any');
 
 define('BX_BASE_MOD_GROUPS_PERIOD_UNIT_DAY', 'day');
 define('BX_BASE_MOD_GROUPS_PERIOD_UNIT_WEEK', 'week');
@@ -1113,19 +1115,31 @@ class BxBaseModGroupsModule extends BxBaseModProfileModule
 
     public function isAllowedActionByRole($sAction, $aDataEntry, $iGroupProfileId, $iProfileId)
     {
-        $bResult = false;
-
         $iProfileRole = $this->_oDb->getRole($iGroupProfileId, $iProfileId);
-        if(!empty($iProfileRole))
-            switch($sAction) {
-                case BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES:
-                    if($this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR))
-                        $bResult = true;
-                    break;
 
-                default:
-                    $bResult = true;
+        $bResult = $iProfileId ? $this->isAllowedModuleActionByRole($this->getName(), $sAction, $iProfileRole) : false;
+        // in case neithe of the profile's roles are having permissions set explicitly
+        if ($bResult === NULL) {
+            $bResult = false;
+            if(!empty($iProfileRole)) {
+                switch ($sAction) {
+                    case BX_BASE_MOD_GROUPS_ACTION_DELETE:
+                    case BX_BASE_MOD_GROUPS_ACTION_EDIT:
+                    case BX_BASE_MOD_GROUPS_ACTION_CHANGE_COVER:
+                    case BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES:
+                        if ($this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR)) $bResult = true;
+                        break;
+                    case BX_BASE_MOD_GROUPS_ACTION_MANAGE_FANS:
+                    case BX_BASE_MOD_GROUPS_ACTION_INVITE:
+                    case BX_BASE_MOD_GROUPS_ACTION_EDIT_CONTENT:
+                    case BX_BASE_MOD_GROUPS_ACTION_DELETE_CONTENT:
+                        if ($this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR) || $this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_MODERATOR)) $bResult = true;
+                        break;
+                    default:
+                        $bResult = true;
+                }
             }
+        }
 
         // call alert to allow custom checks
         bx_alert('system', 'check_allowed_action_by_role', 0, 0, array(
@@ -1142,6 +1156,56 @@ class BxBaseModGroupsModule extends BxBaseModProfileModule
         return $bResult;
     }
 
+    public function isAllowedModuleActionByRole($sModule, $sAction, $iProfileRole) {
+        static $aRoles;
+        if (!$aRoles && isset($this->_oConfig->CNF['OBJECT_PRE_LIST_ROLES']) && !empty($this->_oConfig->CNF['OBJECT_PRE_LIST_ROLES']))
+            $aRoles = BxBaseFormView::getDataItems($this->_oConfig->CNF['OBJECT_PRE_LIST_ROLES'], true, BX_DATA_VALUES_ALL);
+
+        if ($aRoles) {
+            foreach ($aRoles as $iRole => $aRoleData) {
+                if ($iRole == 0 && $iProfileRole == 0 || $iRole > 0 && $this->isRole($iProfileRole, $iRole)) {
+                    $mPermissions = isset($aRoles[$iRole]) && isset($aRoles[$iRole]['Data']) && !empty($aRoles[$iRole]['Data']) ? unserialize($aRoles[$iRole]['Data']) : false;
+                    if ($mPermissions && isset($mPermissions[$sModule])) {
+                         return isset($mPermissions[$sModule][$sAction]) && $mPermissions[$sModule][$sAction];
+                    } else {
+                        // default values in case a role has not been specified explicitly
+                        switch ($sAction) {
+                            case BX_BASE_MOD_GROUPS_ACTION_EDIT:
+                            case BX_BASE_MOD_GROUPS_ACTION_CHANGE_COVER:
+                            case BX_BASE_MOD_GROUPS_ACTION_MANAGE_ROLES:
+                                if ($this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR)) return true;
+                                break;
+                            case BX_BASE_MOD_GROUPS_ACTION_MANAGE_FANS:
+                            case BX_BASE_MOD_GROUPS_ACTION_INVITE:
+                            case BX_BASE_MOD_GROUPS_ACTION_EDIT_CONTENT:
+                            case BX_BASE_MOD_GROUPS_ACTION_DELETE_CONTENT:
+                                if ($this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR) || $this->isRole($iProfileRole, BX_BASE_MOD_GROUPS_ROLE_MODERATOR)) return true;
+                                break;
+                            // for the rest of the actions like "Post" still return NULL
+                            // to let the code go down the stack of checkAllowed* function calls for a default behavior
+                        }
+                    }
+                }
+            }
+        }
+
+        return NULL;
+    }
+
+    public function isAllowedModuleActionByProfile($iContentId, $sPostModule, $sAction, $iProfileId = 0) {
+        if (!$iProfileId) $iProfileId = bx_get_logged_profile_id();
+
+        if ($iProfileId && $this->isFan($iContentId, $iProfileId)) {
+            $oGroupProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $this->getName());
+            $iProfileRole = $this->_oDb->getRole($oGroupProfile->id(), $iProfileId);
+            $bResult = $this->isAllowedModuleActionByRole($sPostModule, $sAction, $iProfileRole);
+            if ($bResult === true) return CHECK_ACTION_RESULT_ALLOWED;
+            if ($bResult === false) return _t('_sys_txt_access_denied');
+        }
+
+        return NULL; //undefined, because the profile is either not a fan or his role is not having permissions defined. So process the default way then.
+    }
+
     public function isRole($iProfileRole, $iRole)
     {
         if(!$this->_oConfig->isMultiRoles())

+ 16 - 6
modules/base/profile/classes/BxBaseModProfileModule.php

@@ -509,15 +509,18 @@ class BxBaseModProfileModule extends BxBaseModGeneralModule implements iBxDolCon
             else
                 $a = array_merge($a, $o->getConnectedContentByType($iProfileId, $this->getName()));
         }
-        $a = array_unique($a);
-        $aRet = array();
-        foreach ($a as $iConnectedProfileId) {
+        $aRet = array_unique($a);
+
+        // the check for an ability to post in profile has been moved to BxDolPrivacy because we need to have an extended check
+        // with an ability to check for extended roles taking into account the type of content which is going be posted/edited
+        // so now this service returns just a fans, not filtered by an ability to post into an entry's context
+        /*foreach ($a as $iConnectedProfileId) {
             if (!($oConnectedProfile = BxDolProfile::getInstance($iConnectedProfileId)))
                 continue;
 
-            if (CHECK_ACTION_RESULT_ALLOWED === bx_srv($oConnectedProfile->getModule(), 'check_allowed_post_in_profile', array($oConnectedProfile->getContentId(), $iProfileId)))
+             if (CHECK_ACTION_RESULT_ALLOWED === bx_srv($oConnectedProfile->getModule(), 'check_allowed_post_in_profile', array($oConnectedProfile->getContentId(), $iProfileId)))
                 $aRet[] = $iConnectedProfileId;
-        }
+        }*/
 
         bx_alert('system', 'get_participating_profiles', $iProfileId, false, array(
             'module' => $this->_oConfig->getName(),
@@ -1255,8 +1258,15 @@ class BxBaseModProfileModule extends BxBaseModGeneralModule implements iBxDolCon
     /**
      * @see iBxDolProfileService::serviceCheckAllowedPostInProfile
      */
-    public function serviceCheckAllowedPostInProfile($iContentId)
+    public function serviceCheckAllowedPostInProfile($iContentId, $sPostModule = '')
     {
+        // for groups based profiles we do have a Role permissions which have a higher priority than the site-wide permissions.
+        if (method_exists($this, 'isAllowedModuleActionByProfile')) {
+            $bResult = $this->isAllowedModuleActionByProfile($iContentId, $sPostModule, 'post');
+            // if a profile is having a role and a role is having permissions set then it overrides the site-wide setting.
+            if ($bResult !== NULL) return $bResult;
+        }
+
         return $this->serviceCheckAllowedWithContent('Post', $iContentId);
     }
 

+ 15 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -3479,4 +3479,19 @@ If it is not enabled then please consider implement this optimization, since it
     <string name="_sys_wiki_title_content"><![CDATA[{0} content]]></string>
     <string name="_sys_wiki_title_time"><![CDATA[{0} updated]]></string>
     <string name="_sys_wiki_orig"><![CDATA[Orig.]]></string>
+
+	<string name="_adm_lmi_cpt_groups_roles"><![CDATA[Roles]]></string>
+	<string name="_adm_form_txt_groups_roles_add_popup"><![CDATA[Create role]]></string>
+	<string name="_adm_form_txt_groups_role_value"><![CDATA[Role name]]></string>
+	<string name="_adm_form_txt_groups_role_value_err"><![CDATA[Role name is required]]></string>
+	<string name="_adm_form_txt_groups_roles_edit_popup"><![CDATA[Edit role]]></string>
+	<string name="_adm_form_txt_groups_role_manage_fans"><![CDATA[Manage fans]]></string>
+	<string name="_adm_form_txt_groups_role_manage_roles"><![CDATA[Manage roles]]></string>
+	<string name="_adm_form_txt_groups_role_edit"><![CDATA[Edit]]></string>
+	<string name="_adm_form_txt_groups_role_invite"><![CDATA[Invite]]></string>
+	<string name="_adm_form_txt_groups_role_change_cover"><![CDATA[Change cover]]></string>
+	<string name="_adm_form_txt_groups_role_post"><![CDATA[Post]]></string>
+	<string name="_adm_form_txt_groups_role_edit_any"><![CDATA[Edit any entry]]></string>
+	<string name="_adm_form_txt_groups_role_delete_any"><![CDATA[Delete any entry]]></string>
 </resources>
+

+ 14 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -3453,4 +3453,18 @@
     <string name="_sys_wiki_title_content"><![CDATA[{0} содержимое]]></string>
     <string name="_sys_wiki_title_time"><![CDATA[{0} обновлен]]></string>
     <string name="_sys_wiki_orig"><![CDATA[Ориг.]]></string>
+
+	<string name="_adm_lmi_cpt_groups_roles"><![CDATA[Роли]]></string>
+	<string name="_adm_form_txt_groups_roles_add_popup"><![CDATA[Создать роль]]></string>
+	<string name="_adm_form_txt_groups_role_value"><![CDATA[Имя роли]]></string>
+	<string name="_adm_form_txt_groups_role_value_err"><![CDATA[Имя роли обязательно]]></string>
+	<string name="_adm_form_txt_groups_roles_edit_popup"><![CDATA[Редактировать роль]]></string>
+	<string name="_adm_form_txt_groups_role_manage_fans"><![CDATA[Управлять участниками]]></string>
+	<string name="_adm_form_txt_groups_role_manage_roles"><![CDATA[Управлять ролями]]></string>
+	<string name="_adm_form_txt_groups_role_edit"><![CDATA[Редактировать]]></string>
+	<string name="_adm_form_txt_groups_role_invite"><![CDATA[Приглашать]]></string>
+	<string name="_adm_form_txt_groups_role_change_cover"><![CDATA[Менять обложку]]></string>
+	<string name="_adm_form_txt_groups_role_post"><![CDATA[Создавать]]></string>
+	<string name="_adm_form_txt_groups_role_edit_any"><![CDATA[Редактировать любое/все]]></string>
+	<string name="_adm_form_txt_groups_role_delete_any"><![CDATA[Удалять любое/все]]></string>
 </resources>

+ 1 - 0
studio/classes/BxDolStudioForms.php

@@ -16,6 +16,7 @@ define('BX_DOL_STUDIO_FORM_TYPE_SEARCH_FORMS', 'search_forms');
 define('BX_DOL_STUDIO_FORM_TYPE_SEARCH_FIELDS', 'search_fields');
 define('BX_DOL_STUDIO_FORM_TYPE_LABELS', 'labels');
 define('BX_DOL_STUDIO_FORM_TYPE_CATEGORIES', 'categories');
+define('BX_DOL_STUDIO_FORM_TYPE_GROUPS_ROLES', 'groups_roles');
 
 define('BX_DOL_STUDIO_FORM_TYPE_DEFAULT', BX_DOL_STUDIO_FORM_TYPE_FORMS);
 

+ 46 - 0
studio/classes/BxDolStudioFormsGroupsRoles.php

@@ -0,0 +1,46 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+
+class BxDolStudioFormsGroupsRoles extends BxTemplStudioGrid
+{
+    protected $sModule;
+    protected $sRolesDataList;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->oDb = new BxDolStudioFormsQuery();
+
+        $sModule = bx_get('module');
+        if(!empty($sModule)) {
+            $oModule = BxDolModule::getInstance($sModule);
+            if ($oModule) {
+                $sRolesDataList = isset($oModule->_oConfig->CNF['OBJECT_PRE_LIST_ROLES']) ? $oModule->_oConfig->CNF['OBJECT_PRE_LIST_ROLES'] : '';
+                if ($sRolesDataList) {
+                    $this->sModule = bx_process_input($sModule);
+                    $this->sRolesDataList = $sRolesDataList;
+                    $this->_aQueryAppend['module'] = $this->sModule;
+                }
+            }
+        }
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        if($this->sRolesDataList != '') {
+            $this->_aOptions['source'] .= $this->oDb->prepareAsString(" AND `Key` = ?", $this->sRolesDataList);
+            return parent::_getDataSql('', $sOrderField, $sOrderDir, $iStart, $iPerPage);
+        }
+
+        return false;
+    }
+}
+
+/** @} */

+ 40 - 0
studio/js/forms_groups_roles.js

@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+function BxDolStudioFormsGroupsRoles(oOptions) {
+    this.sActionsUrl = oOptions.sActionUrl;
+    this.sPageUrl = oOptions.sPageUrl;
+    this.sObjNameGrid = oOptions.sObjNameGrid;
+    this.sObjName = oOptions.sObjName == undefined ? 'oBxDolStudioFormsGroupsRoles' : oOptions.sObjName;
+    this.sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'fade' : oOptions.sAnimationEffect;
+    this.iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+}
+
+BxDolStudioFormsGroupsRoles.prototype.onChangeModule = function () {
+    this.reloadGrid($('#bx-grid-module-' + this.sObjNameGrid).val());
+};
+
+BxDolStudioFormsGroupsRoles.prototype.reloadGrid = function (sModule) {
+    var bReload = false;
+    var oActions = $("[bx_grid_action_independent]");
+    if(!sModule){
+        oActions.addClass('bx-btn-disabled');
+    }
+    else {
+        oActions.removeClass('bx-btn-disabled');
+    }
+
+    if (glGrids[this.sObjNameGrid]._oQueryAppend['module'] != sModule) {
+        glGrids[this.sObjNameGrid]._oQueryAppend['module'] = sModule;
+        bReload = true;
+    }
+
+    if (bReload) {
+        glGrids[this.sObjNameGrid].reload(0);
+    }
+};
+/** @} */

+ 19 - 0
studio/template/form_add_groups_role.html

@@ -0,0 +1,19 @@
+<div class="bx-form-add-label bx-def-color-bg-block">
+    <div class="bx-form-add-groups-role-cnt">
+        __form__
+        <script language="javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (data) {
+                        $(".bx-popup-applied:visible").dolPopupHide();
+                        glGrids.__object__.processJson(data, '__action__');
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>

+ 8 - 0
studio/template/forms_groups_roles.html

@@ -0,0 +1,8 @@
+__content__
+<script language="javascript">
+    var __js_object__ = new BxDolStudioFormsGroupsRoles({
+        sActionUrl: '<bx_url_root />grid.php',
+        sPageUrl: '__page_url__',
+        sObjNameGrid: '__grid_object__'
+    });
+</script>

+ 12 - 0
studio/template/scripts/BxBaseStudioForms.php

@@ -30,6 +30,7 @@ class BxBaseStudioForms extends BxDolStudioForms
             BX_DOL_STUDIO_FORM_TYPE_SEARCH_FIELDS => array('icon' => 'check-square'),
             BX_DOL_STUDIO_FORM_TYPE_LABELS => array('icon' => 'tags'),
             BX_DOL_STUDIO_FORM_TYPE_CATEGORIES => array('icon' => 'folder'),
+            BX_DOL_STUDIO_FORM_TYPE_GROUPS_ROLES => array('icon' => 'user'),
         );
 
         $this->aGridObjects = array(
@@ -42,6 +43,7 @@ class BxBaseStudioForms extends BxDolStudioForms
             'search_fields' => 'sys_studio_search_forms_fields',
             'labels' => 'sys_studio_labels',
             'categories' => 'sys_studio_categories',
+            'groups_roles' => 'sys_studio_groups_roles',
     	);
     }
 
@@ -207,6 +209,16 @@ class BxBaseStudioForms extends BxDolStudioForms
         return $this->getGridObject($this->aGridObjects['categories']);
     }
 
+    protected function getGroupsRoles()
+    {
+        return $this->getGrid($this->aGridObjects['groups_roles']);
+    }
+
+    protected function getGroupsRolesObject()
+    {
+        return $this->getGridObject($this->aGridObjects['groups_roles']);
+    }
+
     protected function getGridObject($sObjectName)
     {
         $oGrid = BxDolGrid::getObjectInstance($sObjectName);

+ 422 - 0
studio/template/scripts/BxBaseStudioFormsGroupsRoles.php

@@ -0,0 +1,422 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+bx_import('BxTemplStudioFormView');
+
+define('BX_DOL_STUDIO_FIELD_PRE_VALUE_INT_MAX', round(log(BX_DOL_INT_MAX, 2)));
+
+define('BX_DOL_MOD_GROUPS_ROLE_COMMON', 0);
+define('BX_DOL_MOD_GROUPS_ROLE_ADMINISTRATOR', 1);
+define('BX_DOL_MOD_GROUPS_ROLE_MODERATOR', 2);
+
+class BxBaseStudioFormsGroupsRoles extends BxDolStudioFormsGroupsRoles
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+        $this->sUrlPage = BX_DOL_URL_STUDIO . 'builder_forms.php?page=groups_roles';
+    }
+    
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+        
+        if(!$this->canAdd()) {
+            echoJson(array());
+            exit;
+        }
+
+        $oForm = $this->_getPermissionsForm($sAction);
+
+        if (!$oForm)
+            return '';
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?' . bx_encode_url_params($_GET, array('ids', '_r'));
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $iNewValue = $this->_getAvailableSetValue($this->sRolesDataList);
+
+            if(!$this->canUseForSet($iNewValue)) {
+                echoJson(array('msg' => _t('_adm_form_err_pre_values_create_forbidden', BX_DOL_STUDIO_FIELD_PRE_VALUE_INT_MAX)));
+                return;
+            }
+
+            $aData = $oForm->getCleanValue('Data');
+            $aAllActions = $this->_getDefaultActionsArray(0);
+            foreach ($aAllActions as $sModule => $aActions)
+                if (!isset($aData[$sModule])) $aData[$sModule] = [];
+
+            $mixedResult = $oForm->insert([
+                'LKey2' => '',
+                'Value' => $iNewValue,
+                'Order' => $this->oDb->getValuesOrderMax($this->sRolesDataList) + 1,
+                'Key' => $this->sRolesDataList,
+                'Data' => serialize($aData),
+            ]);
+            if(is_numeric($mixedResult))
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $mixedResult);
+            else
+                $aRes = array('msg' => $mixedResult);
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox('adm-form-groups-roles-add-popup', _t('_adm_form_txt_groups_roles_add_popup'), $this->_oTemplate->parseHtmlByName('form_add_groups_role.html', array(
+               'form_id' => $oForm->aFormAttrs['id'],
+               'form' => $oForm->getCode(true),
+               'object' => $this->_sObject,
+               'action' => $sAction
+           )));
+
+           echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+        }
+    }
+    
+    public function performActionEdit()
+    {
+        $sAction = 'edit';
+        
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId)
+                return echoJson(array());
+
+            $aIds = array($iId);
+        }
+
+        $iId = (int)array_shift($aIds);
+
+        $aItem = array();
+        $this->oDb->getValues(array('type' => 'by_id', 'value' => $iId), $aItem, false);
+        if(!is_array($aItem) || empty($aItem)) {
+            echoJson([]);
+            exit;
+        }
+
+        $oForm = $this->_getPermissionsForm($sAction, $aItem);
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $aData = $oForm->getCleanValue('Data');
+            $aAllActions = $this->_getDefaultActionsArray($aItem['Value']);
+            foreach ($aAllActions as $sModule => $aActions)
+                if (!isset($aData[$sModule])) $aData[$sModule] = [];
+
+            $mixedResult = $oForm->update($iId, ['Data' => serialize($aData)]);
+            if(is_numeric($mixedResult))
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $mixedResult);
+            else
+                $aRes = array('msg' => $mixedResult);
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox('adm-form-groups-roles-edit-popup', _t('_adm_form_txt_groups_roles_edit_popup', _t($aItem['LKey'])), $this->_oTemplate->parseHtmlByName('form_add_groups_role.html', array(
+               'form_id' => $oForm->aFormAttrs['id'],
+               'form' => $oForm->getCode(true),
+               'object' => $this->_sObject,
+               'action' => $sAction
+           )));
+
+           echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+        }
+    }
+
+    public function performActionDelete()
+    {
+        $this->_replaceMarkers ();
+
+        $iAffected = 0;
+        $aIds = bx_get('ids');
+        if (!$aIds || !is_array($aIds)) {
+            echoJson(array());
+            exit;
+        }
+
+        $oLanguage = BxDolStudioLanguagesUtils::getInstance();
+
+        $aIdsAffected = array ();
+        foreach($aIds as $iId) {
+            $aValue = array();
+            $this->oDb->getValues(array('type' => 'by_id', 'value' => (int)$iId), $aValue);
+            if(!is_array($aValue) || empty($aValue))
+                continue;
+
+            if((int)$this->_delete($iId) <= 0)
+                continue;
+
+            $oLanguage->deleteLanguageString($aValue['lkey']);
+            $oLanguage->deleteLanguageString($aValue['lkey2']);
+
+            $aIdsAffected[] = $iId;
+            $iAffected++;
+        }
+
+        echo echoJson(array_merge(
+            array(
+                'grid' => $this->getCode(false),
+            ),
+            $iAffected ? array() : array('msg' => _t("_sys_grid_delete_failed"))
+        ));
+    }
+
+    protected function _getPermissionsForm($sFormAction, $aRole = [])
+    {
+        if (!empty($aRole['Data']) && !is_array($aRole['Data'])) $aRole['Data'] = unserialize($aRole['Data']);
+
+        $aInputs = [];
+        $aInputs['id'] = [
+            'type' => 'hidden',
+            'name' => 'id',
+            'value' => isset($aRole['id']) ? (int)$aRole['id'] : 0,
+            'db' => [
+                'pass' => 'Int',
+            ],
+        ];
+        $aInputs['LKey'] = [
+            'type' => 'text_translatable',
+            'name' => 'LKey',
+            'caption' => _t('_adm_form_txt_groups_role_value'),
+            'info' => '',
+            'value' => isset($aRole['LKey']) ? $aRole['LKey'] : '',
+            'required' => '1',
+            'db' => [
+                'pass' => 'Xss',
+            ],
+            'checker' => [
+                'func' => 'LengthTranslatable',
+                'params' => [1,100, 'LKey'],
+                'error' => _t('_adm_form_txt_groups_role_value_err'),
+            ],
+        ];
+
+        $aAllActions = $this->_getDefaultActionsArray(isset($aRole['id']) ? (int)$aRole['id'] : 0);
+        foreach ($aAllActions as $sModule => $aActionsList) {
+            $oModule = BxDolModule::getInstance($sModule);
+
+            $aInputs[$sModule.'_begin'] = [
+                'type' => 'block_header',
+                'caption' => BxDolModule::getTitle($oModule->_aModule['uri']),
+                'collapsed' => true,
+            ];
+
+            foreach ($aActionsList as $sAction => $bAllowedByDefault) {
+                $bChecked = false;
+                // if pemission is not set explicitly then consider the default value
+                if ((empty($aRole) || !is_array($aRole['Data']) || !isset($aRole['Data'][$sModule])) && $bAllowedByDefault) $bChecked = true;
+
+                // if pemission is set explicitly then use the value set
+                if (!empty($aRole) && is_array($aRole['Data']) && isset($aRole['Data'][$sModule]) && isset($aRole['Data'][$sModule][$sAction]) && $aRole['Data'][$sModule][$sAction]) $bChecked = true;
+
+                $aInputs[$sModule.'_'.$sAction] = [
+                    'type' => 'switcher',
+                    'name' => "Data[{$sModule}][{$sAction}]",
+                    'caption' => _t('_adm_form_txt_groups_role_'.$sAction),
+                    'value' => 1,
+                    'checked' => $bChecked,
+                ];
+            }
+        }
+
+        $aInputs['end'] = [
+            'type' => 'block_end',
+        ];
+
+        $aInputs['controls'] = [
+            'name' => 'controls',
+            'type' => 'input_set',
+            [
+                'type' => 'submit',
+                'name' => 'do_submit',
+                'value' => _t('_adm_form_btn_labels_submit'),
+            ],
+            [
+                'type' => 'reset',
+                'name' => 'close',
+                'value' => _t('_adm_form_btn_labels_cancel'),
+                'attrs' => [
+                    'onclick' => "$('.bx-popup-applied:visible').dolPopupHide()",
+                    'class' => 'bx-def-margin-sec-left',
+                ],
+            ]
+        ];
+
+        $aForm = array(
+            'form_attrs' => array(
+                'id' => 'adm-form-groups-role-edit',
+                'action' => BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&module=' . $this->sModule . '&a=' . $sFormAction,
+                'method' => BX_DOL_STUDIO_METHOD_DEFAULT
+            ),
+            'params' => array (
+                'db' => array(
+                    'table' => 'sys_form_pre_values',
+                    'key' => 'id',
+                    'uri' => '',
+                    'uri_title' => '',
+                    'submit_name' => 'do_submit'
+                ),
+            ),
+            'inputs' => $aInputs
+        );
+        return new BxTemplStudioFormView($aForm);
+    }
+
+    protected function _getCellActionsList($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mPermissions = $aRow['Data'] ? unserialize($aRow['Data']) : false;
+        $aDefaultActionsByModules = $this->_getDefaultActionsArray($aRow['Value']);
+
+        $iAllowedPermissions = 0;
+        foreach ($aDefaultActionsByModules as $sModule => $aDefaultActions) {
+            foreach ($aDefaultActions as $sAction => $bAllowedByDefault) {
+                // if pemission is not set explicitly then consider the default value
+                if ((!is_array($mPermissions) || !isset($mPermissions[$sModule])) && $bAllowedByDefault) $iAllowedPermissions++;
+
+                // if pemission is set explicitly then use the value set
+                if (is_array($mPermissions) && isset($mPermissions[$sModule]) && isset($mPermissions[$sModule][$sAction]) && $mPermissions[$sModule][$sAction]) $iAllowedPermissions++;
+            }
+        }
+
+        $sLink = 'javascript: glGrids.'.$this->_sObject.'.action(\'edit\', {id: '.$aRow['id'].'});';
+        $mixedValue = $this->_oTemplate->parseLink($sLink, _t('_adm_prm_txt_n_actions', $iAllowedPermissions), array(
+            'title' => _t('_adm_prm_txt_manage_actions')
+        ));
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+        $this->_oTemplate->addJs(array('jquery.form.min.js', 'forms_groups_roles.js'));
+
+        $oForm = new BxTemplStudioFormView(array());
+        $oForm->addCssJs();
+    }
+    
+    protected function canAdd()
+    {
+        return $this->sModule != '';
+    }
+    
+    protected function _getActionAdd($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if(!$this->canAdd())
+            $isDisabled = true;
+
+        return parent::_getActionDefault($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+    
+    protected function _getFilterControls ()
+    {
+        parent::_getFilterControls();
+        return $this->getModulesSelectOne('', false, false);
+    }
+
+    public function getModulesSelectOneArray($sGetItemsMethod, $bShowCustom = true, $bShowSystem = true)
+    {
+        $aModules = $this->getModules($bShowCustom, $bShowSystem);
+        foreach ($aModules as $sModuleUri => $sModuleName) {
+            $oModule = BxDolModule::getInstance($sModuleUri);
+            if ($oModule) {
+                $sRolesDataList = isset($oModule->_oConfig->CNF['OBJECT_PRE_LIST_ROLES']) ? $oModule->_oConfig->CNF['OBJECT_PRE_LIST_ROLES'] : '';
+                if ($sRolesDataList) {
+                    $aRoles = BxBaseFormView::getDataItems($sRolesDataList);
+                    $aModules[$sModuleUri] = $sModuleName . ' (' . ($aRoles ? count($aRoles) : 0) . ')';
+                    continue;
+                }
+            }
+            unset($aModules[$sModuleUri]);
+        }
+
+        $aInputModules = array(
+            'type' => 'select',
+            'name' => 'module',
+            'attrs' => array(
+                'id' => 'bx-grid-module-' . $this->_sObject,
+                'onChange' => 'javascript:' . $this->getJsObject() . '.onChangeModule()'
+            ),
+            'value' => $this->sModule,
+            'values' => $aModules
+        );
+
+        return $aInputModules;
+    }
+
+    protected function _getDefaultActionsArray($iRole) {
+        $bAdminOrModerator = $iRole == BX_DOL_MOD_GROUPS_ROLE_ADMINISTRATOR || $iRole == BX_DOL_MOD_GROUPS_ROLE_MODERATOR;
+
+        $aDefaultActions = [
+            $this->sModule => [
+                'invite' => $bAdminOrModerator,
+                'manage_fans' => $bAdminOrModerator,
+                'manage_roles' => $iRole == BX_DOL_MOD_GROUPS_ROLE_ADMINISTRATOR,
+                'edit' => $iRole == BX_DOL_MOD_GROUPS_ROLE_ADMINISTRATOR,
+                'change_cover' => $iRole == BX_DOL_MOD_GROUPS_ROLE_ADMINISTRATOR,
+            ]
+        ];
+
+        $aModules = $this->getModules(false, false);
+        foreach ($aModules as $sModuleUri => $sModuleName) {
+            $oModule = BxDolModule::getInstance($sModuleUri);
+            if ($oModule) {
+                if (isset($oModule->_oConfig->CNF['FIELD_ALLOW_VIEW_TO']) && !BxDolRequest::serviceExists($sModuleUri, 'act_as_profile')) {
+                    $aDefaultActions[$sModuleUri] = [
+                        'post' => 1,
+                        'edit_any' => $bAdminOrModerator,
+                        'delete_any' => $bAdminOrModerator,
+                    ];
+                }
+            }
+        }
+
+        return $aDefaultActions;
+    }
+
+    protected function _getAvailableSetValue($sList)
+    {
+        $aValues = array();
+        $this->oDb->getValues(array('type' =>'by_key_key_value', 'value' => $sList), $aValues, false);
+        ksort($aValues);
+
+        $iValue = 1;
+        foreach($aValues as $aValue) {
+            if((int)$aValue['value'] == 0)
+                continue;
+
+            if((int)$aValue['value'] != $iValue)
+                break;
+
+            $iValue++;
+        }
+
+        return $iValue;
+    }
+
+    protected function canUseForSet($mixedValue)
+    {
+        return is_numeric($mixedValue) && (int)$mixedValue >= 1 && (int)$mixedValue <= BX_DOL_STUDIO_FIELD_PRE_VALUE_INT_MAX;
+    }
+    
+    function getJsObject()
+    {
+        return 'oBxDolStudioFormsGroupsRoles';
+    }
+    
+    function getCode($isDisplayHeader = true)
+    {
+        return $this->_oTemplate->parseHtmlByName('forms_groups_roles.html', array(
+            'content' => parent::getCode($isDisplayHeader),
+            'js_object' => $this->getJsObject(),
+            'grid_object' => $this->_sObject,
+            'params_divider' => $this->sParamsDivider
+        ));
+    }
+}
+
+/** @} */

+ 19 - 0
studio/template/scripts_templ/BxTemplStudioFormsGroupsRoles.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudioView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+defined('BX_DOL') or die('hack attempt');
+
+class BxTemplStudioFormsGroupsRoles extends BxBaseStudioFormsGroupsRoles
+{
+    function __construct($aOptions, $oTemplate = false)
+    {
+        parent::__construct($aOptions, $oTemplate);
+    }
+}
+/** @} */

+ 1 - 1
template/scripts/BxBaseServices.php

@@ -448,7 +448,7 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
     /**
      * @see iBxDolProfileService::serviceCheckAllowedPostInProfile
      */ 
-    public function serviceCheckAllowedPostInProfile($iContentId)
+    public function serviceCheckAllowedPostInProfile($iContentId, $sPostModule = '')
     {
         return _t('_Access denied');
     }