password reset workflow changed

This commit is contained in:
vfedosevich 2015-04-30 04:24:15 -07:00
parent 2f1e740d5a
commit 410b15c2c4
36 changed files with 1229 additions and 255 deletions

View file

@ -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(

View file

@ -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";

View file

@ -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
/// <summary>
@ -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);

View file

@ -0,0 +1,8 @@
namespace WebsitePanel.WebDavPortal.Models.Account.Enums
{
public enum PincodeSendMethod
{
Mobile,
Email
}
}

View file

@ -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")]

View file

@ -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; }

View file

@ -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; }
}
}

View file

@ -160,7 +160,7 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
/// <summary>
/// Looks up a localized string similar to Please enter the verification code we sent to your phone. If you didn&apos;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&apos;t receive a code, you can {0}..
/// </summary>
public static string PasswordResetSmsHintFormat {
get {
@ -213,6 +213,24 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Pincode was not sent to your email address..
/// </summary>
public static string PincodeEmailWasNotSent {
get {
return ResourceManager.GetString("PincodeEmailWasNotSent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pincode was sent to your email address..
/// </summary>
public static string PincodeEmailWasSent {
get {
return ResourceManager.GetString("PincodeEmailWasSent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} field is required.
/// </summary>

View file

@ -151,7 +151,7 @@
<value>A message was sent to your email address. Please check your email for further instructions.</value>
</data>
<data name="PasswordResetSmsHintFormat" xml:space="preserve">
<value>Please enter the verification code we sent to your phone. If you didn't receive a code, you can {0}.</value>
<value>Please enter the verification code we sent to you. If you didn't receive a code, you can {0}.</value>
</data>
<data name="PasswordResetUserReason" xml:space="preserve">
<value>Webdav portal user request.</value>
@ -168,6 +168,12 @@
<data name="PhoneNumberInvalid" xml:space="preserve">
<value>Phone number is invalid</value>
</data>
<data name="PincodeEmailWasNotSent" xml:space="preserve">
<value>Pincode was not sent to your email address.</value>
</data>
<data name="PincodeEmailWasSent" xml:space="preserve">
<value>Pincode was sent to your email address.</value>
</data>
<data name="Required" xml:space="preserve">
<value>{0} field is required</value>
</data>

View file

@ -699,6 +699,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Pincode.
/// </summary>
public static string Pincode {
get {
return ResourceManager.GetString("Pincode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please wait....
/// </summary>
@ -807,6 +816,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Send.
/// </summary>
public static string Send {
get {
return ResourceManager.GetString("Send", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Send email.
/// </summary>
@ -816,6 +834,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// 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..
/// </summary>
public static string SendPincodeTo {
get {
return ResourceManager.GetString("SendPincodeTo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Size.
/// </summary>

View file

@ -411,4 +411,13 @@
<data name="YouRChangingPswForFormat" xml:space="preserve">
<value>You are changing password for '{0}' account.</value>
</data>
<data name="Pincode" xml:space="preserve">
<value>Pincode</value>
</data>
<data name="Send" xml:space="preserve">
<value>Send</value>
</data>
<data name="SendPincodeTo" xml:space="preserve">
<value>When you click the send button below, a Password Reset PIN will be sent to your Cell Phone or Email Address.</value>
</data>
</root>

View file

@ -36,7 +36,7 @@
<button type="submit" class="btn btn-default">Sign in</button>
@if (Model.PasswordResetEnabled)
{
<a href="@Url.RouteUrl(AccountRouteNames.PasswordResetEmail)" class="forgot-your-password-link">@UI.ForgotYourPassword</a>
<a href="@Url.RouteUrl(AccountRouteNames.PasswordResetLogin)" class="forgot-your-password-link">@UI.ForgotYourPassword</a>
}
</div>
</div>

View file

@ -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 @@
<div class="container row">
@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" }))
{
<div class="form-group">
<h3>@UI.PasswordReset</h3>
@ -18,6 +18,6 @@
@Html.TextBoxFor(x => x.Email, new { @class = "form-control", placeholder = UI.Login })
@Html.ValidationMessageFor(x => x.Email)
</div>
<button type="submit" class="btn btn-default">@UI.SendEmail</button>
<button type="submit" class="btn btn-default">@UI.Next</button>
}
</div>

View file

@ -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)
{
<div class="container row">
@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 @@
<h3>@UI.PasswordReset</h3>
</div>
<div class="form-group">
<label for="@Html.IdFor(x => x.Sms)" class="control-label">@Html.Raw(string.Format(Messages.PasswordResetSmsHintFormat, Html.RouteLink(UI.TryAgain.ToLowerInvariant(), AccountRouteNames.PasswordResetSendSms)))</label>
<label for="@Html.IdFor(x => x.Sms)" class="control-label">@Html.Raw(string.Format(Messages.PasswordResetSmsHintFormat, Html.RouteLink(UI.TryAgain.ToLowerInvariant(), AccountRouteNames.PasswordResetPincodeSendOptions)))</label>
<div >
@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)
</div>
</div>

View file

@ -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);
}
<div class="container row">
@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" }))
{
<div class="form-group">
<h3>@UI.PasswordReset</h3>
</div>
<div class="form-group">
<div class="input-group">
<label class="control-label">@UI.SendPincodeTo </label>
</div>
<div class="input-group">
@Html.RadioButtonFor(x => x.Method, PincodeSendMethod.Mobile)
@maskedPhone (@UI.MobilePhone)
</div>
<div class="input-group">
@Html.RadioButtonFor(x => x.Method, PincodeSendMethod.Email)
@maskedEmail (@UI.Email)
</div>
</div>
<button type="submit" class="btn btn-default">@UI.Send</button>
}
</div>

View file

@ -54,6 +54,7 @@
<add key="UserGroupsKey" value="UserGroups" />
<add key="OwaEditFoldersSession" value="OwaEditFolders" />
<add key="PasswordResetSmsKey" value="PasswordResetSms" />
<add key="AccountIdKey" value="AccountId" />
</sessionKeys>
<fileIcons defaultPath="~/Content/Images/other-icon.png" folderPath="~/Content/Images/folder_100x100.png">
<add extension=".txt" path="~/Content/Images/txt-icon.png" />

View file

@ -196,10 +196,12 @@
<Compile Include="Mapping\Profiles\Webdav\ResourceTableItemProfile.cs" />
<Compile Include="ModelBinders\DataTables\JqueryDataTableModelBinder.cs" />
<Compile Include="Models\AccountModel.cs" />
<Compile Include="Models\Account\Enums\PincodeSendMethod.cs" />
<Compile Include="Models\Account\PasswordChangeModel.cs" />
<Compile Include="Models\Account\PasswordResetEmailModel.cs" />
<Compile Include="Models\Account\PasswordResetLoginModel.cs" />
<Compile Include="Models\Account\PasswordResetFinalStepModel.cs" />
<Compile Include="Models\Account\PasswordResetSmsModel.cs" />
<Compile Include="Models\Account\PasswordResetPincodeSendOptionsModel.cs" />
<Compile Include="Models\Account\PasswordResetPincodeModel.cs" />
<Compile Include="Models\Account\UserProfile.cs" />
<Compile Include="Models\Common\AjaxModel.cs" />
<Compile Include="Models\Common\DataTable\JqueryDataTableBaseEntity.cs" />
@ -486,11 +488,12 @@
<Content Include="Views\Shared\EditorTemplates\CountrySelector.cshtml" />
<Content Include="Views\Account\PasswordChange.cshtml" />
<Content Include="Views\Shared\EditorTemplates\PasswordEditor.cshtml" />
<Content Include="Views\Account\PasswordResetEmail.cshtml" />
<Content Include="Views\Account\PasswordResetLogin.cshtml" />
<Content Include="Views\Account\PasswordResetEmailSent.cshtml" />
<Content Include="Views\Account\PasswordResetSms.cshtml" />
<Content Include="Views\Account\PasswordResetPincode.cshtml" />
<Content Include="Views\Account\PasswordResetFinalStep.cshtml" />
<Content Include="Views\Account\PasswordSuccessfullyChanged.cshtml" />
<Content Include="Views\Account\PasswordResetPincodeSendOptions.cshtml" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\FileSystem\Enums\" />