From f7fae8fe2fca344ddb392a361fa422f35ee649a7 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Fri, 23 Aug 2013 17:53:43 +0300 Subject: [PATCH] added "memberOf" functionality and bugs fixed --- WebsitePanel/Database/update_db.sql | 66 ++++ .../OrganizationProxy.cs | 286 +++++++++++++++++- .../HostedSolution/OrganizationController.cs | 159 +++++++++- .../esOrganizations.asmx.cs | 22 +- .../HostedSolution/ActiveDirectoryUtils.cs | 16 +- .../HostedSolution/IOrganization.cs | 2 + .../OrganizationProvider.cs | 28 ++ .../OrganizationProxy.cs | 63 ++++ .../WebsitePanel.Server/Organizations.asmx.cs | 6 + ...zationSecurityGroupGeneralSettings.ascx.cs | 2 + .../OrganizationSecurityGroups.ascx | 2 +- .../OrganizationUserMemberOf.ascx | 8 +- .../OrganizationUserMemberOf.ascx.cs | 32 +- .../OrganizationUserMemberOf.ascx.designer.cs | 2 +- .../App_LocalResources/GroupsList.ascx.resx | 147 +++++++++ .../UserControls/GroupsList.ascx | 105 +++++++ .../UserControls/GroupsList.ascx.cs | 197 ++++++++++++ .../UserControls/GroupsList.ascx.designer.cs | 159 ++++++++++ .../UserControls/UsersList.ascx.cs | 5 + .../WebsitePanel.Portal.Modules.csproj | 11 + 20 files changed, 1283 insertions(+), 35 deletions(-) create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/GroupsList.ascx.resx create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.designer.cs diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index b0d6956d..24dbdd04 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -1967,3 +1967,69 @@ GO + +ALTER PROCEDURE [dbo].[SearchExchangeAccounts] +( + @ActorID int, + @ItemID int, + @IncludeMailboxes bit, + @IncludeContacts bit, + @IncludeDistributionLists bit, + @IncludeRooms bit, + @IncludeEquipment bit, + @FilterColumn nvarchar(50) = '', + @FilterValue nvarchar(50) = '', + @SortColumn nvarchar(50) +) +AS +DECLARE @PackageID int +SELECT @PackageID = PackageID FROM ServiceItems +WHERE ItemID = @ItemID + +-- check rights +IF dbo.CheckActorPackageRights(@ActorID, @PackageID) = 0 +RAISERROR('You are not allowed to access this package', 16, 1) + +-- start +DECLARE @condition nvarchar(700) +SET @condition = ' +((@IncludeMailboxes = 1 AND EA.AccountType = 1) +OR (@IncludeContacts = 1 AND EA.AccountType = 2) +OR (@IncludeDistributionLists = 1 AND EA.AccountType = 3) +OR (@IncludeRooms = 1 AND EA.AccountType = 5) +OR (@IncludeEquipment = 1 AND EA.AccountType = 6) +OR (@IncludeEquipment = 0 AND @IncludeContacts = 0 AND @IncludeDistributionLists = 0 AND @IncludeRooms = 0 AND @IncludeEquipment = 0 AND EA.AccountType = 8)) +AND EA.ItemID = @ItemID +' + +IF @FilterColumn <> '' AND @FilterColumn IS NOT NULL +AND @FilterValue <> '' AND @FilterValue IS NOT NULL +SET @condition = @condition + ' AND ' + @FilterColumn + ' LIKE ''' + @FilterValue + '''' + +IF @SortColumn IS NULL OR @SortColumn = '' +SET @SortColumn = 'EA.DisplayName ASC' + +DECLARE @sql nvarchar(3500) + +set @sql = ' +SELECT + EA.AccountID, + EA.ItemID, + EA.AccountType, + EA.AccountName, + EA.DisplayName, + EA.PrimaryEmailAddress, + EA.MailEnabledPublicFolder, + EA.SubscriberNumber, + EA.UserPrincipalName +FROM ExchangeAccounts AS EA +WHERE ' + @condition + +print @sql + +exec sp_executesql @sql, N'@ItemID int, @IncludeMailboxes int, @IncludeContacts int, + @IncludeDistributionLists int, @IncludeRooms bit, @IncludeEquipment bit', +@ItemID, @IncludeMailboxes, @IncludeContacts, @IncludeDistributionLists, @IncludeRooms, @IncludeEquipment + +RETURN +GO \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs index d2c60dd8..89e5b4d7 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs @@ -129,6 +129,12 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution private System.Threading.SendOrPostCallback AddUserToSecurityGroupOperationCompleted; + private System.Threading.SendOrPostCallback DeleteUserFromSecurityGroupOperationCompleted; + + private System.Threading.SendOrPostCallback GetSecurityGroupsByMemberOperationCompleted; + + private System.Threading.SendOrPostCallback SearchSecurityGroupsOperationCompleted; + /// public esOrganizations() { @@ -231,6 +237,15 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution /// public event AddUserToSecurityGroupCompletedEventHandler AddUserToSecurityGroupCompleted; + /// + public event DeleteUserFromSecurityGroupCompletedEventHandler DeleteUserFromSecurityGroupCompleted; + + /// + public event GetSecurityGroupsByMemberCompletedEventHandler GetSecurityGroupsByMemberCompleted; + + /// + public event SearchSecurityGroupsCompletedEventHandler SearchSecurityGroupsCompleted; + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CheckOrgIdExists", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public bool CheckOrgIdExists(string orgId) @@ -2158,22 +2173,22 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/AddUserToSecurityGroup", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public int AddUserToSecurityGroup(int itemId, int userAccountId, int groupAccountId) + public int AddUserToSecurityGroup(int itemId, int userAccountId, string groupName) { object[] results = this.Invoke("AddUserToSecurityGroup", new object[] { itemId, userAccountId, - groupAccountId}); + groupName}); return ((int)(results[0])); } /// - public System.IAsyncResult BeginAddUserToSecurityGroup(int itemId, int userAccountId, int groupAccountId, System.AsyncCallback callback, object asyncState) + public System.IAsyncResult BeginAddUserToSecurityGroup(int itemId, int userAccountId, string groupName, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("AddUserToSecurityGroup", new object[] { itemId, userAccountId, - groupAccountId}, callback, asyncState); + groupName}, callback, asyncState); } /// @@ -2184,13 +2199,13 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution } /// - public void AddUserToSecurityGroupAsync(int itemId, int userAccountId, int groupAccountId) + public void AddUserToSecurityGroupAsync(int itemId, int userAccountId, string groupName) { - this.AddUserToSecurityGroupAsync(itemId, userAccountId, groupAccountId, null); + this.AddUserToSecurityGroupAsync(itemId, userAccountId, groupName, null); } /// - public void AddUserToSecurityGroupAsync(int itemId, int userAccountId, int groupAccountId, object userState) + public void AddUserToSecurityGroupAsync(int itemId, int userAccountId, string groupName, object userState) { if ((this.AddUserToSecurityGroupOperationCompleted == null)) { @@ -2199,7 +2214,7 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution this.InvokeAsync("AddUserToSecurityGroup", new object[] { itemId, userAccountId, - groupAccountId}, this.AddUserToSecurityGroupOperationCompleted, userState); + groupName}, this.AddUserToSecurityGroupOperationCompleted, userState); } private void OnAddUserToSecurityGroupOperationCompleted(object arg) @@ -2211,6 +2226,171 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution } } + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DeleteUserFromSecurityGroup", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public int DeleteUserFromSecurityGroup(int itemId, int userAccountId, string groupName) + { + object[] results = this.Invoke("DeleteUserFromSecurityGroup", new object[] { + itemId, + userAccountId, + groupName}); + return ((int)(results[0])); + } + + /// + public System.IAsyncResult BeginDeleteUserFromSecurityGroup(int itemId, int userAccountId, string groupName, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteUserFromSecurityGroup", new object[] { + itemId, + userAccountId, + groupName}, callback, asyncState); + } + + /// + public int EndDeleteUserFromSecurityGroup(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((int)(results[0])); + } + + /// + public void DeleteUserFromSecurityGroupAsync(int itemId, int userAccountId, string groupName) + { + this.DeleteUserFromSecurityGroupAsync(itemId, userAccountId, groupName, null); + } + + /// + public void DeleteUserFromSecurityGroupAsync(int itemId, int userAccountId, string groupName, object userState) + { + if ((this.DeleteUserFromSecurityGroupOperationCompleted == null)) + { + this.DeleteUserFromSecurityGroupOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteUserFromSecurityGroupOperationCompleted); + } + this.InvokeAsync("DeleteUserFromSecurityGroup", new object[] { + itemId, + userAccountId, + groupName}, this.DeleteUserFromSecurityGroupOperationCompleted, userState); + } + + private void OnDeleteUserFromSecurityGroupOperationCompleted(object arg) + { + if ((this.DeleteUserFromSecurityGroupCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteUserFromSecurityGroupCompleted(this, new DeleteUserFromSecurityGroupCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetSecurityGroupsByMember", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public ExchangeAccount[] GetSecurityGroupsByMember(int itemId, int accountId) + { + object[] results = this.Invoke("GetSecurityGroupsByMember", new object[] { + itemId, + accountId}); + return ((ExchangeAccount[])(results[0])); + } + + /// + public System.IAsyncResult BeginGetSecurityGroupsByMember(int itemId, int accountId, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("GetSecurityGroupsByMember", new object[] { + itemId, + accountId}, callback, asyncState); + } + + /// + public ExchangeAccount[] EndGetSecurityGroupsByMember(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((ExchangeAccount[])(results[0])); + } + + /// + public void GetSecurityGroupsByMemberAsync(int itemId, int accountId) + { + this.GetSecurityGroupsByMemberAsync(itemId, accountId, null); + } + + /// + public void GetSecurityGroupsByMemberAsync(int itemId, int accountId, object userState) + { + if ((this.GetSecurityGroupsByMemberOperationCompleted == null)) + { + this.GetSecurityGroupsByMemberOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetSecurityGroupsByMemberOperationCompleted); + } + this.InvokeAsync("GetSecurityGroupsByMember", new object[] { + itemId, + accountId}, this.GetSecurityGroupsByMemberOperationCompleted, userState); + } + + private void OnGetSecurityGroupsByMemberOperationCompleted(object arg) + { + if ((this.GetSecurityGroupsByMemberCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetSecurityGroupsByMemberCompleted(this, new GetSecurityGroupsByMemberCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SearchSecurityGroups", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public ExchangeAccount[] SearchSecurityGroups(int itemId, string filterColumn, string filterValue, string sortColumn) + { + object[] results = this.Invoke("SearchSecurityGroups", new object[] { + itemId, + filterColumn, + filterValue, + sortColumn}); + return ((ExchangeAccount[])(results[0])); + } + + /// + public System.IAsyncResult BeginSearchSecurityGroups(int itemId, string filterColumn, string filterValue, string sortColumn, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("SearchSecurityGroups", new object[] { + itemId, + filterColumn, + filterValue, + sortColumn}, callback, asyncState); + } + + /// + public ExchangeAccount[] EndSearchSecurityGroups(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((ExchangeAccount[])(results[0])); + } + + /// + public void SearchSecurityGroupsAsync(int itemId, string filterColumn, string filterValue, string sortColumn) + { + this.SearchSecurityGroupsAsync(itemId, filterColumn, filterValue, sortColumn, null); + } + + /// + public void SearchSecurityGroupsAsync(int itemId, string filterColumn, string filterValue, string sortColumn, object userState) + { + if ((this.SearchSecurityGroupsOperationCompleted == null)) + { + this.SearchSecurityGroupsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSearchSecurityGroupsOperationCompleted); + } + this.InvokeAsync("SearchSecurityGroups", new object[] { + itemId, + filterColumn, + filterValue, + sortColumn}, this.SearchSecurityGroupsOperationCompleted, userState); + } + + private void OnSearchSecurityGroupsOperationCompleted(object arg) + { + if ((this.SearchSecurityGroupsCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.SearchSecurityGroupsCompleted(this, new SearchSecurityGroupsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { @@ -3177,4 +3357,94 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void DeleteUserFromSecurityGroupCompletedEventHandler(object sender, DeleteUserFromSecurityGroupCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DeleteUserFromSecurityGroupCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal DeleteUserFromSecurityGroupCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public int Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((int)(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetSecurityGroupsByMemberCompletedEventHandler(object sender, GetSecurityGroupsByMemberCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetSecurityGroupsByMemberCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal GetSecurityGroupsByMemberCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public ExchangeAccount[] Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((ExchangeAccount[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void SearchSecurityGroupsCompletedEventHandler(object sender, SearchSecurityGroupsCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SearchSecurityGroupsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal SearchSecurityGroupsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public ExchangeAccount[] Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((ExchangeAccount[])(this.results[0])); + } + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs index 9f87df13..f7a1df6f 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs @@ -42,6 +42,7 @@ using WebsitePanel.Providers.SharePoint; using WebsitePanel.Providers.Common; using WebsitePanel.Providers.DNS; using WebsitePanel.Providers.OCS; +using System.Linq; using System.IO; using System.Xml; @@ -2257,14 +2258,16 @@ namespace WebsitePanel.EnterpriseServer Organizations orgProxy = GetOrganizationProxy(org.ServiceId); - TaskManager.Write("accountName :" + displayName); + string groupName = BuildAccountNameWithOrgId(org.OrganizationId, displayName, org.ServiceId); - if (orgProxy.CreateSecurityGroup(org.OrganizationId, displayName, managedBy) == 0) + TaskManager.Write("accountName :" + groupName); + + if (orgProxy.CreateSecurityGroup(org.OrganizationId, groupName, managedBy) == 0) { - OrganizationSecurityGroup retSecurityGroup = orgProxy.GetSecurityGroupGeneralSettings(displayName, org.OrganizationId); + OrganizationSecurityGroup retSecurityGroup = orgProxy.GetSecurityGroupGeneralSettings(groupName, org.OrganizationId); TaskManager.Write("sAMAccountName :" + retSecurityGroup.SAMAccountName); - securityGroupId = AddAccount(itemId, ExchangeAccountType.SecurityGroup, displayName, + securityGroupId = AddAccount(itemId, ExchangeAccountType.SecurityGroup, groupName, displayName, null, false, 0, retSecurityGroup.SAMAccountName, null, 0, null); } @@ -2324,16 +2327,25 @@ namespace WebsitePanel.EnterpriseServer securityGroup.IsDefault = account.AccountType == ExchangeAccountType.DefaultSecurityGroup; + List members = new List(); + foreach (OrganizationUser user in securityGroup.MembersAccounts) { OrganizationUser userAccount = GetAccountByAccountName(itemId, user.SamAccountName); - user.AccountId = userAccount.AccountId; - user.AccountName = userAccount.AccountName; - user.PrimaryEmailAddress = userAccount.PrimaryEmailAddress; - user.AccountType = userAccount.AccountType; + if (userAccount != null) + { + user.AccountId = userAccount.AccountId; + user.AccountName = userAccount.AccountName; + user.PrimaryEmailAddress = userAccount.PrimaryEmailAddress; + user.AccountType = userAccount.AccountType; + + members.Add(user); + } } + securityGroup.MembersAccounts = members.ToArray(); + return securityGroup; } catch (Exception ex) @@ -2497,7 +2509,7 @@ namespace WebsitePanel.EnterpriseServer return result; } - public static int AddUserToSecurityGroup(int itemId, int userAccountId, int groupAccountId) + public static int AddUserToSecurityGroup(int itemId, int userAccountId, string groupName) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); @@ -2516,12 +2528,9 @@ namespace WebsitePanel.EnterpriseServer // load user account OrganizationUser userAccount = GetAccount(itemId, userAccountId); - //load group account - ExchangeAccount groupAccount = ExchangeServerController.GetAccount(itemId, groupAccountId); - Organizations orgProxy = GetOrganizationProxy(org.ServiceId); - orgProxy.AddUserToSecurityGroup(org.OrganizationId, userAccount.AccountName, groupAccount.AccountName); + orgProxy.AddUserToSecurityGroup(org.OrganizationId, userAccount.AccountName, groupName); return 0; } @@ -2534,6 +2543,130 @@ namespace WebsitePanel.EnterpriseServer TaskManager.CompleteTask(); } } + + public static int DeleteUserFromSecurityGroup(int itemId, int userAccountId, string groupName) + { + // check account + int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); + if (accountCheck < 0) return accountCheck; + + // place log record + TaskManager.StartTask("ORGANIZATION", "DELETE_USER_FROM_SECURITY_GROUP", itemId); + + try + { + // load organization + Organization org = GetOrganization(itemId); + if (org == null) + return -1; + + // load user account + OrganizationUser userAccount = GetAccount(itemId, userAccountId); + + Organizations orgProxy = GetOrganizationProxy(org.ServiceId); + + orgProxy.DeleteUserFromSecurityGroup(org.OrganizationId, userAccount.AccountName, groupName); + + return 0; + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + } + + public static ExchangeAccount[] GetSecurityGroupsByMember(int itemId, int accountId) + { + #region Demo Mode + if (IsDemoMode) + { + return null; + } + #endregion + + // place log record + TaskManager.StartTask("ORGANIZATION", "GET_SECURITY_GROUPS_BYMEMBER"); + TaskManager.ItemId = itemId; + + List ret = new List(); + + try + { + // load organization + Organization org = GetOrganization(itemId); + if (org == null) + return null; + + Organizations orgProxy = GetOrganizationProxy(org.ServiceId); + + // load account + ExchangeAccount account = ExchangeServerController.GetAccount(itemId, accountId); + + List SecurytyGroups = ExchangeServerController.GetAccounts(itemId, ExchangeAccountType.SecurityGroup); + foreach (ExchangeAccount SecurytyGroupAccount in SecurytyGroups) + { + OrganizationSecurityGroup SecurytyGroup = GetSecurityGroupGeneralSettings(itemId, SecurytyGroupAccount.AccountId); + + foreach (OrganizationUser member in SecurytyGroup.MembersAccounts) + { + if (member.AccountName == account.AccountName) + { + ret.Add(SecurytyGroupAccount); + break; + } + + } + } + + return ret.ToArray(); + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + } + + public static List SearchSecurityGroups(int itemId, string filterColumn, string filterValue, string sortColumn) + { + #region Demo Mode + + if (IsDemoMode) + { + List demoSecurityGroups = new List(); + + ExchangeAccount r1 = new ExchangeAccount(); + r1.AccountId = 20; + r1.AccountName = "group1_fabrikam"; + r1.AccountType = ExchangeAccountType.SecurityGroup; + r1.DisplayName = "Group 1"; + demoSecurityGroups.Add(r1); + + ExchangeAccount r2 = new ExchangeAccount(); + r1.AccountId = 21; + r1.AccountName = "group2_fabrikam"; + r1.AccountType = ExchangeAccountType.SecurityGroup; + r1.DisplayName = "Group 2"; + demoSecurityGroups.Add(r2); + + return demoSecurityGroups; + } + + #endregion + + List accounts = ObjectUtils.CreateListFromDataReader( + DataProvider.SearchExchangeAccounts( + SecurityContext.User.UserId, itemId, false, false, false, false, false, filterColumn, filterValue, sortColumn)); + + return accounts.Where(x => x.AccountType == ExchangeAccountType.SecurityGroup).ToList(); + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs index 6d632462..22609706 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs @@ -276,11 +276,29 @@ namespace WebsitePanel.EnterpriseServer } [WebMethod] - public int AddUserToSecurityGroup(int itemId, int userAccountId, int groupAccountId) + public int AddUserToSecurityGroup(int itemId, int userAccountId, string groupName) { - return OrganizationController.AddUserToSecurityGroup(itemId, userAccountId, groupAccountId); + return OrganizationController.AddUserToSecurityGroup(itemId, userAccountId, groupName); } + [WebMethod] + public int DeleteUserFromSecurityGroup(int itemId, int userAccountId, string groupName) + { + return OrganizationController.DeleteUserFromSecurityGroup(itemId, userAccountId, groupName); + } + + [WebMethod] + public ExchangeAccount[] GetSecurityGroupsByMember(int itemId, int accountId) + { + return OrganizationController.GetSecurityGroupsByMember(itemId, accountId); + } + + [WebMethod] + public List SearchSecurityGroups(int itemId, string filterColumn, string filterValue, string sortColumn) + { + return OrganizationController.SearchSecurityGroups(itemId, filterColumn, filterValue, sortColumn); + } + #endregion } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ActiveDirectoryUtils.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ActiveDirectoryUtils.cs index 773afad4..195ccdba 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ActiveDirectoryUtils.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/ActiveDirectoryUtils.cs @@ -51,7 +51,7 @@ namespace WebsitePanel.Providers.HostedSolution DirectorySearcher deSearch = new DirectorySearcher { Filter = - ("(&(objectClass=user))") + "(&(objectClass=user))" }; SearchResultCollection srcUsers = deSearch.FindAll(); @@ -63,9 +63,19 @@ namespace WebsitePanel.Providers.HostedSolution foreach (string str in props) { - if (str.IndexOf(group) != -1) + string groupName = ""; + + string[] parts = str.Split(','); + for (int i = 0; i < parts.Length; i++) { - rets.Add(de.Path); + if (parts[i].StartsWith("CN=")) + { + if (parts[i].Substring(3) == group) + { + rets.Add(de.Path); + } + break; + } } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs index bda213b7..57aa3d98 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs @@ -52,6 +52,8 @@ namespace WebsitePanel.Providers.HostedSolution void AddUserToSecurityGroup(string organizationId, string loginName, string groupName); + void DeleteUserFromSecurityGroup(string organizationId, string loginName, string groupName); + void SetUserGeneralSettings(string organizationId, string accountName, string displayName, string password, bool hideFromAddressBook, bool disabled, bool locked, string firstName, string initials, string lastName, diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs index f1cab4d2..bd03c64c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs @@ -1041,6 +1041,34 @@ namespace WebsitePanel.Providers.HostedSolution ActiveDirectoryUtils.AddUserToGroup(userPath, groupPath); } + public void DeleteUserFromSecurityGroup(string organizationId, string loginName, string groupName) + { + DeleteUserFromSecurityGroupInternal(organizationId, loginName, groupName); + } + + internal void DeleteUserFromSecurityGroupInternal(string organizationId, string loginName, string groupName) + { + HostedSolutionLog.LogStart("AddUserToSecurityGroupInternal"); + HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId); + HostedSolutionLog.DebugInfo("loginName : {0}", loginName); + HostedSolutionLog.DebugInfo("groupName : {0}", groupName); + + if (string.IsNullOrEmpty(organizationId)) + throw new ArgumentNullException("organizationId"); + + if (string.IsNullOrEmpty(loginName)) + throw new ArgumentNullException("loginName"); + + if (string.IsNullOrEmpty(groupName)) + throw new ArgumentNullException("groupName"); + + string userPath = GetUserPath(organizationId, loginName); + + string groupPath = GetGroupPath(organizationId, groupName); + + ActiveDirectoryUtils.RemoveUserFromGroup(userPath, groupPath); + } + #endregion public override bool IsInstalled() diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs index b01c7dc4..083d4c91 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs @@ -87,6 +87,8 @@ namespace WebsitePanel.Providers.HostedSolution private System.Threading.SendOrPostCallback AddUserToSecurityGroupOperationCompleted; + private System.Threading.SendOrPostCallback DeleteUserFromSecurityGroupOperationCompleted; + private System.Threading.SendOrPostCallback SetUserGeneralSettingsOperationCompleted; private System.Threading.SendOrPostCallback SetUserPasswordOperationCompleted; @@ -142,6 +144,9 @@ namespace WebsitePanel.Providers.HostedSolution /// public event AddUserToSecurityGroupCompletedEventHandler AddUserToSecurityGroupCompleted; + /// + public event DeleteUserFromSecurityGroupCompletedEventHandler DeleteUserFromSecurityGroupCompleted; + /// public event SetUserGeneralSettingsCompletedEventHandler SetUserGeneralSettingsCompleted; @@ -757,6 +762,60 @@ namespace WebsitePanel.Providers.HostedSolution } } + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DeleteUserFromSecurityGroup", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void DeleteUserFromSecurityGroup(string organizationId, string loginName, string groupName) + { + this.Invoke("DeleteUserFromSecurityGroup", new object[] { + organizationId, + loginName, + groupName}); + } + + /// + public System.IAsyncResult BeginDeleteUserFromSecurityGroup(string organizationId, string loginName, string groupName, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteUserFromSecurityGroup", new object[] { + organizationId, + loginName, + groupName}, callback, asyncState); + } + + /// + public void EndDeleteUserFromSecurityGroup(System.IAsyncResult asyncResult) + { + this.EndInvoke(asyncResult); + } + + /// + public void DeleteUserFromSecurityGroupAsync(string organizationId, string loginName, string groupName) + { + this.DeleteUserFromSecurityGroupAsync(organizationId, loginName, groupName, null); + } + + /// + public void DeleteUserFromSecurityGroupAsync(string organizationId, string loginName, string groupName, object userState) + { + if ((this.DeleteUserFromSecurityGroupOperationCompleted == null)) + { + this.DeleteUserFromSecurityGroupOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteUserFromSecurityGroupOperationCompleted); + } + this.InvokeAsync("DeleteUserFromSecurityGroup", new object[] { + organizationId, + loginName, + groupName}, this.DeleteUserFromSecurityGroupOperationCompleted, userState); + } + + private void OnDeleteUserFromSecurityGroupOperationCompleted(object arg) + { + if ((this.DeleteUserFromSecurityGroupCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteUserFromSecurityGroupCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SetUserGeneralSettings", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] @@ -1568,6 +1627,10 @@ namespace WebsitePanel.Providers.HostedSolution [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void AddUserToSecurityGroupCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void DeleteUserFromSecurityGroupCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void SetUserGeneralSettingsCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); diff --git a/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs index dd7f3504..3c1dced6 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs @@ -140,6 +140,12 @@ namespace WebsitePanel.Server Organization.AddUserToSecurityGroup(organizationId, loginName, groupName); } + [WebMethod, SoapHeader("settings")] + public void DeleteUserFromSecurityGroup(string organizationId, string loginName, string groupName) + { + Organization.DeleteUserFromSecurityGroup(organizationId, loginName, groupName); + } + [WebMethod, SoapHeader("settings")] public void SetUserGeneralSettings(string organizationId, string accountName, string displayName, string password, bool hideFromAddressBook, bool disabled, bool locked, string firstName, string initials, string lastName, diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroupGeneralSettings.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroupGeneralSettings.ascx.cs index d8f71bf4..3f65ec36 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroupGeneralSettings.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroupGeneralSettings.ascx.cs @@ -77,6 +77,8 @@ namespace WebsitePanel.Portal.ExchangeServer txtNotes.ReadOnly = true; manager.Enabled = false; members.Enabled = false; + + btnSave.Visible = false; } } catch (Exception ex) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroups.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroups.ascx index 14eabbc4..13dcbc4c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroups.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSecurityGroups.ascx @@ -53,7 +53,7 @@ DataSourceID="odsSecurityGroupsPaged" PageSize="20"> - + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx index 845db39c..36c12744 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx @@ -10,7 +10,7 @@ <%@ Register Src="UserControls/Breadcrumb.ascx" TagName="Breadcrumb" TagPrefix="wsp" %> <%@ Register Src="UserControls/EmailAddress.ascx" TagName="EmailAddress" TagPrefix="wsp" %> <%@ Register Src="UserControls/AccountsList.ascx" TagName="AccountsList" TagPrefix="wsp" %> -<%@ Register Src="UserControls/UsersList.ascx" TagName="UsersList" TagPrefix="wsp" %> +<%@ Register Src="UserControls/GroupsList.ascx" TagName="GroupsList" TagPrefix="wsp" %> @@ -63,11 +63,7 @@ - + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.cs index 616eb0b4..cf175d4a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.cs @@ -58,10 +58,17 @@ namespace WebsitePanel.Portal.HostedSolution // title litDisplayName.Text = mailbox.DisplayName; - + + //Distribution Lists ExchangeAccount[] dLists = ES.Services.ExchangeServer.GetDistributionListsByMember(PanelRequest.ItemID, PanelRequest.AccountID); distrlists.SetAccounts(dLists); + + //Security Groups + ExchangeAccount[] securGroups = ES.Services.Organizations.GetSecurityGroupsByMember(PanelRequest.ItemID, PanelRequest.AccountID); + + securegroups.SetAccounts(securGroups); + } catch (Exception ex) { @@ -76,6 +83,7 @@ namespace WebsitePanel.Portal.HostedSolution try { + //Distribution Lists ExchangeAccount[] oldDistributionLists = ES.Services.ExchangeServer.GetDistributionListsByMember(PanelRequest.ItemID, PanelRequest.AccountID); List newDistributionLists = new List(distrlists.GetAccounts()); foreach (ExchangeAccount oldlist in oldDistributionLists) @@ -89,7 +97,29 @@ namespace WebsitePanel.Portal.HostedSolution foreach (string newlist in newDistributionLists) ES.Services.ExchangeServer.AddDistributionListMember(PanelRequest.ItemID, newlist, PanelRequest.AccountID); + //Security Groups + ExchangeAccount[] oldDSecurityGroups = ES.Services.Organizations.GetSecurityGroupsByMember(PanelRequest.ItemID, PanelRequest.AccountID); + List newSecurityGroups = new List(securegroups.GetAccounts()); + foreach (ExchangeAccount oldgroup in oldDSecurityGroups) + { + if (newSecurityGroups.Contains(oldgroup.AccountName)) + { + newSecurityGroups.Remove(oldgroup.AccountName); + } + else + { + ES.Services.Organizations.DeleteUserFromSecurityGroup(PanelRequest.ItemID, PanelRequest.AccountID, oldgroup.AccountName); + } + } + + foreach (string newgroup in newSecurityGroups) + { + ES.Services.Organizations.AddUserToSecurityGroup(PanelRequest.ItemID, PanelRequest.AccountID, newgroup); + } + messageBox.ShowSuccessMessage("EXCHANGE_UPDATE_MAILBOX_SETTINGS"); + + BindSettings(); } catch (Exception ex) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.designer.cs index 0de5ac65..a93df787 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserMemberOf.ascx.designer.cs @@ -163,7 +163,7 @@ namespace WebsitePanel.Portal.HostedSolution { /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::WebsitePanel.Portal.ExchangeServer.UserControls.AccountsList securegroups; + protected global::WebsitePanel.Portal.ExchangeServer.UserControls.GroupsList securegroups; /// /// btnSave control. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/GroupsList.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/GroupsList.ascx.resx new file mode 100644 index 00000000..58447d25 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/GroupsList.ascx.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Add... + + + Add Groups + + + Cancel + + + Delete + + + Display Name + + + The list of groups is empty. Click "Add..." button to add groups. + + + Display Name + + + No groups found. + + + Groups + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx new file mode 100644 index 00000000..185955d8 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx @@ -0,0 +1,105 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="GroupsList.ascx.cs" Inherits="WebsitePanel.Portal.ExchangeServer.UserControls.GroupsList" %> +<%@ Register Src="../../UserControls/PopupHeader.ascx" TagName="PopupHeader" TagPrefix="wsp" %> + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.cs new file mode 100644 index 00000000..85508aec --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.cs @@ -0,0 +1,197 @@ +// Copyright (c) 2012, Outercurve Foundation. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// - Neither the name of the Outercurve Foundation nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.Web.UI; +using System.Web.UI.WebControls; +using WebsitePanel.Providers.HostedSolution; +using System.Linq; + +namespace WebsitePanel.Portal.ExchangeServer.UserControls +{ + public partial class GroupsList : WebsitePanelControlBase + { + private enum SelectedState + { + All, + Selected, + Unselected + } + + public void SetAccounts(ExchangeAccount[] accounts) + { + BindAccounts(accounts, false); + } + + public string[] GetAccounts() + { + // get selected accounts + List selectedAccounts = GetGridViewAccounts(gvGroups, SelectedState.All); + + List accountNames = new List(); + foreach (ExchangeAccount account in selectedAccounts) + accountNames.Add(account.AccountName); + + return accountNames.ToArray(); + } + + protected void Page_Load(object sender, EventArgs e) + { + // register javascript + if (!Page.ClientScript.IsClientScriptBlockRegistered("SelectAllCheckboxes")) + { + string script = @" function SelectAllCheckboxes(box) + { + var state = box.checked; + var elm = box.parentElement.parentElement.parentElement.parentElement.getElementsByTagName(""INPUT""); + for(i = 0; i < elm.length; i++) + if(elm[i].type == ""checkbox"" && elm[i].id != box.id && elm[i].checked != state && !elm[i].disabled) + elm[i].checked = state; + }"; + Page.ClientScript.RegisterClientScriptBlock(typeof(AccountsList), "SelectAllCheckboxes", + script, true); + } + } + + public string GetAccountImage(int accountTypeId) + { + ExchangeAccountType accountType = (ExchangeAccountType)accountTypeId; + string imgName = "dlist_16.gif"; + + return GetThemedImage("Exchange/" + imgName); + } + + protected void btnAdd_Click(object sender, EventArgs e) + { + // bind all accounts + BindPopupAccounts(); + + // show modal + AddGroupsModal.Show(); + } + + protected void btnDelete_Click(object sender, EventArgs e) + { + // get selected accounts + List selectedAccounts = GetGridViewAccounts(gvGroups, SelectedState.Unselected); + + // add to the main list + BindAccounts(selectedAccounts.ToArray(), false); + } + + protected void btnAddSelected_Click(object sender, EventArgs e) + { + // get selected accounts + List selectedAccounts = GetGridViewAccounts(gvPopupGroups, SelectedState.Selected); + + // add to the main list + BindAccounts(selectedAccounts.ToArray(), true); + } + + private void BindPopupAccounts() + { + ExchangeAccount[] accounts = ES.Services.Organizations.SearchSecurityGroups(PanelRequest.ItemID, + ddlSearchColumn.SelectedValue, txtSearchValue.Text + "%", ""); + + accounts = accounts.Where(x => !GetAccounts().Contains(x.AccountName)).ToArray(); + + gvPopupGroups.DataSource = accounts; + gvPopupGroups.DataBind(); + } + + private void BindAccounts(ExchangeAccount[] newAccounts, bool preserveExisting) + { + // get binded addresses + List accounts = new List(); + if(preserveExisting) + accounts.AddRange(GetGridViewAccounts(gvGroups, SelectedState.All)); + + // add new accounts + if (newAccounts != null) + { + foreach (ExchangeAccount newAccount in newAccounts) + { + // check if exists + bool exists = false; + foreach (ExchangeAccount account in accounts) + { + if (String.Compare(newAccount.AccountName, account.AccountName, true) == 0) + { + exists = true; + break; + } + } + + if (exists) + continue; + + accounts.Add(newAccount); + } + } + + gvGroups.DataSource = accounts; + gvGroups.DataBind(); + + btnDelete.Visible = gvGroups.Rows.Count > 0; + } + + private List GetGridViewAccounts(GridView gv, SelectedState state) + { + List accounts = new List(); + for (int i = 0; i < gv.Rows.Count; i++) + { + GridViewRow row = gv.Rows[i]; + CheckBox chkSelect = (CheckBox)row.FindControl("chkSelect"); + if (chkSelect == null) + continue; + + ExchangeAccount account = new ExchangeAccount(); + account.AccountType = (ExchangeAccountType)Enum.Parse(typeof(ExchangeAccountType), ((Literal)row.FindControl("litAccountType")).Text); + account.AccountName = (string)gv.DataKeys[i][0]; + account.DisplayName = ((Literal)row.FindControl("litDisplayName")).Text; + + if(state == SelectedState.All || + (state == SelectedState.Selected && chkSelect.Checked) || + (state == SelectedState.Unselected && !chkSelect.Checked)) + accounts.Add(account); + } + return accounts; + } + + protected void chkIncludeMailboxes_CheckedChanged(object sender, EventArgs e) + { + BindPopupAccounts(); + } + + protected void cmdSearch_Click(object sender, ImageClickEventArgs e) + { + BindPopupAccounts(); + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.designer.cs new file mode 100644 index 00000000..1c6bff39 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/GroupsList.ascx.designer.cs @@ -0,0 +1,159 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WebsitePanel.Portal.ExchangeServer.UserControls { + + + public partial class GroupsList { + + /// + /// GroupsUpdatePanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.UpdatePanel GroupsUpdatePanel; + + /// + /// btnAdd control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnAdd; + + /// + /// btnDelete control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnDelete; + + /// + /// gvGroups control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.GridView gvGroups; + + /// + /// AddGroupsPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel AddGroupsPanel; + + /// + /// headerAddGroups control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize headerAddGroups; + + /// + /// AddGroupsUpdatePanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.UpdatePanel AddGroupsUpdatePanel; + + /// + /// SearchPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel SearchPanel; + + /// + /// ddlSearchColumn control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddlSearchColumn; + + /// + /// txtSearchValue control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtSearchValue; + + /// + /// cmdSearch control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ImageButton cmdSearch; + + /// + /// gvPopupGroups control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.GridView gvPopupGroups; + + /// + /// btnAddSelected control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnAddSelected; + + /// + /// btnCancelAdd control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnCancelAdd; + + /// + /// btnAddAccountsFake control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnAddAccountsFake; + + /// + /// AddGroupsModal control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::AjaxControlToolkit.ModalPopupExtender AddGroupsModal; + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/UsersList.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/UsersList.ascx.cs index d518459a..b8311fd5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/UsersList.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/UsersList.ascx.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Web.UI; using System.Web.UI.WebControls; using WebsitePanel.Providers.HostedSolution; +using System.Linq; namespace WebsitePanel.Portal.ExchangeServer.UserControls { @@ -218,6 +219,10 @@ namespace WebsitePanel.Portal.ExchangeServer.UserControls OrganizationUser[] accounts = ES.Services.Organizations.SearchAccounts(PanelRequest.ItemID, ddlSearchColumn.SelectedValue, txtSearchValue.Text + "%", "", IncludeMailboxes); + List newAccounts = new List(); + + accounts = accounts.Where(x => !GetAccounts().Contains(x.AccountName)).ToArray(); + if (ExcludeAccountId > 0) { List updatedAccounts = new List(); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj index 0216f51a..975475c9 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj @@ -283,6 +283,13 @@ AccountsListWithPermissions.ascx ASPXCodeBehind + + GroupsList.ascx + ASPXCodeBehind + + + GroupsList.ascx + MailboxPlanSelector.ascx ASPXCodeBehind @@ -3977,6 +3984,7 @@ + @@ -5189,6 +5197,9 @@ + + Designer + Designer