DocSpace-buildtools/common/ASC.ActiveDirectory/ComplexOperations/LdapSaveSyncOperation.cs
Vashchuk Nikita 9c5f0d5fd9 fix
2022-03-15 11:11:39 +03:00

1031 lines
40 KiB
C#

/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using ASC.ActiveDirectory.Base.Settings;
using ASC.ActiveDirectory.ComplexOperations.Data;
using ASC.ActiveDirectory.Novell.Exceptions;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Web.Core;
using ASC.Web.Core.Users;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
// ReSharper disable RedundantToStringCall
namespace ASC.ActiveDirectory.ComplexOperations
{
[Scope]
public class LdapSaveSyncOperation : LdapOperation
{
private LdapChangeCollection _ldapChanges;
private UserInfo _currentUser;
private UserFormatter _userFormatter;
private SettingsManager _settingsManager;
private UserPhotoManager _userPhotoManager;
private WebItemSecurity _webItemSecurity;
private UserManager _userManager;
private DisplayUserSettingsHelper _displayUserSettingsHelper;
private TenantManager _tenantManager;
private readonly IServiceProvider _serviceProvider;
public LdapSaveSyncOperation(
IServiceProvider serviceProvider,
IOptionsMonitor<ILog> options)
: base(serviceProvider, options)
{
_serviceProvider = serviceProvider;
}
public void Init(
LdapSettings settings,
Tenant tenant,
LdapOperationType operation,
LdapLocalization resource = null,
string userId = null)
{
using var scope = _serviceProvider.CreateScope();
var userManager = _serviceProvider.GetService<UserManager>();
_currentUser = userId != null ? userManager.GetUsers(Guid.Parse(userId)) : null;
base.Init(settings, tenant, operation, resource);
}
protected override void Do()
{
using var scope = _serviceProvider.CreateScope();
_ldapChanges = scope.ServiceProvider.GetService<LdapChangeCollection>();
_ldapChanges.Tenant = CurrentTenant;
_userFormatter = scope.ServiceProvider.GetService<UserFormatter>();
_settingsManager = scope.ServiceProvider.GetService<SettingsManager>();
_userPhotoManager = scope.ServiceProvider.GetService<UserPhotoManager>();
_webItemSecurity = scope.ServiceProvider.GetService<WebItemSecurity>();
_userManager = scope.ServiceProvider.GetService<UserManager>();
_displayUserSettingsHelper = scope.ServiceProvider.GetService<DisplayUserSettingsHelper>();
_tenantManager = scope.ServiceProvider.GetService<TenantManager>();
try
{
if (OperationType == LdapOperationType.Save)
{
SetProgress(10, Resource.LdapSettingsStatusSavingSettings);
LDAPSettings.IsDefault = LDAPSettings.Equals(LDAPSettings.GetDefault(_serviceProvider));
if (!_settingsManager.Save(LDAPSettings))
{
Logger.Error("Can't save LDAP settings.");
Error = Resource.LdapSettingsErrorCantSaveLdapSettings;
return;
}
}
if (LDAPSettings.EnableLdapAuthentication)
{
if (Logger.IsDebugEnabled)
{
var sb = new StringBuilder();
sb.AppendLine("SyncLDAP()");
sb.AppendLine(string.Format("Server: {0}:{1}", LDAPSettings.Server, LDAPSettings.PortNumber));
sb.AppendLine("UserDN: " + LDAPSettings.UserDN);
sb.AppendLine("LoginAttr: " + LDAPSettings.LoginAttribute);
sb.AppendLine("UserFilter: " + LDAPSettings.UserFilter);
sb.AppendLine("Groups: " + LDAPSettings.GroupMembership);
if (LDAPSettings.GroupMembership)
{
sb.AppendLine("GroupDN: " + LDAPSettings.GroupDN);
sb.AppendLine("UserAttr: " + LDAPSettings.UserAttribute);
sb.AppendLine("GroupFilter: " + LDAPSettings.GroupFilter);
sb.AppendLine("GroupName: " + LDAPSettings.GroupNameAttribute);
sb.AppendLine("GroupMember: " + LDAPSettings.GroupAttribute);
}
Logger.Debug(sb.ToString());
}
SyncLDAP();
if (!string.IsNullOrEmpty(Error))
return;
}
else
{
Logger.Debug("TurnOffLDAP()");
TurnOffLDAP();
var ldapCurrentUserPhotos = _settingsManager.Load<LdapCurrentUserPhotos>().GetDefault(_serviceProvider);
_settingsManager.Save(ldapCurrentUserPhotos);
var ldapCurrentAcccessSettings = _settingsManager.Load<LdapCurrentAcccessSettings>().GetDefault(_serviceProvider);
_settingsManager.Save(ldapCurrentAcccessSettings);
//не снимать права при выключении
//var rights = new List<LdapSettings.AccessRight>();
//TakeUsersRights(rights);
//if (rights.Count > 0)
//{
// Warning = Resource.LdapSettingsErrorLostRights;
//}
}
}
catch (NovellLdapTlsCertificateRequestedException ex)
{
Logger.ErrorFormat(
"CheckSettings(acceptCertificate={0}, cert thumbprint: {1}): NovellLdapTlsCertificateRequestedException: {2}",
LDAPSettings.AcceptCertificate, LDAPSettings.AcceptCertificateHash, ex.ToString());
Error = Resource.LdapSettingsStatusCertificateVerification;
//TaskInfo.SetProperty(CERT_REQUEST, ex.CertificateConfirmRequest);
}
catch (TenantQuotaException e)
{
Logger.ErrorFormat("TenantQuotaException. {0}", e.ToString());
Error = Resource.LdapSettingsTenantQuotaSettled;
}
catch (FormatException e)
{
Logger.ErrorFormat("FormatException error. {0}", e.ToString());
Error = Resource.LdapSettingsErrorCantCreateUsers;
}
catch (Exception e)
{
Logger.ErrorFormat("Internal server error. {0}", e.ToString());
Error = Resource.LdapSettingsInternalServerError;
}
finally
{
SetProgress(99, Resource.LdapSettingsStatusDisconnecting, "");
}
SetProgress(100, OperationType == LdapOperationType.SaveTest ||
OperationType == LdapOperationType.SyncTest
? JsonSerializer.Serialize(_ldapChanges)
: "", "");
}
private void TurnOffLDAP()
{
const double percents = 48;
SetProgress((int)percents, Resource.LdapSettingsModifyLdapUsers);
var existingLDAPUsers = _userManager.GetUsers(EmployeeStatus.All).Where(u => u.Sid != null).ToList();
var step = percents / existingLDAPUsers.Count;
var percentage = (double)GetProgress();
var index = 0;
var count = existingLDAPUsers.Count;
foreach (var existingLDAPUser in existingLDAPUsers)
{
SetProgress(Convert.ToInt32(percentage),
currentSource:
string.Format("({0}/{1}): {2}", ++index, count,
_userFormatter.GetUserName(existingLDAPUser, DisplayUserNameFormat.Default)));
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
existingLDAPUser.Sid = null;
existingLDAPUser.ConvertExternalContactsToOrdinary();
Logger.DebugFormat("CoreContext.UserManager.SaveUserInfo({0})", existingLDAPUser.GetUserInfoString());
_userManager.SaveUserInfo(existingLDAPUser);
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
_ldapChanges.SetSaveAsPortalUserChange(existingLDAPUser);
break;
default:
throw new ArgumentOutOfRangeException();
}
percentage += step;
}
}
private void SyncLDAP()
{
var t = TenantManager.GetCurrentTenant();
var currentDomainSettings = _settingsManager.Load<LdapCurrentDomain>();
if (string.IsNullOrEmpty(currentDomainSettings.CurrentDomain) || currentDomainSettings.CurrentDomain != Importer.LDAPDomain)
{
currentDomainSettings.CurrentDomain = Importer.LDAPDomain;
_settingsManager.Save(currentDomainSettings);
}
if (!LDAPSettings.GroupMembership)
{
Logger.Debug("SyncLDAPUsers()");
SyncLDAPUsers();
}
else
{
Logger.Debug("SyncLDAPUsersInGroups()");
SyncLDAPUsersInGroups();
}
SyncLdapAvatar();
SyncLdapAccessRights();
}
private void SyncLdapAvatar()
{
SetProgress(90, Resource.LdapSettingsStatusUpdatingUserPhotos);
if (!LDAPSettings.LdapMapping.ContainsKey(LdapSettings.MappingFields.AvatarAttribute))
{
var ph = _settingsManager.Load<LdapCurrentUserPhotos>();
if (ph.CurrentPhotos == null || !ph.CurrentPhotos.Any())
{
return;
}
foreach (var guid in ph.CurrentPhotos.Keys)
{
Logger.InfoFormat("SyncLdapAvatar() Removing photo for '{0}'", guid);
_userPhotoManager.RemovePhoto(guid);
_userPhotoManager.ResetThumbnailSettings(guid);
}
ph.CurrentPhotos = null;
_settingsManager.Save(ph);
return;
}
var photoSettings = _settingsManager.Load<LdapCurrentUserPhotos>();
if (photoSettings.CurrentPhotos == null)
{
photoSettings.CurrentPhotos = new Dictionary<Guid, string>();
}
var ldapUsers = Importer.AllDomainUsers.Where(x => !x.IsDisabled);
var step = 5.0 / ldapUsers.Count();
var currentPercent = 90.0;
foreach (var ldapUser in ldapUsers)
{
var image = ldapUser.GetValue(LDAPSettings.LdapMapping[LdapSettings.MappingFields.AvatarAttribute], true);
if (image == null || image.GetType() != typeof(byte[]))
{
continue;
}
string hash;
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
hash = Convert.ToBase64String(md5.ComputeHash((byte[])image));
}
var user = _userManager.GetUserBySid(ldapUser.Sid);
Logger.DebugFormat("SyncLdapAvatar() Found photo for '{0}'", ldapUser.Sid);
if (photoSettings.CurrentPhotos.ContainsKey(user.ID) && photoSettings.CurrentPhotos[user.ID] == hash)
{
Logger.Debug("SyncLdapAvatar() Same hash, skipping.");
continue;
}
try
{
SetProgress((int)(currentPercent += step),
string.Format("{0}: {1}", Resource.LdapSettingsStatusSavingUserPhoto, _userFormatter.GetUserName(user, DisplayUserNameFormat.Default)));
_userPhotoManager.SyncPhoto(user.ID, (byte[])image);
if (photoSettings.CurrentPhotos.ContainsKey(user.ID))
{
photoSettings.CurrentPhotos[user.ID] = hash;
}
else
{
photoSettings.CurrentPhotos.Add(user.ID, hash);
}
}
catch
{
Logger.DebugFormat("SyncLdapAvatar() Couldn't save photo for '{0}'", user.ID);
if (photoSettings.CurrentPhotos.ContainsKey(user.ID))
{
photoSettings.CurrentPhotos.Remove(user.ID);
}
}
}
_settingsManager.Save(photoSettings);
}
private void SyncLdapAccessRights()
{
SetProgress(95, Resource.LdapSettingsStatusUpdatingAccessRights);
var currentUserRights = new List<LdapSettings.AccessRight>();
TakeUsersRights(_currentUser != null ? currentUserRights : null);
if (LDAPSettings.GroupMembership && LDAPSettings.AccessRights != null && LDAPSettings.AccessRights.Count > 0)
{
GiveUsersRights(LDAPSettings.AccessRights, _currentUser != null ? currentUserRights : null);
}
if (currentUserRights.Count > 0)
{
Warning = Resource.LdapSettingsErrorLostRights;
}
_settingsManager.Save(LDAPSettings);
}
private void TakeUsersRights(List<LdapSettings.AccessRight> currentUserRights)
{
var current = _settingsManager.Load<LdapCurrentAcccessSettings>();
if (current.CurrentAccessRights == null || !current.CurrentAccessRights.Any())
{
Logger.Debug("TakeUsersRights() CurrentAccessRights is empty, skipping");
return;
}
SetProgress(95, Resource.LdapSettingsStatusRemovingOldRights);
foreach (var right in current.CurrentAccessRights)
{
foreach (var user in right.Value)
{
var userId = Guid.Parse(user);
if (_currentUser != null && _currentUser.ID == userId)
{
Logger.DebugFormat("TakeUsersRights() Attempting to take admin rights from yourself `{0}`, skipping", user);
if (currentUserRights != null)
{
currentUserRights.Add(right.Key);
}
}
else
{
Logger.DebugFormat("TakeUsersRights() Taking admin rights ({0}) from '{1}'", right.Key, user);
_webItemSecurity.SetProductAdministrator(LdapSettings.AccessRightsGuids[right.Key], userId, false);
}
}
}
current.CurrentAccessRights = null;
_settingsManager.Save(current);
}
private void GiveUsersRights(Dictionary<LdapSettings.AccessRight, string> accessRightsSettings, List<LdapSettings.AccessRight> currentUserRights)
{
var current = _settingsManager.Load<LdapCurrentAcccessSettings>();
var currentAccessRights = new Dictionary<LdapSettings.AccessRight, List<string>>();
var usersWithRightsFlat = current.CurrentAccessRights == null ? new List<string>() : current.CurrentAccessRights.SelectMany(x => x.Value).Distinct().ToList();
var step = 3.0 / accessRightsSettings.Count;
var currentPercent = 95.0;
foreach (var access in accessRightsSettings)
{
currentPercent += step;
var ldapGroups = Importer.FindGroupsByAttribute(LDAPSettings.GroupNameAttribute, access.Value.Split(',').Select(x => x.Trim()));
if (!ldapGroups.Any())
{
Logger.DebugFormat("GiveUsersRights() No ldap groups found for ({0}) access rights, skipping", access.Key);
continue;
}
foreach (var ldapGr in ldapGroups)
{
var gr = _userManager.GetGroupInfoBySid(ldapGr.Sid);
if (gr == null)
{
Logger.DebugFormat("GiveUsersRights() Couldn't find portal group for '{0}'", ldapGr.Sid);
continue;
}
var users = _userManager.GetUsersByGroup(gr.ID);
Logger.DebugFormat("GiveUsersRights() Found '{0}' users for group '{1}' ({2})", users.Count(), gr.Name, gr.ID);
foreach (var user in users)
{
if (!user.Equals(Constants.LostUser) && !user.IsVisitor(_userManager))
{
if (!usersWithRightsFlat.Contains(user.ID.ToString()))
{
usersWithRightsFlat.Add(user.ID.ToString());
var cleared = false;
foreach (var r in Enum.GetValues(typeof(LdapSettings.AccessRight)).Cast<LdapSettings.AccessRight>())
{
var prodId = LdapSettings.AccessRightsGuids[r];
if (_webItemSecurity.IsProductAdministrator(prodId, user.ID))
{
cleared = true;
_webItemSecurity.SetProductAdministrator(prodId, user.ID, false);
}
}
if (cleared)
{
Logger.DebugFormat("GiveUsersRights() Cleared manually added user rights for '{0}'", user.DisplayUserName(_displayUserSettingsHelper));
}
}
if (!currentAccessRights.ContainsKey(access.Key))
{
currentAccessRights.Add(access.Key, new List<string>());
}
currentAccessRights[access.Key].Add(user.ID.ToString());
SetProgress((int)currentPercent,
string.Format(Resource.LdapSettingsStatusGivingRights, _userFormatter.GetUserName(user, DisplayUserNameFormat.Default), access.Key));
_webItemSecurity.SetProductAdministrator(LdapSettings.AccessRightsGuids[access.Key], user.ID, true);
if (currentUserRights != null && currentUserRights.Contains(access.Key))
{
currentUserRights.Remove(access.Key);
}
}
}
}
}
current.CurrentAccessRights = currentAccessRights;
_settingsManager.Save(current);
}
private void SyncLDAPUsers()
{
SetProgress(15, Resource.LdapSettingsStatusGettingUsersFromLdap);
var ldapUsers = Importer.GetDiscoveredUsersByAttributes();
if (!ldapUsers.Any())
{
Error = Resource.LdapSettingsErrorUsersNotFound;
return;
}
Logger.DebugFormat("Importer.GetDiscoveredUsersByAttributes() Success: Users count: {0}",
Importer.AllDomainUsers.Count);
SetProgress(20, Resource.LdapSettingsStatusRemovingOldUsers, "");
ldapUsers = RemoveOldDbUsers(ldapUsers);
SetProgress(30,
OperationType == LdapOperationType.Save || OperationType == LdapOperationType.SaveTest
? Resource.LdapSettingsStatusSavingUsers
: Resource.LdapSettingsStatusSyncingUsers,
"");
SyncDbUsers(ldapUsers);
SetProgress(70, Resource.LdapSettingsStatusRemovingOldGroups, "");
RemoveOldDbGroups(new List<GroupInfo>()); // Remove all db groups with sid
}
private void SyncLDAPUsersInGroups()
{
SetProgress(15, Resource.LdapSettingsStatusGettingGroupsFromLdap);
var ldapGroups = Importer.GetDiscoveredGroupsByAttributes();
if (!ldapGroups.Any())
{
Error = Resource.LdapSettingsErrorGroupsNotFound;
return;
}
Logger.DebugFormat("Importer.GetDiscoveredGroupsByAttributes() Success: Groups count: {0}",
Importer.AllDomainGroups.Count);
SetProgress(20, Resource.LdapSettingsStatusGettingUsersFromLdap);
//Get All found groups users
List<UserInfo> uniqueLdapGroupUsers;
var ldapGroupsUsers = GetGroupsUsers(ldapGroups, out uniqueLdapGroupUsers);
if (!uniqueLdapGroupUsers.Any())
{
Error = Resource.LdapSettingsErrorUsersNotFound;
return;
}
Logger.DebugFormat("GetGroupsUsers() Success: Users count: {0}",
Importer.AllDomainUsers.Count);
SetProgress(30,
OperationType == LdapOperationType.Save || OperationType == LdapOperationType.SaveTest
? Resource.LdapSettingsStatusSavingUsers
: Resource.LdapSettingsStatusSyncingUsers,
"");
var newUniqueLdapGroupUsers = SyncGroupsUsers(uniqueLdapGroupUsers);
SetProgress(60, Resource.LdapSettingsStatusSavingGroups, "");
SyncDbGroups(ldapGroupsUsers);
SetProgress(80, Resource.LdapSettingsStatusRemovingOldGroups, "");
RemoveOldDbGroups(ldapGroups);
SetProgress(90, Resource.LdapSettingsStatusRemovingOldUsers, "");
RemoveOldDbUsers(newUniqueLdapGroupUsers);
}
private void SyncDbGroups(Dictionary<GroupInfo, List<UserInfo>> ldapGroupsWithUsers)
{
const double percents = 20;
var step = percents / ldapGroupsWithUsers.Count;
var percentage = (double)GetProgress();
if (!ldapGroupsWithUsers.Any())
return;
var gIndex = 0;
var gCount = ldapGroupsWithUsers.Count;
foreach (var ldapGroupWithUsers in ldapGroupsWithUsers)
{
var ldapGroup = ldapGroupWithUsers.Key;
var ldapGroupUsers = ldapGroupWithUsers.Value;
++gIndex;
SetProgress(Convert.ToInt32(percentage),
currentSource:
string.Format("({0}/{1}): {2}", gIndex,
gCount, ldapGroup.Name));
var dbLdapGroup = _userManager.GetGroupInfoBySid(ldapGroup.Sid);
if (Equals(dbLdapGroup, Constants.LostGroupInfo))
{
AddNewGroup(ldapGroup, ldapGroupUsers, gIndex, gCount);
}
else
{
UpdateDbGroup(dbLdapGroup, ldapGroup, ldapGroupUsers, gIndex, gCount);
}
percentage += step;
}
}
private void AddNewGroup(GroupInfo ldapGroup, List<UserInfo> ldapGroupUsers, int gIndex, int gCount)
{
if (!ldapGroupUsers.Any()) // Skip empty groups
{
if (OperationType == LdapOperationType.SaveTest ||
OperationType == LdapOperationType.SyncTest)
{
_ldapChanges.SetSkipGroupChange(ldapGroup);
}
return;
}
var groupMembersToAdd =
ldapGroupUsers.Select(ldapGroupUser => SearchDbUserBySid(ldapGroupUser.Sid))
.Where(userBySid => !Equals(userBySid, Constants.LostUser))
.ToList();
if (groupMembersToAdd.Any())
{
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
ldapGroup = _userManager.SaveGroupInfo(ldapGroup);
var index = 0;
var count = groupMembersToAdd.Count;
foreach (var userBySid in groupMembersToAdd)
{
SetProgress(
currentSource:
string.Format("({0}/{1}): {2}, {3} ({4}/{5}): {6}", gIndex,
gCount, ldapGroup.Name,
Resource.LdapSettingsStatusAddingGroupUser,
++index, count,
_userFormatter.GetUserName(userBySid, DisplayUserNameFormat.Default)));
_userManager.AddUserIntoGroup(userBySid.ID, ldapGroup.ID);
}
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
_ldapChanges.SetAddGroupChange(ldapGroup);
_ldapChanges.SetAddGroupMembersChange(ldapGroup, groupMembersToAdd);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
else
{
if (OperationType == LdapOperationType.SaveTest ||
OperationType == LdapOperationType.SyncTest)
{
_ldapChanges.SetSkipGroupChange(ldapGroup);
}
}
}
private static bool NeedUpdateGroup(GroupInfo portalGroup, GroupInfo ldapGroup)
{
var needUpdate =
!portalGroup.Name.Equals(ldapGroup.Name, StringComparison.InvariantCultureIgnoreCase) ||
!portalGroup.Sid.Equals(ldapGroup.Sid, StringComparison.InvariantCultureIgnoreCase);
return needUpdate;
}
private void UpdateDbGroup(GroupInfo dbLdapGroup, GroupInfo ldapGroup, List<UserInfo> ldapGroupUsers, int gIndex,
int gCount)
{
SetProgress(currentSource:
string.Format("({0}/{1}): {2}", gIndex, gCount, ldapGroup.Name));
var dbGroupMembers =
_userManager.GetUsersByGroup(dbLdapGroup.ID, EmployeeStatus.All)
.Where(u => u.Sid != null)
.ToList();
var groupMembersToRemove =
dbGroupMembers.Where(
dbUser => ldapGroupUsers.FirstOrDefault(lu => dbUser.Sid.Equals(lu.Sid)) == null).ToList();
var groupMembersToAdd = (from ldapGroupUser in ldapGroupUsers
let dbUser = dbGroupMembers.FirstOrDefault(u => u.Sid.Equals(ldapGroupUser.Sid))
where dbUser == null
select SearchDbUserBySid(ldapGroupUser.Sid)
into userBySid
where !Equals(userBySid, Constants.LostUser)
select userBySid)
.ToList();
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
if (NeedUpdateGroup(dbLdapGroup, ldapGroup))
{
dbLdapGroup.Name = ldapGroup.Name;
dbLdapGroup.Sid = ldapGroup.Sid;
dbLdapGroup = _userManager.SaveGroupInfo(dbLdapGroup);
}
var index = 0;
var count = groupMembersToRemove.Count;
foreach (var dbUser in groupMembersToRemove)
{
SetProgress(
currentSource:
string.Format("({0}/{1}): {2}, {3} ({4}/{5}): {6}", gIndex, gCount,
dbLdapGroup.Name,
Resource.LdapSettingsStatusRemovingGroupUser,
++index, count,
_userFormatter.GetUserName(dbUser, DisplayUserNameFormat.Default)));
_userManager.RemoveUserFromGroup(dbUser.ID, dbLdapGroup.ID);
}
index = 0;
count = groupMembersToAdd.Count;
foreach (var userInfo in groupMembersToAdd)
{
SetProgress(
currentSource:
string.Format("({0}/{1}): {2}, {3} ({4}/{5}): {6}", gIndex, gCount,
ldapGroup.Name,
Resource.LdapSettingsStatusAddingGroupUser,
++index, count,
_userFormatter.GetUserName(userInfo, DisplayUserNameFormat.Default)));
_userManager.AddUserIntoGroup(userInfo.ID, dbLdapGroup.ID);
}
if (dbGroupMembers.All(dbUser => groupMembersToRemove.Exists(u => u.ID.Equals(dbUser.ID)))
&& !groupMembersToAdd.Any())
{
SetProgress(currentSource:
string.Format("({0}/{1}): {2}", gIndex, gCount, dbLdapGroup.Name));
_userManager.DeleteGroup(dbLdapGroup.ID);
}
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
if (NeedUpdateGroup(dbLdapGroup, ldapGroup))
_ldapChanges.SetUpdateGroupChange(ldapGroup);
if (groupMembersToRemove.Any())
_ldapChanges.SetRemoveGroupMembersChange(dbLdapGroup, groupMembersToRemove);
if (groupMembersToAdd.Any())
_ldapChanges.SetAddGroupMembersChange(dbLdapGroup, groupMembersToAdd);
if (dbGroupMembers.All(dbUser => groupMembersToRemove.Exists(u => u.ID.Equals(dbUser.ID)))
&& !groupMembersToAdd.Any())
{
_ldapChanges.SetRemoveGroupChange(dbLdapGroup, Logger);
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private UserInfo SearchDbUserBySid(string sid)
{
if (string.IsNullOrEmpty(sid))
return Constants.LostUser;
var foundUser = _userManager.GetUserBySid(sid);
return foundUser;
}
private void SyncDbUsers(List<UserInfo> ldapUsers)
{
const double percents = 35;
var step = percents / ldapUsers.Count;
var percentage = (double)GetProgress();
if (!ldapUsers.Any())
return;
var index = 0;
var count = ldapUsers.Count;
foreach (var userInfo in ldapUsers)
{
SetProgress(Convert.ToInt32(percentage),
currentSource:
string.Format("({0}/{1}): {2}", ++index, count,
_userFormatter.GetUserName(userInfo, DisplayUserNameFormat.Default)));
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
LDAPUserManager.SyncLDAPUser(userInfo, ldapUsers);
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
LdapChangeCollection changes;
LDAPUserManager.GetLDAPSyncUserChange(userInfo, ldapUsers, out changes);
_ldapChanges.AddRange(changes);
break;
default:
throw new ArgumentOutOfRangeException();
}
percentage += step;
}
}
/// <summary>
/// Remove old LDAP users from db
/// </summary>
/// <param name="ldapUsers">list of actual LDAP users</param>
/// <returns>New list of actual LDAP users</returns>
private List<UserInfo> RemoveOldDbUsers(List<UserInfo> ldapUsers)
{
var dbLdapUsers = _userManager.GetUsers(EmployeeStatus.All).Where(u => u.Sid != null).ToList();
if (!dbLdapUsers.Any())
return ldapUsers;
var removedUsers =
dbLdapUsers.Where(u => ldapUsers.FirstOrDefault(lu => u.Sid.Equals(lu.Sid)) == null).ToList();
if (!removedUsers.Any())
return ldapUsers;
const double percents = 8;
var step = percents / removedUsers.Count;
var percentage = (double)GetProgress();
var index = 0;
var count = removedUsers.Count;
foreach (var removedUser in removedUsers)
{
SetProgress(Convert.ToInt32(percentage),
currentSource:
string.Format("({0}/{1}): {2}", ++index, count,
_userFormatter.GetUserName(removedUser, DisplayUserNameFormat.Default)));
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
removedUser.Sid = null;
if (!removedUser.IsOwner(_tenantManager.GetCurrentTenant()) && !(_currentUser != null && _currentUser.ID == removedUser.ID && removedUser.IsAdmin(_userManager)))
{
removedUser.Status = EmployeeStatus.Terminated; // Disable user on portal
}
else
{
Warning = Resource.LdapSettingsErrorRemovedYourself;
Logger.DebugFormat("RemoveOldDbUsers() Attempting to exclude yourself `{0}` from group or user filters, skipping.", removedUser.ID);
}
removedUser.ConvertExternalContactsToOrdinary();
Logger.DebugFormat("CoreContext.UserManager.SaveUserInfo({0})", removedUser.GetUserInfoString());
_userManager.SaveUserInfo(removedUser);
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
_ldapChanges.SetSaveAsPortalUserChange(removedUser);
break;
default:
throw new ArgumentOutOfRangeException();
}
percentage += step;
}
dbLdapUsers.RemoveAll(removedUsers.Contains);
var newLdapUsers = ldapUsers.Where(u => !removedUsers.Exists(ru => ru.ID.Equals(u.ID))).ToList();
return newLdapUsers;
}
private void RemoveOldDbGroups(List<GroupInfo> ldapGroups)
{
var percentage = (double)GetProgress();
var removedDbLdapGroups =
_userManager.GetGroups()
.Where(g => g.Sid != null && ldapGroups.FirstOrDefault(lg => g.Sid.Equals(lg.Sid)) == null)
.ToList();
if (!removedDbLdapGroups.Any())
return;
const double percents = 10;
var step = percents / removedDbLdapGroups.Count;
var index = 0;
var count = removedDbLdapGroups.Count;
foreach (var groupInfo in removedDbLdapGroups)
{
SetProgress(Convert.ToInt32(percentage),
currentSource: string.Format("({0}/{1}): {2}", ++index, count, groupInfo.Name));
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
_userManager.DeleteGroup(groupInfo.ID);
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
_ldapChanges.SetRemoveGroupChange(groupInfo);
break;
default:
throw new ArgumentOutOfRangeException();
}
percentage += step;
}
}
private List<UserInfo> SyncGroupsUsers(List<UserInfo> uniqueLdapGroupUsers)
{
const double percents = 30;
var step = percents / uniqueLdapGroupUsers.Count;
var percentage = (double)GetProgress();
var newUniqueLdapGroupUsers = new List<UserInfo>();
var index = 0;
var count = uniqueLdapGroupUsers.Count;
int i, len;
for (i = 0, len = uniqueLdapGroupUsers.Count; i < len; i++)
{
var ldapGroupUser = uniqueLdapGroupUsers[i];
SetProgress(Convert.ToInt32(percentage),
currentSource:
string.Format("({0}/{1}): {2}", ++index, count,
_userFormatter.GetUserName(ldapGroupUser, DisplayUserNameFormat.Default)));
UserInfo user;
switch (OperationType)
{
case LdapOperationType.Save:
case LdapOperationType.Sync:
user = LDAPUserManager.SyncLDAPUser(ldapGroupUser, uniqueLdapGroupUsers);
if (!Equals(user, Constants.LostUser))
newUniqueLdapGroupUsers.Add(user);
break;
case LdapOperationType.SaveTest:
case LdapOperationType.SyncTest:
LdapChangeCollection changes;
user = LDAPUserManager.GetLDAPSyncUserChange(ldapGroupUser, uniqueLdapGroupUsers, out changes);
if (!Equals(user, Constants.LostUser))
{
newUniqueLdapGroupUsers.Add(user);
}
_ldapChanges.AddRange(changes);
break;
default:
throw new ArgumentOutOfRangeException();
}
percentage += step;
}
return newUniqueLdapGroupUsers;
}
private Dictionary<GroupInfo, List<UserInfo>> GetGroupsUsers(List<GroupInfo> ldapGroups,
out List<UserInfo> uniqueLdapGroupUsers)
{
uniqueLdapGroupUsers = new List<UserInfo>();
var listGroupsUsers = new Dictionary<GroupInfo, List<UserInfo>>();
foreach (var ldapGroup in ldapGroups)
{
var ldapGroupUsers = Importer.GetGroupUsers(ldapGroup);
listGroupsUsers.Add(ldapGroup, ldapGroupUsers);
foreach (var ldapGroupUser in ldapGroupUsers)
{
if (!uniqueLdapGroupUsers.Any(u => u.Sid.Equals(ldapGroupUser.Sid)))
{
uniqueLdapGroupUsers.Add(ldapGroupUser);
}
}
}
return listGroupsUsers;
}
}
}