diff --git a/_build/config.json b/_build/config.json index 5690cab..2159cd5 100644 --- a/_build/config.json +++ b/_build/config.json @@ -573,6 +573,15 @@ "description": "prop_register.usergroupsfield_desc", "value": "" }, + { + "name": "usergroupsFieldDisallow", + "description": "prop_register.usergroupsfielddisallow_desc", + "value": "Administrator" + }, + { + "name": "usergroupsFieldAllow", + "description": "prop_register.usergroupsfieldallow_desc" + }, { "name": "submittedResourceId", "description": "prop_register.submittedresourceid_desc", diff --git a/core/components/login/lexicon/en/properties.inc.php b/core/components/login/lexicon/en/properties.inc.php index 0c9fdc3..5fc03f6 100644 --- a/core/components/login/lexicon/en/properties.inc.php +++ b/core/components/login/lexicon/en/properties.inc.php @@ -69,6 +69,8 @@ $_lang['prop_register.submitvar_desc'] = 'The var to check for to load the Register functionality. If empty or set to false, Register will process the form on all POST requests.'; $_lang['prop_register.usergroups_desc'] = 'Optional. A comma-separated list of User Group names or IDs to add the newly-registered User to.'; $_lang['prop_register.usergroupsfield_desc'] = 'The name of the field to use to specify the User Group(s) to automatically add the new User to. Only used if this value is not blank.'; +$_lang['prop_register.usergroupsfielddisallow_desc'] = 'Optional. A comma-separated list of User Group names or IDs to prevent the newly-registered User from being added to. Only used if this value is not blank.'; +$_lang['prop_register.usergroupsfieldallow_desc'] = 'Optional. A comma-separated allowlist of User Group names or IDs the newly-registered User can be added to. Only used if this value is not blank.'; $_lang['prop_register.submittedresourceid_desc'] = 'If set, will redirect to the specified Resource after the User submits the registration form.'; $_lang['prop_register.usernamefield_desc'] = 'The name of the field to use for the new User’s username.'; $_lang['prop_register.passwordfield_desc'] = 'The name of the field to use for the new User’s password.'; diff --git a/core/components/login/processors/register.php b/core/components/login/processors/register.php index 484f518..bdcc292 100644 --- a/core/components/login/processors/register.php +++ b/core/components/login/processors/register.php @@ -166,7 +166,9 @@ public function setUserFields() { /* add user groups, if set */ $userGroupsField = $this->controller->getProperty('usergroupsField',''); $userGroups = !empty($userGroupsField) && array_key_exists($userGroupsField,$fields) ? $fields[$userGroupsField] : array(); - $this->setUserGroups($userGroups); + $userGroupsFieldDisallow = $this->controller->getProperty('usergroupsFieldDisallow','Administrator'); + $userGroupsFieldAllow = $this->controller->getProperty('usergroupsFieldAllow',''); + $this->setUserGroups($userGroups, $userGroupsFieldDisallow, $userGroupsFieldAllow); } /** @@ -198,12 +200,16 @@ public function filterAllowedFields(array $fields = array()) { * @param string $userGroups * @return array */ - public function setUserGroups($userGroups) { + public function setUserGroups($userGroups, $userGroupsFieldDisallow = 'Administrator', $userGroupsFieldAllow = '') { $added = array(); /* if $userGroups set in form, override here; otherwise use snippet property */ $this->userGroups = !empty($userGroups) ? $userGroups : $this->controller->getProperty('usergroups', ''); if (!empty($this->userGroups)) { $this->userGroups = is_array($this->userGroups) ? $this->userGroups : explode(',',$this->userGroups); + $disallowed = $this->getUserGroups($userGroupsFieldDisallow); + $disallowedKeys = array_keys($disallowed); + $allowed = $this->getUserGroups($userGroupsFieldAllow); + $allowedKeys = array_keys($allowed); foreach ($this->userGroups as $userGroupMeta) { $userGroupMeta = explode(':',$userGroupMeta); @@ -221,6 +227,37 @@ public function setUserGroups($userGroups) { /** @var modUserGroupRole $role */ $role = $this->modx->getObject('modUserGroupRole',array('name' => $rolePk)); + /* check if role is disallowed */ + if (in_array($userGroup->get('name'), $disallowedKeys, true) || + in_array($userGroup->get('id'), $disallowedKeys, true)) { + $disallowedKey = in_array($userGroup->get('name'), $disallowedKeys, true) ? + $userGroup->get('name') : $userGroup->get('id'); + $disallowedRank = $disallowed[$disallowedKey]; + if ($disallowedRank) { + if ($role && ($role->get('rank') < $disallowedRank)) { + continue; + } + } else { + continue; + } + } + + if (!empty($allowedKeys)) { + if (!in_array($userGroup->get('name'), $allowedKeys, true) && + !in_array($userGroup->get('id'), $allowedKeys, true)) { + continue; + } + $allowKey = in_array($userGroup->get('name'), $allowedKeys, true) ? + $userGroup->get('name') : $userGroup->get('id'); + $allowRank = $allowed[$allowKey]; + if ($allowRank) { + if ($role && ($role->get('rank') < $allowRank)) { + continue; + } + } + } + + /* create membership */ /** @var modUserGroupMember $member */ $member = $this->modx->newObject('modUserGroupMember'); @@ -444,5 +481,28 @@ public function autoLogin() { return true; } + + private function getUserGroups($userGroupsFieldDisallow): array + { + $userGroupsDisallowed = array(); + $userGroupsFieldDisallow = is_array($userGroupsFieldDisallow) ? + $userGroupsFieldDisallow : explode(',',$userGroupsFieldDisallow); + foreach ($userGroupsFieldDisallow as $userGroupDisallow) { + $groupRole = explode(':',$userGroupDisallow); + $rank = 0; + if (empty($groupRole[0])) continue; + if (isset($groupRole[1]) && !empty($groupRole[1])) { + $role_pk = (int) $groupRole[1] > 0 ? ['id' => (int) $groupRole[1]] : ['name' => $groupRole[1]]; + $role = $this->modx->getObject('modUserGroupRole', $role_pk); + if ($role) { + $rank = $role->get('rank'); + } else if ((int) $groupRole[1] > 0) { + $rank = (int) $groupRole[1]; + } + } + $userGroupsDisallowed[$groupRole[0]] = $rank; + } + return $userGroupsDisallowed; + } } return 'LoginRegisterProcessor';