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 void CreateAccount_HappyPath()
        {
            using (var disposer = new Disposer())
            {
                AuthenticationController controller;
                var hasBeenSaved = false;
                CreateAccountViewModel vm;

                var wasEmailSent = false;
                string emailBody = null, emailSubject = null, emailToAddress = null;

                var utcNow = new DateTime(2012, 08, 31, 0, 0, 0, DateTimeKind.Utc);

                try
                {
                    var mr = new MockRepository();

                    var mve = mr.SetupViewEngine(disposer);
                    mve.SetViewContent(
                        "ConfirmationEmail",
                        vc => vc.ViewData.Model.ConvertObjectToString("<div>{0}={1}</div>"));
                    mr.SetRouteData_ControllerAndActionOnly("Home", "Index");

                    mr.SetupHttpContext(disposer);

                    controller = mr.CreateController<AuthenticationController>(
                        setupNewDb: db2 => db2.SavingChanges += (s, e) => { hasBeenSaved = true; });

                    controller.UtcNowGetter = () => utcNow;

                    controller.EmailSender = mm =>
                    {
                        wasEmailSent = true;
                        emailBody = mm.Body;
                        emailSubject = mm.Subject;
                        emailToAddress = mm.To.Single().Address;
                    };

                    // Creating ViewModel, and setting the ModelState of the controller.
                    vm = new CreateAccountViewModel
                    {
                        UserName = "******",
                        PracticeName = "consultoriodrhouse_08sd986",
                        Password = "******",
                        ConfirmPassword = "******",
                        DateOfBirth = new DateTime(1984, 05, 04),
                        EMail = "*****@*****.**",
                        FullName = "André",
                        Gender = (short)TypeGender.Male,
                    };
                    Mvc3TestHelper.SetModelStateErrors(controller, vm);
                }
                catch (Exception ex)
                {
                    InconclusiveInit(ex);
                    return;
                }

                // Creating a new user without an e-mail.
                // This must be ok, no exceptions, no validation errors.
                ActionResult actionResult;

                {
                    actionResult = controller.CreateAccount(vm);
                }

                // Getting the user that was saved.
                var savedUser = this.db.Users.Single(u => u.UserName == "andré-01");
                var savedToken = this.db.GLB_Token.Single();

                // Assertions.
                Assert.IsNotNull(actionResult, "The result of the controller method is null.");
                Assert.IsInstanceOfType(actionResult, typeof(RedirectToRouteResult));
                var redirectResult = (RedirectToRouteResult)actionResult;
                Assert.AreEqual(redirectResult.RouteValues["action"], "CreateAccountCompleted");
                Assert.IsTrue(controller.ModelState.IsValid, "ModelState should be valid.");
                Assert.IsTrue(hasBeenSaved, "The database should be changed, but it was not.");

                // Assert DB values.
                Assert.AreEqual(savedUser.UserNameNormalized, "andre01");
                Assert.AreEqual(32, savedToken.Value.Length);
                Assert.AreEqual(savedUser.Practice.VerificationDate, null);
                Assert.AreEqual(utcNow.AddDays(30), savedToken.ExpirationDate);
                Assert.IsTrue(savedUser.IsOwner, "Saved user should be the owner of the practice.");
                Assert.AreEqual(savedUser.Id, savedUser.Practice.OwnerId, "Saved user should be the owner of the practice.");
                Assert.IsNotNull(savedUser.Administrator, "Practice owner must be administrator.");

                // Assert user is logged-in.
                Assert.IsTrue(
                    controller.HttpContext.Response.Cookies.Keys.Cast<string>().Contains(".ASPXAUTH"),
                    "Authentication cookie should be present in the Response.");
                var authCookie = controller.HttpContext.Response.Cookies[".ASPXAUTH"];
                Assert.IsNotNull(authCookie, @"Response.Cookies["".ASPXAUTH""] must not be null.");
                var ticket = System.Web.Security.FormsAuthentication.Decrypt(authCookie.Value);
                Assert.AreEqual("andré-01", ticket.Name);
                var token = SecurityTokenHelper.FromString(ticket.UserData);
                Assert.AreEqual(savedUser.Id, token.UserData.Id);
                Assert.AreEqual("André", token.UserData.FullName);
                Assert.AreEqual("*****@*****.**", token.UserData.Email);
                Assert.AreEqual(false, token.UserData.IsUsingDefaultPassword);

                // Assertion for email.
                Assert.IsTrue(wasEmailSent, "E-mail was not sent, but it should.");
                var emailViewModel = new UserEmailViewModel(savedUser)
                {
                    Token = new TokenId(savedToken.Id, savedToken.Value).ToString(),
                };
                var emailExpected = emailViewModel.ConvertObjectToString("<div>{0}={1}</div>");
                Assert.AreEqual(emailExpected, emailBody);
                Assert.AreEqual("Bem vindo ao Cerebello! Por favor, confirme a criação de sua conta.", emailSubject);
                Assert.AreEqual("*****@*****.**", emailToAddress);
            }
        }
        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 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);
        }
        public ActionResult Cancel(CancelAccountViewModel viewModel)
        {
            if (!viewModel.Confirm)
            {
                var mainContract = this.DbPractice.AccountContract;

                // Get plan informations of this practice.
                // Contract text, title, description, and other things to display.
                viewModel.CurrentContract = new ConfigAccountViewModel.Contract
                {
                    PlanTitle = mainContract.SYS_ContractType.Name,
                    UrlIdentifier = mainContract.SYS_ContractType.UrlIdentifier.Trim(),
                };

                this.ModelState.AddModelError(() => viewModel.Confirm, "A caixa de checagem de confirmação precisa ser marcada para prosseguir.");

                return this.View(viewModel);
            }

            // Payd accounts are canceled manually.
            if (!this.DbPractice.AccountContract.SYS_ContractType.IsTrial)
            {
                this.DbPractice.AccountCancelRequest = true;

                this.db.SaveChanges();

                this.ViewBag.CancelRequested = true;

                return this.View(viewModel);
            }

            // Sending e-mail with data.
            if (viewModel.SendDataByEmail)
            {
                foreach (var eachDoctorUser in this.DbPractice.Users.Where(u => u.DoctorId != null))
                {
                    // Rendering message bodies from partial view.
                    var emailViewModel = new UserEmailViewModel(eachDoctorUser);
                    var toAddress = new MailAddress(eachDoctorUser.Person.Email, eachDoctorUser.Person.FullName);
                    var mailMessage = this.CreateEmailMessagePartial("AccountDataEmail", toAddress, emailViewModel);

                    // attaching pdf
                    var pdf = ReportController.ExportPatientsPdf(null, this.db, this.DbPractice, eachDoctorUser.Doctor);

                    mailMessage.Attachments.Add(
                        new Attachment(new MemoryStream(pdf), "Prontuários.pdf", "application/pdf"));

                    // attaching xml
                    var xml = ReportController.ExportDoctorXml(this.db, this.DbPractice, eachDoctorUser.Doctor);

                    mailMessage.Attachments.Add(
                        new Attachment(
                            new MemoryStream(Encoding.UTF8.GetBytes(xml)), "Prontuários.xml", "text/xml"));

                    // sending message
                    using (mailMessage)
                    {
                        this.TrySendEmail(mailMessage);
                    }
                }
            }

            var userReason = string.IsNullOrWhiteSpace(viewModel.Reason) ? "No reason provided by user." : viewModel.Reason;
            // sending self e-mail with user reason for canceling
            using (var message = EmailHelper.CreateEmailMessage(
                        new MailAddress("*****@*****.**"),
                        string.Format("Conta cancelada pelo usuário: {0}", this.DbPractice.UrlIdentifier),
                        userReason))
            {
                this.TrySendEmail(message);
            }

            // logging off
            FormsAuthentication.SignOut();

            // disabling account
            this.DbPractice.AccountDisabled = true;
            this.DbPractice.UrlIdentifier += " !disabled"; // change this, so that a new practice with this name can be created.
            this.db.SaveChanges();

            // redirecting user to success message (outside of the app, because the account was canceled)
            return this.RedirectToAction("AccountCanceled", "Home", new { area = "", practice = this.DbPractice.UrlIdentifier });
        }