Windows group sync
This commit is contained in:
parent
4ced8c519f
commit
bb9f1f0eff
|
@ -1,7 +1,9 @@
|
||||||
December 2018 6.6
|
December 2018 6.6
|
||||||
- New import/export in tools menu
|
- New import/export in tools menu
|
||||||
- YubiKey support
|
- 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:
|
- LAM Pro:
|
||||||
-> Easy setting of background color in self service profile
|
-> Easy setting of background color in self service profile
|
||||||
-> Cron jobs: added Windows/Qmail/FreeRadius account expiration notification jobs
|
-> Cron jobs: added Windows/Qmail/FreeRadius account expiration notification jobs
|
||||||
|
|
|
@ -1186,7 +1186,7 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<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
|
<para>Please activate the account type "Users" in your LAM server
|
||||||
profile and then add the user module "Windows (windowsUser)(*)".</para>
|
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>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>
|
<screenshot>
|
||||||
<mediaobject>
|
<mediaobject>
|
||||||
<imageobject>
|
<imageobject>
|
||||||
<imagedata fileref="images/mod_windowsUser5.png"/>
|
<imagedata contentwidth="1172"
|
||||||
|
fileref="images/mod_windowsUser5.png"/>
|
||||||
</imageobject>
|
</imageobject>
|
||||||
</mediaobject>
|
</mediaobject>
|
||||||
</screenshot>
|
</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(
|
'noObjectClass' => array(
|
||||||
"Headline" => _("Do not add object class"),
|
"Headline" => _("Do not add object class"),
|
||||||
"Text" => _("This will not add the posixAccount object class to the account.")
|
"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(
|
'user' => array(
|
||||||
'uid' => array(
|
'uid' => array(
|
||||||
|
@ -1447,7 +1451,7 @@ class posixAccount extends baseModule implements passwordService {
|
||||||
* @param $allGons list of all group of names
|
* @param $allGons list of all group of names
|
||||||
* @return string cn value
|
* @return string cn value
|
||||||
*/
|
*/
|
||||||
private function getGonName($dn, &$allGons) {
|
public function getGonName($dn, &$allGons) {
|
||||||
if (!empty($allGons[$dn]['cn'][0])) {
|
if (!empty($allGons[$dn]['cn'][0])) {
|
||||||
return $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 = new htmlResponsiveInputCheckbox('posixAccount_' . $typeId . '_syncGroups', false, _('Sync groups'), null, false);
|
||||||
$syncGroupsCheckbox->setTableRowsToHide(array('posixAccount_' . $typeId . '_syncGroupsExclusions'));
|
$syncGroupsCheckbox->setTableRowsToHide(array('posixAccount_' . $typeId . '_syncGroupsExclusions'));
|
||||||
$configUserContainer->add($syncGroupsCheckbox, 12);
|
$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;
|
$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')))
|
* @return array groups array(dn => array('cn' => array('groupName'), 'objectclass' => array('top', 'groupOfNames')))
|
||||||
*/
|
*/
|
||||||
private function findGroupOfNames() {
|
public function findGroupOfNames() {
|
||||||
if ($this->gonCache != null) {
|
if ($this->gonCache != null) {
|
||||||
return $this->gonCache;
|
return $this->gonCache;
|
||||||
}
|
}
|
||||||
|
@ -3948,6 +3952,24 @@ class posixAccount extends baseModule implements passwordService {
|
||||||
return $replacements;
|
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',
|
"Headline" => _("Add photo"), 'attr' => 'jpegPhoto',
|
||||||
"Text" => _("Please select an image file to upload. It must be in JPG format (.jpg/.jpeg).")
|
"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
|
// upload fields
|
||||||
$return['upload_columns'] = array(
|
$return['upload_columns'] = array(
|
||||||
|
@ -1745,7 +1749,7 @@ class windowsUser extends baseModule implements passwordService {
|
||||||
*
|
*
|
||||||
* @return htmlElement meta HTML code
|
* @return htmlElement meta HTML code
|
||||||
*/
|
*/
|
||||||
function display_html_group() {
|
public function display_html_group() {
|
||||||
$return = new htmlTable();
|
$return = new htmlTable();
|
||||||
$groups = $this->findGroups();
|
$groups = $this->findGroups();
|
||||||
// sort by DN
|
// sort by DN
|
||||||
|
@ -1796,6 +1800,51 @@ class windowsUser extends baseModule implements passwordService {
|
||||||
$return->addElement($groupContainer);
|
$return->addElement($groupContainer);
|
||||||
$return->addNewLine();
|
$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 = new htmlGroup();
|
||||||
$backGroup->colspan = 10;
|
$backGroup->colspan = 10;
|
||||||
$backGroup->addElement(new htmlSpacer(null, '10px'), true);
|
$backGroup->addElement(new htmlSpacer(null, '10px'), true);
|
||||||
|
@ -1811,7 +1860,7 @@ class windowsUser extends baseModule implements passwordService {
|
||||||
*
|
*
|
||||||
* @return array list of info/error messages
|
* @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
|
if (isset($_POST['addgroups']) && isset($_POST['addgroups_button'])) { // Add groups to list
|
||||||
// add new group
|
// add new group
|
||||||
$this->groupList = @array_merge($this->groupList, $_POST['addgroups']);
|
$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
|
elseif (isset($_POST['removegroups']) && isset($_POST['removegroups_button'])) { // remove groups from list
|
||||||
$this->groupList = array_delete($_POST['removegroups'], $this->groupList);
|
$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();
|
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.
|
* Displays the photo upload page.
|
||||||
*
|
*
|
||||||
|
@ -3413,6 +3571,7 @@ class windowsUser extends baseModule implements passwordService {
|
||||||
* @see baseModule::get_configOptions()
|
* @see baseModule::get_configOptions()
|
||||||
*/
|
*/
|
||||||
public function get_configOptions($scopes, $allScopes) {
|
public function get_configOptions($scopes, $allScopes) {
|
||||||
|
$typeManager = new TypeManager($_SESSION['conf_config']);
|
||||||
// configuration options
|
// configuration options
|
||||||
$configContainer = new htmlResponsiveRow();
|
$configContainer = new htmlResponsiveRow();
|
||||||
$configContainer->add(new htmlResponsiveInputTextarea('windowsUser_domains', '', 30, 3, _('Domains'), 'domains'), 12);
|
$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_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_hideo', true, _('Organisation'), null, true), 12, 4);
|
||||||
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidemanager', true, _('Manager'), null, true), 12, 4);
|
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidemanager', true, _('Manager'), null, true), 12, 4);
|
||||||
for ($i = 0; $i < 1; $i++) {
|
$syncTypes = $typeManager->getConfiguredTypesForScopes(array('group', 'gon', 'user'));
|
||||||
$configContainer->add(new htmlOutputText(''), 0, 4);
|
$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 = new htmlResponsiveRow();
|
||||||
$advancedOptions->add(new htmlSubTitle(_('Photo')), 12);
|
$advancedOptions->add(new htmlSubTitle(_('Photo')), 12);
|
||||||
|
|
Loading…
Reference in New Issue