public InternalCreateAccountEmailViewModel(User user, CreateAccountViewModel registrationData)
        {
            this.RegistrationData                 = registrationData.Clone();
            this.RegistrationData.Password        = "******";
            this.RegistrationData.ConfirmPassword = "******";

            this.UrlIdentifier = user.Practice.UrlIdentifier;
            this.UserName      = user.UserName;
        }
        public InternalCreateAccountEmailViewModel(User user, CreateAccountViewModel registrationData)
        {
            this.RegistrationData = registrationData.Clone();
            this.RegistrationData.Password = "******";
            this.RegistrationData.ConfirmPassword = "******";

            this.UrlIdentifier = user.Practice.UrlIdentifier;
            this.UserName = user.UserName;
        }
Пример #3
0
        /// <summary>
        /// Creates a new user and adds it to the storage object context.
        /// </summary>
        /// <param name="createdUser">Output paramater that returns the new user.</param>
        /// <param name="registrationData">Object containing informations about the user to be created.</param>
        /// <param name="dbUserSet">Storage object context used to add the new user. It won't be saved, just changed.</param>
        /// <param name="utcNow"> </param>
        /// <param name="practiceId">The id of the practice that the new user belongs to.</param>
        /// <returns>An enumerated value indicating what has happened.</returns>
        public static CreateUserResult CreateUser(out User createdUser, CreateAccountViewModel registrationData, IObjectSet<User> dbUserSet, DateTime utcNow, int? practiceId)
        {
            // Password cannot be null, nor empty.
            if (string.IsNullOrEmpty(registrationData.Password))
            {
                createdUser = null;
                return CreateUserResult.InvalidUserNameOrPassword;
            }

            // User-name cannot be null, nor empty.
            if (string.IsNullOrEmpty(registrationData.UserName))
            {
                createdUser = null;
                return CreateUserResult.InvalidUserNameOrPassword;
            }

            // Password salt and hash.
            string passwordSalt = CipherHelper.GenerateSalt();
            var passwordHash = CipherHelper.Hash(registrationData.Password, passwordSalt);

            // Normalizing user name.
            // The normalized user-name will be used to discover if another user with the same user-name already exists.
            // This is a security measure. This makes it very difficult to guess what a person's user name may be.
            // You can only login with the exact user name that you provided the first timestamp,
            // but if someone tries to register a similar user name just to know if that one is the one you used...
            // the attacker won't be sure... because it could be any other variation.
            // e.g. I register user-name "Miguel.Angelo"... the attacker tries to register "miguelangelo", he'll be denied...
            // but that doesn't mean the exact user-name "miguelangelo" is the one I used, in fact it is not.
            var normalizedUserName = StringHelper.NormalizeUserName(registrationData.UserName);

            var isUserNameAlreadyInUse =
                practiceId != null &&
                dbUserSet.Any(u => u.UserNameNormalized == normalizedUserName && u.PracticeId == practiceId);

            if (isUserNameAlreadyInUse)
            {
                createdUser = null;
                return CreateUserResult.UserNameAlreadyInUse;
            }

            // Creating user.
            createdUser = new User
            {
                Person = new Person
                {
                    // Note: DateOfBirth property cannot be set in this method because of Utc/Local conversions.
                    // The caller of this method must set the property.
                    Gender = registrationData.Gender ?? 0,
                    FullName = registrationData.FullName,
                    CreatedOn = utcNow,
                    Email = registrationData.EMail,
                    EmailGravatarHash = GravatarHelper.GetGravatarHash(registrationData.EMail),
                },
                UserName = registrationData.UserName,
                UserNameNormalized = normalizedUserName,
                PasswordSalt = passwordSalt,
                Password = passwordHash,
                SYS_PasswordAlt = null,
                LastActiveOn = utcNow,
            };

            if (practiceId != null)
            {
                createdUser.PracticeId = (int)practiceId;
                createdUser.Person.PracticeId = (int)practiceId;
            }

            dbUserSet.AddObject(createdUser);

            return CreateUserResult.Ok;
        }
        public void CreateAccount_2_PracticeNameThatAlreadyExists()
        {
            using (var disposer = new Disposer())
            {
                AuthenticationController controller;
                var hasBeenSaved = false;
                CreateAccountViewModel vm;

                try
                {
                    var mr = new MockRepository();

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

                    mr.SetupHttpContext(disposer);

                    controller = mr.CreateController<AuthenticationController>(
                        setupNewDb: db2 => db2.SavingChanges += (s, e) => { hasBeenSaved = true; });
                    var practiceName = this.db.Practices.Single().UrlIdentifier;

                    controller.EmailSender = mm =>
                    {
                        // Do nothing, instead of sending a REAL e-mail.
                        // Don't need to test if this has been called... another test already does this.
                    };

                    vm = new CreateAccountViewModel
                    {
                        UserName = "******",
                        PracticeName = practiceName,
                        Password = "******",
                        ConfirmPassword = "******",
                        DateOfBirth = new DateTime(1984, 05, 04),
                        EMail = "*****@*****.**",
                        FullName = "Miguel Angelo Santos Bicudo",
                        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);
                }

                // Assertions.
                Assert.IsNotNull(actionResult, "The result of the controller method is null.");
                Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
                var viewResult = (ViewResult)actionResult;
                Assert.AreEqual(viewResult.ViewName, "");
                Assert.IsFalse(controller.ModelState.IsValid, "ModelState should not be valid.");
                Assert.AreEqual(1, controller.ModelState.GetAllErrors().Count, "ModelState should contain one validation message.");
                Assert.IsTrue(
                    controller.ModelState.ContainsKey("PracticeName"),
                    "ModelState must contain validation message for 'PracticeName'.");
                Assert.IsFalse(hasBeenSaved, "The database has been changed. This was not supposed to happen.");
            }
        }
        public void CreateAccount_WithDoctor_HappyPath()
        {
            using (var disposer = new Disposer())
            {
                AuthenticationController controller;
                var hasBeenSaved = false;
                CreateAccountViewModel vm;

                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; });
                    mr.SetupUrlHelper(controller);

                    controller.EmailSender = mm =>
                    {
                        // Do nothing, instead of sending a REAL e-mail.
                        // Don't need to test if this has been called... another test already does this.
                    };

                    // Creating ViewModel, and setting the ModelState of the controller.
                    var me = Firestarter.GetMedicalEntity_Psicologia(this.db);
                    var ms = Firestarter.GetMedicalSpecialty_Psiquiatra(this.db);
                    vm = new CreateAccountViewModel
                    {
                        UserName = "******",
                        PracticeName = "consultoriodrhouse_08sd986",
                        Password = "******",
                        ConfirmPassword = "******",
                        DateOfBirth = new DateTime(1984, 05, 04),
                        EMail = "*****@*****.**",
                        FullName = "André",
                        Gender = (short)TypeGender.Male,
                        IsDoctor = true,
                        MedicCRM = "98237",
                        MedicalEntityId = me.Id,
                        MedicalSpecialtyId = ms.Id,
                        MedicalSpecialtyName = ms.Name,
                        MedicalEntityJurisdiction = (int)TypeEstadoBrasileiro.RJ,
                    };
                    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");

                // 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.AreEqual(savedUser.UserNameNormalized, "andre01");

                // Assert user is logged-in: this is already done in CreateAccount_HappyPath.

                // Assertion for email: this is already done in CreateAccount_HappyPath.
            }
        }
        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);
            }
        }
        public void CreateAccount_4_UserNameIsInvalid()
        {
            using (var disposer = new Disposer())
            {
                AuthenticationController controller;
                var hasBeenSaved = false;
                CreateAccountViewModel vm;
                var hasEmail = false;
                try
                {
                    var mr = new MockRepository();
                    mr.SetRouteData(typeof(AuthenticationController), "CreateAccount");

                    var mve = mr.SetupViewEngine(disposer);
                    mve.SetViewContent("ConfirmationEmail", vc => "<html>Test e-mail string.</html>");

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

                    controller.EmailSender = mm => { hasEmail = true; };

                    // Creating ViewModel, and setting the ModelState of the controller.
                    vm = new CreateAccountViewModel
                    {
                        UserName = "******", // char # is invalid
                        PracticeName = "New Practice Name 4146",
                        Password = "******",
                        ConfirmPassword = "******",
                        DateOfBirth = new DateTime(1984, 09, 01),
                        EMail = "*****@*****.**",
                        FullName = "André Rodrigues Pena",
                        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);
                }

                // Assertions.
                Assert.IsNotNull(actionResult, "The result of the controller method is null.");
                Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
                var viewResult = (ViewResult)actionResult;
                Assert.AreEqual(viewResult.ViewName, "");
                Assert.IsFalse(controller.ModelState.IsValid, "ModelState should not be valid.");
                Assert.AreEqual(1, controller.ModelState.GetAllErrors().Count, "ModelState should contain one validation message.");
                Assert.IsTrue(
                    controller.ModelState.ContainsKey("UserName"),
                    "ModelState must contain validation message for 'PracticeName'.");
                Assert.IsFalse(hasBeenSaved, "The database has been changed. This was not supposed to happen.");
                Assert.IsFalse(hasEmail, "A confirmation e-mail has been sent. This was not supposed to happen.");
            }
        }
        /// <summary>
        /// Simulates the creation of a new account,
        /// by using the real controller,
        /// and mocking everything that is of no interest.
        /// </summary>
        /// <param name="utcNow"></param>
        /// <param name="password"> </param>
        /// <param name="outToken"> </param>
        private static int CreateAccount_Helper(DateTime utcNow, out string password, out string outToken)
        {
            using (var disposer = new Disposer())
            {
                var mr = new MockRepository();

                string token = null;
                var mve = mr.SetupViewEngine(disposer);
                mve.SetViewContent(
                    "ConfirmationEmail",
                    vc =>
                    {
                        token = ((UserEmailViewModel)vc.ViewData.Model).Token;
                        return "Fake e-mail message.";
                    });

                mr.SetupHttpContext(disposer);

                var controller = mr.CreateController<AuthenticationController>();

                controller.UtcNowGetter = () => utcNow;

                controller.EmailSender = mm =>
                    {
                        // Just don't send any REAL e-mail.
                    };

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

                // Call the action on the controller to create the new account.
                // No assertions will be made to this, because this is not a test.
                // If you want to test any values, do it in a TEST METHOD.
                controller.CreateAccount(vm);

                outToken = token;

                // Getting the Id of the user that was created, and returning it.
                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);
                var securityToken = SecurityTokenHelper.FromString(ticket.UserData);

                return securityToken.UserData.Id;
            }
        }
        public void CreateAccount_3_UserNameExistsInAnotherPractice_HappyPath()
        {
            using (var disposer = new Disposer())
            {
                AuthenticationController controller;
                var hasBeenSaved = false;
                CreateAccountViewModel vm;

                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; });
                    var userFullName = this.db.Users.Single().Person.FullName;
                    var userName = this.db.Users.Single().UserName;

                    controller.EmailSender = mm =>
                    {
                        // Do nothing, instead of sending a REAL e-mail.
                        // Don't need to test if this has been called... another test already does this.
                    };

                    vm = new CreateAccountViewModel
                    {
                        UserName = userName,
                        PracticeName = "consultoriodrhouse_0832986",
                        Password = "******",
                        ConfirmPassword = "******",
                        DateOfBirth = new DateTime(1984, 05, 04),
                        EMail = "*****@*****.**",
                        FullName = userFullName,
                        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);
                }

                // 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.");
            }
        }
        public ActionResult CreateAccount(string subscription)
        {
            subscription = StringHelper.FirstNonEmpty(subscription, "trial");
            if (!validSubscriptions.Contains(subscription))
                subscription = "trial";

            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();

            var registrationData = new CreateAccountViewModel
                {
                    Subscription = subscription,
                };

            return this.View(registrationData);
        }
        public ActionResult PayPalConfirmed(string practice)
        {
            var utcNow = this.GetUtcNow();

            // Creating confirmation email, with a token.
            using (var emailMessageToUser = this.EmailMessageToUser(this.dbUser, utcNow, isTrial: false))
            {
                var createAccountViewModel = new CreateAccountViewModel
                    {
                        DateOfBirth = this.dbUser.Person.DateOfBirth,
                        PracticeName = this.dbPractice.Name,
                        PracticePhone = this.dbPractice.PhoneMain,
                        Password = "",
                        Subscription =
                            string.Format(
                                "{0}{1}", this.dbPractice.AccountContract.BillingPeriodSize, this.dbPractice.AccountContract.BillingPeriodType),
                        UserName = this.dbUser.UserName,
                        ConfirmPassword = "",
                        EMail = this.dbUser.Person.Email,
                        AsTrial = null,
                        FullName = this.dbUser.Person.FullName,
                        Gender = this.dbUser.Person.Gender,
                        IsDoctor = this.dbUser.DoctorId.HasValue,
                        PracticeProvince = this.dbPractice.Province,
                    };

                var doctor = this.dbUser.Doctor;
                if (doctor != null)
                {
                    var medicalEntity = UsersController.GetDoctorEntity(this.db.SYS_MedicalEntity, doctor);
                    var medicalSpecialty = UsersController.GetDoctorSpecialty(this.db.SYS_MedicalSpecialty, doctor);

                    // Getting all patients data.
                    var viewModel = new UserViewModel();
                    UsersController.FillDoctorViewModel(this.dbUser, medicalEntity, medicalSpecialty, viewModel, doctor);

                    createAccountViewModel.MedicCRM = viewModel.MedicCRM;
                    createAccountViewModel.MedicalEntityId = viewModel.MedicalEntityId;
                    createAccountViewModel.MedicalEntityJurisdiction = viewModel.MedicalEntityJurisdiction;
                    createAccountViewModel.MedicalSpecialtyId = viewModel.MedicalSpecialtyId;
                    createAccountViewModel.MedicalSpecialtyName = viewModel.MedicalSpecialtyName;
                }

                this.SendAccountCreatedSelfEmail(createAccountViewModel, this.dbUser);

                if (emailMessageToUser != null)
                    this.TrySendEmail(emailMessageToUser);
            }

            return this.RedirectToAction("Welcome", "Home", new { practice });
        }
 private void SendAccountCreatedSelfEmail(CreateAccountViewModel registrationData, User user)
 {
     // sending e-mail to [email protected]
     // to tell us the good news
     // lots of try catch... this is an internal thing, and should never fail to the client, even if it fails
     try
     {
         var emailViewModel2 = new InternalCreateAccountEmailViewModel(user, registrationData);
         var toAddress2 = new MailAddress("*****@*****.**", registrationData.FullName);
         var mailMessage2 = this.CreateEmailMessagePartial("InternalCreateAccountEmail", toAddress2, emailViewModel2);
         this.SendEmailAsync(mailMessage2).ContinueWith(
             t =>
             {
                 // send e-mail again is not an option, SendEmailAsync already tries a lot of times
                 // observing exception so that it is not raised
                 var ex = t.Exception;
                 Trace.TraceError(
                     string.Format(
                         "AuthenticationController.CreateAccount(CreateAccountViewModel): exception when sending internal e-mail: {0}",
                         TraceHelper.GetExceptionMessage(ex)));
             });
     }
     catch (Exception ex)
     {
         Trace.TraceError(
             string.Format(
                 "AuthenticationController.CreateAccount(CreateAccountViewModel): exception when sending internal e-mail: {0}",
                 TraceHelper.GetExceptionMessage(ex)));
     }
 }
        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);
        }
Пример #14
0
        public ActionResult Edit(UserViewModel formModel)
        {
            var isEditingOrCreating = formModel.Id != null ? 'E' : 'C';

            this.ViewBag.IsEditingOrCreating = isEditingOrCreating;

            var utcNow = this.GetUtcNow();

            User user;

            // Normalizing the name of the person.
            if (!string.IsNullOrEmpty(formModel.FullName))
                formModel.FullName = Regex.Replace(formModel.FullName, @"\s+", " ").Trim();

            if (isEditingOrCreating == 'E')
            {
                // Note: User name cannot be edited, and should not be validated.
                this.ModelState.ClearPropertyErrors(() => formModel.UserName);

                user = this.db.Users.First(p => p.Id == formModel.Id);

                // TODO: suggest that r# use the attribute EdmScalarPropertyAttribute(IsNullable=false)
                // as a way to determine if a property can ever receive a null value or not
                // there was a bug in the line inside the following if, that could be detected by r# if it did consider that attribute.
                if (!string.IsNullOrWhiteSpace(formModel.FullName))
                    user.Person.FullName = formModel.FullName;

                user.Person.Gender = (short)formModel.Gender;

                // If there are model errors, we must return original user name to the view.
                formModel.UserName = user.UserName;
            }
            else
            {
                // UserName must not be null nor empty.
                if (string.IsNullOrWhiteSpace(formModel.UserName))
                {
                    this.ModelState.AddModelError(() => formModel.UserName, "Nome de usuário inválido.");
                }

                var loggedUser = this.DbUser;

                // Checking doctors limit of this account.
                if (formModel.IsDoctor)
                {
                    var doctorsCount = this.DbPractice.Users.Count(u => u.DoctorId != null);
                    if (doctorsCount >= this.DbPractice.AccountContract.DoctorsLimit)
                        this.ModelState.AddModelError(
                            "DoctorsLimit",
                            "Essa conta está configurada para suportar até {0} médicos.",
                            this.DbPractice.AccountContract.DoctorsLimit);
                }

                // Looking for another user with the same UserName or Email.
                var conflictingData = this.db.Users
                    .Where(u => u.PracticeId == loggedUser.PracticeId)
                    .Where(u => u.UserName == formModel.UserName || u.Person.Email == formModel.Email)
                    .Select(u => new { u.UserName, u.Person.Email })
                    .ToList();

                // Verifying wich fields are conflicting: Email.
            #warning [Validate] Must validate all emails.
                bool emailConflict = conflictingData.Any(c => c.Email == formModel.Email);

                // For every new user we must create a login, with a common
                // password used the first time the person logs in.
                // The only action allowed with this password,
                // is to change the password.
                var userData = new CreateAccountViewModel
                {
                    UserName = formModel.UserName,
                    Password = Constants.DEFAULT_PASSWORD,
                    ConfirmPassword = Constants.DEFAULT_PASSWORD,
                    EMail = formModel.Email,
                    FullName = formModel.FullName,
                    Gender = (short)formModel.Gender,
                };

                // Creating the new user.
                // The user belongs to the same practice as the logged user.
                var result = SecurityManager.CreateUser(out user, userData, this.db.Users, utcNow, loggedUser.PracticeId);

                if (result == CreateUserResult.UserNameAlreadyInUse)
                {
                    this.ModelState.AddModelError(
                        () => formModel.UserName,
                        // Todo: this message is also used in the AuthenticationController.
                        "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.");
                }
            }

            #warning Must validade all emails, cannot repeat emails in the same practice.

            if (!formModel.IsDoctor && !formModel.IsAdministrador && !formModel.IsSecretary)
                this.ModelState.AddModelError("", "Usuário tem que ter pelo menos uma função: médico, administrador ou secretária.");

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

            if (user != null)
            {
                if (formModel.DateOfBirth.HasValue)
                    user.Person.DateOfBirth = ConvertToUtcDateTime(this.DbPractice, formModel.DateOfBirth.Value);
                user.Person.BirthPlace = formModel.BirthPlace;
                user.Person.CPF = formModel.Cpf;
                user.Person.CreatedOn = this.GetUtcNow();
                user.Person.MaritalStatus = formModel.MaritalStatus;
                user.Person.Profession = formModel.Profissao;
                user.Person.Email = formModel.Email;
                user.Person.EmailGravatarHash = GravatarHelper.GetGravatarHash(formModel.Email);

                // handle address
                if (!user.Person.Addresses.Any())
                    user.Person.Addresses.Add(
                        new Address
                            {
                                PracticeId = this.DbUser.PracticeId,
                                CEP = formModel.Address.CEP,
                                City = formModel.Address.City,
                                Complement = formModel.Address.Complement,
                                Neighborhood = formModel.Address.Neighborhood,
                                StateProvince = formModel.Address.StateProvince,
                                Street = formModel.Address.Street,
                            });

                // when the user is a doctor, we need to fill the properties of the doctor
                if (formModel.IsDoctor)
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        // 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 { PracticeId = this.DbUser.PracticeId, };
                            BusHelper.FillNewDoctorUtilityBelt(user.Doctor);
                        }
                    }

                    // Changing the doctor's informations.
                    if (!string.IsNullOrWhiteSpace(formModel.MedicCRM))
                        user.Doctor.CRM = formModel.MedicCRM;

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

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

                    if (formModel.MedicalEntityJurisdiction != null)
                        user.Doctor.MedicalEntityJurisdiction =
                            ((TypeEstadoBrasileiro)formModel.MedicalEntityJurisdiction.Value).ToString();

                    // Creating an unique UrlIdentifier for this doctor.
                    // This does not consider UrlIdentifier's used by other kinds of objects.
                    string urlId = GetUniqueDoctorUrlId(this.db.Doctors, formModel.FullName, this.DbPractice.Id);
                    if (urlId == null && !string.IsNullOrWhiteSpace(formModel.FullName))
                    {
                        this.ModelState.AddModelError(
                            () => formModel.FullName,
                            // Todo: this message is also used in the AuthenticationController.
                            string.Format("Quantidade máxima de homônimos excedida para esta conta: {0}.", this.DbPractice.UrlIdentifier));
                    }

                    if (!string.IsNullOrWhiteSpace(urlId))
                        user.Doctor.UrlIdentifier = urlId;
                }
                else
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Doctor != null)
                            this.db.Doctors.DeleteObject(user.Doctor);

                        // if the user is not a doctor, then we make sure
                        // by assigning the doctor property to null
                        user.Doctor = null;
                    }
                }

                // when the user is an administrator
                if (formModel.IsAdministrador)
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                        if (user.Administrator == null)
                            user.Administrator = new Administrator { PracticeId = this.DbUser.PracticeId, };
                }
                else
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Administrator != null)
                            this.db.Administrators.DeleteObject(user.Administrator);
                        user.Administrator = null;
                    }
                }

                if (user.IsOwner)
                {
                    if (!formModel.IsAdministrador)
                        this.ModelState.AddModelError(
                            () => formModel.IsAdministrador,
                            "Não é possível remover o papel de administrador do proprietário da conta.");
                }

                // when the user is a secretary
                if (formModel.IsSecretary)
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                        if (user.Secretary == null)
                            user.Secretary = new Secretary { PracticeId = this.DbUser.PracticeId, };
                }
                else
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Secretary != null)
                            this.db.Secretaries.DeleteObject(user.Secretary);
                        user.Secretary = null;
                    }
                }
            }

            // If ModelState is still valid, save the objects to the database.
            if (this.ModelState.IsValid)
            {
                if (formModel.Id == null)
                {
                    var notificationData = new NewUserCreatedNotificationData() { UserName = user.UserName };
                    var dbNotification = new Notification()
                        {
                            CreatedOn = this.GetUtcNow(),
                            PracticeId = this.DbPractice.Id,
                            UserToId = this.DbUser.Id,
                            Type = NotificationConstants.NEW_USER_NOTIFICATION_TYPE,
                            Data = new JavaScriptSerializer().Serialize(notificationData)
                        };
                    this.db.Notifications.AddObject(dbNotification);
                    this.db.SaveChanges();
                    NotificationsHub.BroadcastDbNotification(dbNotification, notificationData);
                }

                // Saving all the changes.
                this.db.SaveChanges();

                return this.RedirectToAction("Details", new { id = user.Id });
            }

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

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

            if (this.DbUser.AdministratorId != null || this.DbUser.IsOwner)
                this.ViewBag.CanEditRole = true;

            // Removes all duplicated messages.
            this.ModelState.RemoveDuplicates();

            return this.View("Edit", formModel);
        }