public void Login_RemeberMe_HappyPath()
        {
            AuthenticationController controller;
            var hasBeenSaved = false;
            LoginViewModel vm;

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

            User user;
            try
            {
                user = this.db.Users.Single(u => u.UserName == "andrerpena");

                var mr = new MockRepository();

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

                controller.UtcNowGetter = () => utcNow;

                // Creating ViewModel, and setting the ModelState of the controller.
                vm = new LoginViewModel
                {
                    UserNameOrEmail = "andrerpena",
                    PracticeIdentifier = "consultoriodrhouse",
                    Password = "******",
                    RememberMe = true,
                };
                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.Login(vm);
            }

            // 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"], "Index");
            Assert.IsTrue(controller.ModelState.IsValid, "ModelState should be valid.");
            Assert.IsTrue(hasBeenSaved, "The database should be changed, but it was not.");

            // 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.");
            Assert.IsTrue(authCookie.Expires > utcNow, "Cookie expire date must be set to the future.");

            var ticket = System.Web.Security.FormsAuthentication.Decrypt(authCookie.Value);
            Assert.AreEqual("andrerpena", ticket.Name);
            Assert.IsTrue(ticket.Expiration > utcNow, "Ticket expire date must be set to the future.");
            Assert.IsTrue(ticket.IsPersistent, "Ticket must be persistent.");

            var token = SecurityTokenHelper.FromString(ticket.UserData);
            Assert.AreEqual(user.Id, token.UserData.Id);
            Assert.AreEqual("André Pena", token.UserData.FullName);
            Assert.AreEqual("*****@*****.**", token.UserData.Email);
            Assert.AreEqual("consultoriodrhouse", token.UserData.PracticeIdentifier);
            Assert.AreEqual(false, token.UserData.IsUsingDefaultPassword);
        }
        /// <summary>
        /// Logs an user in.
        /// </summary>
        /// <param name="cookieCollection">
        /// Cookie collection that is going to hold an encrypted cookie with informations about the user.
        /// </param>
        /// <param name="loginModel">
        /// Model containing login informations such as practice-name, user-name and password.
        /// </param>
        /// <param name="dbUserSet">
        /// Object set used to get informations about the user.
        /// No data will be saved to this object set.
        /// </param>
        /// <param name="loggedInUser">
        /// Out parameter returning the database User object representing the logged in user, only if the
        /// login succeded. Otherwise null.
        /// </param>
        /// <returns>Returns whether the login succeded or not.</returns>
        public static bool Login(HttpCookieCollection cookieCollection, LoginViewModel loginModel, IObjectSet<User> dbUserSet, out User loggedInUser, DateTime utcNow)
        {
            loggedInUser = null;

            try
            {
                string securityToken;
                loggedInUser = AuthenticateUser(loginModel.UserNameOrEmail, loginModel.Password, loginModel.PracticeIdentifier, dbUserSet, out securityToken);

                if (loggedInUser != null)
                {
                    var expiryDate = utcNow.AddYears(1);
                    var ticket = new FormsAuthenticationTicket(
                        1,
                        loginModel.UserNameOrEmail,
                        utcNow,
                        expiryDate,
                        loginModel.RememberMe,
                        securityToken,
                        FormsAuthentication.FormsCookiePath);

                    var encryptedTicket = FormsAuthentication.Encrypt(ticket);
                    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
                        {
                            Expires = loginModel.RememberMe ? utcNow.AddYears(1) : DateTime.MinValue
                        };

                    cookieCollection.Add(cookie);

                    return true;
                }
            }
            catch
            {
                // Any excpetion will be ignored here, and the login will just fail.
            }

            // add log information about this exception
            FormsAuthentication.SignOut();
            return false;
        }
        public void Login_NotRemeberMe_HappyPath()
        {
            AuthenticationController controller;
            LoginViewModel vm;

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

            try
            {
                var mr = new MockRepository();
                controller = mr.CreateController<AuthenticationController>();
                controller.UtcNowGetter = () => utcNow;

                // Creating ViewModel, and setting the ModelState of the controller.
                vm = new LoginViewModel
                {
                    UserNameOrEmail = "andrerpena",
                    PracticeIdentifier = "consultoriodrhouse",
                    Password = "******",
                    RememberMe = false,
                };
                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.

            {
                controller.Login(vm);
            }

            // 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.");
            Assert.IsTrue(authCookie.Expires == DateTime.MinValue, "Cookie expire date must be set to DateTime.MinValue.");

            var ticket = System.Web.Security.FormsAuthentication.Decrypt(authCookie.Value);
            Assert.AreEqual("andrerpena", ticket.Name);
            Assert.IsTrue(ticket.Expiration > utcNow, "Ticket expire date must be set to the future.");
            Assert.IsFalse(ticket.IsPersistent, "Ticket must not be persistent.");
        }
        public ActionResult Login(LoginViewModel loginModel)
        {
            User user;

            var cookieCollection = this.HttpContext.Response.Cookies;

            if (!SecurityManager.Login(cookieCollection, loginModel, this.db.Users, out user, this.GetUtcNow()))
            {
                this.ModelState.Clear();
                this.ModelState.AddModelError(() => loginModel.PracticeIdentifier, "As credenciais informadas não estão corretas.");
            }

            if (!this.ModelState.IsValid)
            {
                this.ViewBag.LoginFailed = true;
                return this.View(loginModel);
            }

            user.LastActiveOn = this.GetUtcNow();
            user.SYS_PasswordAlt = null; // clearing sys password (this password can only be used once)

            this.db.SaveChanges();

            // We only use the returnUrl if it is a valid URL
            // allowing an invalid URL is a security issue
            {
                bool useReturnUrl = false;
                if (!string.IsNullOrEmpty(loginModel.ReturnUrl))
                {
                    try
                    {
                        // extract practice name from returnUrl
                        var routeData = RouteHelper.GetRouteDataByUrl("~" + loginModel.ReturnUrl);
                        if (routeData.Values.ContainsKey("practice"))
                            useReturnUrl = loginModel.PracticeIdentifier == (string)routeData.Values["practice"];
                    }
                    catch
                    {
                        // the returnUrl must be invalid, let's just ignore it
                    }
                }

                if (!useReturnUrl)
                    loginModel.ReturnUrl = null;
            }

            if (loginModel.Password == Constants.DEFAULT_PASSWORD)
            {
                return this.RedirectToAction("ChangePassword", "Users", new { area = "App", practice = loginModel.PracticeIdentifier });
            }
            else if (!string.IsNullOrWhiteSpace(loginModel.ReturnUrl))
            {
                return this.Redirect(loginModel.ReturnUrl);
            }
            else
            {
                // if the user is a doctor, redirect to the specific doctor profile
                if (user.DoctorId != null)
                    return this.RedirectToAction("Index", "DoctorHome", new { area = "App", practice = loginModel.PracticeIdentifier, doctor = user.Doctor.UrlIdentifier });

                return this.RedirectToAction("Index", "PracticeHome", new { area = "App", practice = loginModel.PracticeIdentifier });
            }
        }
        public ActionResult Login(string returnUrl)
        {
            var viewModel = new LoginViewModel();

            if (!string.IsNullOrEmpty(returnUrl))
            {
                try
                {
                    // extract practice name from returnUrl
                    var routeData = RouteHelper.GetRouteDataByUrl("~" + returnUrl);
                    if (routeData != null && routeData.Values.ContainsKey("practice"))
                        viewModel.PracticeIdentifier = (string)routeData.Values["practice"];

                    if (this.User.Identity.IsAuthenticated)
                        this.ModelState.AddModelError(
                            "returnUrl",
                            "Suas credenciais não te permitem acessar esta área do Cerebello. "
                            + "Entre com as credenciais apropriadas nos campos abaixo.");
                    else
                        this.ModelState.AddModelError(
                            "returnUrl",
                            "Entre com suas credenciais para poder acessar o Cerebello.");

                    viewModel.ReturnUrl = returnUrl;
                }
                catch
                {
                    // the returnUrl must be invalid, let's just ignore it
                }
            }

            return this.View(viewModel);
        }
        public ActionResult CreateAccount(CreateAccountViewModel registrationData)
        {
            // If the user being edited is a medic, then we must check the fields that are required for medics.
            if (!registrationData.IsDoctor)
            {
                // Removing validation error of medic properties, because this user is not a medic.
                this.ModelState.ClearPropertyErrors(() => registrationData.MedicCRM);
                this.ModelState.ClearPropertyErrors(() => registrationData.MedicalEntityId);
                this.ModelState.ClearPropertyErrors(() => registrationData.MedicalSpecialtyId);
                this.ModelState.ClearPropertyErrors(() => registrationData.MedicalSpecialtyName);
                this.ModelState.ClearPropertyErrors(() => registrationData.MedicalEntityJurisdiction);
            }

            if (this.ModelState.Remove(e => e.ErrorMessage.Contains("requerido")))
                this.ModelState.AddModelError("MultipleItems", "É necessário preencher todos os campos.");

            // Normalizing name properties.
            if (!string.IsNullOrEmpty(registrationData.PracticeName))
                registrationData.PracticeName = Regex.Replace(registrationData.PracticeName, @"\s+", " ").Trim();

            if (!string.IsNullOrEmpty(registrationData.FullName))
                registrationData.FullName = Regex.Replace(registrationData.FullName, @"\s+", " ").Trim();

            var urlPracticeId = StringHelper.GenerateUrlIdentifier(registrationData.PracticeName);

            var subscription = StringHelper.FirstNonEmpty(registrationData.Subscription, "trial");
            if (!validSubscriptions.Contains(subscription) || registrationData.AsTrial == true)
                subscription = "trial";

            // Note: Url identifier for the name of the user, don't need any verification.
            // The name of the user must be unique inside a practice, not the entire database.

            var alreadyLoggedUser = this.User as AuthenticatedPrincipal;

            Practice practiceToReuse = null;
            if (alreadyLoggedUser != null)
            {
                practiceToReuse = this.db.Practices
                    .SingleOrDefault(p => p.UrlIdentifier == alreadyLoggedUser.Profile.PracticeIdentifier
                        && p.AccountContract.IsPartialBillingInfo);
            }

            var alreadyExistingPractice = this.db.Practices.SingleOrDefault(p => p.UrlIdentifier == urlPracticeId);
            if (alreadyExistingPractice != null)
            {
                if (alreadyExistingPractice.AccountContract != null && alreadyExistingPractice.AccountContract.IsPartialBillingInfo)
                    practiceToReuse = practiceToReuse ?? alreadyExistingPractice;
                else
                {
                    // killing practice that already exists if it expires, and freeing the name for a new practice
                    if (alreadyExistingPractice.AccountExpiryDate < this.GetUtcNow())
                    {
                        alreadyExistingPractice.AccountDisabled = true;
                        alreadyExistingPractice.UrlIdentifier += " !expired"; // change this, so that a new practice with this name can be created.
                        this.db.SaveChanges();
                    }
                    else
                    {
                        this.ModelState.AddModelError(
                            () => registrationData.PracticeName,
                            "Nome de consultório já está em uso.");
                    }
                }
            }

            var utcNow = this.GetUtcNow();

            // Creating the new user.
            User user;
            if (practiceToReuse == null)
            {
                var result = SecurityManager.CreateUser(out user, registrationData, this.db.Users, utcNow, null);

                if (result == CreateUserResult.InvalidUserNameOrPassword)
                {
                    // Note: nothing to do because user-name and password fields are already validated.
                }

                if (result == CreateUserResult.UserNameAlreadyInUse)
                {
                    this.ModelState.AddModelError(
                        () => registrationData.UserName,
                        // Todo: this message is also used in the App -> UsersController.
                        "O nome de usuário não pode ser registrado pois já está em uso. "
                        + "Note que nomes de usuário diferenciados por acentos, "
                        + "maiúsculas/minúsculas ou por '.', '-' ou '_' não são permitidos."
                        + "(Não é possível cadastrar 'MiguelAngelo' e 'miguel.angelo' no mesmo consultório.");
                }
            }
            else
            {
                user = this.db.Users.SingleOrDefault(u => u.Id == alreadyLoggedUser.Profile.Id && u.PracticeId == practiceToReuse.Id);
                SecurityManager.UpdateUser(user, registrationData, this.db.Users, utcNow);
            }

            if (user != null)
            {
                string timeZoneId = null;
                if (registrationData.PracticeProvince != null)
                    timeZoneId = TimeZoneDataAttribute.GetAttributeFromEnumValue((TypeEstadoBrasileiro)registrationData.PracticeProvince.Value).Id;

                user.Practice = practiceToReuse ?? new Practice();
                user.Practice.Name = registrationData.PracticeName;
                user.Practice.UrlIdentifier = urlPracticeId;
                user.Practice.CreatedOn = utcNow;
                user.Practice.WindowsTimeZoneId = timeZoneId;
                user.Practice.Province = registrationData.PracticeProvince;
                user.Practice.PhoneMain = registrationData.PracticePhone;

                // Setting the BirthDate of the user as a person.
                user.Person.DateOfBirth = PracticeController.ConvertToUtcDateTime(user.Practice, registrationData.DateOfBirth ?? new DateTime());

                user.IsOwner = true;

                if (user.Administrator == null)
                    user.Administrator = new Administrator { };

                bool isNewDoctor = false;
                // when the user is a doctor, we need to fill the properties of the doctor
                if (registrationData.IsDoctor)
                {
                    // if user is already a doctor, we just edit the properties
                    // otherwise we create a new doctor instance
                    if (user.Doctor == null)
                    {
                        user.Doctor = new Doctor();
                        isNewDoctor = true;
                    }

                    user.Doctor.CRM = registrationData.MedicCRM;

                    if (registrationData.MedicalSpecialtyId != null)
                    {
                        var ms = this.db.SYS_MedicalSpecialty
                                     .Single(ms1 => ms1.Id == registrationData.MedicalSpecialtyId);
                        user.Doctor.MedicalSpecialtyCode = ms.Code;
                        user.Doctor.MedicalSpecialtyName = ms.Name;
                    }

                    if (registrationData.MedicalEntityId != null)
                    {
                        var me = this.db.SYS_MedicalEntity
                                     .Single(me1 => me1.Id == registrationData.MedicalEntityId);
                        user.Doctor.MedicalEntityCode = me.Code;
                        user.Doctor.MedicalEntityName = me.Name;
                    }

                    user.Doctor.MedicalEntityJurisdiction = ((TypeEstadoBrasileiro)registrationData.MedicalEntityJurisdiction).ToString();

                    // Creating an unique UrlIdentifier for this doctor.
                    // This is the first doctor, so there will be no conflicts.
                    var urlId = UsersController.GetUniqueDoctorUrlId(this.db.Doctors, registrationData.FullName, null);
                    if (urlId == null)
                    {
                        this.ModelState.AddModelError(
                            () => registrationData.FullName,
                            // Todo: this message is also used in the UserController.
                            "Quantidade máxima de homônimos excedida.");
                    }

                    user.Doctor.UrlIdentifier = urlId;
                }
                else
                {
                    // todo: create a program that clears all orphaned Doctor objects
                    user.Doctor = null;
                }

                if (practiceToReuse == null)
                    this.db.Users.AddObject(user);

                if (this.ModelState.IsValid)
                {
                    MailMessage emailMessageToUser = null;
                    if (subscription == "trial")
                    {
                        // Creating confirmation email, with a token.
                        emailMessageToUser = this.EmailMessageToUser(user, utcNow, subscription == "trial");

                        // Sending e-mail to tell us the good news.
                        this.SendAccountCreatedSelfEmail(registrationData, user);
                    }

                    // If the ModelState is still valid, then save objects to the database,
                    // and send confirmation email message to the user.
                    using (emailMessageToUser)
                    {
                        // Saving changes to the DB.
                        this.db.SaveChanges();

                        if (subscription == "trial")
                        {
                            // Creating a new trial account contract.
                            var contract = user.Practice.AccountContract ?? new AccountContract();
                            contract.Practice = user.Practice;

                            contract.ContractTypeId = (int)ContractTypes.TrialContract;
                            contract.IsTrial = true;
                            contract.IssuanceDate = utcNow;
                            contract.StartDate = utcNow;
                            contract.EndDate = null; // indeterminated
                            contract.CustomText = null;

                            contract.DoctorsLimit = null;
                            contract.PatientsLimit = 50; // fixed limit for trial account

                            // no billings
                            contract.BillingAmount = null;
                            contract.BillingDueDay = null;
                            contract.BillingPaymentMethod = null;
                            contract.BillingPeriodCount = null;
                            contract.BillingPeriodSize = null;
                            contract.BillingPeriodType = null;
                            contract.BillingDiscountAmount = null;

                            user.Practice.AccountExpiryDate = utcNow.AddHours(Constants.MAX_HOURS_TO_VERIFY_TRIAL_ACCOUNT);
                            user.Practice.AccountContract = contract;

                            if (practiceToReuse == null)
                                this.db.AccountContracts.AddObject(contract);
                        }
                        else
                        {
                            // Creating a new account contract, getting info from the subscription string.
                            var dicData = new Dictionary<string, dynamic>(StringComparer.InvariantCultureIgnoreCase)
                                {
                                    { "1M", new { Price = Bus.Pro.PRICE_MONTH, PeriodSize = 1 } },
                                    { "3M", new { Price = Bus.Pro.PRICE_QUARTER, PeriodSize = 3 } },
                                    { "6M", new { Price = Bus.Pro.PRICE_SEMESTER, PeriodSize = 6 } },
                                    { "12M", new { Price = Bus.Pro.PRICE_YEAR, PeriodSize = 12 } }
                                };

                            var data = dicData[subscription];

                            var contract = user.Practice.AccountContract ?? new AccountContract();
                            contract.Practice = user.Practice;

                            contract.ContractTypeId = (int)ContractTypes.ProfessionalContract;
                            contract.IsTrial = false;
                            contract.IssuanceDate = utcNow;
                            contract.StartDate = null; // inderterminated (will be defined when user pays)
                            contract.EndDate = null; // indeterminated
                            contract.CustomText = null;

                            contract.DoctorsLimit = null; // unknown at this moment (will be defined after user fills payment info)
                            contract.PatientsLimit = null; // fixed limit for trial account

                            // billings data can be redefined when the user fills payment info
                            // for now these are the default values
                            contract.IsPartialBillingInfo = true; // indicates that the billing info for this contract must be defined by the user
                            contract.BillingAmount = Bus.Pro.PRICE_MONTH * (int)data.PeriodSize;
                            contract.BillingDueDay = null; // payment method has no default (will be defined in the payment-info step)
                            contract.BillingPaymentMethod = null; // payment method has no default (will be defined in the payment-info step)
                            contract.BillingPeriodCount = null;
                            contract.BillingPeriodSize = data.PeriodSize;
                            contract.BillingPeriodType = "M";
                            contract.BillingDiscountAmount = (Bus.Pro.PRICE_MONTH * (int)data.PeriodSize) - data.Price;

                            user.Practice.AccountExpiryDate = utcNow + Constants.MaxTimeToVerifyProfessionalAccount;
                            user.Practice.AccountContract = contract;

                            if (practiceToReuse == null)
                                this.db.AccountContracts.AddObject(contract);
                        }

                        this.db.SaveChanges();

                        // if the new user is a doctor, create some other useful things
                        // like some medical-certificates and a default health-insurance
                        if (isNewDoctor)
                            BusHelper.FillNewDoctorUtilityBelt(user.Doctor);

                        if (practiceToReuse == null)
                        {
                            // adding message to the user so that he/she completes his/her profile informations
                            // todo: add complete profile notification
                            // If practice is being reused then notification was already sent.
                            var notificationData = new CompletePracticeInfoNotificationData();
                            var notificationDataString = new JavaScriptSerializer().Serialize(notificationData);
                            var dbNotification = new Notification
                                {
                                    CreatedOn = this.GetUtcNow(),
                                    PracticeId = user.PracticeId,
                                    Data = notificationDataString,
                                    UserToId = user.Id,
                                    Type = NotificationConstants.COMPLETE_INFO_NOTIFICATION_TYPE,
                                };
                            this.db.Notifications.AddObject(dbNotification);
                            NotificationsHub.BroadcastDbNotification(dbNotification, notificationData);
                        }

                        if (practiceToReuse == null)
                        {
                            // If practice is being reused then these values were already set.
                            user.Practice.Owner = user;
                            user.Person.PracticeId = user.PracticeId;
                            user.Administrator.PracticeId = user.PracticeId;
                            if (user.Doctor != null)
                                user.Doctor.PracticeId = user.PracticeId;
                        }

                        this.db.SaveChanges();

                        // Sending the confirmation e-mail to the new user.
                        // This must be synchronous.
                        // If practice is being reused then an email was already sent.
                        if (practiceToReuse == null && emailMessageToUser != null)
                            this.TrySendEmail(emailMessageToUser);

                        // Log the user in.
                        var loginModel = new LoginViewModel
                        {
                            Password = registrationData.Password,
                            PracticeIdentifier = user.Practice.UrlIdentifier,
                            RememberMe = false,
                            UserNameOrEmail = registrationData.UserName,
                        };

                        if (!SecurityManager.Login(this.HttpContext.Response.Cookies, loginModel, this.db.Users, out user, this.GetUtcNow()))
                        {
                            throw new Exception("Login cannot fail.");
                        }

                        if (subscription == "trial")
                            return this.RedirectToAction("CreateAccountCompleted", new { practice = user.Practice.UrlIdentifier });
                        else
                            return this.RedirectToAction("SetAccountPaymentInfo", new { practice = user.Practice.UrlIdentifier });
                    }
                }
            }

            this.ViewBag.MedicalSpecialtyOptions =
                this.db.SYS_MedicalSpecialty
                .ToList()
                .Select(me => new SelectListItem { Value = me.Id.ToString(), Text = me.Name })
                .ToList();

            this.ViewBag.MedicalEntityOptions =
                this.db.SYS_MedicalEntity
                .ToList()
                .Select(me => new SelectListItem { Value = me.Id.ToString(), Text = me.Name })
                .ToList();

            return this.View(registrationData);
        }
        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);
        }