diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 6e66d880..aa60afa4 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -9684,4 +9684,65 @@ SELECT TokenType FROM AccessTokens Where AccessTokenGuid = @AccessToken AND ExpirationDate > getdate() AND TokenType = @TokenType +GO + + +-- ORGANIZATION SETTINGS + + +IF EXISTS (SELECT * FROM SYS.TABLES WHERE name = 'ExchangeOrganizationSettings') +DROP TABLE ExchangeOrganizationSettings +GO +CREATE TABLE ExchangeOrganizationSettings +( + ItemId INT NOT NULL, + SettingsName nvarchar(100) NOT NULL, + Xml nvarchar(max) NOT NULL +) +GO + +ALTER TABLE [dbo].[ExchangeOrganizationSettings] WITH CHECK ADD CONSTRAINT [FK_ExchangeOrganizationSettings_ExchangeOrganizations_ItemId] FOREIGN KEY([ItemId]) +REFERENCES [dbo].[ExchangeOrganizations] ([ItemId]) +ON DELETE CASCADE +GO + + + +IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE type = 'P' AND name = 'UpdateExchangeOrganizationSettings') +DROP PROCEDURE UpdateExchangeOrganizationSettings +GO +CREATE PROCEDURE [dbo].[UpdateExchangeOrganizationSettings] +( + @ItemId INT , + @SettingsName nvarchar(100) , + @Xml nvarchar(max) +) +AS +IF NOT EXISTS (SELECT * FROM [dbo].[ExchangeOrganizationSettings] WHERE [ItemId] = @ItemId AND [SettingsName]= @SettingsName ) +BEGIN +INSERT [dbo].[ExchangeOrganizationSettings] ([ItemId], [SettingsName], [Xml]) VALUES (@ItemId, @SettingsName, @Xml) +END +ELSE +UPDATE [dbo].[ExchangeOrganizationSettings] SET [Xml] = @Xml WHERE [ItemId] = @ItemId AND [SettingsName]= @SettingsName +GO + + + + +IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE type = 'P' AND name = 'GetExchangeOrganizationSettings') +DROP PROCEDURE GetExchangeOrganizationSettings +GO +CREATE PROCEDURE [dbo].[GetExchangeOrganizationSettings] +( + @ItemId INT , + @SettingsName nvarchar(100) +) +AS +SELECT + ItemId, + SettingsName, + Xml + +FROM ExchangeOrganizationSettings +Where ItemId = @ItemId AND SettingsName = @SettingsName GO \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs index 6740094f..f6780cf5 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs @@ -66,6 +66,7 @@ namespace WebsitePanel.EnterpriseServer public const string RDS_SETUP_LETTER = "RDSSetupLetter"; public const string RDS_POLICY = "RdsPolicy"; public const string USER_PASSWORD_EXPIRATION_LETTER = "UserPasswordExpirationLetter"; + public const string HOSTED_ORGANIZATION_PASSWORD_POLICY = "MailboxPasswordPolicy"; public int UserId; diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs index 92580b04..fa3c8d81 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs @@ -12,11 +12,11 @@ // This source code was auto-generated by wsdl, Version=2.0.50727.3038. // +using WebsitePanel.EnterpriseServer.Base.HostedSolution; using WebsitePanel.Providers; using WebsitePanel.Providers.Common; -using WebsitePanel.Providers.ResultObjects; using WebsitePanel.Providers.HostedSolution; -using WebsitePanel.EnterpriseServer.Base.HostedSolution; +using WebsitePanel.Providers.ResultObjects; namespace WebsitePanel.EnterpriseServer.HostedSolution { using System.Xml.Serialization; @@ -36,6 +36,10 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { [System.Xml.Serialization.XmlIncludeAttribute(typeof(ServiceProviderItem))] public partial class esOrganizations : Microsoft.Web.Services3.WebServicesClientProtocol { + private System.Threading.SendOrPostCallback UpdateOrganizationPasswordSettingsOperationCompleted; + + private System.Threading.SendOrPostCallback GetOrganizationPasswordSettingsOperationCompleted; + private System.Threading.SendOrPostCallback CheckOrgIdExistsOperationCompleted; private System.Threading.SendOrPostCallback CreateOrganizationOperationCompleted; @@ -145,6 +149,12 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { this.Url = "http://localhost:9002/esOrganizations.asmx"; } + /// + public event UpdateOrganizationPasswordSettingsCompletedEventHandler UpdateOrganizationPasswordSettingsCompleted; + + /// + public event GetOrganizationPasswordSettingsCompletedEventHandler GetOrganizationPasswordSettingsCompleted; + /// public event CheckOrgIdExistsCompletedEventHandler CheckOrgIdExistsCompleted; @@ -301,6 +311,89 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { /// public event GetSupportServiceLevelCompletedEventHandler GetSupportServiceLevelCompleted; + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/UpdateOrganizationPasswordSettings", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void UpdateOrganizationPasswordSettings(int itemId, OrganizationPasswordSettings settings) { + this.Invoke("UpdateOrganizationPasswordSettings", new object[] { + itemId, + settings}); + } + + /// + public System.IAsyncResult BeginUpdateOrganizationPasswordSettings(int itemId, OrganizationPasswordSettings settings, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("UpdateOrganizationPasswordSettings", new object[] { + itemId, + settings}, callback, asyncState); + } + + /// + public void EndUpdateOrganizationPasswordSettings(System.IAsyncResult asyncResult) { + this.EndInvoke(asyncResult); + } + + /// + public void UpdateOrganizationPasswordSettingsAsync(int itemId, OrganizationPasswordSettings settings) { + this.UpdateOrganizationPasswordSettingsAsync(itemId, settings, null); + } + + /// + public void UpdateOrganizationPasswordSettingsAsync(int itemId, OrganizationPasswordSettings settings, object userState) { + if ((this.UpdateOrganizationPasswordSettingsOperationCompleted == null)) { + this.UpdateOrganizationPasswordSettingsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnUpdateOrganizationPasswordSettingsOperationCompleted); + } + this.InvokeAsync("UpdateOrganizationPasswordSettings", new object[] { + itemId, + settings}, this.UpdateOrganizationPasswordSettingsOperationCompleted, userState); + } + + private void OnUpdateOrganizationPasswordSettingsOperationCompleted(object arg) { + if ((this.UpdateOrganizationPasswordSettingsCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.UpdateOrganizationPasswordSettingsCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetOrganizationPasswordSettings", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public OrganizationPasswordSettings GetOrganizationPasswordSettings(int itemId) { + object[] results = this.Invoke("GetOrganizationPasswordSettings", new object[] { + itemId}); + return ((OrganizationPasswordSettings)(results[0])); + } + + /// + public System.IAsyncResult BeginGetOrganizationPasswordSettings(int itemId, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("GetOrganizationPasswordSettings", new object[] { + itemId}, callback, asyncState); + } + + /// + public OrganizationPasswordSettings EndGetOrganizationPasswordSettings(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((OrganizationPasswordSettings)(results[0])); + } + + /// + public void GetOrganizationPasswordSettingsAsync(int itemId) { + this.GetOrganizationPasswordSettingsAsync(itemId, null); + } + + /// + public void GetOrganizationPasswordSettingsAsync(int itemId, object userState) { + if ((this.GetOrganizationPasswordSettingsOperationCompleted == null)) { + this.GetOrganizationPasswordSettingsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetOrganizationPasswordSettingsOperationCompleted); + } + this.InvokeAsync("GetOrganizationPasswordSettings", new object[] { + itemId}, this.GetOrganizationPasswordSettingsOperationCompleted, userState); + } + + private void OnGetOrganizationPasswordSettingsOperationCompleted(object arg) { + if ((this.GetOrganizationPasswordSettingsCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetOrganizationPasswordSettingsCompleted(this, new GetOrganizationPasswordSettingsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// [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) { @@ -2936,6 +3029,36 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { } } + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void UpdateOrganizationPasswordSettingsCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetOrganizationPasswordSettingsCompletedEventHandler(object sender, GetOrganizationPasswordSettingsCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetOrganizationPasswordSettingsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal GetOrganizationPasswordSettingsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public OrganizationPasswordSettings Result { + get { + this.RaiseExceptionIfNecessary(); + return ((OrganizationPasswordSettings)(this.results[0])); + } + } + } + /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void CheckOrgIdExistsCompletedEventHandler(object sender, CheckOrgIdExistsCompletedEventArgs e); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Common/ObjectUtils.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Common/ObjectUtils.cs index 67b8a138..ea5744ca 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Common/ObjectUtils.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Common/ObjectUtils.cs @@ -27,11 +27,13 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; +using System.IO; using System.Reflection; using System.Data; using System.Collections; using System.Collections.Generic; - +using System.Xml; +using System.Xml.Serialization; using WebsitePanel.Providers; namespace WebsitePanel.EnterpriseServer @@ -645,6 +647,37 @@ namespace WebsitePanel.EnterpriseServer return type.FullName + ", " + type.Assembly.GetName().Name; } + public static TResult Deserialize(string inputString) + { + TResult result; + + var serializer = new XmlSerializer(typeof(TResult)); + + using (TextReader reader = new StringReader(inputString)) + { + result = (TResult)serializer.Deserialize(reader); + } + + return result; + } + + public static string Serialize(TEntity entity) + { + string result = string.Empty; + + var xmlSerializer = new XmlSerializer(typeof(TEntity)); + + using (var stringWriter = new StringWriter()) + { + using (XmlWriter writer = XmlWriter.Create(stringWriter)) + { + xmlSerializer.Serialize(writer, entity); + result = stringWriter.ToString(); + } + } + + return result; + } #region Helper Functions diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs index c7bff6f7..a9ee96ac 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs @@ -3236,6 +3236,23 @@ namespace WebsitePanel.EnterpriseServer ); } + public static void UpdateOrganizationSettings(int itemId, string settingsName, string xml) + { + SqlHelper.ExecuteNonQuery(ConnectionString, CommandType.StoredProcedure, + ObjectQualifier + "UpdateExchangeOrganizationSettings", + new SqlParameter("@ItemId", itemId), + new SqlParameter("@SettingsName", settingsName), + new SqlParameter("@Xml", xml)); + } + + public static IDataReader GetOrganizationSettings(int itemId, string settingsName) + { + return SqlHelper.ExecuteReader(ConnectionString, CommandType.StoredProcedure, + ObjectQualifier + "GetExchangeOrganizationSettings", + new SqlParameter("@ItemId", itemId), + new SqlParameter("@SettingsName", settingsName)); + } + public static int AddOrganizationDeletedUser(int accountId, int originAT, string storagePath, string folderName, string fileName, DateTime expirationDate) { SqlParameter outParam = new SqlParameter("@ID", SqlDbType.Int); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs index 499f9bfc..5f0a1e59 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs @@ -1647,6 +1647,56 @@ namespace WebsitePanel.EnterpriseServer return token; } + public static void UpdateOrganizationPasswordSettings(int itemId, OrganizationPasswordSettings settings) + { + TaskManager.StartTask("ORGANIZATION", "UPDATE_PASSWORD_SETTINGS"); + + try + { + // load organization + Organization org = GetOrganization(itemId); + + if (org == null) + { + TaskManager.WriteWarning("Organization with itemId '{0}' not found", itemId.ToString()); + return; + } + + Organizations orgProxy = GetOrganizationProxy(org.ServiceId); + + orgProxy.ApplyPasswordSettings(org.OrganizationId, settings); + + var xml = ObjectUtils.Serialize(settings); + + DataProvider.UpdateOrganizationSettings(itemId, OrganizationSettings.PasswordSettings, xml); + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + TaskManager.CompleteTask(); + } + } + + public static OrganizationPasswordSettings GetOrganizationPasswordSettings(int itemId) + { + return GetOrganizationSettings(itemId, OrganizationSettings.PasswordSettings); + } + + private static T GetOrganizationSettings(int itemId, string settingsName) + { + var entity = ObjectUtils.FillObjectFromDataReader(DataProvider.GetOrganizationSettings(itemId, settingsName)); + + if (entity == null) + { + return default(T); + } + + return ObjectUtils.Deserialize(entity.Xml); + } + private static bool EmailAddressExists(string emailAddress) { return DataProvider.ExchangeAccountEmailAddressExists(emailAddress); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs index 6352e52b..0524c2d8 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs @@ -47,6 +47,18 @@ namespace WebsitePanel.EnterpriseServer { #region Organizations + [WebMethod] + public void UpdateOrganizationPasswordSettings(int itemId, OrganizationPasswordSettings settings) + { + OrganizationController.UpdateOrganizationPasswordSettings(itemId, settings); + } + + [WebMethod] + public OrganizationPasswordSettings GetOrganizationPasswordSettings(int itemId) + { + return OrganizationController.GetOrganizationPasswordSettings(itemId); + } + [WebMethod] public bool CheckOrgIdExists(string orgId) { diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs index 99e2c637..8386310e 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs @@ -99,5 +99,6 @@ namespace WebsitePanel.Providers.HostedSolution void ChangeDriveMapFolderPath(string organizationId, string oldFolder, string newFolder); List GetOrganizationUsersWithExpiredPassword(string organizationId, int daysBeforeExpiration); + void ApplyPasswordSettings(string organizationId, OrganizationPasswordSettings passwordSettings); } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationPasswordSettings.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationPasswordSettings.cs new file mode 100644 index 00000000..cc00f552 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationPasswordSettings.cs @@ -0,0 +1,19 @@ +namespace WebsitePanel.Providers.HostedSolution +{ + public class OrganizationPasswordSettings + { + public int MinimumLength { get; set; } + public int MaximumLength { get; set; } + public int EnforcePasswordHistory { get; set; } + + public bool LockoutSettingsEnabled { get; set; } + public int AccountLockoutDuration { get; set; } + public int AccountLockoutThreshold { get; set; } + public int ResetAccountLockoutCounterAfter { get; set; } + + public bool PasswordComplexityEnabled { get; set; } + public int UppercaseLettersCount { get; set; } + public int NumbersCount { get; set; } + public int SymbolsCount { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationSettings.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationSettings.cs new file mode 100644 index 00000000..38e01f95 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationSettings.cs @@ -0,0 +1,7 @@ +namespace WebsitePanel.Providers.HostedSolution +{ + public class OrganizationSettings + { + public const string PasswordSettings = "PasswordSettings"; + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationSettingsEntity.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationSettingsEntity.cs new file mode 100644 index 00000000..750e26a2 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/OrganizationSettingsEntity.cs @@ -0,0 +1,9 @@ +namespace WebsitePanel.Providers.HostedSolution +{ + public class OrganizationSettingsEntity + { + public int ItemId { get; set; } + public string SettingsName { get; set; } + public string Xml { get; set; } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index e72359e6..a8951639 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -119,9 +119,12 @@ + + + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs index 26d4dfb8..ddeeba63 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs @@ -552,6 +552,114 @@ namespace WebsitePanel.Providers.HostedSolution } } + public void ApplyPasswordSettings(string organizationId, OrganizationPasswordSettings settings) + { + HostedSolutionLog.LogStart("ApplyPasswordPolicy"); + + Runspace runspace = null; + + try + { + runspace = OpenRunspace(); + + var gpoId = CreatePolicyIfNotExist(runspace, organizationId, FormOrganizationSettingsGpoName(organizationId)); + } + catch (Exception ex) + { + HostedSolutionLog.LogError(ex); + throw; + } + finally + { + CloseRunspace(runspace); + HostedSolutionLog.LogEnd("ApplyPasswordPolicy"); + } + } + + private string FormOrganizationSettingsGpoName(string organizationId) + { + return string.Format("{0}-settings", organizationId); + } + + private string CreatePolicyIfNotExist(Runspace runspace, string organizationId, string gpoName) + { + string gpoId = GetPolicyId(runspace, gpoName); + + if (string.IsNullOrEmpty(gpoId)) + { + gpoId = CreateAndLinkPolicy(runspace, gpoName, organizationId); + } + + return gpoId; + } + + private void DeleteGpo(Runspace runspace, string gpoName) + { + Command cmd = new Command("Remove-GPO"); + cmd.Parameters.Add("Name", gpoName); + + // Collection result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd); + } + + private string CreateAndLinkPolicy(Runspace runspace, string gpoName, string organizationId) + { + string pathOU = GetOrganizationTargetPath(organizationId); + + //create new gpo + Command cmd = new Command("New-GPO"); + cmd.Parameters.Add("Name", gpoName); + + Collection result = ExecuteShellCommand(runspace, cmd); + + string gpoId = null; + + if (result != null && result.Count > 0) + { + PSObject gpo = result[0]; + //get gpo id + gpoId = ((Guid) GetPSObjectProperty(gpo, "Id")).ToString("B"); + + } + + //create gpo link + cmd = new Command("New-GPLink"); + cmd.Parameters.Add("Name", gpoName); + cmd.Parameters.Add("Target", pathOU); + + ExecuteShellCommand(runspace, cmd); + + return gpoId; + } + + private string GetPolicyId(Runspace runspace, string gpoName) + { + Runspace runSpace = null; + + string gpoId = null; + + try + { + runSpace = OpenRunspace(); + + Command cmd = new Command("Get-GPO"); + cmd.Parameters.Add("Name", gpoName); + + Collection result = ExecuteShellCommand(runSpace, cmd); + + if (result != null && result.Count > 0) + { + PSObject gpo = result[0]; + gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B"); + } + } + finally + { + CloseRunspace(runSpace); + } + + return gpoId; + } + public PasswordPolicyResult GetPasswordPolicy() { return GetPasswordPolicyInternal(); diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs index ef15952c..ddbe1a66 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs @@ -12,6 +12,7 @@ // This source code was auto-generated by wsdl, Version=2.0.50727.3038. // + using WebsitePanel.Providers.Common; using WebsitePanel.Providers.OS; using WebsitePanel.Providers.ResultObjects; @@ -94,6 +95,8 @@ namespace WebsitePanel.Providers.HostedSolution { private System.Threading.SendOrPostCallback GetOrganizationUsersWithExpiredPasswordOperationCompleted; + private System.Threading.SendOrPostCallback ApplyPasswordSettingsOperationCompleted; + /// public Organizations() { this.Url = "http://localhost:9003/Organizations.asmx"; @@ -186,6 +189,9 @@ namespace WebsitePanel.Providers.HostedSolution { /// public event GetOrganizationUsersWithExpiredPasswordCompletedEventHandler GetOrganizationUsersWithExpiredPasswordCompleted; + /// + public event ApplyPasswordSettingsCompletedEventHandler ApplyPasswordSettingsCompleted; + /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/OrganizationExists", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] @@ -1675,6 +1681,49 @@ namespace WebsitePanel.Providers.HostedSolution { } } + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ApplyPasswordSettings", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void ApplyPasswordSettings(string organizationId, OrganizationPasswordSettings passwordSettings) { + this.Invoke("ApplyPasswordSettings", new object[] { + organizationId, + passwordSettings}); + } + + /// + public System.IAsyncResult BeginApplyPasswordSettings(string organizationId, OrganizationPasswordSettings passwordSettings, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("ApplyPasswordSettings", new object[] { + organizationId, + passwordSettings}, callback, asyncState); + } + + /// + public void EndApplyPasswordSettings(System.IAsyncResult asyncResult) { + this.EndInvoke(asyncResult); + } + + /// + public void ApplyPasswordSettingsAsync(string organizationId, OrganizationPasswordSettings passwordSettings) { + this.ApplyPasswordSettingsAsync(organizationId, passwordSettings, null); + } + + /// + public void ApplyPasswordSettingsAsync(string organizationId, OrganizationPasswordSettings passwordSettings, object userState) { + if ((this.ApplyPasswordSettingsOperationCompleted == null)) { + this.ApplyPasswordSettingsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnApplyPasswordSettingsOperationCompleted); + } + this.InvokeAsync("ApplyPasswordSettings", new object[] { + organizationId, + passwordSettings}, this.ApplyPasswordSettingsOperationCompleted, userState); + } + + private void OnApplyPasswordSettingsOperationCompleted(object arg) { + if ((this.ApplyPasswordSettingsCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.ApplyPasswordSettingsCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { base.CancelAsync(userState); @@ -2060,4 +2109,8 @@ namespace WebsitePanel.Providers.HostedSolution { } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void ApplyPasswordSettingsCompletedEventHandler(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 4cae8631..61c568b3 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs @@ -261,5 +261,11 @@ namespace WebsitePanel.Server { return Organization.GetOrganizationUsersWithExpiredPassword(organizationId, daysBeforeExpiration); } + + [WebMethod, SoapHeader("settings")] + public void ApplyPasswordSettings(string organizationId, OrganizationPasswordSettings passwordSettings) + { + Organization.ApplyPasswordSettings(organizationId, passwordSettings); + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config index e3263482..4a2b2c76 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config @@ -476,6 +476,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx index 975a6a96..490b50b0 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx @@ -5713,4 +5713,7 @@ User password expiration notification + + Error during updating settings. + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationHome.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationHome.ascx.resx index 7b71c51e..2e38b9a4 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationHome.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationHome.ascx.resx @@ -237,4 +237,10 @@ RDS Users + + Edit + + + Organization settings + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationSettingsPasswordSettings.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationSettingsPasswordSettings.ascx.resx new file mode 100644 index 00000000..8387aed9 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationSettingsPasswordSettings.ascx.resx @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Save Changes + + + Enable Lockout Settings + + + Enable Password Complexity + + + Password settings + + + Account lockout duration: + + + Enforce password history: + + + Account lockout threshold: + + + Lock out settings: + + + Maximum length: + + + Minimum length: + + + Numbers: + + + Non-alphanumeric symbols: + + + Uppercase letters: + + + Reset account lockout counter after (minutes): + + + Password should contain at least: + + + Edit settings + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + + * + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeCreateMailbox.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeCreateMailbox.ascx.cs index 90254770..20d3049f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeCreateMailbox.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/ExchangeCreateMailbox.ascx.cs @@ -49,23 +49,7 @@ namespace WebsitePanel.Portal.ExchangeServer if (!IsPostBack) { - password.SetPackagePolicy(PanelSecurity.PackageId, UserSettings.EXCHANGE_POLICY, "MailboxPasswordPolicy"); - PasswordPolicyResult passwordPolicy = ES.Services.Organizations.GetPasswordPolicy(PanelRequest.ItemID); - if (passwordPolicy.IsSuccess) - { - password.MinimumLength = passwordPolicy.Value.MinLength; - if (passwordPolicy.Value.IsComplexityEnable) - { - password.MinimumNumbers = 1; - password.MinimumSymbols = 1; - password.MinimumUppercase = 1; - } - } - else - { - messageBox.ShowMessage(passwordPolicy, "EXCHANGE_CREATE_MAILBOX", "HostedOrganization"); - return; - } + BindPasswordSettings(); string instructions = ES.Services.ExchangeServer.GetMailboxSetupInstructions(PanelRequest.ItemID, PanelRequest.AccountID, false, false, false); if (!string.IsNullOrEmpty(instructions)) @@ -135,6 +119,37 @@ namespace WebsitePanel.Portal.ExchangeServer } + private void BindPasswordSettings() + { + var grainedPasswordSettigns = ES.Services.Organizations.GetOrganizationPasswordSettings(PanelRequest.ItemID); + + if (grainedPasswordSettigns != null) + { + password.SetUserPolicy(grainedPasswordSettigns); + } + else + { + password.SetPackagePolicy(PanelSecurity.PackageId, UserSettings.EXCHANGE_POLICY, "MailboxPasswordPolicy"); + + PasswordPolicyResult passwordPolicy = ES.Services.Organizations.GetPasswordPolicy(PanelRequest.ItemID); + + if (passwordPolicy.IsSuccess) + { + password.MinimumLength = passwordPolicy.Value.MinLength; + if (passwordPolicy.Value.IsComplexityEnable) + { + password.MinimumNumbers = 1; + password.MinimumSymbols = 1; + password.MinimumUppercase = 1; + } + } + else + { + messageBox.ShowMessage(passwordPolicy, "CREATE_ORGANIZATION_USER", "HostedOrganization"); + } + } + } + protected void btnCreate_Click(object sender, EventArgs e) { CreateMailbox(); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationCreateUser.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationCreateUser.ascx.cs index 97a724d6..11f190db 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationCreateUser.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationCreateUser.ascx.cs @@ -40,23 +40,7 @@ namespace WebsitePanel.Portal.HostedSolution { if (!IsPostBack) { - password.SetPackagePolicy(PanelSecurity.PackageId, UserSettings.EXCHANGE_POLICY, "MailboxPasswordPolicy"); - - PasswordPolicyResult passwordPolicy = ES.Services.Organizations.GetPasswordPolicy(PanelRequest.ItemID); - if (passwordPolicy.IsSuccess) - { - password.MinimumLength = passwordPolicy.Value.MinLength; - if (passwordPolicy.Value.IsComplexityEnable) - { - password.MinimumNumbers = 1; - password.MinimumSymbols = 1; - password.MinimumUppercase = 1; - } - } - else - { - messageBox.ShowMessage(passwordPolicy, "CREATE_ORGANIZATION_USER", "HostedOrganization"); - } + BindPasswordSettings(); string instructions = ES.Services.Organizations.GetOrganizationUserSummuryLetter(PanelRequest.ItemID, PanelRequest.AccountID, false, false, false); if (!string.IsNullOrEmpty(instructions)) @@ -88,6 +72,37 @@ namespace WebsitePanel.Portal.HostedSolution } + private void BindPasswordSettings() + { + var grainedPasswordSettigns = ES.Services.Organizations.GetOrganizationPasswordSettings(PanelRequest.ItemID); + + if (grainedPasswordSettigns != null) + { + password.SetUserPolicy(grainedPasswordSettigns); + } + else + { + password.SetPackagePolicy(PanelSecurity.PackageId, UserSettings.EXCHANGE_POLICY, "MailboxPasswordPolicy"); + + PasswordPolicyResult passwordPolicy = ES.Services.Organizations.GetPasswordPolicy(PanelRequest.ItemID); + + if (passwordPolicy.IsSuccess) + { + password.MinimumLength = passwordPolicy.Value.MinLength; + if (passwordPolicy.Value.IsComplexityEnable) + { + password.MinimumNumbers = 1; + password.MinimumSymbols = 1; + password.MinimumUppercase = 1; + } + } + else + { + messageBox.ShowMessage(passwordPolicy, "CREATE_ORGANIZATION_USER", "HostedOrganization"); + } + } + } + protected void btnCreate_Click(object sender, EventArgs e) { CreateMailbox(); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx index 532fc488..e8c1d3e7 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx @@ -37,6 +37,14 @@ + + + + + + + +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.cs index 7a483c39..de167b9a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.cs @@ -175,6 +175,9 @@ namespace WebsitePanel.Portal.ExchangeServer lblOrganizationNameValue.Text = org.Name; lblOrganizationIDValue.Text = org.OrganizationId; lblCreatedValue.Text = org.CreatedDate.Date.ToShortDateString(); + lnkEditOrganizationSettings.NavigateUrl = EditUrl("ItemID", PanelRequest.ItemID.ToString(), "organization_settings_password_settings", + "SpaceID=" + PanelSecurity.PackageId); + OrganizationStatistics orgStats = ES.Services.Organizations.GetOrganizationStatisticsByOrganization(PanelRequest.ItemID); OrganizationStatistics tenantStats = ES.Services.Organizations.GetOrganizationStatistics(PanelRequest.ItemID); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.designer.cs index 26a5655d..f0f7aab1 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationHome.ascx.designer.cs @@ -84,6 +84,24 @@ namespace WebsitePanel.Portal.ExchangeServer { /// protected global::System.Web.UI.WebControls.Label lblCreatedValue; + /// + /// Label1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label Label1; + + /// + /// lnkEditOrganizationSettings control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink lnkEditOrganizationSettings; + /// /// organizationStatsPanel control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx new file mode 100644 index 00000000..0b99d95e --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx @@ -0,0 +1,164 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OrganizationSettingsPasswordSettings.ascx.cs" Inherits="WebsitePanel.Portal.ExchangeServer.OrganizationSettingsPasswordSettings" %> + +<%@ Register Src="UserControls/OrganizationSettingsTabs.ascx" TagName="CollectionTabs" TagPrefix="wsp" %> +<%@ Register TagPrefix="wsp" TagName="CollapsiblePanel" Src="../UserControls/CollapsiblePanel.ascx" %> +<%@ Register Src="../UserControls/SimpleMessageBox.ascx" TagName="SimpleMessageBox" TagPrefix="wsp" %> +<%@ Register Src="../UserControls/ItemButtonPanel.ascx" TagName="ItemButtonPanel" TagPrefix="wsp" %> +<%@ Register Src="../UserControls/EnableAsyncTasksSupport.ascx" TagName="EnableAsyncTasksSupport" TagPrefix="wsp" %> + + + + +
+
+
+
+
+
+
+ + + + +
+
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ + +
+ +
+ + +
+ + + +
+ + + +
+ +
+ + + + +
+ + + + +
+ + + + +
+ +
+ + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx.cs new file mode 100644 index 00000000..48ceea57 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using WebsitePanel.EnterpriseServer; +using WebsitePanel.Providers.HostedSolution; + +namespace WebsitePanel.Portal.ExchangeServer +{ + public partial class OrganizationSettingsPasswordSettings : WebsitePanelModuleBase + { + protected void Page_Load(object sender, EventArgs e) + { + if (!IsPostBack) + { + Organization org = ES.Services.Organizations.GetOrganization(PanelRequest.ItemID); + litOrganizationName.Text = org.OrganizationId; + + BindSettings(); + } + + } + + private void BindSettings() + { + var settings = ES.Services.Organizations.GetOrganizationPasswordSettings(PanelRequest.ItemID); + + if (settings == null) + { + var defaultSettings = ES.Services.Users.GetUserSettings(PanelSecurity.LoggedUserId, UserSettings.EXCHANGE_POLICY); + + BindDefaultSettings(defaultSettings[UserSettings.HOSTED_ORGANIZATION_PASSWORD_POLICY]); + } + else + { + BindSettings(settings); + } + + ToggleLockoutControls(chkLockOutSettigns.Checked); + ToggleComplexityControls(chkPasswordComplexity.Checked); + } + + private void BindDefaultSettings(string defaultSettings) + { + // parse settings + string[] parts = defaultSettings.Split(';'); + txtMinimumLength.Text = parts[1]; + txtMaximumLength.Text = parts[2]; + txtMinimumUppercase.Text = parts[3]; + txtMinimumNumbers.Text = parts[4]; + txtMinimumSymbols.Text = parts[5]; + chkNotEqualUsername.Checked = Utils.ParseBool(parts[6], false); + txtLockedOut.Text = parts[7]; + + txtEnforcePasswordHistory.Text = PasswordPolicyEditor.GetValueSafe(parts, 8, "0"); + txtAccountLockoutDuration.Text = PasswordPolicyEditor.GetValueSafe(parts, 9, "0"); + txtResetAccountLockout.Text = PasswordPolicyEditor.GetValueSafe(parts, 10, "0"); + chkLockOutSettigns.Checked = PasswordPolicyEditor.GetValueSafe(parts, 11, false); + chkPasswordComplexity.Checked = PasswordPolicyEditor.GetValueSafe(parts, 12, true); + } + + private void BindSettings(OrganizationPasswordSettings settings) + { + txtMinimumLength.Text = settings.MinimumLength.ToString(); + txtMaximumLength.Text = settings.MaximumLength.ToString(); + txtMinimumUppercase.Text = settings.UppercaseLettersCount.ToString(); + txtMinimumNumbers.Text = settings.NumbersCount.ToString(); + txtMinimumSymbols.Text = settings.SymbolsCount.ToString(); + txtLockedOut.Text = settings.AccountLockoutThreshold.ToString(); + + txtEnforcePasswordHistory.Text = settings.EnforcePasswordHistory.ToString(); + txtAccountLockoutDuration.Text = settings.AccountLockoutDuration.ToString(); + txtResetAccountLockout.Text = settings.ResetAccountLockoutCounterAfter.ToString(); + chkLockOutSettigns.Checked = settings.LockoutSettingsEnabled; + chkPasswordComplexity.Checked = settings.PasswordComplexityEnabled; + } + + private OrganizationPasswordSettings GetSettings() + { + var settings = new OrganizationPasswordSettings(); + + settings.MinimumLength = Utils.ParseInt(txtMinimumLength.Text, 3); + settings.MaximumLength = Utils.ParseInt(txtMaximumLength.Text, 7); + settings.UppercaseLettersCount = Utils.ParseInt(txtMinimumUppercase.Text, 3); + settings.NumbersCount = Utils.ParseInt(txtMinimumNumbers.Text, 3); + settings.SymbolsCount = Utils.ParseInt(txtMinimumSymbols.Text, 3); + settings.AccountLockoutThreshold = Utils.ParseInt(txtLockedOut.Text, 3); + settings.EnforcePasswordHistory = Utils.ParseInt(txtEnforcePasswordHistory.Text, 3); + settings.AccountLockoutDuration = Utils.ParseInt(txtAccountLockoutDuration.Text, 3); + settings.ResetAccountLockoutCounterAfter = Utils.ParseInt(txtResetAccountLockout.Text, 3); + + settings.LockoutSettingsEnabled = chkLockOutSettigns.Checked; + settings.PasswordComplexityEnabled =chkPasswordComplexity.Checked; + + return settings; + } + + + private bool SavePasswordSettings() + { + try + { + ES.Services.Organizations.UpdateOrganizationPasswordSettings(PanelRequest.ItemID, GetSettings()); + } + catch (Exception ex) + { + ShowErrorMessage("ORANIZATIONSETTINGS_NOT_UPDATED", ex); + return false; + } + + return true; + } + + protected void btnSave_Click(object sender, EventArgs e) + { + if (!Page.IsValid) + { + return; + } + + SavePasswordSettings(); + } + + private void ToggleLockoutControls(bool visible) + { + RowAccountLockoutDuration.Visible = visible; + RowLockedOut.Visible = visible; + RowResetAccountLockout.Visible = visible; + } + + protected void chkLockOutSettigns_CheckedChanged(object sender, EventArgs e) + { + ToggleLockoutControls(chkLockOutSettigns.Checked); + } + + private void ToggleComplexityControls(bool visible) + { + RowMinimumUppercase.Visible = visible; + RowMinimumNumbers.Visible = visible; + RowMinimumSymbols.Visible = visible; + } + + protected void chkPasswordComplexity_CheckedChanged(object sender, EventArgs e) + { + ToggleComplexityControls(chkPasswordComplexity.Checked); + } + + protected void btnSaveExit_Click(object sender, EventArgs e) + { + if (!Page.IsValid) + { + return; + } + + if (SavePasswordSettings()) + { + Response.Redirect(EditUrl("ItemID", PanelRequest.ItemID.ToString(), "organization_home", "SpaceID=" + PanelSecurity.PackageId)); + } + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx.designer.cs new file mode 100644 index 00000000..345b5367 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationSettingsPasswordSettings.ascx.designer.cs @@ -0,0 +1,519 @@ +//------------------------------------------------------------------------------ +// +// 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 { + + + public partial class OrganizationSettingsPasswordSettings { + + /// + /// asyncTasks control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.EnableAsyncTasksSupport asyncTasks; + + /// + /// Image1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Image Image1; + + /// + /// locTitle control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locTitle; + + /// + /// litOrganizationName control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal litOrganizationName; + + /// + /// tabs control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.ExchangeServer.UserControls.OrganizationSettingsTabs tabs; + + /// + /// messageBox control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.UserControls.SimpleMessageBox messageBox; + + /// + /// PasswordPolicyPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.UpdatePanel PasswordPolicyPanel; + + /// + /// colPasswordSettings control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.CollapsiblePanel colPasswordSettings; + + /// + /// panelPasswordSettings control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel panelPasswordSettings; + + /// + /// PolicyTable control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTable PolicyTable; + + /// + /// lblMinimumLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblMinimumLength; + + /// + /// txtMinimumLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtMinimumLength; + + /// + /// valRequireMinLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireMinLength; + + /// + /// valCorrectMinLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectMinLength; + + /// + /// lblMaximumLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblMaximumLength; + + /// + /// txtMaximumLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtMaximumLength; + + /// + /// valRequireMaxLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireMaxLength; + + /// + /// valCorrectMaxLength control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectMaxLength; + + /// + /// lblEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblEnforcePasswordHistory; + + /// + /// txtEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtEnforcePasswordHistory; + + /// + /// valRequireEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireEnforcePasswordHistory; + + /// + /// valCorrectEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectEnforcePasswordHistory; + + /// + /// RowChkLockOutSettigns control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowChkLockOutSettigns; + + /// + /// chkLockOutSettigns control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox chkLockOutSettigns; + + /// + /// RowAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowAccountLockoutDuration; + + /// + /// lblAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblAccountLockoutDuration; + + /// + /// txtAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtAccountLockoutDuration; + + /// + /// valRequireAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireAccountLockoutDuration; + + /// + /// valCorrectAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectAccountLockoutDuration; + + /// + /// RowLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowLockedOut; + + /// + /// lblLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblLockedOut; + + /// + /// txtLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtLockedOut; + + /// + /// valCorrectLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectLockedOut; + + /// + /// RowResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowResetAccountLockout; + + /// + /// lblResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblResetAccountLockout; + + /// + /// txtResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtResetAccountLockout; + + /// + /// valResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valResetAccountLockout; + + /// + /// chkPasswordComplexity control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox chkPasswordComplexity; + + /// + /// RowMinimumUppercase control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowMinimumUppercase; + + /// + /// lblMinimumUppercase control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblMinimumUppercase; + + /// + /// txtMinimumUppercase control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtMinimumUppercase; + + /// + /// valRequireUppercase control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireUppercase; + + /// + /// valCorrectUppercase control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectUppercase; + + /// + /// RowMinimumNumbers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowMinimumNumbers; + + /// + /// lblMinimumNumbers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblMinimumNumbers; + + /// + /// txtMinimumNumbers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtMinimumNumbers; + + /// + /// valRequireNumbers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireNumbers; + + /// + /// valCorrectNumbers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectNumbers; + + /// + /// RowMinimumSymbols control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowMinimumSymbols; + + /// + /// lblMinimumSymbols control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblMinimumSymbols; + + /// + /// txtMinimumSymbols control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtMinimumSymbols; + + /// + /// valRequireSymbols control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireSymbols; + + /// + /// valCorrectSymbols control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectSymbols; + + /// + /// rowEqualUsername control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow rowEqualUsername; + + /// + /// chkNotEqualUsername control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox chkNotEqualUsername; + + /// + /// buttonPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.ItemButtonPanel buttonPanel; + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserGeneralSettings.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserGeneralSettings.ascx.cs index bde31fc9..7eed531f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserGeneralSettings.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserGeneralSettings.ascx.cs @@ -59,18 +59,7 @@ namespace WebsitePanel.Portal.HostedSolution { try { - password.SetPackagePolicy(PanelSecurity.PackageId, UserSettings.EXCHANGE_POLICY, "MailboxPasswordPolicy"); - PasswordPolicyResult passwordPolicy = ES.Services.Organizations.GetPasswordPolicy(PanelRequest.ItemID); - if (passwordPolicy.IsSuccess) - { - password.MinimumLength = passwordPolicy.Value.MinLength; - if (passwordPolicy.Value.IsComplexityEnable) - { - password.MinimumNumbers = 1; - password.MinimumSymbols = 1; - password.MinimumUppercase = 1; - } - } + BindPasswordSettings(); // get settings OrganizationUser user = ES.Services.Organizations.GetUserGeneralSettings(PanelRequest.ItemID, @@ -273,6 +262,37 @@ namespace WebsitePanel.Portal.HostedSolution } + private void BindPasswordSettings() + { + var grainedPasswordSettigns = ES.Services.Organizations.GetOrganizationPasswordSettings(PanelRequest.ItemID); + + if (grainedPasswordSettigns != null) + { + password.SetUserPolicy(grainedPasswordSettigns); + } + else + { + password.SetPackagePolicy(PanelSecurity.PackageId, UserSettings.EXCHANGE_POLICY, "MailboxPasswordPolicy"); + + PasswordPolicyResult passwordPolicy = ES.Services.Organizations.GetPasswordPolicy(PanelRequest.ItemID); + + if (passwordPolicy.IsSuccess) + { + password.MinimumLength = passwordPolicy.Value.MinLength; + if (passwordPolicy.Value.IsComplexityEnable) + { + password.MinimumNumbers = 1; + password.MinimumSymbols = 1; + password.MinimumUppercase = 1; + } + } + else + { + messageBox.ShowMessage(passwordPolicy, "CREATE_ORGANIZATION_USER", "HostedOrganization"); + } + } + } + private bool CheckServiceLevelQuota(QuotaValueInfo quota) { diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/OrganizationSettingsTabs.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/OrganizationSettingsTabs.ascx.resx new file mode 100644 index 00000000..ecbb2a94 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/App_LocalResources/OrganizationSettingsTabs.ascx.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Password Settings + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx new file mode 100644 index 00000000..5575c4e1 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx @@ -0,0 +1,32 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OrganizationSettingsTabs.ascx.cs" Inherits="WebsitePanel.Portal.ExchangeServer.UserControls.OrganizationSettingsTabs" %> + + + + + + +
+ + + + + <%# Eval("Name") %> + + + + + + <%# Eval("Name") %> + + + +
+
+ + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx.cs new file mode 100644 index 00000000..3fa348da --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using WebsitePanel.Portal.Code.UserControls; + +namespace WebsitePanel.Portal.ExchangeServer.UserControls +{ + public partial class OrganizationSettingsTabs : WebsitePanelControlBase + { + public string SelectedTab { get; set; } + + protected void Page_Load(object sender, EventArgs e) + { + BindTabs(); + } + + private void BindTabs() + { + List tabsList = new List(); + tabsList.Add(CreateTab("organization_settings_password_settings", "Tab.PasswordSettings")); + + int idx = 0; + + foreach (Tab tab in tabsList) + { + if (String.Compare(tab.Id, SelectedTab, true) == 0) + { + break; + } + + idx++; + } + + osTabs.SelectedIndex = idx; + osTabs.DataSource = tabsList; + osTabs.DataBind(); + } + + private Tab CreateTab(string id, string text) + { + return new Tab(id, GetLocalizedString(text), + HostModule.EditUrl("ItemID", PanelRequest.ItemID.ToString(), id, + "SpaceID=" + PanelSecurity.PackageId + )); + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx.designer.cs new file mode 100644 index 00000000..07100ae3 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/UserControls/OrganizationSettingsTabs.ascx.designer.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// +// 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 OrganizationSettingsTabs { + + /// + /// osTabs control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DataList osTabs; + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx index 517be9ab..8aca548c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx @@ -13,7 +13,7 @@ - + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx.designer.cs index 0e14d0a6..4eca5840 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsExchangePolicy.ascx.designer.cs @@ -1,30 +1,11 @@ -// Copyright (c) 2015, Outercurve Foundation. -// All rights reserved. +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. // -// 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. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ namespace WebsitePanel.Portal { diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/App_LocalResources/PasswordPolicyEditor.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/App_LocalResources/PasswordPolicyEditor.ascx.resx index 205a3bce..a4b1ce09 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/App_LocalResources/PasswordPolicyEditor.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/App_LocalResources/PasswordPolicyEditor.ascx.resx @@ -120,11 +120,26 @@ Enable Policy + + Enable Lockout Settings + Should not be equal to username + + Enable Password Complexity + + + Account lockout duration: + + + Enforce password history: + - Lock out after # attempts: + Account lockout threshold: + + + Lock out settings: Maximum length: @@ -141,9 +156,18 @@ Uppercase letters: + + Reset account lockout counter after (minutes): + Password should contain at least: + + * + + + * + * @@ -162,6 +186,12 @@ * + + * + + + * + * @@ -177,4 +207,7 @@ * + + * + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordControl.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordControl.ascx.cs index 15473082..d297936e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordControl.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordControl.ascx.cs @@ -27,6 +27,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; +using System.Configuration.Internal; using System.Data; using System.Configuration; using System.Collections; @@ -41,6 +42,7 @@ using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using WebsitePanel.EnterpriseServer; +using WebsitePanel.Providers.HostedSolution; namespace WebsitePanel.Portal { @@ -112,7 +114,14 @@ namespace WebsitePanel.Portal public int MaximumLength { get { return (ViewState["MaximumLength"] != null) ? (int)ViewState["MaximumLength"] : 0; } - set { ViewState["MaximumLength"] = value; } + set + { + { + txtPassword.MaxLength = value; + txtConfirmPassword.MaxLength = value; + ViewState["MaximumLength"] = value; + } + } } public int MinimumNumbers @@ -182,6 +191,38 @@ namespace WebsitePanel.Portal ToggleControls(); } + public void SetUserPolicy(OrganizationPasswordSettings settings) + { + int minimumUppercase; + int minimumNumbers; + int minimumSymbols; + + + if (settings.PasswordComplexityEnabled) + { + minimumUppercase = settings.UppercaseLettersCount; + minimumNumbers = settings.NumbersCount; + minimumSymbols = settings.SymbolsCount; + } + else + { + minimumUppercase = 0; + minimumNumbers = 0; + minimumSymbols = 0; + } + + PolicyValue = string.Join(";", true, settings.MinimumLength, settings.MaximumLength, minimumUppercase, minimumNumbers, minimumSymbols, true); + + ToggleControls(); + } + + public void SetUserPolicy(bool enabled, int minLength, int maxLength, int minimumUppercase, int minimumNumbers, int minimumSymbols, bool notEqualToUsername) + { + PolicyValue = string.Join(";", enabled, minLength, maxLength, minimumUppercase, minimumNumbers, minimumSymbols, notEqualToUsername); + + ToggleControls(); + } + protected void Page_Load(object sender, EventArgs e) { txtPassword.Attributes["value"] = txtPassword.Text; diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx index 2086c289..ab2431fc 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx @@ -28,10 +28,59 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -43,7 +92,7 @@ Display="Dynamic" ErrorMessage="*" ValidationExpression="\d{1,3}" ValidationGroup="SettingsEditor"> - + @@ -55,7 +104,7 @@ Display="Dynamic" ErrorMessage="*" ValidationExpression="\d{1,3}" ValidationGroup="SettingsEditor"> - + @@ -72,18 +121,6 @@ - - - - - - - - - - diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.cs index f74ecd8b..8a3c2e6e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.cs @@ -42,6 +42,8 @@ namespace WebsitePanel.Portal { public partial class PasswordPolicyEditor : WebsitePanelControlBase { + public bool ShowLockoutSettings { get; set; } + public string Value { get @@ -56,6 +58,12 @@ namespace WebsitePanel.Portal sb.Append(chkNotEqualUsername.Checked.ToString()).Append(";"); sb.Append(txtLockedOut.Text).Append(";"); + sb.Append(txtEnforcePasswordHistory.Text).Append(";"); + sb.Append(txtAccountLockoutDuration.Text).Append(";"); + sb.Append(txtResetAccountLockout.Text).Append(";"); + sb.Append(chkLockOutSettigns.Checked.ToString()).Append(";"); + sb.Append(chkPasswordComplexity.Checked.ToString()).Append(";"); + return sb.ToString(); } set @@ -70,6 +78,7 @@ namespace WebsitePanel.Portal txtMinimumNumbers.Text = "0"; txtMinimumSymbols.Text = "0"; txtLockedOut.Text = "3"; + chkPasswordComplexity.Checked = true; } else { @@ -85,8 +94,17 @@ namespace WebsitePanel.Portal txtMinimumSymbols.Text = parts[5]; chkNotEqualUsername.Checked = Utils.ParseBool(parts[6], false); txtLockedOut.Text = parts[7]; + + txtEnforcePasswordHistory.Text = GetValueSafe(parts, 8, "0"); + txtAccountLockoutDuration.Text = GetValueSafe(parts, 9, "0"); + txtResetAccountLockout.Text = GetValueSafe(parts, 10, "0"); + chkLockOutSettigns.Checked = GetValueSafe(parts, 11, false) && ShowLockoutSettings; + chkPasswordComplexity.Checked = GetValueSafe(parts, 12, true); + } + catch + { + /* skip */ } - catch { /* skip */ } } ToggleControls(); } @@ -99,11 +117,56 @@ namespace WebsitePanel.Portal private void ToggleControls() { PolicyTable.Visible = chkEnabled.Checked; + + ToggleLockOutSettignsControls(); + TogglePasswordCompelxitySettignsControls(); + + RowChkLockOutSettigns.Visible = ShowLockoutSettings; } protected void chkEnabled_CheckedChanged(object sender, EventArgs e) { ToggleControls(); } + + private void ToggleLockOutSettignsControls() + { + RowAccountLockoutDuration.Visible = chkLockOutSettigns.Checked; + RowLockedOut.Visible = chkLockOutSettigns.Checked; + RowResetAccountLockout.Visible = chkLockOutSettigns.Checked; + } + + private void TogglePasswordCompelxitySettignsControls() + { + RowMinimumUppercase.Visible = chkPasswordComplexity.Checked; + RowMinimumNumbers.Visible = chkPasswordComplexity.Checked; + RowMinimumSymbols.Visible = chkPasswordComplexity.Checked; + } + + protected void chkLockOutSettigns_CheckedChanged(object sender, EventArgs e) + { + ToggleLockOutSettignsControls(); + } + + protected void chkPasswordComplexity_CheckedChanged(object sender, EventArgs e) + { + TogglePasswordCompelxitySettignsControls(); + } + + public static T GetValueSafe(string[] array, int index, T defaultValue) + { + if (array.Length > index) + { + if (string.IsNullOrEmpty(array[index])) + { + return defaultValue; + } + + return (T)Convert.ChangeType(array[index], typeof(T)); + } + + return defaultValue; + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.designer.cs index a5bf2867..557e0e74 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserControls/PasswordPolicyEditor.ascx.designer.cs @@ -1,31 +1,3 @@ -// Copyright (c) 2015, 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. - //------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -140,13 +112,193 @@ namespace WebsitePanel.Portal { protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectMaxLength; /// - /// lblShouldContain control. + /// lblEnforcePasswordHistory control. /// /// /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::System.Web.UI.WebControls.Label lblShouldContain; + protected global::System.Web.UI.WebControls.Label lblEnforcePasswordHistory; + + /// + /// txtEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtEnforcePasswordHistory; + + /// + /// valRequireEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireEnforcePasswordHistory; + + /// + /// valCorrectEnforcePasswordHistory control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectEnforcePasswordHistory; + + /// + /// RowChkLockOutSettigns control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowChkLockOutSettigns; + + /// + /// chkLockOutSettigns control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox chkLockOutSettigns; + + /// + /// RowAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowAccountLockoutDuration; + + /// + /// lblAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblAccountLockoutDuration; + + /// + /// txtAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtAccountLockoutDuration; + + /// + /// valRequireAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RequiredFieldValidator valRequireAccountLockoutDuration; + + /// + /// valCorrectAccountLockoutDuration control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectAccountLockoutDuration; + + /// + /// RowLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowLockedOut; + + /// + /// lblLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblLockedOut; + + /// + /// txtLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtLockedOut; + + /// + /// valCorrectLockedOut control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectLockedOut; + + /// + /// RowResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowResetAccountLockout; + + /// + /// lblResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblResetAccountLockout; + + /// + /// txtResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtResetAccountLockout; + + /// + /// valResetAccountLockout control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.RegularExpressionValidator valResetAccountLockout; + + /// + /// chkPasswordComplexity control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox chkPasswordComplexity; + + /// + /// RowMinimumUppercase control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowMinimumUppercase; /// /// lblMinimumUppercase control. @@ -184,6 +336,15 @@ namespace WebsitePanel.Portal { /// protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectUppercase; + /// + /// RowMinimumNumbers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowMinimumNumbers; + /// /// lblMinimumNumbers control. /// @@ -220,6 +381,15 @@ namespace WebsitePanel.Portal { /// protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectNumbers; + /// + /// RowMinimumSymbols control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlTableRow RowMinimumSymbols; + /// /// lblMinimumSymbols control. /// @@ -273,32 +443,5 @@ namespace WebsitePanel.Portal { /// To modify move field declaration from designer file to code-behind file. /// protected global::System.Web.UI.WebControls.CheckBox chkNotEqualUsername; - - /// - /// lblLockedOut control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label lblLockedOut; - - /// - /// txtLockedOut control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox txtLockedOut; - - /// - /// valCorrectLockedOut control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RegularExpressionValidator valCorrectLockedOut; } } 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 e7326a7d..cde0ab55 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj @@ -244,6 +244,13 @@ OrganizationDeletedUserGeneralSettings.ascx ASPXCodeBehind + + OrganizationSettingsPasswordSettings.ascx + ASPXCodeBehind + + + OrganizationSettingsPasswordSettings.ascx + OrganizationUserResetPassword.ascx ASPXCodeBehind @@ -265,6 +272,13 @@ EnterpriseStorageOwaUsersList.ascx + + OrganizationSettingsTabs.ascx + ASPXCodeBehind + + + OrganizationSettingsTabs.ascx + HyperV2012R2_Settings.ascx ASPXCodeBehind @@ -4557,9 +4571,11 @@ + + @@ -4622,6 +4638,8 @@ + +