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