From dde62638b23d907c933694dcec939c51c4c66b29 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Wed, 29 Apr 2015 05:44:09 -0700 Subject: [PATCH 01/15] password reset feedback fixes --- .../System/SystemSettings.cs | 1 + .../HostedSolution/OrganizationController.cs | 9 ++- .../OrganizationProvider.cs | 17 +++-- .../Controllers/AccountController.cs | 14 ++-- .../Account/PasswordResetFinalStepModel.cs | 15 ++++ .../Resources/UI.Designer.cs | 18 +++++ .../Resources/UI.resx | 6 ++ .../Account/PasswordResetFinalStep.cshtml | 75 +++++++++++++++++-- .../EditorTemplates/PasswordEditor.cshtml | 4 +- .../WebsitePanel.WebDavPortal.csproj | 2 + .../SystemSettings.ascx.resx | 3 + .../OrganizationUserResetPassword.ascx.resx | 3 + .../OrganizationUserResetPassword.ascx | 1 + .../OrganizationUserResetPassword.ascx.cs | 49 +++++++++++- ...nizationUserResetPassword.ascx.designer.cs | 9 +++ .../WebsitePanel/SystemSettings.ascx | 5 ++ .../WebsitePanel/SystemSettings.ascx.cs | 2 + .../SystemSettings.ascx.designer.cs | 18 +++++ 18 files changed, 228 insertions(+), 23 deletions(-) create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetFinalStepModel.cs diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/System/SystemSettings.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/System/SystemSettings.cs index d713ba88..ba6a885f 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/System/SystemSettings.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/System/SystemSettings.cs @@ -56,6 +56,7 @@ namespace WebsitePanel.EnterpriseServer public const string TWILIO_PHONEFROM_KEY = "TwilioPhoneFrom"; public const string WEBDAV_PASSWORD_RESET_ENABLED_KEY = "WebdavPswResetEnabled"; + public const string WEBDAV_PASSWORD_RESET_LINK_LIFE_SPAN = "WebdavPswdResetLinkLifeSpan"; // key to access to wpi main & custom feed in wpi settings public const string WPI_MAIN_FEED_KEY = "WpiMainFeedUrl"; diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs index 13d20ed1..fbf7b81e 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs @@ -1877,7 +1877,9 @@ namespace WebsitePanel.EnterpriseServer var webdavPortalUrl = new Uri(settings["WebdavPortalUrl"]); - var token = CreateAccessToken(itemId, accountId, AccessTokenTypes.PasswrodReset); + var hours = settings.GetValueOrDefault(SystemSettings.WEBDAV_PASSWORD_RESET_LINK_LIFE_SPAN, 1); + + var token = CreateAccessToken(itemId, accountId, AccessTokenTypes.PasswrodReset, hours); tokenGuid = token.AccessTokenGuid; @@ -1892,7 +1894,7 @@ namespace WebsitePanel.EnterpriseServer return resultUrl.ToString(); } - private static AccessToken CreateAccessToken(int itemId, int accountId, AccessTokenTypes type) + private static AccessToken CreateAccessToken(int itemId, int accountId, AccessTokenTypes type, int hours) { var token = new AccessToken { @@ -1900,7 +1902,7 @@ namespace WebsitePanel.EnterpriseServer ItemId = itemId, AccountId = accountId, TokenType = type, - ExpirationDate = DateTime.Now.AddHours(12) + ExpirationDate = DateTime.Now.AddHours(hours) }; token.Id = DataProvider.AddAccessToken(token); @@ -2890,6 +2892,7 @@ namespace WebsitePanel.EnterpriseServer OrganizationUser retUser = orgProxy.GetOrganizationUserWithExtraData(accountName, org.OrganizationId); retUser.AccountId = accountId; + retUser.ItemId = itemId; retUser.AccountName = account.AccountName; retUser.PrimaryEmailAddress = account.PrimaryEmailAddress; retUser.AccountType = account.AccountType; diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs index 7aae57fa..a60a5682 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs @@ -576,6 +576,11 @@ namespace WebsitePanel.Providers.HostedSolution if (span != null) { + if (span.Value.Duration() == new TimeSpan().Duration()) + { + return TimeSpan.MaxValue; + } + return span.Value; } } @@ -679,15 +684,15 @@ namespace WebsitePanel.Providers.HostedSolution if (!FineGrainedPasswordPolicyExist(runspace, psoName)) { CreateFineGrainedPasswordPolicy(runspace, organizationId, psoName, settings); - - string groupPath = GetGroupPath(organizationId); - - SetFineGrainedPasswordPolicySubject(runspace, groupPath, psoName); } else { UpdateFineGrainedPasswordPolicy(runspace, psoName, settings); } + + string groupPath = GetGroupPath(organizationId); + + SetFineGrainedPasswordPolicySubject(runspace, groupPath, psoName); } catch (Exception ex) { @@ -759,12 +764,12 @@ namespace WebsitePanel.Providers.HostedSolution var cmd = new Command("Add-ADFineGrainedPasswordPolicySubject"); cmd.Parameters.Add("Identity", psoName); - cmd.Parameters.Add("Subjects", entry.Properties[ADAttributes.SAMAccountName].Value.ToString()); + cmd.Parameters.Add("Subjects", entry.Properties[ADAttributes.DistinguishedName].Value.ToString()); ExecuteShellCommand(runspace, cmd); cmd = new Command("Set-ADGroup"); - cmd.Parameters.Add("Identity", entry.Properties[ADAttributes.SAMAccountName].Value.ToString()); + cmd.Parameters.Add("Identity", entry.Properties[ADAttributes.DistinguishedName].Value.ToString()); cmd.Parameters.Add("GroupScope", "Global"); ExecuteShellCommand(runspace, cmd); diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs index b63a7e2d..5d383a1b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs @@ -267,15 +267,21 @@ namespace WebsitePanel.WebDavPortal.Controllers return result; } + var tokenEntity = WspContext.Services.Organizations.GetPasswordresetAccessToken(token); + var account = WspContext.Services.Organizations.GetUserGeneralSettings(tokenEntity.ItemId, + tokenEntity.AccountId); - var model = new PasswordEditor(); + var model = new PasswordResetFinalStepModel(); + + model.PasswordEditor.Settings = WspContext.Services.Organizations.GetOrganizationPasswordSettings(tokenEntity.ItemId); + model.Login = account.UserPrincipalName; return View(model); } [HttpPost] [AllowAnonymous] - public ActionResult PasswordResetFinalStep(Guid token, string pincode, PasswordEditor model) + public ActionResult PasswordResetFinalStep(Guid token, string pincode, PasswordResetFinalStepModel model) { if (!ModelState.IsValid) { @@ -293,12 +299,10 @@ namespace WebsitePanel.WebDavPortal.Controllers WspContext.Services.Organizations.SetUserPassword( tokenEntity.ItemId, tokenEntity.AccountId, - model.NewPassword); + model.PasswordEditor.NewPassword); WspContext.Services.Organizations.DeletePasswordresetAccessToken(token); - AddMessage(MessageType.Success, Resources.Messages.PasswordSuccessfullyChanged); - return RedirectToRoute(AccountRouteNames.PasswordResetSuccess); } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetFinalStepModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetFinalStepModel.cs new file mode 100644 index 00000000..4bb82f03 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetFinalStepModel.cs @@ -0,0 +1,15 @@ +using WebsitePanel.WebDavPortal.Models.Common.EditorTemplates; + +namespace WebsitePanel.WebDavPortal.Models.Account +{ + public class PasswordResetFinalStepModel + { + public PasswordResetFinalStepModel() + { + PasswordEditor = new PasswordEditor(); + } + + public string Login { get; set; } + public PasswordEditor PasswordEditor { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs index 4fc8c9ae..0df331bf 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs @@ -654,6 +654,15 @@ namespace WebsitePanel.WebDavPortal.Resources { } } + /// + /// Looks up a localized string similar to Password must meet the following requirements:. + /// + public static string PasswordFollowingRequirements { + get { + return ResourceManager.GetString("PasswordFollowingRequirements", resourceCulture); + } + } + /// /// Looks up a localized string similar to Password never expires. If you want to change password then please click {0}.. /// @@ -915,6 +924,15 @@ namespace WebsitePanel.WebDavPortal.Resources { } } + /// + /// Looks up a localized string similar to You are changing password for '{0}' account.. + /// + public static string YouRChangingPswForFormat { + get { + return ResourceManager.GetString("YouRChangingPswForFormat", resourceCulture); + } + } + /// /// Looks up a localized string similar to Zip/Postal Code. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx index 508f4a2d..ca01221f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx @@ -405,4 +405,10 @@ Your new password has been set. + + Password must meet the following requirements: + + + You are changing password for '{0}' account. + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetFinalStep.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetFinalStep.cshtml index 11fbfbfc..6432a19b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetFinalStep.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetFinalStep.cshtml @@ -1,9 +1,9 @@ -@{ +@using WebsitePanel.WebDavPortal.Resources +@using WebsitePanel.WebDavPortal.UI.Routes +@model WebsitePanel.WebDavPortal.Models.Account.PasswordResetFinalStepModel +@{ Layout = "~/Views/Shared/_Layout.cshtml"; } -@using WebsitePanel.WebDavPortal.Resources -@using WebsitePanel.WebDavPortal.UI.Routes -@model WebsitePanel.WebDavPortal.Models.Common.EditorTemplates.PasswordEditor
@using (Html.BeginRouteForm(AccountRouteNames.PasswordResetFinalStep, FormMethod.Post, new { @class = "form-horizontal user-password-reset-final-step bs-val-styles col-lg-9 col-lg-offset-3", id = "user-password-reset" })) @@ -12,8 +12,14 @@

@UI.PasswordReset

+ +
+ + @string.Format(UI.YouRChangingPswForFormat, Model.Login) + +
- @Html.EditorFor(x=>x) + @Html.EditorFor(x => x.PasswordEditor)
@@ -23,5 +29,64 @@ }
+@if (Model.PasswordEditor.Settings != null) +{ + +} + +@section scripts{ + +} + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/EditorTemplates/PasswordEditor.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/EditorTemplates/PasswordEditor.cshtml index d285f042..45fc478b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/EditorTemplates/PasswordEditor.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/EditorTemplates/PasswordEditor.cshtml @@ -8,7 +8,7 @@
- @Html.PasswordFor(x => x.NewPassword, new { @class = "form-control", placeholder = UI.NewPassword, maxlength }) + @Html.PasswordFor(x => x.NewPassword, new { @class = "form-control password-input", placeholder = UI.NewPassword, maxlength }) @Html.Raw(HttpUtility.HtmlDecode(Html.ValidationMessageFor(m => m.NewPassword).ToHtmlString()))
@@ -16,7 +16,7 @@
- @Html.PasswordFor(x => x.NewPasswordConfirmation, new { @class = "form-control", placeholder = UI.NewPasswordConfirmation, maxlength }) + @Html.PasswordFor(x => x.NewPasswordConfirmation, new { @class = "form-control" , placeholder = UI.NewPasswordConfirmation, maxlength }) @Html.ValidationMessageFor(x => x.NewPasswordConfirmation)
diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj index 62be767a..f8d0894a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj @@ -198,6 +198,7 @@ + @@ -510,6 +511,7 @@ PublicResXFileCodeGenerator Messages.Designer.cs + Designer PublicResXFileCodeGenerator diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SystemSettings.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SystemSettings.ascx.resx index 050f293a..0df8b577 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SystemSettings.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SystemSettings.ascx.resx @@ -192,4 +192,7 @@ Twilio + + Password Reset Link Life Span (hours): + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationUserResetPassword.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationUserResetPassword.ascx.resx index f9dc009b..a21310ff 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationUserResetPassword.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/OrganizationUserResetPassword.ascx.resx @@ -120,6 +120,9 @@ Send Password Reset Email + + Don't save as user mobile + Email: diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx index b4b70839..f1e7870a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx @@ -45,6 +45,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.cs index 8b5a315d..7fea70e6 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.cs @@ -39,11 +39,13 @@ namespace WebsitePanel.Portal.ExchangeServer if (rbtnEmail.Checked) { - ES.Services.Organizations.SendResetUserPasswordEmail(PanelRequest.ItemID,PanelRequest.AccountID, txtReason.Text, txtEmailAddress.Text, true); + ES.Services.Organizations.SendResetUserPasswordEmail(PanelRequest.ItemID, PanelRequest.AccountID, + txtReason.Text, txtEmailAddress.Text, true); } else { - var result = ES.Services.Organizations.SendResetUserPasswordLinkSms(PanelRequest.ItemID, PanelRequest.AccountID, txtReason.Text, txtMobile.Text); + var result = ES.Services.Organizations.SendResetUserPasswordLinkSms(PanelRequest.ItemID, + PanelRequest.AccountID, txtReason.Text, txtMobile.Text); if (!result.IsSuccess) { @@ -51,6 +53,49 @@ namespace WebsitePanel.Portal.ExchangeServer return; } + + if (chkDontSaveAsMobile.Checked == false) + { + OrganizationUser user = ES.Services.Organizations.GetUserGeneralSettings(PanelRequest.ItemID, + PanelRequest.AccountID); + + ES.Services.Organizations.SetUserGeneralSettings( + PanelRequest.ItemID, PanelRequest.AccountID, + user.DisplayName, + string.Empty, + false, + user.Disabled, + user.Locked, + + user.FirstName, + user.Initials, + user.LastName, + + user.Address, + user.City, + user.State, + user.Zip, + user.Country, + + user.JobTitle, + user.Company, + user.Department, + user.Office, + user.Manager == null ? null : user.Manager.AccountName, + + user.BusinessPhone, + user.Fax, + user.HomePhone, + txtMobile.Text, + user.Pager, + user.WebPage, + user.Notes, + user.ExternalEmail, + user.SubscriberNumber, + user.LevelId, + user.IsVIP, + user.UserMustChangePassword); + } } Response.Redirect(PortalUtils.EditUrl("ItemID", PanelRequest.ItemID.ToString(), diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.designer.cs index 7c1339cb..f0d3eba0 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/OrganizationUserResetPassword.ascx.designer.cs @@ -147,6 +147,15 @@ namespace WebsitePanel.Portal.ExchangeServer { /// protected global::System.Web.UI.WebControls.TextBox txtMobile; + /// + /// chkDontSaveAsMobile control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox chkDontSaveAsMobile; + /// /// valMobile control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx index 83198973..d39e917c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx @@ -92,10 +92,15 @@ + + + + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.cs index c0f9586a..90aeee79 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.cs @@ -166,6 +166,7 @@ namespace WebsitePanel.Portal { chkEnablePasswordReset.Checked = Utils.ParseBool(settings[WSP.SystemSettings.WEBDAV_PASSWORD_RESET_ENABLED_KEY], false); txtWebdavPortalUrl.Text = settings[WEBDAV_PORTAL_URL]; + txtPasswordResetLinkLifeSpan.Text = settings[WSP.SystemSettings.WEBDAV_PASSWORD_RESET_LINK_LIFE_SPAN]; } // Twilio portal @@ -262,6 +263,7 @@ namespace WebsitePanel.Portal settings = new WSP.SystemSettings(); settings[WEBDAV_PORTAL_URL] = txtWebdavPortalUrl.Text; settings[WSP.SystemSettings.WEBDAV_PASSWORD_RESET_ENABLED_KEY] = chkEnablePasswordReset.Checked.ToString(); + settings[WSP.SystemSettings.WEBDAV_PASSWORD_RESET_LINK_LIFE_SPAN] = txtPasswordResetLinkLifeSpan.Text; result = ES.Services.System.SetSystemSettings(WSP.SystemSettings.WEBDAV_PORTAL_SETTINGS, settings); if (result < 0) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.designer.cs index ea97810e..a027a548 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SystemSettings.ascx.designer.cs @@ -264,6 +264,24 @@ namespace WebsitePanel.Portal { /// protected global::System.Web.UI.WebControls.CheckBox chkEnablePasswordReset; + /// + /// lblPasswordResetLinkLifeSpan control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize lblPasswordResetLinkLifeSpan; + + /// + /// txtPasswordResetLinkLifeSpan control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtPasswordResetLinkLifeSpan; + /// /// lblWebdavPortalUrl control. /// From 2f1e740d5ae0be7f086b2309c5271290bbb48836 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Wed, 29 Apr 2015 07:36:48 -0700 Subject: [PATCH 02/15] password never expires fix --- .../OrganizationProvider.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs index a60a5682..a4d839f4 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs @@ -693,6 +693,11 @@ namespace WebsitePanel.Providers.HostedSolution string groupPath = GetGroupPath(organizationId); SetFineGrainedPasswordPolicySubject(runspace, groupPath, psoName); + + if (settings.MaxPasswordAge == 0) + { + SetPasswordNeverExpiresInFineGrainedPasswordPolicy(runspace, psoName); + } } catch (Exception ex) { @@ -711,6 +716,24 @@ namespace WebsitePanel.Providers.HostedSolution return string.Format("{0}-PSO", organizationId); } + private void SetPasswordNeverExpiresInFineGrainedPasswordPolicy(Runspace runspace, string psoName) + { + var psoObject = GetFineGrainedPasswordPolicy(runspace, psoName); + + var distinguishedName = GetPSObjectProperty(psoObject, "DistinguishedName") as string; + + var cmd = new Command("Set-ADObject"); + cmd.Parameters.Add("Identity", distinguishedName); + + var hashTable = new Hashtable(); + + hashTable.Add("msDS-MaximumPasswordAge", "-9223372036854775808"); + + cmd.Parameters.Add("Replace", hashTable); + + ExecuteShellCommand(runspace, cmd); + } + private bool FineGrainedPasswordPolicyExist(Runspace runspace, string psoName) { try From 3ff58d60866a1c2216459e45a72f1d8f858ca781 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 29 Apr 2015 10:58:17 -0400 Subject: [PATCH 03/15] Added tag build-2.1.0.689 for changeset 93ebd9f406d0 From b550151385060b4cedb597c38427de1d5698fdc2 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 29 Apr 2015 12:07:48 -0400 Subject: [PATCH 04/15] Added tag build-2.1.0.690 for changeset 2e3a546d7628 From 7a743723179cc4fb189a3fcf6ddfb4c85522bbf4 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 29 Apr 2015 12:38:19 -0400 Subject: [PATCH 05/15] Added tag build-2.1.0.691 for changeset 91f3846beaa9 From d1664e716320b4aba036801920141e9a54d8a6c0 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 29 Apr 2015 18:55:02 -0400 Subject: [PATCH 06/15] Added tag build-2.1.0.692 for changeset a00b14bc59d5 From 410b15c2c47bead2623cf9571bae39b18396f0a3 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Thu, 30 Apr 2015 04:24:15 -0700 Subject: [PATCH 07/15] password reset workflow changed --- WebsitePanel/Database/update_db.sql | 114 ++++- .../Users/UserSettings.cs | 1 + .../OrganizationProxy.cs | 437 ++++++++++++------ .../HostedSolution/OrganizationController.cs | 103 ++++- .../esOrganizations.asmx.cs | 12 + .../Config/Entities/SessionKeysCollection.cs | 10 + .../WebConfigSections/SessionKeysElement.cs | 1 + .../Extensions/StringExtensions.cs | 10 + .../App_Start/RouteConfig.cs | 14 +- .../App_Start/Routes/AccountRouteNames.cs | 6 +- .../Controllers/AccountController.cs | 166 ++++--- .../Models/Account/Enums/PincodeSendMethod.cs | 8 + ...ailModel.cs => PasswordResetLoginModel.cs} | 2 +- ...sModel.cs => PasswordResetPincodeModel.cs} | 2 +- .../PasswordResetPincodeSendOptionsModel.cs | 11 + .../Resources/Messages.Designer.cs | 20 +- .../Resources/Messages.resx | 8 +- .../Resources/UI.Designer.cs | 27 ++ .../Resources/UI.resx | 9 + .../Views/Account/Login.cshtml | 2 +- ...Email.cshtml => PasswordResetLogin.cshtml} | 6 +- ...Sms.cshtml => PasswordResetPincode.cshtml} | 8 +- .../PasswordResetPincodeSendOptions.cshtml | 51 ++ .../WebsitePanel.WebDavPortal/Web.config | 1 + .../WebsitePanel.WebDavPortal.csproj | 11 +- ...gsUserPasswordResetPincodeLetter.ascx.resx | 159 +++++++ .../UserAccountMailTemplateSettings.ascx.resx | 3 + .../SettingsUserPasswordResetLetter.ascx | 7 - .../SettingsUserPasswordResetLetter.ascx.cs | 2 - ...gsUserPasswordResetLetter.ascx.designer.cs | 18 - ...ettingsUserPasswordResetPincodeLetter.ascx | 55 +++ ...ingsUserPasswordResetPincodeLetter.ascx.cs | 37 ++ ...asswordResetPincodeLetter.ascx.designer.cs | 141 ++++++ .../UserAccountMailTemplateSettings.ascx | 4 + ...countMailTemplateSettings.ascx.designer.cs | 9 + .../WebsitePanel.Portal.Modules.csproj | 9 + 36 files changed, 1229 insertions(+), 255 deletions(-) create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/Enums/PincodeSendMethod.cs rename WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/{PasswordResetEmailModel.cs => PasswordResetLoginModel.cs} (89%) rename WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/{PasswordResetSmsModel.cs => PasswordResetPincodeModel.cs} (83%) create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeSendOptionsModel.cs rename WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/{PasswordResetEmail.cshtml => PasswordResetLogin.cshtml} (69%) rename WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/{PasswordResetSms.cshtml => PasswordResetPincode.cshtml} (73%) create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SettingsUserPasswordResetPincodeLetter.ascx.resx create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.designer.cs diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 2df1f2da..e2b0b133 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -10045,6 +10045,114 @@ ELSE UPDATE [dbo].[UserSettings] SET [PropertyValue] = @UserPasswordResetSMSBody WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetLetter' AND [PropertyName]= N'PasswordResetLinkSmsBody' GO +-- USER PASSWORD RESET EMAIL PINCODE TEMPLATE + +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'From' ) +BEGIN +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'From', N'support@HostingCompany.com') +END +GO + +DECLARE @UserPasswordResetPincodeLetterHtmlBody nvarchar(2500) + +Set @UserPasswordResetPincodeLetterHtmlBody = N' + + Password reset notification + + + +
+
+ +
+

Password reset notification

+ + +

+Hello #user.FirstName#, +

+
+ +

+We received a request to reset the password for your account. Your password reset pincode: +

+ +#passwordResetPincode# + +

+If you have any questions regarding your hosting account, feel free to contact our support department at any time. +

+ +

+Best regards +

+
+'; + +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'HtmlBody' ) +BEGIN +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'HtmlBody', @UserPasswordResetPincodeLetterHtmlBody) +END +ELSE +UPDATE [dbo].[UserSettings] SET [PropertyValue] = @UserPasswordResetPincodeLetterHtmlBody WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'HtmlBody' +GO + + +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'Priority' ) +BEGIN +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'Priority', N'Normal') +END +GO +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'Subject' ) +BEGIN +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'Subject', N'Password reset notification') +END +GO +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'LogoUrl' ) +BEGIN +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'LogoUrl', N'https://controlpanel.virtuworks.net/App_Themes/Default/Images/logo.png') +END +GO + + +DECLARE @UserPasswordResetPincodeLetterTextBody nvarchar(2500) + +Set @UserPasswordResetPincodeLetterTextBody = N'========================================= + Password reset notification +========================================= + + +Hello #user.FirstName#, + + +We received a request to reset the password for your account. Your password reset pincode: + +#passwordResetPincode# + +If you have any questions regarding your hosting account, feel free to contact our support department at any time. + +Best regards' + +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'TextBody' ) +BEGIN +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'TextBody', @UserPasswordResetPincodeLetterTextBody) +END +ELSE +UPDATE [dbo].[UserSettings] SET [PropertyValue] = @UserPasswordResetPincodeLetterTextBody WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'TextBody' +GO DECLARE @UserPasswordPincodeSMSBody nvarchar(2500) @@ -10052,12 +10160,12 @@ Set @UserPasswordPincodeSMSBody = N' Your password reset pincode: #passwordResetPincode#' -IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetLetter' AND [PropertyName]= N'PasswordResetPincodeSmsBody' ) +IF NOT EXISTS (SELECT * FROM [dbo].[UserSettings] WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'PasswordResetPincodeSmsBody' ) BEGIN -INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetLetter', N'PasswordResetPincodeSmsBody', @UserPasswordPincodeSMSBody) +INSERT [dbo].[UserSettings] ([UserID], [SettingsName], [PropertyName], [PropertyValue]) VALUES (1, N'UserPasswordResetPincodeLetter', N'PasswordResetPincodeSmsBody', @UserPasswordPincodeSMSBody) END ELSE -UPDATE [dbo].[UserSettings] SET [PropertyValue] = @UserPasswordPincodeSMSBody WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetLetter' AND [PropertyName]= N'PasswordResetPincodeSmsBody' +UPDATE [dbo].[UserSettings] SET [PropertyValue] = @UserPasswordPincodeSMSBody WHERE [UserID] = 1 AND [SettingsName]= N'UserPasswordResetPincodeLetter' AND [PropertyName]= N'PasswordResetPincodeSmsBody' GO -- Exchange setup EMAIL TEMPLATE diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs index 3d163d59..aeaff4d3 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Users/UserSettings.cs @@ -67,6 +67,7 @@ namespace WebsitePanel.EnterpriseServer public const string RDS_POLICY = "RdsPolicy"; public const string USER_PASSWORD_EXPIRATION_LETTER = "UserPasswordExpirationLetter"; public const string USER_PASSWORD_RESET_LETTER = "UserPasswordResetLetter"; + public const string USER_PASSWORD_RESET_PINCODE_LETTER = "UserPasswordResetPincodeLetter"; public const string HOSTED_ORGANIZATION_PASSWORD_POLICY = "MailboxPasswordPolicy"; diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs index 05baf043..3d729acc 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/OrganizationProxy.cs @@ -12,6 +12,7 @@ // 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; @@ -36,6 +37,10 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { [System.Xml.Serialization.XmlIncludeAttribute(typeof(ServiceProviderItem))] public partial class esOrganizations : Microsoft.Web.Services3.WebServicesClientProtocol { + private System.Threading.SendOrPostCallback AddSupportServiceLevelOperationCompleted; + + private System.Threading.SendOrPostCallback GetSupportServiceLevelOperationCompleted; + private System.Threading.SendOrPostCallback CheckPhoneNumberIsInUseOperationCompleted; private System.Threading.SendOrPostCallback DeletePasswordresetAccessTokenOperationCompleted; @@ -86,6 +91,8 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { private System.Threading.SendOrPostCallback SendResetUserPasswordPincodeSmsOperationCompleted; + private System.Threading.SendOrPostCallback SendResetUserPasswordPincodeEmailOperationCompleted; + private System.Threading.SendOrPostCallback AddOrganizationDomainOperationCompleted; private System.Threading.SendOrPostCallback ChangeOrganizationDomainTypeOperationCompleted; @@ -128,6 +135,8 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { private System.Threading.SendOrPostCallback SendResetUserPasswordEmailOperationCompleted; + private System.Threading.SendOrPostCallback CreatePasswordResetAccessTokenOperationCompleted; + private System.Threading.SendOrPostCallback CreateSecurityGroupOperationCompleted; private System.Threading.SendOrPostCallback GetSecurityGroupGeneralSettingsOperationCompleted; @@ -160,15 +169,17 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { private System.Threading.SendOrPostCallback DeleteSupportServiceLevelOperationCompleted; - private System.Threading.SendOrPostCallback AddSupportServiceLevelOperationCompleted; - - private System.Threading.SendOrPostCallback GetSupportServiceLevelOperationCompleted; - /// public esOrganizations() { this.Url = "http://localhost:9002/esOrganizations.asmx"; } + /// + public event AddSupportServiceLevelCompletedEventHandler AddSupportServiceLevelCompleted; + + /// + public event GetSupportServiceLevelCompletedEventHandler GetSupportServiceLevelCompleted; + /// public event CheckPhoneNumberIsInUseCompletedEventHandler CheckPhoneNumberIsInUseCompleted; @@ -244,6 +255,9 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { /// public event SendResetUserPasswordPincodeSmsCompletedEventHandler SendResetUserPasswordPincodeSmsCompleted; + /// + public event SendResetUserPasswordPincodeEmailCompletedEventHandler SendResetUserPasswordPincodeEmailCompleted; + /// public event AddOrganizationDomainCompletedEventHandler AddOrganizationDomainCompleted; @@ -307,6 +321,9 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { /// public event SendResetUserPasswordEmailCompletedEventHandler SendResetUserPasswordEmailCompleted; + /// + public event CreatePasswordResetAccessTokenCompletedEventHandler CreatePasswordResetAccessTokenCompleted; + /// public event CreateSecurityGroupCompletedEventHandler CreateSecurityGroupCompleted; @@ -356,10 +373,89 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { public event DeleteSupportServiceLevelCompletedEventHandler DeleteSupportServiceLevelCompleted; /// - public event AddSupportServiceLevelCompletedEventHandler AddSupportServiceLevelCompleted; + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/AddSupportServiceLevel", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public int AddSupportServiceLevel(string levelName, string levelDescription) { + object[] results = this.Invoke("AddSupportServiceLevel", new object[] { + levelName, + levelDescription}); + return ((int)(results[0])); + } /// - public event GetSupportServiceLevelCompletedEventHandler GetSupportServiceLevelCompleted; + public System.IAsyncResult BeginAddSupportServiceLevel(string levelName, string levelDescription, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("AddSupportServiceLevel", new object[] { + levelName, + levelDescription}, callback, asyncState); + } + + /// + public int EndAddSupportServiceLevel(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((int)(results[0])); + } + + /// + public void AddSupportServiceLevelAsync(string levelName, string levelDescription) { + this.AddSupportServiceLevelAsync(levelName, levelDescription, null); + } + + /// + public void AddSupportServiceLevelAsync(string levelName, string levelDescription, object userState) { + if ((this.AddSupportServiceLevelOperationCompleted == null)) { + this.AddSupportServiceLevelOperationCompleted = new System.Threading.SendOrPostCallback(this.OnAddSupportServiceLevelOperationCompleted); + } + this.InvokeAsync("AddSupportServiceLevel", new object[] { + levelName, + levelDescription}, this.AddSupportServiceLevelOperationCompleted, userState); + } + + private void OnAddSupportServiceLevelOperationCompleted(object arg) { + if ((this.AddSupportServiceLevelCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.AddSupportServiceLevelCompleted(this, new AddSupportServiceLevelCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetSupportServiceLevel", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public ServiceLevel GetSupportServiceLevel(int levelID) { + object[] results = this.Invoke("GetSupportServiceLevel", new object[] { + levelID}); + return ((ServiceLevel)(results[0])); + } + + /// + public System.IAsyncResult BeginGetSupportServiceLevel(int levelID, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("GetSupportServiceLevel", new object[] { + levelID}, callback, asyncState); + } + + /// + public ServiceLevel EndGetSupportServiceLevel(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((ServiceLevel)(results[0])); + } + + /// + public void GetSupportServiceLevelAsync(int levelID) { + this.GetSupportServiceLevelAsync(levelID, null); + } + + /// + public void GetSupportServiceLevelAsync(int levelID, object userState) { + if ((this.GetSupportServiceLevelOperationCompleted == null)) { + this.GetSupportServiceLevelOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetSupportServiceLevelOperationCompleted); + } + this.InvokeAsync("GetSupportServiceLevel", new object[] { + levelID}, this.GetSupportServiceLevelOperationCompleted, userState); + } + + private void OnGetSupportServiceLevelOperationCompleted(object arg) { + if ((this.GetSupportServiceLevelCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetSupportServiceLevelCompleted(this, new GetSupportServiceLevelCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CheckPhoneNumberIsInUse", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] @@ -1463,6 +1559,50 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { } } + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SendResetUserPasswordPincodeEmail", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public ResultObject SendResetUserPasswordPincodeEmail(System.Guid token, string mailTo) { + object[] results = this.Invoke("SendResetUserPasswordPincodeEmail", new object[] { + token, + mailTo}); + return ((ResultObject)(results[0])); + } + + /// + public System.IAsyncResult BeginSendResetUserPasswordPincodeEmail(System.Guid token, string mailTo, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("SendResetUserPasswordPincodeEmail", new object[] { + token, + mailTo}, callback, asyncState); + } + + /// + public ResultObject EndSendResetUserPasswordPincodeEmail(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((ResultObject)(results[0])); + } + + /// + public void SendResetUserPasswordPincodeEmailAsync(System.Guid token, string mailTo) { + this.SendResetUserPasswordPincodeEmailAsync(token, mailTo, null); + } + + /// + public void SendResetUserPasswordPincodeEmailAsync(System.Guid token, string mailTo, object userState) { + if ((this.SendResetUserPasswordPincodeEmailOperationCompleted == null)) { + this.SendResetUserPasswordPincodeEmailOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSendResetUserPasswordPincodeEmailOperationCompleted); + } + this.InvokeAsync("SendResetUserPasswordPincodeEmail", new object[] { + token, + mailTo}, this.SendResetUserPasswordPincodeEmailOperationCompleted, userState); + } + + private void OnSendResetUserPasswordPincodeEmailOperationCompleted(object arg) { + if ((this.SendResetUserPasswordPincodeEmailCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.SendResetUserPasswordPincodeEmailCompleted(this, new SendResetUserPasswordPincodeEmailCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/AddOrganizationDomain", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int AddOrganizationDomain(int itemId, string domainName) { @@ -2697,6 +2837,50 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { } } + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CreatePasswordResetAccessToken", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public AccessToken CreatePasswordResetAccessToken(int itemId, int accountId) { + object[] results = this.Invoke("CreatePasswordResetAccessToken", new object[] { + itemId, + accountId}); + return ((AccessToken)(results[0])); + } + + /// + public System.IAsyncResult BeginCreatePasswordResetAccessToken(int itemId, int accountId, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("CreatePasswordResetAccessToken", new object[] { + itemId, + accountId}, callback, asyncState); + } + + /// + public AccessToken EndCreatePasswordResetAccessToken(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((AccessToken)(results[0])); + } + + /// + public void CreatePasswordResetAccessTokenAsync(int itemId, int accountId) { + this.CreatePasswordResetAccessTokenAsync(itemId, accountId, null); + } + + /// + public void CreatePasswordResetAccessTokenAsync(int itemId, int accountId, object userState) { + if ((this.CreatePasswordResetAccessTokenOperationCompleted == null)) { + this.CreatePasswordResetAccessTokenOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCreatePasswordResetAccessTokenOperationCompleted); + } + this.InvokeAsync("CreatePasswordResetAccessToken", new object[] { + itemId, + accountId}, this.CreatePasswordResetAccessTokenOperationCompleted, userState); + } + + private void OnCreatePasswordResetAccessTokenOperationCompleted(object arg) { + if ((this.CreatePasswordResetAccessTokenCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.CreatePasswordResetAccessTokenCompleted(this, new CreatePasswordResetAccessTokenCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CreateSecurityGroup", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int CreateSecurityGroup(int itemId, string displayName) { @@ -3419,97 +3603,64 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { } } - /// - [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/AddSupportServiceLevel", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public int AddSupportServiceLevel(string levelName, string levelDescription) { - object[] results = this.Invoke("AddSupportServiceLevel", new object[] { - levelName, - levelDescription}); - return ((int)(results[0])); - } - - /// - public System.IAsyncResult BeginAddSupportServiceLevel(string levelName, string levelDescription, System.AsyncCallback callback, object asyncState) { - return this.BeginInvoke("AddSupportServiceLevel", new object[] { - levelName, - levelDescription}, callback, asyncState); - } - - /// - public int EndAddSupportServiceLevel(System.IAsyncResult asyncResult) { - object[] results = this.EndInvoke(asyncResult); - return ((int)(results[0])); - } - - /// - public void AddSupportServiceLevelAsync(string levelName, string levelDescription) { - this.AddSupportServiceLevelAsync(levelName, levelDescription, null); - } - - /// - public void AddSupportServiceLevelAsync(string levelName, string levelDescription, object userState) { - if ((this.AddSupportServiceLevelOperationCompleted == null)) { - this.AddSupportServiceLevelOperationCompleted = new System.Threading.SendOrPostCallback(this.OnAddSupportServiceLevelOperationCompleted); - } - this.InvokeAsync("AddSupportServiceLevel", new object[] { - levelName, - levelDescription}, this.AddSupportServiceLevelOperationCompleted, userState); - } - - private void OnAddSupportServiceLevelOperationCompleted(object arg) { - if ((this.AddSupportServiceLevelCompleted != null)) { - System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); - this.AddSupportServiceLevelCompleted(this, new AddSupportServiceLevelCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); - } - } - - /// - [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetSupportServiceLevel", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public ServiceLevel GetSupportServiceLevel(int levelID) { - object[] results = this.Invoke("GetSupportServiceLevel", new object[] { - levelID}); - return ((ServiceLevel)(results[0])); - } - - /// - public System.IAsyncResult BeginGetSupportServiceLevel(int levelID, System.AsyncCallback callback, object asyncState) { - return this.BeginInvoke("GetSupportServiceLevel", new object[] { - levelID}, callback, asyncState); - } - - /// - public ServiceLevel EndGetSupportServiceLevel(System.IAsyncResult asyncResult) { - object[] results = this.EndInvoke(asyncResult); - return ((ServiceLevel)(results[0])); - } - - /// - public void GetSupportServiceLevelAsync(int levelID) { - this.GetSupportServiceLevelAsync(levelID, null); - } - - /// - public void GetSupportServiceLevelAsync(int levelID, object userState) { - if ((this.GetSupportServiceLevelOperationCompleted == null)) { - this.GetSupportServiceLevelOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetSupportServiceLevelOperationCompleted); - } - this.InvokeAsync("GetSupportServiceLevel", new object[] { - levelID}, this.GetSupportServiceLevelOperationCompleted, userState); - } - - private void OnGetSupportServiceLevelOperationCompleted(object arg) { - if ((this.GetSupportServiceLevelCompleted != null)) { - System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); - this.GetSupportServiceLevelCompleted(this, new GetSupportServiceLevelCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); - } - } - /// public new void CancelAsync(object userState) { base.CancelAsync(userState); } } + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void AddSupportServiceLevelCompletedEventHandler(object sender, AddSupportServiceLevelCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class AddSupportServiceLevelCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal AddSupportServiceLevelCompletedEventArgs(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 GetSupportServiceLevelCompletedEventHandler(object sender, GetSupportServiceLevelCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetSupportServiceLevelCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal GetSupportServiceLevelCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public ServiceLevel Result { + get { + this.RaiseExceptionIfNecessary(); + return ((ServiceLevel)(this.results[0])); + } + } + } + /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void CheckPhoneNumberIsInUseCompletedEventHandler(object sender, CheckPhoneNumberIsInUseCompletedEventArgs e); @@ -4050,6 +4201,32 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { } } + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void SendResetUserPasswordPincodeEmailCompletedEventHandler(object sender, SendResetUserPasswordPincodeEmailCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SendResetUserPasswordPincodeEmailCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal SendResetUserPasswordPincodeEmailCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public ResultObject Result { + get { + this.RaiseExceptionIfNecessary(); + return ((ResultObject)(this.results[0])); + } + } + } + /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void AddOrganizationDomainCompletedEventHandler(object sender, AddOrganizationDomainCompletedEventArgs e); @@ -4574,6 +4751,32 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void SendResetUserPasswordEmailCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void CreatePasswordResetAccessTokenCompletedEventHandler(object sender, CreatePasswordResetAccessTokenCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CreatePasswordResetAccessTokenCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal CreatePasswordResetAccessTokenCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public AccessToken Result { + get { + this.RaiseExceptionIfNecessary(); + return ((AccessToken)(this.results[0])); + } + } + } + /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void CreateSecurityGroupCompletedEventHandler(object sender, CreateSecurityGroupCompletedEventArgs e); @@ -4923,56 +5126,4 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution { } } } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] - public delegate void AddSupportServiceLevelCompletedEventHandler(object sender, AddSupportServiceLevelCompletedEventArgs e); - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class AddSupportServiceLevelCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { - - private object[] results; - - internal AddSupportServiceLevelCompletedEventArgs(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 GetSupportServiceLevelCompletedEventHandler(object sender, GetSupportServiceLevelCompletedEventArgs e); - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class GetSupportServiceLevelCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { - - private object[] results; - - internal GetSupportServiceLevelCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : - base(exception, cancelled, userState) { - this.results = results; - } - - /// - public ServiceLevel Result { - get { - this.RaiseExceptionIfNecessary(); - return ((ServiceLevel)(this.results[0])); - } - } - } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs index fbf7b81e..05fbb37b 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs @@ -1654,15 +1654,14 @@ namespace WebsitePanel.EnterpriseServer } UserInfo owner = PackageController.GetPackageOwner(org.PackageId); - OrganizationUser user = OrganizationController.GetUserGeneralSettingsWithExtraData(accessToken.ItemId, - accessToken.AccountId); + OrganizationUser user = OrganizationController.GetUserGeneralSettingsWithExtraData(accessToken.ItemId, accessToken.AccountId); if (string.IsNullOrEmpty(phoneTo)) { phoneTo = user.MobilePhone; } - UserSettings settings = UserController.GetUserSettings(owner.UserId, UserSettings.USER_PASSWORD_RESET_LETTER); + UserSettings settings = UserController.GetUserSettings(owner.UserId, UserSettings.USER_PASSWORD_RESET_PINCODE_LETTER); string body = settings["PasswordResetPincodeSmsBody"]; @@ -1700,6 +1699,90 @@ namespace WebsitePanel.EnterpriseServer return result; } + public static ResultObject SendResetUserPasswordPincodeEmail(Guid token, string mailTo = null) + { + var result = TaskManager.StartResultTask("ORGANIZATION", "SEND_USER_PASSWORD_RESET_EMAIL_PINCODE"); + + try + { + var accessToken = OrganizationController.GetAccessToken(token, AccessTokenTypes.PasswrodReset); + + if (accessToken == null) + { + throw new Exception(string.Format("Access token not found")); + } + + // load organization + Organization org = GetOrganization(accessToken.ItemId); + + if (org == null) + { + throw new Exception(string.Format("Organization not found")); + } + + UserInfo owner = PackageController.GetPackageOwner(org.PackageId); + OrganizationUser user = OrganizationController.GetUserGeneralSettingsWithExtraData(accessToken.ItemId, accessToken.AccountId); + + if (string.IsNullOrEmpty(mailTo)) + { + mailTo = user.PrimaryEmailAddress; + } + + UserSettings settings = UserController.GetUserSettings(owner.UserId, UserSettings.USER_PASSWORD_RESET_PINCODE_LETTER); + + var generalSettings = OrganizationController.GetOrganizationGeneralSettings(accessToken.ItemId); + + var logoUrl = generalSettings != null ? generalSettings.OrganizationLogoUrl : string.Empty; + + if (string.IsNullOrEmpty(logoUrl)) + { + logoUrl = settings["LogoUrl"]; + } + + string from = settings["From"]; + + string subject = settings["Subject"]; + string body = owner.HtmlMail ? settings["HtmlBody"] : settings["TextBody"]; + bool isHtml = owner.HtmlMail; + + MailPriority priority = MailPriority.Normal; + + if (!String.IsNullOrEmpty(settings["Priority"])) + { + priority = (MailPriority)Enum.Parse(typeof(MailPriority), settings["Priority"], true); + } + + string pincode = GeneratePincode() ; + + Hashtable items = new Hashtable(); + + items["user"] = user; + items["logoUrl"] = logoUrl; + items["passwordResetPincode"] = pincode; + + body = PackageController.EvaluateTemplate(body, items); + + SetAccessTokenResponse(token, pincode); + + TaskManager.Write("Organization ID : " + user.ItemId); + TaskManager.Write("Account : " + user.DisplayName); + TaskManager.Write("MailTo : " + mailTo); + + // send mail message + MailHelper.SendMessage(from, mailTo, null, subject, body, priority, isHtml); + } + catch (Exception ex) + { + TaskManager.WriteError(ex); + TaskManager.CompleteResultTask(result); + result.AddError("", ex); + return result; + } + + TaskManager.CompleteResultTask(); + return result; + } + private static string GeneratePincode() { var random = new Random(Guid.NewGuid().GetHashCode()); @@ -1894,6 +1977,20 @@ namespace WebsitePanel.EnterpriseServer return resultUrl.ToString(); } + public static AccessToken CreatePasswordResetAccessToken(int itemId, int accountId) + { + var settings = GetWebDavSystemSettings(); + + if (settings == null || !settings.GetValueOrDefault(SystemSettings.WEBDAV_PASSWORD_RESET_ENABLED_KEY, false)) + { + return null; + } + + var hours = settings.GetValueOrDefault(SystemSettings.WEBDAV_PASSWORD_RESET_LINK_LIFE_SPAN, 1); + + return CreateAccessToken(itemId, accountId, AccessTokenTypes.PasswrodReset, hours); + } + private static AccessToken CreateAccessToken(int itemId, int accountId, AccessTokenTypes type, int hours) { var token = new AccessToken diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs index ce6aa6f4..3e6c1188 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esOrganizations.asmx.cs @@ -204,6 +204,12 @@ namespace WebsitePanel.EnterpriseServer return OrganizationController.SendResetUserPasswordPincodeSms(token, phoneTo); } + [WebMethod] + public ResultObject SendResetUserPasswordPincodeEmail(Guid token, string mailTo = null) + { + return OrganizationController.SendResetUserPasswordPincodeEmail(token, mailTo); + } + #endregion @@ -361,6 +367,12 @@ namespace WebsitePanel.EnterpriseServer OrganizationController.SendResetUserPasswordEmail(itemId, accountId, reason, mailTo, finalStep); } + [WebMethod] + public AccessToken CreatePasswordResetAccessToken(int itemId, int accountId) + { + return OrganizationController.CreatePasswordResetAccessToken(itemId, accountId); + } + #endregion #region Security Groups diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs index 32309430..6951662a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs @@ -75,6 +75,16 @@ namespace WebsitePanel.WebDav.Core.Config.Entities } } + public string AccountIdKey + { + get + { + SessionKeysElement sessionKey = + _sessionKeys.FirstOrDefault(x => x.Key == SessionKeysElement.AccountIdKey); + return sessionKey != null ? sessionKey.Value : null; + } + } + public string ResourseRenderCount { get diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs index 07b43395..1eeada8f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs @@ -16,6 +16,7 @@ namespace WebsitePanel.WebDav.Core.Config.WebConfigSections public const string ResourseRenderCountKey = "ResourseRenderCountSessionKey"; public const string ItemIdSessionKey = "ItemId"; public const string OwaEditFoldersSessionKey = "OwaEditFoldersSession"; + public const string AccountIdKey = "AccountIdKey"; [ConfigurationProperty(KeyKey, IsKey = true, IsRequired = true)] public string Key diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Extensions/StringExtensions.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Extensions/StringExtensions.cs index 37c67e2c..3dc3f838 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Extensions/StringExtensions.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Extensions/StringExtensions.cs @@ -8,5 +8,15 @@ string result = source.Remove(index, target.Length).Insert(index, newValue); return result; } + + public static string Tail(this string source, int tailLength) + { + if (source == null || tailLength >= source.Length) + { + return source; + } + + return source.Substring(source.Length - tailLength); + } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs index 022aa747..b5f38611 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs @@ -25,21 +25,21 @@ namespace WebsitePanel.WebDavPortal ); routes.MapRoute( - name: AccountRouteNames.PasswordResetEmail, + name: AccountRouteNames.PasswordResetLogin, url: "account/password-reset/step-1", - defaults: new { controller = "Account", action = "PasswordResetEmail" } + defaults: new { controller = "Account", action = "PasswordResetLogin" } ); routes.MapRoute( - name: AccountRouteNames.PasswordResetSms, + name: AccountRouteNames.PasswordResetPincodeSendOptions, url: "account/password-reset/step-2/{token}", - defaults: new { controller = "Account", action = "PasswordResetSms" } + defaults: new { controller = "Account", action = "PasswordResetPincodeSendOptions" } ); routes.MapRoute( - name: AccountRouteNames.PasswordResetSendSms, - url: "account/password-reset/send-new-sms/{token}", - defaults: new { controller = "Account", action = "PasswordResetSendSms" } + name: AccountRouteNames.PasswordResetPincode, + url: "account/password-reset/step-3/{token}", + defaults: new { controller = "Account", action = "PasswordResetPincode" } ); routes.MapRoute( diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/Routes/AccountRouteNames.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/Routes/AccountRouteNames.cs index 6d28ac8e..b690540d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/Routes/AccountRouteNames.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/Routes/AccountRouteNames.cs @@ -12,9 +12,9 @@ namespace WebsitePanel.WebDavPortal.UI.Routes public const string UserProfile = "UserProfileRoute"; public const string PasswordChange = "PasswordChangeRoute"; - public const string PasswordResetEmail = "PasswordResetEmailRoute"; - public const string PasswordResetSms = "PasswordResetSmsRoute"; - public const string PasswordResetSendSms = "PasswordResetSendSmsRoute"; + public const string PasswordResetLogin = "PasswordResetLoginRoute"; + public const string PasswordResetPincodeSendOptions = "PasswordResetPincodeSendOptionsRoute"; + public const string PasswordResetPincode = "PasswordResetPincodeRoute"; public const string PasswordResetFinalStep = "PasswordResetFinalStepRoute"; public const string PasswordResetSuccess = "PasswordResetSuccess"; diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs index 5d383a1b..b2c0bec9 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs @@ -14,6 +14,7 @@ using WebsitePanel.WebDav.Core.Wsp.Framework; using WebsitePanel.WebDavPortal.CustomAttributes; using WebsitePanel.WebDavPortal.Models; using WebsitePanel.WebDavPortal.Models.Account; +using WebsitePanel.WebDavPortal.Models.Account.Enums; using WebsitePanel.WebDavPortal.Models.Common; using WebsitePanel.WebDavPortal.Models.Common.EditorTemplates; using WebsitePanel.WebDavPortal.Models.Common.Enums; @@ -162,16 +163,16 @@ namespace WebsitePanel.WebDavPortal.Controllers [HttpGet] [AllowAnonymous] - public ActionResult PasswordResetEmail() + public ActionResult PasswordResetLogin() { - var model = new PasswordResetEmailModel(); + var model = new PasswordResetLoginModel(); return View(model); } [HttpPost] [AllowAnonymous] - public ActionResult PasswordResetEmail(PasswordResetEmailModel model) + public ActionResult PasswordResetLogin(PasswordResetLoginModel model) { if (!ModelState.IsValid) { @@ -187,17 +188,117 @@ namespace WebsitePanel.WebDavPortal.Controllers return View(model); } - WspContext.Services.Organizations.SendResetUserPasswordEmail(exchangeAccount.ItemId, exchangeAccount.AccountId, Resources.Messages.PasswordResetUserReason, exchangeAccount.PrimaryEmailAddress, false); + var tokenEntity = WspContext.Services.Organizations.CreatePasswordResetAccessToken(exchangeAccount.ItemId, exchangeAccount.AccountId); - return View("PasswordResetEmailSent"); + return RedirectToRoute(AccountRouteNames.PasswordResetPincodeSendOptions, new {token = tokenEntity.AccessTokenGuid.ToString("N")}); } - [HttpGet] [AllowAnonymous] - public ActionResult PasswordResetSms(Guid token) + public ActionResult PasswordResetPincodeSendOptions(Guid token) { - var model = new PasswordResetSmsModel(); + var accessToken = WspContext.Services.Organizations.GetPasswordresetAccessToken(token); + + if (accessToken == null) + { + AddMessage(MessageType.Error, Resources.Messages.IncorrectPasswordResetUrl); + + return RedirectToRoute(AccountRouteNames.PasswordResetLogin); + } + + var user = WspContext.Services.Organizations.GetUserGeneralSettings(accessToken.ItemId, accessToken.AccountId); + + if (string.IsNullOrEmpty(user.MobilePhone)) + { + var result = WspContext.Services.Organizations.SendResetUserPasswordPincodeEmail(accessToken.AccessTokenGuid, user.PrimaryEmailAddress); + + if (result.IsSuccess) + { + AddMessage(MessageType.Success, Resources.Messages.PincodeEmailWasSent); + } + else + { + AddMessage(MessageType.Error, Resources.Messages.PincodeEmailWasNotSent); + } + + return RedirectToRoute(AccountRouteNames.PasswordResetPincode); + } + + var model = new PasswordResetPincodeSendOptionsModel(); + + model.MobileNumber = user.MobilePhone; + model.Email = user.PrimaryEmailAddress; + + return View(model); + } + + [HttpPost] + [AllowAnonymous] + public ActionResult PasswordResetPincodeSendOptions(Guid token, PasswordResetPincodeSendOptionsModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + + var accessToken = WspContext.Services.Organizations.GetPasswordresetAccessToken(token); + + if (accessToken == null) + { + AddMessage(MessageType.Error, Resources.Messages.IncorrectPasswordResetUrl); + + return RedirectToRoute(AccountRouteNames.PasswordResetLogin); + } + + var user = WspContext.Services.Organizations.GetUserGeneralSettings(accessToken.ItemId, accessToken.AccountId); + + switch (model.Method) + { + case PincodeSendMethod.Mobile: + { + var result = WspContext.Services.Organizations.SendResetUserPasswordPincodeSms(accessToken.AccessTokenGuid, user.MobilePhone); + + if (result.IsSuccess) + { + AddMessage(MessageType.Success, Resources.Messages.SmsWasSent); + } + else + { + AddMessage(MessageType.Error, Resources.Messages.SmsWasNotSent); + + return RedirectToRoute(AccountRouteNames.PasswordResetPincodeSendOptions); + } + + break; + } + case PincodeSendMethod.Email: + { + var result = WspContext.Services.Organizations.SendResetUserPasswordPincodeEmail(accessToken.AccessTokenGuid, user.PrimaryEmailAddress); + + if (result.IsSuccess) + { + AddMessage(MessageType.Success, Resources.Messages.PincodeEmailWasSent); + } + else + { + AddMessage(MessageType.Error, Resources.Messages.PincodeEmailWasNotSent); + + return RedirectToRoute(AccountRouteNames.PasswordResetPincodeSendOptions); + } + + break; + } + + } + + return RedirectToRoute(AccountRouteNames.PasswordResetPincode); + } + + [HttpGet] + [AllowAnonymous] + public ActionResult PasswordResetPincode(Guid token) + { + var model = new PasswordResetPincodeModel(); var accessToken = WspContext.Services.Organizations.GetPasswordresetAccessToken(token); @@ -207,25 +308,13 @@ namespace WebsitePanel.WebDavPortal.Controllers { AddMessage(MessageType.Error, Resources.Messages.IncorrectPasswordResetUrl); - return View(model); + return RedirectToRoute(AccountRouteNames.PasswordResetLogin); } if (accessToken != null && accessToken.IsSmsSent == false) { - var user = WspContext.Services.Organizations.GetUserGeneralSettings(accessToken.ItemId, - accessToken.AccountId); - - var result = WspContext.Services.Organizations.SendResetUserPasswordPincodeSms(token, user.MobilePhone); - - if (result.IsSuccess) - { - AddMessage(MessageType.Success, Resources.Messages.SmsWasSent); - } - else - { - AddMessage(MessageType.Error, Resources.Messages.SmsWasNotSent); - } + return RedirectToRoute(AccountRouteNames.PasswordResetPincodeSendOptions); } return View(model); @@ -233,7 +322,7 @@ namespace WebsitePanel.WebDavPortal.Controllers [HttpPost] [AllowAnonymous] - public ActionResult PasswordResetSms(Guid token, PasswordResetSmsModel model) + public ActionResult PasswordResetPincode(Guid token, PasswordResetPincodeModel model) { if (!ModelState.IsValid) { @@ -313,35 +402,6 @@ namespace WebsitePanel.WebDavPortal.Controllers return View(); } - [HttpGet] - [AllowAnonymous] - public ActionResult PasswordResetSendSms(Guid token) - { - var accessToken = WspContext.Services.Organizations.GetPasswordresetAccessToken(token); - - if (accessToken == null) - { - return RedirectToRoute(AccountRouteNames.PasswordResetSms); - } - - var user = WspContext.Services.Organizations.GetUserGeneralSettings(accessToken.ItemId, - accessToken.AccountId); - - var result = WspContext.Services.Organizations.SendResetUserPasswordPincodeSms(accessToken.AccessTokenGuid, - user.MobilePhone); - - if (result.IsSuccess) - { - AddMessage(MessageType.Success, Resources.Messages.SmsWasSent); - } - else - { - AddMessage(MessageType.Error, Resources.Messages.SmsWasNotSent); - } - - return RedirectToRoute(AccountRouteNames.PasswordResetSms); - } - #region Helpers /// @@ -362,7 +422,7 @@ namespace WebsitePanel.WebDavPortal.Controllers { AddMessage(MessageType.Error, Resources.Messages.IncorrectSmsResponse); - return RedirectToRoute(AccountRouteNames.PasswordResetSms); + return RedirectToRoute(AccountRouteNames.PasswordResetPincode); //todo } var tokenEntity = WspContext.Services.Organizations.GetPasswordresetAccessToken(token); diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/Enums/PincodeSendMethod.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/Enums/PincodeSendMethod.cs new file mode 100644 index 00000000..c578c01a --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/Enums/PincodeSendMethod.cs @@ -0,0 +1,8 @@ +namespace WebsitePanel.WebDavPortal.Models.Account.Enums +{ + public enum PincodeSendMethod + { + Mobile, + Email + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetEmailModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetLoginModel.cs similarity index 89% rename from WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetEmailModel.cs rename to WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetLoginModel.cs index 36d5b895..6cd58203 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetEmailModel.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetLoginModel.cs @@ -4,7 +4,7 @@ using WebsitePanel.WebDavPortal.Resources; namespace WebsitePanel.WebDavPortal.Models.Account { - public class PasswordResetEmailModel + public class PasswordResetLoginModel { [Required] [Display(ResourceType = typeof(Resources.UI), Name = "Email")] diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetSmsModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeModel.cs similarity index 83% rename from WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetSmsModel.cs rename to WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeModel.cs index 45a9de72..86aad9d5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetSmsModel.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeModel.cs @@ -3,7 +3,7 @@ using WebsitePanel.WebDavPortal.Models.Common; namespace WebsitePanel.WebDavPortal.Models.Account { - public class PasswordResetSmsModel + public class PasswordResetPincodeModel { [Required] public string Sms { get; set; } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeSendOptionsModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeSendOptionsModel.cs new file mode 100644 index 00000000..5f207a0a --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Account/PasswordResetPincodeSendOptionsModel.cs @@ -0,0 +1,11 @@ +using WebsitePanel.WebDavPortal.Models.Account.Enums; + +namespace WebsitePanel.WebDavPortal.Models.Account +{ + public class PasswordResetPincodeSendOptionsModel + { + public PincodeSendMethod Method { get; set; } + public string MobileNumber { get; set; } + public string Email { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.Designer.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.Designer.cs index d456d0af..5c011c95 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.Designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.Designer.cs @@ -160,7 +160,7 @@ namespace WebsitePanel.WebDavPortal.Resources { } /// - /// Looks up a localized string similar to Please enter the verification code we sent to your phone. If you didn't receive a code, you can {0}.. + /// Looks up a localized string similar to Please enter the verification code we sent to you. If you didn't receive a code, you can {0}.. /// public static string PasswordResetSmsHintFormat { get { @@ -213,6 +213,24 @@ namespace WebsitePanel.WebDavPortal.Resources { } } + /// + /// Looks up a localized string similar to Pincode was not sent to your email address.. + /// + public static string PincodeEmailWasNotSent { + get { + return ResourceManager.GetString("PincodeEmailWasNotSent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pincode was sent to your email address.. + /// + public static string PincodeEmailWasSent { + get { + return ResourceManager.GetString("PincodeEmailWasSent", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0} field is required. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.resx b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.resx index 3155ac22..99417c89 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/Messages.resx @@ -151,7 +151,7 @@ A message was sent to your email address. Please check your email for further instructions. - Please enter the verification code we sent to your phone. If you didn't receive a code, you can {0}. + Please enter the verification code we sent to you. If you didn't receive a code, you can {0}. Webdav portal user request. @@ -168,6 +168,12 @@ Phone number is invalid + + Pincode was not sent to your email address. + + + Pincode was sent to your email address. + {0} field is required diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs index 0df331bf..57565d1d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.Designer.cs @@ -699,6 +699,15 @@ namespace WebsitePanel.WebDavPortal.Resources { } } + /// + /// Looks up a localized string similar to Pincode. + /// + public static string Pincode { + get { + return ResourceManager.GetString("Pincode", resourceCulture); + } + } + /// /// Looks up a localized string similar to Please wait.... /// @@ -807,6 +816,15 @@ namespace WebsitePanel.WebDavPortal.Resources { } } + /// + /// Looks up a localized string similar to Send. + /// + public static string Send { + get { + return ResourceManager.GetString("Send", resourceCulture); + } + } + /// /// Looks up a localized string similar to Send email. /// @@ -816,6 +834,15 @@ namespace WebsitePanel.WebDavPortal.Resources { } } + /// + /// Looks up a localized string similar to When you click the send button below, a Password Reset PIN will be sent to your Cell Phone or Email Address.. + /// + public static string SendPincodeTo { + get { + return ResourceManager.GetString("SendPincodeTo", resourceCulture); + } + } + /// /// Looks up a localized string similar to Size. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx index ca01221f..e5779ae5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Resources/UI.resx @@ -411,4 +411,13 @@ You are changing password for '{0}' account. + + Pincode + + + Send + + + When you click the send button below, a Password Reset PIN will be sent to your Cell Phone or Email Address. + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/Login.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/Login.cshtml index 23aaf2f0..3658975d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/Login.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/Login.cshtml @@ -36,7 +36,7 @@ @if (Model.PasswordResetEnabled) { - @UI.ForgotYourPassword + @UI.ForgotYourPassword }
diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetEmail.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetLogin.cshtml similarity index 69% rename from WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetEmail.cshtml rename to WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetLogin.cshtml index fca5271d..e8b5dc53 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetEmail.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetLogin.cshtml @@ -1,6 +1,6 @@ @using WebsitePanel.WebDavPortal.Resources @using WebsitePanel.WebDavPortal.UI.Routes -@model WebsitePanel.WebDavPortal.Models.Account.PasswordResetEmailModel +@model WebsitePanel.WebDavPortal.Models.Account.PasswordResetLoginModel @{ Layout = "~/Views/Shared/_Layout.cshtml"; @@ -8,7 +8,7 @@
- @using (Html.BeginRouteForm(AccountRouteNames.PasswordResetEmail, FormMethod.Post, new { @class = "user-password-reset-email bs-val-styles col-lg-10 col-lg-offset-3", id = "user-password-reset" })) + @using (Html.BeginRouteForm(AccountRouteNames.PasswordResetLogin, FormMethod.Post, new { @class = "user-password-reset-email bs-val-styles col-lg-10 col-lg-offset-3", id = "user-password-reset" })) {

@UI.PasswordReset

@@ -18,6 +18,6 @@ @Html.TextBoxFor(x => x.Email, new { @class = "form-control", placeholder = UI.Login }) @Html.ValidationMessageFor(x => x.Email)
- + }
diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetSms.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincode.cshtml similarity index 73% rename from WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetSms.cshtml rename to WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincode.cshtml index ca9a955f..39d4f48e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetSms.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincode.cshtml @@ -1,6 +1,6 @@ @using WebsitePanel.WebDavPortal.Resources @using WebsitePanel.WebDavPortal.UI.Routes -@model WebsitePanel.WebDavPortal.Models.Account.PasswordResetSmsModel +@model WebsitePanel.WebDavPortal.Models.Account.PasswordResetPincodeModel @{ Layout = "~/Views/Shared/_Layout.cshtml"; @@ -9,7 +9,7 @@ @if (Model.IsTokenExist) {
- @using (Html.BeginRouteForm(AccountRouteNames.PasswordResetSms, FormMethod.Post, new {@class = "user-password-reset-sms bs-val-styles col-lg-9 col-lg-offset-3", id = "user-password-reset"})) + @using (Html.BeginRouteForm(AccountRouteNames.PasswordResetPincode, FormMethod.Post, new {@class = "user-password-reset-sms bs-val-styles col-lg-9 col-lg-offset-3", id = "user-password-reset"})) { @Html.HiddenFor(x=>x.IsTokenExist) @@ -17,9 +17,9 @@

@UI.PasswordReset

- +
- @Html.TextBoxFor(x => x.Sms, new {@class = "form-control", placeholder = UI.Sms}) + @Html.TextBoxFor(x => x.Sms, new {@class = "form-control", placeholder = UI.Pincode}) @Html.ValidationMessageFor(x => x.Sms)
diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml new file mode 100644 index 00000000..d35ba688 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml @@ -0,0 +1,51 @@ +@using WebsitePanel.WebDav.Core.Extensions +@using WebsitePanel.WebDavPortal.Models.Account.Enums +@using WebsitePanel.WebDavPortal.Resources +@using WebsitePanel.WebDavPortal.UI.Routes +@model WebsitePanel.WebDavPortal.Models.Account.PasswordResetPincodeSendOptionsModel + +@{ + var indexOf = Model.Email.IndexOf('@'); + + var maskedEmail = string.Empty; + for (int i = 0; i < indexOf - 1; i++) + { + maskedEmail += '*'; + } + + maskedEmail += Model.Email.Substring(indexOf - 1); + + var maskedPhone = string.Empty; + for (int i = 0; i < Model.MobileNumber.Count() - 5; i++) + { + maskedPhone += '*'; + } + + maskedPhone += Model.MobileNumber.Tail(4); +} + + +
+ @using (Html.BeginRouteForm(AccountRouteNames.PasswordResetPincodeSendOptions, FormMethod.Post, new { @class = "user-password-pincode-send-options bs-val-styles col-lg-10 col-lg-offset-3", id = "user-password-reset" })) + { +
+

@UI.PasswordReset

+
+
+
+ +
+
+ @Html.RadioButtonFor(x => x.Method, PincodeSendMethod.Mobile) + @maskedPhone (@UI.MobilePhone) +
+ +
+ @Html.RadioButtonFor(x => x.Method, PincodeSendMethod.Email) + @maskedEmail (@UI.Email) +
+ +
+ + } +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Web.config b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Web.config index 0764725e..1e2c7eb8 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Web.config @@ -54,6 +54,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj index f8d0894a..bbf55b81 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/WebsitePanel.WebDavPortal.csproj @@ -196,10 +196,12 @@ + - + - + + @@ -486,11 +488,12 @@ - + - + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SettingsUserPasswordResetPincodeLetter.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SettingsUserPasswordResetPincodeLetter.ascx.resx new file mode 100644 index 00000000..559ba6bc --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/SettingsUserPasswordResetPincodeLetter.ascx.resx @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + High + + + Low + + + Normal + + + From: + + + HTML Body: + + + Logo Url: + + + No Changes HTML Body: + + + No Changes Text Body: + + + Password Reset Link Sms Body: + + + Password Reset Link Pincode Body: + + + Priority: + + + Subject: + + + Text Body: + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/UserAccountMailTemplateSettings.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/UserAccountMailTemplateSettings.ascx.resx index cedcfc35..3329ebf5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/UserAccountMailTemplateSettings.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/UserAccountMailTemplateSettings.ascx.resx @@ -156,4 +156,7 @@ Organization User Password Reset Letter + + Organization User Password Reset Pincode Letter + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx index 53935cdd..f71a6d2a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx @@ -49,12 +49,5 @@ - tr> -

- - - - - \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.cs index 597d2d4e..7def464d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.cs @@ -20,7 +20,6 @@ namespace WebsitePanel.Portal txtLogoUrl.Text = settings["LogoUrl"]; txtBodyPasswordResetLinkSmsBody.Text = settings["PasswordResetLinkSmsBody"]; - txtPasswordResetPincodeSmsBody.Text = settings["PasswordResetPincodeSmsBody"]; } public void SaveSettings(UserSettings settings) @@ -33,7 +32,6 @@ namespace WebsitePanel.Portal settings["LogoUrl"] = txtLogoUrl.Text; settings["PasswordResetLinkSmsBody"]= txtBodyPasswordResetLinkSmsBody.Text; - settings["PasswordResetPincodeSmsBody"] =txtPasswordResetPincodeSmsBody.Text; } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.designer.cs index e4d4f21f..797b8981 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetLetter.ascx.designer.cs @@ -137,23 +137,5 @@ namespace WebsitePanel.Portal { /// To modify move field declaration from designer file to code-behind file. /// protected global::System.Web.UI.WebControls.TextBox txtBodyPasswordResetLinkSmsBody; - - /// - /// lblPasswordResetPincodeSmsBody control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label lblPasswordResetPincodeSmsBody; - - /// - /// txtPasswordResetPincodeSmsBody control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox txtPasswordResetPincodeSmsBody; } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx new file mode 100644 index 00000000..2ec661d6 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx @@ -0,0 +1,55 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SettingsUserPasswordResetPincodeLetter.ascx.cs" Inherits="WebsitePanel.Portal.SettingsUserPasswordResetPincodeLetter" %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + High + Normal + Low + +
+


+


+


+
\ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.cs new file mode 100644 index 00000000..11ba9573 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using WebsitePanel.EnterpriseServer; + +namespace WebsitePanel.Portal +{ + public partial class SettingsUserPasswordResetPincodeLetter : WebsitePanelControlBase, IUserSettingsEditorControl + { + public void BindSettings(UserSettings settings) + { + txtFrom.Text = settings["From"]; + txtSubject.Text = settings["Subject"]; + Utils.SelectListItem(ddlPriority, settings["Priority"]); + txtHtmlBody.Text = settings["HtmlBody"]; + txtTextBody.Text = settings["TextBody"]; + txtLogoUrl.Text = settings["LogoUrl"]; + + txtPasswordResetPincodeSmsBody.Text = settings["PasswordResetPincodeSmsBody"]; + } + + public void SaveSettings(UserSettings settings) + { + settings["From"] = txtFrom.Text; + settings["Subject"] = txtSubject.Text; + settings["Priority"] = ddlPriority.SelectedValue; + settings["HtmlBody"] = txtHtmlBody.Text; + settings["TextBody"] = txtTextBody.Text; + settings["LogoUrl"] = txtLogoUrl.Text; + + settings["PasswordResetPincodeSmsBody"] = txtPasswordResetPincodeSmsBody.Text; + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.designer.cs new file mode 100644 index 00000000..01935fd4 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/SettingsUserPasswordResetPincodeLetter.ascx.designer.cs @@ -0,0 +1,141 @@ +//------------------------------------------------------------------------------ +// +// 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 { + + + public partial class SettingsUserPasswordResetPincodeLetter { + + /// + /// lblFrom control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblFrom; + + /// + /// txtFrom control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtFrom; + + /// + /// lblSubject control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblSubject; + + /// + /// txtSubject control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtSubject; + + /// + /// lblPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblPriority; + + /// + /// ddlPriority control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddlPriority; + + /// + /// lblLogoUrl control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblLogoUrl; + + /// + /// txtLogoUrl control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtLogoUrl; + + /// + /// lblHtmlBody control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblHtmlBody; + + /// + /// txtHtmlBody control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtHtmlBody; + + /// + /// lblTextBody control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblTextBody; + + /// + /// txtTextBody control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtTextBody; + + /// + /// lblPasswordResetPincodeSmsBody control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblPasswordResetPincodeSmsBody; + + /// + /// txtPasswordResetPincodeSmsBody control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtPasswordResetPincodeSmsBody; + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx index 66a3d537..dd09fdc8 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx @@ -50,6 +50,10 @@ +
  • + +
  • diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx.designer.cs index e402ebb0..a5217667 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/UserAccountMailTemplateSettings.ascx.designer.cs @@ -120,6 +120,15 @@ namespace WebsitePanel.Portal { /// protected global::System.Web.UI.WebControls.HyperLink lnkOrganizationUserPasswordResetLetter; + /// + /// lnkOrganizationUserPasswordResetPincodeLetter control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink lnkOrganizationUserPasswordResetPincodeLetter; + /// /// btnCancel control. /// 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 a1538950..caec4286 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj @@ -342,6 +342,13 @@ UserPasswordExpirationNotificationView.ascx ASPXCodeBehind + + SettingsUserPasswordResetPincodeLetter.ascx + ASPXCodeBehind + + + SettingsUserPasswordResetPincodeLetter.ascx + Connect.aspx ASPXCodeBehind @@ -4876,6 +4883,7 @@ + @@ -4989,6 +4997,7 @@ + From 948e6dbb879c9f359118640bf825821968af2e9f Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 30 Apr 2015 08:02:42 -0400 Subject: [PATCH 08/15] Added tag build-2.1.0.693 for changeset f3150d2962a6 From d022ecf9601afc768d56f885b5100e322ad879b7 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Thu, 30 Apr 2015 05:48:32 -0700 Subject: [PATCH 09/15] password reset style fix --- .../PasswordResetPincodeSendOptions.cshtml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml index d35ba688..72e2f08c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Account/PasswordResetPincodeSendOptions.cshtml @@ -35,14 +35,18 @@
    -
    - @Html.RadioButtonFor(x => x.Method, PincodeSendMethod.Mobile) - @maskedPhone (@UI.MobilePhone) +
    +
    -
    - @Html.RadioButtonFor(x => x.Method, PincodeSendMethod.Email) - @maskedEmail (@UI.Email) +
    +
    From 5065e380716705594ae2f4031e3f5b035a47b864 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 30 Apr 2015 10:02:24 -0400 Subject: [PATCH 10/15] Added tag build-2.1.0.694 for changeset 311b11584ec6 From 2c9716bbe656bdd1fc162c97d8ed4c2ace554175 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 30 Apr 2015 10:26:22 -0400 Subject: [PATCH 11/15] Added tag build-2.1.0.695 for changeset ba266a43ab61 From a6bfba79b7e8b02c6f35e320c624708d04be2245 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 30 Apr 2015 10:46:30 -0400 Subject: [PATCH 12/15] Added tag build-2.1.0.696 for changeset 8b1284ab3caf From 2c7d0d0302347968bba9941861f0a1a08cf26b2e Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 30 Apr 2015 22:31:42 -0400 Subject: [PATCH 13/15] Added tag build-2.1.0.697 for changeset cb3ea5218b34 From 281563d423757862318c91a68095070ccee16c47 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Fri, 1 May 2015 07:30:04 -0400 Subject: [PATCH 14/15] CSS fix --- .../WebsitePanel.WebPortal/App_Themes/Default/Styles/Skin.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Styles/Skin.css b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Styles/Skin.css index b46ae27a..448cd1bb 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Styles/Skin.css +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Styles/Skin.css @@ -124,7 +124,7 @@ table.BorderFillBox td .Brick {padding:0; line-height:normal; margin-bottom:9px; .GridFooter {clear:both; font-size:8pt; color:#888; padding:8px 5px; border:1px solid #ddd; margin:10px 0 20px 0;} .GridFooter img {vertical-align:-2px !important;} .FormBody fieldset {padding:5px 10px 10px 10px; border:1px solid #ccc; margin-top:10px;} -.PreviewArea {background:#f0ad4e; padding:15px; margin:20px; color:#fff; font-size:14px;} +.PreviewArea {background:#f0ad4e; padding:15px; margin:20px; color:#000; font-size:14px;} .HostingPlanGroup .Header {clear:both; background:#aa73c1; color:#fff; height:30px !important; line-height:30px;} .HostingPlanGroup .Header span {font-size:inherit; line-height:inherit;} .HostingPlanGroup .Header .Left {float:left; font-weight:bold;} From be25cb2c1924ce62808d000f33f9c48fff99f070 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Fri, 1 May 2015 07:41:45 -0400 Subject: [PATCH 15/15] Added tag build-2.1.0.698 for changeset 33c84bca8780