Windows group sync
This commit is contained in:
parent
4ced8c519f
commit
bb9f1f0eff
|
@ -1,7 +1,9 @@
|
|||
December 2018 6.6
|
||||
- New import/export in tools menu
|
||||
- YubiKey support
|
||||
- Windows users: manage "departmentNumber" (needs to be activated via LAM server profile)
|
||||
- Windows users:
|
||||
-> Manage "departmentNumber" (needs to be activated via LAM server profile)
|
||||
-> Sync group memberships from Unix and group of names
|
||||
- LAM Pro:
|
||||
-> Easy setting of background color in self service profile
|
||||
-> Cron jobs: added Windows/Qmail/FreeRadius account expiration notification jobs
|
||||
|
|
|
@ -1186,7 +1186,7 @@
|
|||
</section>
|
||||
|
||||
<section>
|
||||
<title>Windows (Samba 4)</title>
|
||||
<title>Windows (Samba 4/Active Directory)</title>
|
||||
|
||||
<para>Please activate the account type "Users" in your LAM server
|
||||
profile and then add the user module "Windows (windowsUser)(*)".</para>
|
||||
|
@ -1218,10 +1218,14 @@
|
|||
|
||||
<para>NIS support is deactivated by default. Enable it if needed.</para>
|
||||
|
||||
<para>You can also set maximum values for user photos in advanced
|
||||
options.</para>
|
||||
|
||||
<screenshot>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/mod_windowsUser5.png"/>
|
||||
<imagedata contentwidth="1172"
|
||||
fileref="images/mod_windowsUser5.png"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 95 KiB |
|
@ -408,6 +408,10 @@ class posixAccount extends baseModule implements passwordService {
|
|||
'noObjectClass' => array(
|
||||
"Headline" => _("Do not add object class"),
|
||||
"Text" => _("This will not add the posixAccount object class to the account.")
|
||||
),
|
||||
'excludeFromGroupSync' => array (
|
||||
"Headline" => _('Exclude from group sync'),
|
||||
"Text" => _('Enter one group per line that should be ignored when syncing groups.')
|
||||
),
|
||||
'user' => array(
|
||||
'uid' => array(
|
||||
|
@ -1447,7 +1451,7 @@ class posixAccount extends baseModule implements passwordService {
|
|||
* @param $allGons list of all group of names
|
||||
* @return string cn value
|
||||
*/
|
||||
private function getGonName($dn, &$allGons) {
|
||||
public function getGonName($dn, &$allGons) {
|
||||
if (!empty($allGons[$dn]['cn'][0])) {
|
||||
return $allGons[$dn]['cn'][0];
|
||||
}
|
||||
|
@ -2249,7 +2253,7 @@ class posixAccount extends baseModule implements passwordService {
|
|||
$syncGroupsCheckbox = new htmlResponsiveInputCheckbox('posixAccount_' . $typeId . '_syncGroups', false, _('Sync groups'), null, false);
|
||||
$syncGroupsCheckbox->setTableRowsToHide(array('posixAccount_' . $typeId . '_syncGroupsExclusions'));
|
||||
$configUserContainer->add($syncGroupsCheckbox, 12);
|
||||
$configUserContainer->add(new htmlResponsiveInputTextarea('posixAccount_' . $typeId . '_syncGroupsExclusions', '', 20, 4, _('Exclude from group sync')), 12);
|
||||
$configUserContainer->add(new htmlResponsiveInputTextarea('posixAccount_' . $typeId . '_syncGroupsExclusions', '', 20, 4, _('Exclude from group sync'), 'excludeFromGroupSync'), 12);
|
||||
}
|
||||
}
|
||||
$return[] = $configUserContainer;
|
||||
|
@ -3485,7 +3489,7 @@ class posixAccount extends baseModule implements passwordService {
|
|||
*
|
||||
* @return array groups array(dn => array('cn' => array('groupName'), 'objectclass' => array('top', 'groupOfNames')))
|
||||
*/
|
||||
private function findGroupOfNames() {
|
||||
public function findGroupOfNames() {
|
||||
if ($this->gonCache != null) {
|
||||
return $this->gonCache;
|
||||
}
|
||||
|
@ -3948,6 +3952,24 @@ class posixAccount extends baseModule implements passwordService {
|
|||
return $replacements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current group names.
|
||||
*
|
||||
* @return string[] group names
|
||||
*/
|
||||
public function getGroups() {
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of group of names where this user is member.
|
||||
*
|
||||
* @return string[] list of DNs
|
||||
*/
|
||||
public function getGroupOfNames() {
|
||||
return $this->gonList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -400,6 +400,10 @@ class windowsUser extends baseModule implements passwordService {
|
|||
"Headline" => _("Add photo"), 'attr' => 'jpegPhoto',
|
||||
"Text" => _("Please select an image file to upload. It must be in JPG format (.jpg/.jpeg).")
|
||||
),
|
||||
'excludeFromGroupSync' => array (
|
||||
"Headline" => _('Exclude from group sync'),
|
||||
"Text" => _('Enter one group per line that should be ignored when syncing groups.')
|
||||
),
|
||||
);
|
||||
// upload fields
|
||||
$return['upload_columns'] = array(
|
||||
|
@ -1745,7 +1749,7 @@ class windowsUser extends baseModule implements passwordService {
|
|||
*
|
||||
* @return htmlElement meta HTML code
|
||||
*/
|
||||
function display_html_group() {
|
||||
public function display_html_group() {
|
||||
$return = new htmlTable();
|
||||
$groups = $this->findGroups();
|
||||
// sort by DN
|
||||
|
@ -1796,6 +1800,51 @@ class windowsUser extends baseModule implements passwordService {
|
|||
$return->addElement($groupContainer);
|
||||
$return->addNewLine();
|
||||
|
||||
// sync options
|
||||
$typeManager = new TypeManager();
|
||||
$syncTypes = $typeManager->getConfiguredTypesForScopes(array('group', 'gon', 'user'));
|
||||
$syncActive = false;
|
||||
$syncUnixActive = false;
|
||||
$syncGonActive = false;
|
||||
$possibleGonSyncModules = array('groupOfNames', 'groupOfMembers', 'groupOfUniqueNames');
|
||||
foreach ($syncTypes as $syncType) {
|
||||
$modules = $syncType->getModules();
|
||||
foreach ($possibleGonSyncModules as $possibleModule) {
|
||||
if (in_array($possibleModule, $modules)) {
|
||||
$syncActive = true;
|
||||
$syncGonActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in_array('posixAccount', $this->getAccountContainer()->get_type()->getModules())) {
|
||||
$syncActive = true;
|
||||
$syncUnixActive = true;
|
||||
}
|
||||
$syncActive = $syncActive && !$this->isBooleanConfigOptionSet('windowsUser_syncGroups');
|
||||
if ($syncActive) {
|
||||
$return->addElement(new htmlSubTitle(_('Sync groups')), true);
|
||||
$syncOptionTable = new htmlTable();
|
||||
$syncOptionTable->addElement(new htmlTableExtendedInputCheckbox('syncDeleteGroups', true, _('Delete non-matching entries')), true);
|
||||
$return->addElement($syncOptionTable, true);
|
||||
$return->addVerticalSpace('1rem');
|
||||
$syncButtons = new htmlGroup();
|
||||
if ($syncUnixActive) {
|
||||
$u2wButton = new htmlAccountPageButton(get_class($this), 'group', 'syncU2W', _('Sync Unix to Windows'));
|
||||
$u2wButton->setIconClass('unixButton');
|
||||
$syncButtons->addElement($u2wButton);
|
||||
$syncButtons->addElement(new htmlSpacer('2rem', null));
|
||||
}
|
||||
if ($syncGonActive) {
|
||||
$g2wButton = new htmlAccountPageButton(get_class($this), 'group', 'syncG2W', _('Sync group of names to Windows'));
|
||||
$g2wButton->setIconClass('groupButton');
|
||||
$syncButtons->addElement($g2wButton);
|
||||
$syncButtons->addElement(new htmlSpacer('2rem', null));
|
||||
}
|
||||
$return->addElement($syncButtons, true);
|
||||
$return->addElement(new htmlSpacer(null, '2rem'), true);
|
||||
}
|
||||
|
||||
$backGroup = new htmlGroup();
|
||||
$backGroup->colspan = 10;
|
||||
$backGroup->addElement(new htmlSpacer(null, '10px'), true);
|
||||
|
@ -1811,7 +1860,7 @@ class windowsUser extends baseModule implements passwordService {
|
|||
*
|
||||
* @return array list of info/error messages
|
||||
*/
|
||||
function process_group() {
|
||||
public function process_group() {
|
||||
if (isset($_POST['addgroups']) && isset($_POST['addgroups_button'])) { // Add groups to list
|
||||
// add new group
|
||||
$this->groupList = @array_merge($this->groupList, $_POST['addgroups']);
|
||||
|
@ -1819,9 +1868,118 @@ class windowsUser extends baseModule implements passwordService {
|
|||
elseif (isset($_POST['removegroups']) && isset($_POST['removegroups_button'])) { // remove groups from list
|
||||
$this->groupList = array_delete($_POST['removegroups'], $this->groupList);
|
||||
}
|
||||
// sync Unix to Windows
|
||||
if (isset($_POST['form_subpage_windowsUser_group_syncU2W'])) {
|
||||
$this->manualSyncUnixToWindows();
|
||||
}
|
||||
// sync group of names to Windows
|
||||
if (isset($_POST['form_subpage_windowsUser_group_syncG2W'])) {
|
||||
$this->manualSyncGonToWindows();
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the Unix groups to Windows.
|
||||
*/
|
||||
private function manualSyncUnixToWindows() {
|
||||
$windowsGroups = $this->getGroupList();
|
||||
$unixGroups = $this->getAccountContainer()->getAccountModule('posixAccount')->getGroups();
|
||||
$allWindowsGroups = searchLDAPByAttribute('cn', '*', 'group', array('cn'), array('group'));
|
||||
$dnToCn = array();
|
||||
foreach ($allWindowsGroups as $windowsGroup) {
|
||||
$dnToCn[$windowsGroup['dn']] = $windowsGroup['cn'][0];
|
||||
}
|
||||
$cnToDn = array_flip($dnToCn);
|
||||
$currentGroupNames = array();
|
||||
foreach ($windowsGroups as $windowsGroup) {
|
||||
$currentGroupNames[] = $dnToCn[$windowsGroup];
|
||||
}
|
||||
$deleteNonMatching = isset($_POST['syncDeleteGroups']) && ($_POST['syncDeleteGroups'] == 'on');
|
||||
$namesToIgnore = array();
|
||||
if (!empty($this->moduleSettings['windowsUser_syncGroupsExclusions'])) {
|
||||
$namesToIgnore = $this->moduleSettings['windowsUser_syncGroupsExclusions'];
|
||||
array_map('trim', $namesToIgnore);
|
||||
}
|
||||
foreach ($unixGroups as $unixGroup) {
|
||||
if (in_array($unixGroup, $namesToIgnore)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($unixGroup, $currentGroupNames) && isset($cnToDn[$unixGroup])) {
|
||||
$windowsGroups[] = $cnToDn[$unixGroup];
|
||||
}
|
||||
}
|
||||
if ($deleteNonMatching) {
|
||||
foreach ($currentGroupNames as $currentGroupName) {
|
||||
if (in_array($currentGroupName, $namesToIgnore)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($currentGroupName, $unixGroups)) {
|
||||
foreach ($windowsGroups as $windowsGroup) {
|
||||
if ($dnToCn[$windowsGroup] == $currentGroupName) {
|
||||
$windowsGroups = array_delete(array($windowsGroup), $windowsGroups);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->groupList = $windowsGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the group of names to Windows.
|
||||
*/
|
||||
private function manualSyncGonToWindows() {
|
||||
$windowsGroups = $this->getGroupList();
|
||||
$gonGroupDns = $this->getAccountContainer()->getAccountModule('posixAccount')->getGroupOfNames();
|
||||
$allGons = $this->getAccountContainer()->getAccountModule('posixAccount')->findGroupOfNames();
|
||||
$gonGroups = array();
|
||||
foreach ($gonGroupDns as $gonGroupDn) {
|
||||
$gonGroups[] = $this->getAccountContainer()->getAccountModule('posixAccount')->getGonName($gonGroupDn, $allGons);
|
||||
}
|
||||
$allWindowsGroups = searchLDAPByAttribute('cn', '*', 'group', array('cn'), array('group'));
|
||||
$dnToCn = array();
|
||||
foreach ($allWindowsGroups as $windowsGroup) {
|
||||
$dnToCn[$windowsGroup['dn']] = $windowsGroup['cn'][0];
|
||||
}
|
||||
$cnToDn = array_flip($dnToCn);
|
||||
$currentGroupNames = array();
|
||||
foreach ($windowsGroups as $windowsGroup) {
|
||||
$currentGroupNames[] = $dnToCn[$windowsGroup];
|
||||
}
|
||||
$deleteNonMatching = isset($_POST['syncDeleteGroups']) && ($_POST['syncDeleteGroups'] == 'on');
|
||||
$namesToIgnore = array();
|
||||
if (!empty($this->moduleSettings['windowsUser_syncGroupsExclusions'])) {
|
||||
$namesToIgnore = $this->moduleSettings['windowsUser_syncGroupsExclusions'];
|
||||
array_map('trim', $namesToIgnore);
|
||||
}
|
||||
foreach ($gonGroups as $gonGroup) {
|
||||
if (in_array($gonGroup, $namesToIgnore)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($gonGroup, $currentGroupNames) && isset($cnToDn[$gonGroup])) {
|
||||
$windowsGroups[] = $cnToDn[$gonGroup];
|
||||
}
|
||||
}
|
||||
if ($deleteNonMatching) {
|
||||
foreach ($currentGroupNames as $currentGroupName) {
|
||||
if (in_array($currentGroupName, $namesToIgnore)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($currentGroupName, $gonGroups)) {
|
||||
foreach ($windowsGroups as $windowsGroup) {
|
||||
if ($dnToCn[$windowsGroup] == $currentGroupName) {
|
||||
$windowsGroups = array_delete(array($windowsGroup), $windowsGroups);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->groupList = $windowsGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the photo upload page.
|
||||
*
|
||||
|
@ -3413,6 +3571,7 @@ class windowsUser extends baseModule implements passwordService {
|
|||
* @see baseModule::get_configOptions()
|
||||
*/
|
||||
public function get_configOptions($scopes, $allScopes) {
|
||||
$typeManager = new TypeManager($_SESSION['conf_config']);
|
||||
// configuration options
|
||||
$configContainer = new htmlResponsiveRow();
|
||||
$configContainer->add(new htmlResponsiveInputTextarea('windowsUser_domains', '', 30, 3, _('Domains'), 'domains'), 12);
|
||||
|
@ -3443,8 +3602,24 @@ class windowsUser extends baseModule implements passwordService {
|
|||
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hideou', true, _('Organisational unit'), null, true), 12, 4);
|
||||
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hideo', true, _('Organisation'), null, true), 12, 4);
|
||||
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidemanager', true, _('Manager'), null, true), 12, 4);
|
||||
for ($i = 0; $i < 1; $i++) {
|
||||
$configContainer->add(new htmlOutputText(''), 0, 4);
|
||||
$syncTypes = $typeManager->getConfiguredTypesForScopes(array('group', 'gon', 'user'));
|
||||
$syncActive = false;
|
||||
$possibleSyncModules = array('groupOfNames', 'groupOfMembers', 'groupOfUniqueNames', 'posixAccount');
|
||||
foreach ($syncTypes as $syncType) {
|
||||
$modules = $syncType->getModules();
|
||||
foreach ($possibleSyncModules as $possibleModule) {
|
||||
if (in_array($possibleModule, $modules)) {
|
||||
$syncActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($syncActive) {
|
||||
$syncGroupsCheckbox = new htmlResponsiveInputCheckbox('windowsUser_syncGroups', false, _('Sync groups'), null, true);
|
||||
$syncGroupsCheckbox->setTableRowsToHide(array('windowsUser_syncGroupsExclusions'));
|
||||
$configContainer->add($syncGroupsCheckbox, 12, 4);
|
||||
$configContainer->addVerticalSpacer('2rem');
|
||||
$configContainer->add(new htmlResponsiveInputTextarea('windowsUser_syncGroupsExclusions', '', 20, 4, _('Exclude from group sync'), 'excludeFromGroupSync'), 12);
|
||||
}
|
||||
$advancedOptions = new htmlResponsiveRow();
|
||||
$advancedOptions->add(new htmlSubTitle(_('Photo')), 12);
|
||||
|
|
Loading…
Reference in New Issue