public void Role_Change_Takes_Effect_Immediately() { // create the test user Create_Edit_User(TestData.ServiceAdminUsername, true); var testUser = new LinqMetaData().User.FirstOrDefault(x => x.FirstName == TestValues["FirstName"]); Assert.IsNotNull(testUser); // remove the restriction on the user account, this is faster than going through the registration process testUser.Username = "******"; testUser.UserAccountRestrictions.DeleteMulti(); testUser.Save(); // check the menu var menuController = Mock <MenuController>(); menuController.RouteData.DataTokens.Add("ParentActionViewContext", MockObjects.MockExtensions.Mock <ControllerContext>()); menuController.HttpContext.User = new RolePrincipal(new GenericIdentity("TestUser1")); menuController.Invoke("ListMenu"); var originalMenu = menuController.Response.Output.ToString(); // change the role var controller = Mock(); controller.HttpContext.User = new RolePrincipal(new GenericIdentity(TestData.ServiceAdminUsername)); var request = controller.Mock(x => x.ControllerContext.HttpContext.Request); request.Setup(x => x.HttpMethod).Returns("POST"); // set the userId controller.RouteData.Values.Add("userId", testUser.UserId); // set the role to something else TestValues["Role"] = OrganizationUtils.GetAllowedRoles(testUser.OrganizationId) .First(x => !testUser.Roles.Any(y => y.RoleId == x.RoleId)).RoleId.ToString(CultureInfo.InvariantCulture); request.SetupGet(x => x.Form).Returns(() => TestValues); controller.Invoke("Edit"); testUser = new LinqMetaData().User.FirstOrDefault(x => x.FirstName == TestValues["FirstName"]); Assert.IsNotNull(testUser); // make sure the role has changed Assert.AreEqual(testUser.Roles.First().RoleId.ToString(CultureInfo.InvariantCulture), TestValues["Role"]); // make sure menu items have changed menuController = Mock <MenuController>(); menuController.RouteData.DataTokens.Add("ParentActionViewContext", MockObjects.MockExtensions.Mock <ControllerContext>()); menuController.HttpContext.User = new RolePrincipal(new GenericIdentity("TestUser1")); menuController.Invoke("ListMenu"); var newMenu = menuController.Response.Output.ToString(); Assert.AreNotEqual(originalMenu, newMenu); }
/// <summary> /// Gets a list of roles that are available to users within the specified organization, /// mostly just filters out making an organization the ServiceHost, which only one is allowed and that is EPIC Central /// </summary> /// <param name="organizationId"></param> /// <returns></returns> public JsonResult GetRoles(int?organizationId) { return(Json(OrganizationUtils.GetAllowedRoles(organizationId).ToDictionary(r => r.RoleId.ToString(CultureInfo.InvariantCulture), x => x.Name), JsonRequestBehavior.AllowGet)); }
public void Service_Administrator_Can_Assign_Any_Role() { // create a test user Create_Edit_User(TestData.ServiceAdminUsername, true); var user = TestData.ServiceAdminUser; var testUser = new LinqMetaData().User.FirstOrDefault(x => x.FirstName == TestValues["FirstName"]); var profile = new UserSettingEntity(user.UserId, "SupportUser") { UserId = user.UserId, Name = "SupportUser" }; Assert.IsFalse(profile.IsNew); Assert.IsNotNull(testUser); Thread.Sleep(5000); // wait for exchange to deliver the e-mail // check the inbox for the e-mail var imap = SupportController.EnsureConnection(user); var msgCount = imap.SelectMailbox("INBOX").NumMsg; Assert.IsTrue(msgCount > 0); var msgs = imap.Search(SearchCondition.Deleted().Not()).Select( x => imap.GetMessage(x, true, true, new[] { "date", "subject", "from", "content-type", "to", "cc", "message-id" })); var message = msgs.Where(x => x.Subject.Contains(ControllerRes.Account.Email_SubjectUserRegistration)). OrderByDescending(x => x.Date).FirstOrDefault(); Assert.IsNotNull(message); message = imap.GetMessage(message.Uid, false, false); // make sure the link matches the current test user in the database var match = Regex.Match(message.Body, "RegistrationKey=([a-zA-Z0-9]*)"); Assert.IsTrue(match.Success); // register the test user var controller = Mock <AccountController>(); var request = controller.Mock(x => x.ControllerContext.HttpContext.Request); request.Setup(x => x.HttpMethod).Returns("POST"); // mock global forms authentication var mockformsAuthenticationService = new Mock <Global.FormsAuthenticationService>(); mockformsAuthenticationService.Setup( service => service.SetAuthCookie(It.IsAny <string>(), It.IsAny <bool>())).Callback <string, bool>( (s, b) => new RolePrincipal(new GenericIdentity(s))); mockformsAuthenticationService.Setup(x => x.SignOut()).Callback(() => { }); Global.FormsAuthentication = mockformsAuthenticationService.Object; // submit test values request.SetupGet(x => x.Form).Returns(() => new NameValueCollection { { "UserName", TestValues["FirstName"] }, { "Email", profile.Value + '@' + SupportController.DOMAIN }, { "Password", "Th1s|sAV4lidPa$$w0rd" }, { "ConfirmPassword", "Th1s|sAV4lidPa$$w0rd" }, { "Pin", "1234" }, { "OriginalEmail", profile.Value + '@' + SupportController.DOMAIN }, { "RegistrationKey", match.Groups[1].Value } }); controller.Invoke("Register"); testUser = new LinqMetaData().User.FirstOrDefault(x => x.Username == TestValues["FirstName"]); Assert.IsNotNull(testUser); // change the role var userController = Mock(); userController.HttpContext.User = new RolePrincipal(new GenericIdentity(TestData.ServiceAdminUsername)); request = userController.Mock(x => x.ControllerContext.HttpContext.Request); request.Setup(x => x.HttpMethod).Returns("POST"); // set the userId userController.RouteData.Values.Add("userId", testUser.UserId); TestValues["Role"] = OrganizationUtils.GetAllowedRoles(testUser.OrganizationId) .First(x => !testUser.Roles.Any(y => y.RoleId == x.RoleId)).RoleId.ToString(CultureInfo.InvariantCulture); request.SetupGet(x => x.Form).Returns(() => TestValues); userController.Invoke("Edit"); testUser = new LinqMetaData().User.FirstOrDefault(x => x.FirstName == TestValues["FirstName"]); Assert.IsNotNull(testUser); Assert.AreEqual(TestValues["Role"], testUser.Roles.Single().RoleId.ToString(CultureInfo.InvariantCulture)); }
public ActionResult Add(int organizationId, AddUserModel model) { var organization = new OrganizationEntity(organizationId); if (organization.IsNew) { throw new HttpException(404, SharedRes.Error.NotFound_Organization); } var restrictionKey = EpicMembershipProvider.CreateSalt(16); if (ModelState.IsValid) { if (!Permissions.UserHasPermission("Edit", organization)) { throw new HttpException(401, SharedRes.Error.Unauthorized_OrganizationEdit); } // Validate submitted role. if (!model.Role.HasValue || !(OrganizationUtils.GetAllowedRoles(organizationId).Any(r => r.RoleId == model.Role))) { throw new HttpException(417, ControllerRes.Account.Invalid_RoleSpecified); } // Locations are only valid for non-admin users. bool isAdmin = RoleUtils.IsRoleForAdmin(model.Role.Value); if (!isAdmin) { // Validate submitted locations are locations of the organization. if (model.Locations.Except(new LinqMetaData().Location.Where(l => l.OrganizationId == organizationId).Select(l => l.LocationId).ToList()).Any()) { throw new HttpException(404, SharedRes.Error.NotFound_Location); } } Transaction transaction = new Transaction(IsolationLevel.ReadCommitted, "user add"); try { UserEntity user = new UserEntity { OrganizationId = organizationId, FirstName = model.FirstName, LastName = model.LastName, EmailAddress = model.EmailAddress, Username = string.Empty, Password = string.Empty }; transaction.Add(user); // If role is non-admin, set up locations. if (!isAdmin) { foreach (var loc in model.Locations) { var assignedLocation = user.UserAssignedLocations.AddNew(); assignedLocation.LocationId = loc; } } var userRole = user.Roles.AddNew(); userRole.RoleId = model.Role.Value; var accountRestriction = new AccountRestrictionEntity { AccountRestrictionType = AccountRestrictionType.NewUser, RestrictionKey = restrictionKey, EmailAddress = model.EmailAddress, Parameters = string.IsNullOrWhiteSpace(model.Pin) ? string.Empty : model.Pin, CreatedBy = Membership.GetUser().GetUserId().Id, IPAddress = Request.ServerVariables["REMOTE_ADDR"] }; transaction.Add(accountRestriction); accountRestriction.Save(); var userRestriction = user.UserAccountRestrictions.AddNew(); userRestriction.AccountRestrictionId = accountRestriction.AccountRestrictionId; // Save recursively ... so assigned locations, role and restriction are saved, too. user.Save(true); transaction.Commit(); } catch (Exception) { transaction.Rollback(); throw new HttpException(500, SharedRes.Error.Error_DatabaseUnknown); } finally { transaction.Dispose(); } // Send email for registration validation. SendRegistrationEmail(model, restrictionKey); // Add user complete. Modal dialog will close, so no response except "success". return(new EmptyResult()); } Response.StatusCode = 417; Response.TrySkipIisCustomErrors = true; return(PartialView(model)); }
public ActionResult Edit(int userId, EditUserModel model) { var user = new UserEntity(userId); if (user.IsNew) { throw new HttpException(404, SharedRes.Error.NotFound_User); } if (!RoleUtils.IsUserServiceAdmin() && !RoleUtils.IsUserOrgAdmin()) { throw new HttpException(401, SharedRes.Error.Unauthorized_UserEdit); } if (RoleUtils.IsUserOrgAdmin() && user.OrganizationId != Membership.GetUser().GetUserId().OrganizationId) { throw new HttpException(401, SharedRes.Error.Unauthorized_OrganizationEdit); } if (ModelState.IsValid) { // Validate submitted role. if (!model.Role.HasValue || !(OrganizationUtils.GetAllowedRoles(model.OrganizationId).Any(r => r.RoleId == model.Role))) { throw new HttpException(417, ControllerRes.Account.Invalid_RoleSpecified); } // Locations are only valid for non-admin users. bool isAdmin = RoleUtils.IsRoleForAdmin(model.Role.Value); if (!isAdmin) { // Validate submitted locations are locations of the organization. if (model.Locations.Except(new LinqMetaData().Location.Where(l => l.OrganizationId == model.OrganizationId).Select(l => l.LocationId).ToList()).Any()) { throw new HttpException(404, SharedRes.Error.NotFound_Location); } } // Set flag to indicate whether or not it's a pending registration. // Not using the posted back value in the model for security reasons. bool isPendingRegistration = user.UserAccountRestrictions.Count > 0 && user.UserAccountRestrictions[0].AccountRestriction.AccountRestrictionType == AccountRestrictionType.NewUser; // If not pending registration and username changed, validate username is unique. // Also, set flag to indicate if it's the current user changing own username. bool isCurrentUsernameChange = false; if (!isPendingRegistration && user.Username != model.UserName) { if (UserUtils.IsUsernameUsed(model.UserName)) { throw new HttpException(417, ControllerRes.Account.Invalid_DuplicateUsername); } isCurrentUsernameChange = Membership.GetUser().GetUserId().Id == userId; } // Set flag to indicate whether or not the email address in a registration // has changed. bool isRegistrationChange = isPendingRegistration && user.EmailAddress != model.EmailAddress; Transaction transaction = new Transaction(IsolationLevel.ReadCommitted, "user add"); try { transaction.Add(user); // Username is empty in pending registrations and can't be changed. // And current user username change isn't a simple change; don't do here. if (!isPendingRegistration && !isCurrentUsernameChange) { user.Username = model.UserName; } user.EmailAddress = model.EmailAddress; user.FirstName = model.FirstName; user.LastName = model.LastName; if (RoleUtils.IsUserServiceAdmin()) { user.IsActive = model.IsActive; } // Did role change? if (user.Roles.Count == 0 || user.Roles[0].RoleId != model.Role.Value) { user.Roles.DeleteMulti(); var userRole = user.Roles.AddNew(); userRole.RoleId = model.Role.Value; } int[] newLocations = new int[0]; int[] oldLocations; if (!isAdmin) { // User is not an admin. So find the set of locations user has been added to, // and the set of location user has been removed from. newLocations = model.Locations.Except(user.UserAssignedLocations.Select(l => l.LocationId)).ToArray(); oldLocations = user.UserAssignedLocations.Select(l => l.LocationId).Except(model.Locations).ToArray(); } else { // User is admin. So user will be removed from all locations (admins aren't // assigned to locations). oldLocations = user.UserAssignedLocations.Select(l => l.LocationId).ToArray(); } if (oldLocations.Length > 0) { user.UserAssignedLocations.DeleteMulti(UserAssignedLocationFields.UserId == user.UserId & UserAssignedLocationFields.LocationId == oldLocations); } if (newLocations.Length > 0) { foreach (var loc in newLocations) { var assignedLocation = user.UserAssignedLocations.AddNew(); assignedLocation.LocationId = loc; } } // If the registration email has changed, update the email address in the account // restriction. if (isRegistrationChange) { user.UserAccountRestrictions[0].AccountRestriction.EmailAddress = model.EmailAddress; } // Is current user changing own username? if (isCurrentUsernameChange) { // Changing the current user's username requres special handling because the // forms-auth cookies must be updated with the new username. The delegate will // be invoked to save the new username updating the datbase. In this case, it // needs to be done within the transaction created here. // // Have already validated the username as unique. So the only reason for this // to fail is with some exception thrown, which will be handled in the "catch". Membership.GetUser().ChangeUsername(model.UserName, delegate(string username) { user.Username = username; user.Save(true); // ReSharper disable AccessToDisposedClosure transaction.Commit(); // ReSharper restore AccessToDisposedClosure }); } else { user.Save(true); transaction.Commit(); } } catch (Exception) { transaction.Rollback(); throw new HttpException(500, SharedRes.Error.Error_DatabaseUnknown); } finally { transaction.Dispose(); } // If registration email has changed, need to re-send the registration email. if (isRegistrationChange) { SendRegistrationEmail(model, user.UserAccountRestrictions[0].AccountRestriction.RestrictionKey); } } return((Request.IsAjaxRequest() || ControllerContext.IsChildAction) ? (ActionResult) new EmptyResult() : View(GetEditModel(userId))); }
protected void Create_Edit_User(string username, bool dontDelete = false) { var user = new LinqMetaData().User.Single(x => x.Username == username); // get the location for the input username var organization = new LinqMetaData().Organization.First(x => x.Users.Any(y => y.Username == username)); // make sure the user inbox is accessible var profile = new UserSettingEntity(user.UserId, "SupportUser") { UserId = user.UserId, Name = "SupportUser" }; Assert.IsFalse(profile.IsNew); // set up a new user account with the email address set to the same as the passed in user var controller = Mock(); controller.HttpContext.User = new RolePrincipal(new GenericIdentity(username)); var request = controller.Mock(x => x.ControllerContext.HttpContext.Request); request.Setup(x => x.HttpMethod).Returns("POST"); // fill in the missing user values TestValues["OrganizationId"] = organization.OrganizationId.ToString(CultureInfo.InvariantCulture); TestValues["Role"] = OrganizationUtils.GetAllowedRoles(organization.OrganizationId) .First().RoleId.ToString(CultureInfo.InvariantCulture); // set the e-mail address equal to the passed in user support center e-mail TestValues["EmailAddress"] = profile.Value + '@' + SupportController.DOMAIN; // submit test values request.SetupGet(x => x.Form).Returns(() => TestValues); controller.Invoke("Add"); var testUser = new LinqMetaData().User.FirstOrDefault(x => x.FirstName == TestValues["FirstName"]); Assert.IsNotNull(testUser); // try to edit the user controller = Mock(); controller.HttpContext.User = new RolePrincipal(new GenericIdentity(username)); request = controller.Mock(x => x.ControllerContext.HttpContext.Request); request.Setup(x => x.HttpMethod).Returns("POST"); // set the userId controller.RouteData.Values.Add("userId", testUser.UserId); // username cannot be changed because registration is still pending at this point // just edit the first name TestValues["FirstName"] = "UserTest1"; TestValues["IsActive"] = "true"; TestValues["UserName"] = "******"; request.SetupGet(x => x.Form).Returns(() => TestValues); controller.Invoke("Edit"); testUser = new LinqMetaData().User.FirstOrDefault(x => x.FirstName == TestValues["FirstName"]); Assert.IsNotNull(testUser); // don't delete for further testing by the caller, which is responsible for cleanup if (!dontDelete) { var ars = testUser.UserAccountRestrictions.Select(y => y.AccountRestriction).ToList(); testUser.UserAccountRestrictions.DeleteMulti(); ars.ForEach(y => y.Delete()); // finally delete the test user testUser.Delete(); } }