Created
May 3, 2023 07:08
-
-
Save hawjeh/c8daf9367fa84c4777cca341d6750a42 to your computer and use it in GitHub Desktop.
Sitefinity v13 Custom Reset Password
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html ng-app="app" ng-controller="LayoutCtrl"> | |
<head> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<title>{siteName}</title> | |
<style> | |
img { | |
width: 100px; | |
height: 100px; | |
} | |
form { | |
margin: 0 auto; | |
box-sizing: border-box; | |
border: 1px solid #ddd; | |
padding: 40px 50px; | |
width: 430px; | |
min-height: 430px; | |
background-color: #fff; | |
} | |
.sfSubmitBtns { | |
display: flex; | |
flex-direction: row; | |
} | |
.sfLoginBtn { | |
width: 45% !important; | |
margin-right: 10px; | |
} | |
.sfForgotPasswordBtn { | |
background-color: #1a4283 !important; | |
} | |
</style> | |
{stylesheets} | |
<script src="content/app/webfont-loader-top.js"></script> | |
</head> | |
<body ng-cloak> | |
<div class="sf-authentication-screen"> | |
<h1 class="sf-logo"></h1> | |
<form name="form" method="post" action="{{model.fullLoginUrl}}" id="loginForm" | |
class="sf-login-form -sf-content-centered -sf-center-text"> | |
<anti-forgery-token token="model.antiForgery"></anti-forgery-token> | |
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAflBMVEXc7PXd7PXd7fXe7fXe7fbf7vbh7/bh7/fi7/fj8Pfk8Pfl8fjm8fjm8vjn8vjo8vjo8/np8/nq9Pnr9Pns9frt9fru9vrv9vrw9/vx+Pvy+Pvz+fz0+fz1+vz2+vz2+v34+/35+/36/P76/f77/f78/f78/v79/v7+//////+lNPEBAAABIElEQVR4Ae3V2w6aUBSE4dkCYj2gICoHQVRQ5v1fsNpoI0gTa9e+aLK+F/iTuRkopZRSSimlPuP6vmu5EB95c4wtdpYNH5olLNnxxQ5WbNmxhQUBewKIcxv2NK7tsawMZi58czGQNeOAmf215PfKOSCHrJIDSsgqOKCArJQDUshac8AasnwO8CGs4psK0iK+iSDNnNhzMhA3Z88cFiTsSGCD2fPF3sAKk/G3zMCWsOEvTQiLRqvscMhWI/zHvAV6Fh5kTbOWqYMXTso2m0KME1W8q0ODBxPWvKsiBxL85MqnczzGzTg+8+ma+PhHJijZVRdFza4yMPiet6n5kXrj4TuTvOXH2nwi97h/ttaIRjRiKeL9+CselFJKKaWUUj0/AWGBopm+4+PNAAAAAElFTkSuQmCC" | |
alt="Default profile photo" /> | |
<h2>{{model.resources["loginHeader"]}}</h2> | |
<ul class="-sf-clearfix"> | |
<li ng-show="model.showProviders"> | |
<label for="membershipProvider">{{model.resources["provider"]}}</label> | |
<select id="membershipProvider" name="membershipProvider" ng-model="model.selectedProvider" | |
ng-options="p.friendlyName for p in model.providers track by p.name"></select> | |
</li> | |
<li> | |
<input required name="username" autofocus id="username" type="text" class="sf-input" | |
placeholder='{{model.resources["emailOrUsername"]}}' ng-model="model.username"> | |
</li> | |
<li> | |
<input required id="password" name="password" type="password" class="sf-input" | |
placeholder='{{model.resources["password"]}}' ng-model="model.password" autocomplete="off"> | |
</li> | |
<li class="sf-login-form__remember" ng-show="model.allowRememberMe"> | |
<input type="checkbox" id="rememberMe" name="rememberMe" ng-model="model.rememberMe" value="true"> | |
<label for="rememberMe">{{model.resources["rememberMe"]}}</label> | |
</li> | |
</ul> | |
<div class="-sf-txt-failure" ng-show="model.errorMessage"> | |
{{model.errorMessage}} | |
</div> | |
<div class="sfSubmitBtns"> | |
<button class="sf-button -sf-action sfLoginBtn" id="loginButton"> | |
<strong> | |
Login | |
</strong> | |
</button> | |
<!--TODO: Change URL below --> | |
<a id="forgotPassowrd" class="sf-button -sf-action sfForgotPasswordBtn" href="/ForgotPassword"> | |
<strong>Forgot Password?</strong> | |
</a> | |
</div> | |
<!--TODO: Uncheck below for external providers --> | |
<!-- <div ng-show="model.externalProviders"> | |
<h2>{{model.resources["useYorAccount"]}}</h2> | |
<ul class="sf-mt--20"> | |
<li ng-repeat="provider in model.externalProviders"> | |
<a class="sf-button {{provider.linkCssClass}}" href="{{provider.href}}">{{provider.text}}</a> | |
</li> | |
</ul> | |
</div> --> | |
</form> | |
</div> | |
<script id='modelJson' type='application/json'> | |
{model} | |
</script> | |
{scripts} | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protected void Application_Start() | |
{ | |
AntiForgeryConfig.SuppressXFrameOptionsHeader = true; | |
} | |
protected void Application_BeginRequest(object sender, EventArgs e) | |
{ | |
HttpContext.Current.Response.AddHeader("X-Frame-Options", "SAMEORIGIN"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Net.Mail; | |
using System.Web.Mvc; | |
using Telerik.Sitefinity; | |
using Telerik.Sitefinity.Data; | |
using Telerik.Sitefinity.DynamicModules; | |
using Telerik.Sitefinity.Model; | |
using Telerik.Sitefinity.Mvc; | |
using Telerik.Sitefinity.Security; | |
using Telerik.Sitefinity.Services; | |
using Telerik.Sitefinity.Services.Notifications; | |
using Telerik.Sitefinity.Utilities.TypeConverters; | |
using Telerik.Sitefinity.Versioning; | |
namespace SitefinityWebApp.Mvc.Controllers | |
{ | |
[ControllerToolboxItem( | |
Title = "ForgotPassword", | |
Name = "ForgotPassword", | |
SectionName = "Sparks Custom App")] | |
public class ForgotPasswordController : Controller | |
{ | |
private readonly Type forgotPasswordRecordType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Sparks.ForgotPasswordRecord"); | |
public ForgotPasswordController() { } | |
public ActionResult Index() | |
{ | |
return View("Index", new ForgotPasswordModel()); | |
} | |
public ActionResult ChangePassword(string id) | |
{ | |
if (string.IsNullOrEmpty(id)) | |
{ | |
return View("Index", new ForgotPasswordModel()); | |
} | |
var model = new ForgotPasswordModel() | |
{ | |
RequestId = id | |
}; | |
return View("ChangePassword", model); | |
} | |
[HttpPost] | |
public ActionResult RequestResetPasswordForm(ForgotPasswordModel model) | |
{ | |
var email = model.Email; | |
var userManager = UserManager.GetManager(); | |
var user = userManager.GetUsers().FirstOrDefault(o => o.Email.ToLower() == email.ToLower()); | |
if (user != null) | |
{ | |
var requestId = Guid.NewGuid().ToString(); | |
var transactionName = "ResetPasswordRequest"; | |
var versionManager = VersionManager.GetManager(null, transactionName); | |
var dynamicModuleManager = DynamicModuleManager.GetManager(string.Empty, transactionName); | |
dynamicModuleManager.Provider.SuppressSecurityChecks = true; | |
var item = dynamicModuleManager.CreateDataItem(forgotPasswordRecordType); | |
item.SetString("RequestId", requestId); | |
item.SetString("UserId", user.Id.ToString()); | |
item.SetWorkflowStatus(dynamicModuleManager.Provider.ApplicationName, "Draft"); | |
versionManager.CreateVersion(item, false); | |
TransactionManager.CommitTransaction(transactionName); | |
dynamicModuleManager.Provider.SuppressSecurityChecks = false; | |
var msg = string.Format("Please visit {0} to update password.", "https://domain/forgotpassword/changepassword?id=" + requestId); // To update url | |
SendEmail(email, msg); | |
model.Error = "Reset password link sent to email"; | |
} | |
else | |
{ | |
model.Error = "Invalid user"; | |
} | |
return View("Index", model); | |
} | |
[HttpPost] | |
public ActionResult RequestChangePasswordForm(ForgotPasswordModel model) | |
{ | |
var transactionName = "ChangePasswordRequest"; | |
var dynamicModuleManager = DynamicModuleManager.GetManager(string.Empty, transactionName); | |
var item = dynamicModuleManager.GetDataItems(forgotPasswordRecordType).ToList().FirstOrDefault(x => x.GetValue<Lstring>("RequestId").ToString().ToLower() == model.RequestId.ToLower()); | |
if (item != null) | |
{ | |
if (model.NewPassword1.ToLower() == model.NewPassword2.ToLower()) | |
{ | |
var userManager = UserManager.GetManager(); | |
var users = userManager.GetUsers().ToList(); | |
var user = users.FirstOrDefault(o => o.Id.ToString().ToLower() == item.GetValue<Lstring>("UserId").ToString().ToLower()); | |
if (user != null) | |
{ | |
userManager.Provider.SuppressSecurityChecks = true; | |
// Reset password | |
var temp = user.ResetPassword(); | |
userManager.SaveChanges(); | |
// Change password | |
user.ChangePassword(temp, model.NewPassword1); | |
userManager.SaveChanges(); | |
userManager.Provider.SuppressSecurityChecks = false; | |
dynamicModuleManager.Provider.SuppressSecurityChecks = true; | |
dynamicModuleManager.DeleteDataItem(item); | |
TransactionManager.CommitTransaction(transactionName); | |
dynamicModuleManager.Provider.SuppressSecurityChecks = false; | |
model.Error = "Password updated"; | |
} | |
} | |
else | |
{ | |
model.Error = "Password is not matched"; | |
} | |
} | |
else | |
{ | |
model.Error = "Invalid request"; | |
} | |
return View("ChangePassword", model); | |
} | |
private void SendEmail(string email, string msg) | |
{ | |
var context = new ServiceContext(string.Empty, "ResetPassword"); | |
var profile = SystemManager.GetNotificationService().GetDefaultSenderProfile(context, "smtp"); | |
var sender = profile.CustomProperties["defaultSenderEmailAddress"]; | |
var message = new MailMessage | |
{ | |
From = new MailAddress(sender, sender), | |
Subject = "Reset Password", | |
IsBodyHtml = true, | |
Body = msg, | |
}; | |
message.To.Add(email); | |
var smtpServer = new SmtpClient | |
{ | |
Host = profile.CustomProperties["host"], | |
Port = Convert.ToInt32(profile.CustomProperties["port"]), | |
EnableSsl = Convert.ToBoolean(profile.CustomProperties["useSSL"]), | |
DeliveryMethod = SmtpDeliveryMethod.Network, | |
Credentials = new System.Net.NetworkCredential(profile.CustomProperties["username"], profile.CustomProperties["password"]) | |
}; | |
smtpServer.Send(message); | |
} | |
protected override void HandleUnknownAction(string actionName) | |
{ | |
this.ActionInvoker.InvokeAction(this.ControllerContext, "Index"); | |
} | |
} | |
public class ForgotPasswordModel | |
{ | |
public string RequestId { get; set; } | |
public string Email { get; set; } | |
public string NewPassword1 { get; set; } | |
public string NewPassword2 { get; set; } | |
public string Error { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model SitefinityWebApp.Mvc.Controllers.ForgotPasswordModel | |
@using Telerik.Sitefinity.UI.MVC; | |
<style> | |
.sfChangePasswordForm { | |
display: flex; | |
justify-content: center; | |
margin-top: 100px; | |
line-height: 2rem; | |
} | |
form[name="ChangePasswordForm"] { | |
min-width: 420px; | |
border: 1px solid lightgray; | |
padding: 2rem; | |
} | |
</style> | |
<div class="sfChangePasswordForm"> | |
@using (Html.BeginFormSitefinity("RequestChangePasswordForm", "ChangePasswordForm", FormMethod.Post)) | |
{ | |
@Html.AntiForgeryToken() | |
<h2>Change Password</h2> | |
<div class="form-group d-none"> | |
<label for="RequestId">Request Id</label> | |
<input name="RequestId" autofocus id="RequestId" type="text" class="form-control" value="@Model.RequestId" /> | |
</div> | |
<div class="form-group mt-3 mb-3"> | |
<label for="NewPassword1">New Password</label> | |
<input required name="NewPassword1" autofocus id="NewPassword1" type="password" class="form-control" /> | |
</div> | |
<div class="form-group mt-3 mb-3"> | |
<label for="NewPassword2">New Password</label> | |
<input required name="NewPassword2" autofocus id="NewPassword2" type="password" class="form-control" /> | |
</div> | |
<button class="btn btn-primary" type="submit">Submit</button> | |
<a class="btn btn-secondary" href="/Sitefinity"> | |
<strong>Back to Login</strong> | |
</a> | |
if (!string.IsNullOrEmpty(Model.Error)) | |
{ | |
<div class="alert alert-danger mt-4" role="alert" aria-live="assertive"> | |
@Model.Error | |
</div> | |
} | |
} | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model SitefinityWebApp.Mvc.Controllers.ForgotPasswordModel | |
@using Telerik.Sitefinity.UI.MVC; | |
<style> | |
.sfResetPasswordForm { | |
display: flex; | |
justify-content: center; | |
margin-top: 100px; | |
line-height: 2rem; | |
} | |
form[name="ResetPasswordForm"] { | |
min-width: 420px; | |
border: 1px solid lightgray; | |
padding: 2rem; | |
} | |
</style> | |
<div class="sfResetPasswordForm"> | |
@using (Html.BeginFormSitefinity("RequestResetPasswordForm", "ResetPasswordForm", FormMethod.Post)) | |
{ | |
@Html.AntiForgeryToken() | |
<h2>Reset Password</h2> | |
<div class="form-group mt-3 mb-3"> | |
<label for="email">Email</label> | |
<input required name="email" autofocus id="email" type="text" class="form-control" /> | |
</div> | |
<button class="btn btn-primary" type="submit">Submit</button> | |
<a class="btn btn-secondary" href="/Sitefinity"> | |
<strong>Back to Login</strong> | |
</a> | |
if (!string.IsNullOrEmpty(Model.Error)) | |
{ | |
<div class="alert alert-danger mt-4" role="alert" aria-live="assertive"> | |
@Model.Error | |
</div> | |
} | |
} | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment