public void ResetPasswordRequest_HappyPath() { using (var disposer = new Disposer()) { AuthenticationController controller; var utcNow = new DateTime(2012, 10, 22, 23, 30, 0, DateTimeKind.Utc); var hasBeenSaved = false; var wasEmailSent = false; User user; string emailToken = null; string emailBody = null; string emailToAddress = null; string emailSubject = null; try { user = this.db.Users.Single(x => x.UserName == "andrerpena"); var mr = new MockRepository(); var mve = mr.SetupViewEngine(disposer); mve.SetViewContent( "ResetPasswordEmail", vc => { emailToken = ((UserEmailViewModel)vc.ViewData.Model).Token; return vc.ViewData.Model.ConvertObjectToString("<div>{0}={1}</div>"); }); controller = mr.CreateController<AuthenticationController>( setupNewDb: db1 => { db1.SavingChanges += (s, e) => hasBeenSaved = true; }); controller.UtcNowGetter = () => utcNow; controller.EmailSender += mm => { wasEmailSent = true; emailBody = mm.Body; emailSubject = mm.Subject; emailToAddress = mm.To.Single().Address; }; } catch (Exception ex) { InconclusiveInit(ex); return; } ActionResult actionResult; { actionResult = controller.ResetPasswordRequest( new IdentityViewModel { PracticeIdentifier = user.Practice.UrlIdentifier, UserNameOrEmail = user.UserName, }); } using (var dbs = CreateNewCerebelloEntities()) { // Asserting. Assert.IsTrue(controller.ModelState.IsValid, "ModelState is not valid."); Assert.IsNotNull(actionResult); Assert.IsInstanceOfType(actionResult, typeof(RedirectToRouteResult)); var redirectToRouteResult = (RedirectToRouteResult)actionResult; Assert.AreEqual("ResetPasswordEmailSent", redirectToRouteResult.RouteValues["action"]); Assert.AreEqual(null, redirectToRouteResult.RouteValues["controller"]); Assert.AreEqual(null, redirectToRouteResult.RouteValues["area"]); // Assert DB values. Assert.IsTrue(hasBeenSaved, "The database has not been changed. This was supposed to happen."); var tokenId = new TokenId(emailToken); var savedToken = dbs.GLB_Token.Single(tk => tk.Id == tokenId.Id); Assert.AreEqual(32, savedToken.Value.Length); Assert.AreEqual(tokenId.Value, savedToken.Value); Assert.AreEqual(utcNow.AddDays(30), savedToken.ExpirationDate); // Assertion for email. Assert.IsTrue(wasEmailSent, "E-mail was not sent, but it should."); var emailViewModel = new UserEmailViewModel(user) { Token = emailToken, }; var emailExpected = emailViewModel.ConvertObjectToString("<div>{0}={1}</div>"); Assert.AreEqual(emailExpected, emailBody); Assert.AreEqual("Redefinir senha da conta no Cerebello", emailSubject); Assert.AreEqual("*****@*****.**", emailToAddress); } } }
public ActionResult ResetPasswordRequest(IdentityViewModel viewModel) { if (string.IsNullOrWhiteSpace(viewModel.PracticeIdentifier)) return this.View(viewModel); if (string.IsNullOrWhiteSpace(viewModel.UserNameOrEmail)) return this.View(viewModel); // Can only reset password if practice has already been verified. var practice = this.db.Practices.SingleOrDefault(p => p.UrlIdentifier == viewModel.PracticeIdentifier); var user = SecurityManager.GetUser(this.db.Users, viewModel.PracticeIdentifier, viewModel.UserNameOrEmail); if (practice == null || user == null) { this.ModelState.ClearPropertyErrors(() => viewModel.PracticeIdentifier); this.ModelState.ClearPropertyErrors(() => viewModel.UserNameOrEmail); this.ModelState.AddModelError( () => viewModel.PracticeIdentifier, "O consultório ou usuário não existem. Por favor verifique se não cometeu nenhum erro de digitação."); } if (practice != null && practice.VerificationDate == null && user != null) { this.ModelState.AddModelError( () => viewModel.PracticeIdentifier, "Não é possível resetar a senha pois o consultório ainda não foi verificado. " + "Confirme o seu e-mail antes de tentar mudar a senha."); } if (this.ModelState.IsValid) { var utcNow = this.GetUtcNow(); // Creating confirmation email, with the token. MailMessage message; if (user.Person.Email != null) { #region Creating token and e-mail message // Setting verification token. // Note: tokens are safe to save even if validation fails. TokenId tokenId; using (var db2 = this.CreateNewCerebelloEntities()) { var token = db2.GLB_Token.CreateObject(); token.Value = Guid.NewGuid().ToString("N"); token.Type = "ResetPassword"; token.Name = string.Format( "Practice={0}&UserName={1}", user.Practice.UrlIdentifier, user.UserName); token.ExpirationDate = utcNow.AddDays(Constants.MAX_DAYS_TO_RESET_PASSWORD); db2.GLB_Token.AddObject(token); db2.SaveChanges(); tokenId = new TokenId(token.Id, token.Value); } // Rendering message bodies from partial view. var emailViewModel = new UserEmailViewModel(user) { Token = tokenId.ToString(), }; var toAddress = new MailAddress(user.Person.Email, user.Person.FullName); message = this.CreateEmailMessagePartial("ResetPasswordEmail", toAddress, emailViewModel); #endregion } else { return this.RedirectToAction("ResetPasswordManually"); } // If the ModelState is still valid, then save objects to the database, // and send confirmation email message to the user. using (message) { if (this.ModelState.IsValid) { try { // Sending the password reset e-mail to the user. this.TrySendEmail(message); } catch (SmtpException) { // if e-mail was not sent, try to send it again, after 10 seconds Thread.Sleep(10000); this.TrySendEmail(message); } return this.RedirectToAction("ResetPasswordEmailSent"); } } } return this.View(viewModel); }
private MailMessage EmailMessageToUser(User user, DateTime utcNow, bool isTrial) { TokenId tokenId; // Setting verification token. using (var db2 = this.CreateNewCerebelloEntities()) { var token = new GLB_Token(); token.Value = Guid.NewGuid().ToString("N"); token.Type = "VerifyPracticeAndEmail"; token.Name = string.Format("Practice={0}&UserName={1}", user.Practice.UrlIdentifier, user.UserName); token.ExpirationDate = utcNow.AddHours(Constants.MAX_HOURS_TO_VERIFY_TRIAL_ACCOUNT); db2.GLB_Token.AddObject(token); db2.SaveChanges(); tokenId = new TokenId(token.Id, token.Value); } // Rendering message bodies from partial view. var emailViewModel = new UserEmailViewModel(user) { Token = tokenId.ToString(), IsTrial = isTrial }; var toAddress = new MailAddress(user.Person.Email, user.Person.FullName); var emailMessageToUser = this.CreateEmailMessage("ConfirmationEmail", toAddress, emailViewModel); return emailMessageToUser; }
public ActionResult ResetPasswordCancel(ResetPasswordViewModel viewModel) { var utcNow = this.GetUtcNow(); var user = SecurityManager.GetUser(this.db.Users, viewModel.PracticeIdentifier, viewModel.UserNameOrEmail); if (user != null) { // Getting token information, so that we can locate the token in the database. var tokenInfo = new TokenId(viewModel.Token); var tokenName = string.Format("Practice={0}&UserName={1}", viewModel.PracticeIdentifier, user.UserName); // Destroying the token. var token = this.db.GLB_Token.SingleOrDefault(tk => tk.Id == tokenInfo.Id && tk.Value == tokenInfo.Value && tk.ExpirationDate >= utcNow && tk.Type == "ResetPassword" && tk.Name == tokenName); if (token != null) { this.db.GLB_Token.DeleteObject(token); this.db.SaveChanges(); } else this.ViewBag.CannotRedefinePassword = true; } return this.View(); }
public ActionResult VerifyPracticeAndEmail(VerifyPracticeAndEmailViewModel viewModel) { var utcNow = this.GetUtcNow(); User user = null; // If user is not logged yet, we will use the userName and password to login. if (this.Request.IsAuthenticated) { var authenticatedPrincipal = this.User as AuthenticatedPrincipal; if (authenticatedPrincipal == null) throw new Exception( "HttpContext.User should be a AuthenticatedPrincipal when the user is authenticated"); if (authenticatedPrincipal.Profile.PracticeIdentifier == viewModel.PracticeIdentifier) user = this.db.Users.FirstOrDefault(u => u.Id == authenticatedPrincipal.Profile.Id); } if (user != null || this.Request.HttpMethod == "GET") { this.ModelState.Remove(() => viewModel.PracticeIdentifier); this.ModelState.Remove(() => viewModel.UserNameOrEmail); this.ModelState.Remove(() => viewModel.Password); this.ModelState.Remove(() => viewModel.Token); } if (user == null) { var loginModel = new LoginViewModel { PracticeIdentifier = viewModel.PracticeIdentifier ?? "", UserNameOrEmail = viewModel.UserNameOrEmail ?? "", Password = viewModel.Password ?? "", RememberMe = viewModel.RememberMe, }; var cookieCollection = this.HttpContext.Response.Cookies; if (!this.ModelState.IsValid || !SecurityManager.Login(cookieCollection, loginModel, this.db.Users, out user, this.GetUtcNow())) { this.ViewBag.LoginFailed = true; } else { user.LastActiveOn = this.GetUtcNow(); user.SYS_PasswordAlt = null; this.db.SaveChanges(); if (loginModel.Password == Constants.DEFAULT_PASSWORD) throw new Exception("Cannot create initial user with a default password."); } } var isTokenValid = TokenId.IsValid(viewModel.Token); GLB_Token token = null; if (isTokenValid && user != null) { var tokenId = new TokenId(viewModel.Token); // Getting verification token, using the informations. var tokenName = string.Format("Practice={0}&UserName={1}", viewModel.PracticeIdentifier, user.UserName); token = this.db.GLB_Token.SingleOrDefault(tk => tk.Id == tokenId.Id && tk.Value == tokenId.Value && tk.Type == "VerifyPracticeAndEmail" && tk.Name == tokenName); } var practice = this.db.Practices .SingleOrDefault(p => p.UrlIdentifier == viewModel.PracticeIdentifier); if (token == null) isTokenValid = false; if (practice == null && this.Request.HttpMethod != "GET" && !this.ModelState.HasPropertyErrors(() => viewModel.PracticeIdentifier)) this.ModelState.AddModelError(() => viewModel.PracticeIdentifier, "Consultório não foi achado."); if (token != null && practice != null) { // setting practice verification data if (utcNow <= token.ExpirationDate) { practice.VerificationDate = utcNow; practice.VerificationMethod = "EMAIL"; } else isTokenValid = false; // Destroying token... it has been used with success, and is no longer needed. this.db.GLB_Token.DeleteObject(token); // Saving changes. // Note: even if ModelState.IsValid is false, // we need to save the changes to invalidate token when it expires. this.db.SaveChanges(); } if (!isTokenValid && user != null) { this.ModelState.AddModelError(() => viewModel.Token, "Problema com o token."); } if (this.ModelState.IsValid && user != null && practice != null) { return this.RedirectToAction( "Welcome", "Home", new { area = "", practice = practice.UrlIdentifier }); } viewModel.Password = null; // cannot allow password going to the view. return this.View(viewModel); }