public async Task <IActionResult> Update(UserEditModel model) { try { if (ModelState.IsValid) { if (model.Roles.Contains("Customer") && model.Roles.Count() > 1) // if user is customer and also some roles, invalid { ModelState.AddModelError("", "Not allowed to assign other roles to customer"); } else { AppUser user = await userManager.FindByNameAsync(model.UserName); if (user == null) { return(NotFound()); } // if existed IEnumerable <string> roles = await userManager.GetRolesAsync(user); bool notChanged = model.Roles.OrderBy(r => r).SequenceEqual(roles.OrderBy(r => r)); // compare to determine if role has changed if (!notChanged) // if role is change { if (model.UserName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase)) // if current user try to remove role admin from his/her account or lock his/her account { if (!model.Roles.Contains("Admin")) { ModelState.AddModelError("", "You are not allowed to remove 'Admin' role from your account"); } if (!model.IsLocked) { ModelState.AddModelError("", "You are not allowed to lock your account"); } } else if (roles.Contains("Customer") && !model.Roles.Contains("Customer")) //if user is a customer and updating remove customer role from user { ModelState.AddModelError("", "Customer is not allowed to change role"); } if (roles.Contains("Guide")) //if user is a guide { if (!model.Roles.Contains("Guide")) // if updating remove guide role from user { IEnumerable <string> tours = await tourDAL.FindToursByUserIdAsync(user.Id); if (tours != null) // if guide is used in any tours then it can't be remove { ModelState.AddModelError("", $"Can't remove 'Guide' role. This guide is used in tours: {string.Join(", ", tours)}"); } } if (model.IsLocked) // if want to lock this guide { IEnumerable <string> tours = await tourDAL.FindFutureToursByUserIdAsync(user.Id); if (tours != null) { ModelState.AddModelError("", $"Can't lock this user. Remove this guide from the following tours before lock: {string.Join(", ", tours)}"); } } } if (!ModelState.IsValid) { model.RoleItems = new List <SelectListItem>(); foreach (IdentityRole role in roleManager.Roles) { model.RoleItems.Add(new SelectListItem(role.Name, role.Name)); } return(View("Edit", model)); } } bool isSameEmail = user.Email.Equals(model.Email, StringComparison.OrdinalIgnoreCase); user.FirstName = model.FirstName; user.LastName = model.LastName; user.Address = model.Address; user.Email = model.Email; user.BirthDate = model.BirthDate; user.Gender = model.Gender; user.PhoneNumber = model.Tel; bool changedStatus = false; if (model.IsLocked) { if (user.LockoutEnd == null) { changedStatus = true; } user.LockoutEnd = DateTimeOffset.MaxValue; } else { if (user.LockoutEnd != null) { changedStatus = true; } user.LockoutEnd = null; } string avatar; if (model.Photo != null && !string.IsNullOrWhiteSpace(model.Photo.FileName)) // if photo is change then copy { string filePath = user.UserName + "." + model.Photo.FileName.Substring(model.Photo.FileName.LastIndexOf(".") + 1); avatar = await blobService.UploadFile("avatars", filePath, model.Photo); } else // if not, preserve old one { avatar = user.Avatar; } if (avatar != null) { user.Avatar = avatar; IdentityResult result = null; if (isSameEmail) { IEnumerable <UserLoginInfo> loginInfos = await userManager.GetLoginsAsync(user); foreach (UserLoginInfo info in loginInfos) { result = await userManager.RemoveLoginAsync(user, info.LoginProvider, info.ProviderKey); } } if (result == null || result.Succeeded) // if don't need to remove external login or remove external login successfully { result = await userManager.UpdateAsync(user); if (result.Succeeded) { if (changedStatus || !notChanged) { if (!notChanged) { result = await userManager.AddToRolesAsync(user, model.Roles.Except(roles)); if (!result.Succeeded) { AddErrorFromResult(result); } result = await userManager.RemoveFromRolesAsync(user, roles.Except(model.Roles)); if (!result.Succeeded) { AddErrorFromResult(result); } } await userManager.UpdateSecurityStampAsync(user); } if (ModelState.IsValid) // if everything is ok { return(RedirectToAction(nameof(Details), new { userName = model.UserName })); } } else // if update failed { AddErrorFromResult(result); } } else // if remove external login failed { AddErrorFromResult(result); } } else { ModelState.AddModelError("", "Can't upload avatar"); } } } model.RoleItems = new List <SelectListItem>(); foreach (IdentityRole role in roleManager.Roles) { model.RoleItems.Add(new SelectListItem(role.Name, role.Name)); } return(View("Edit", model)); } catch (Exception ex) { logger.Error(ex.Message); throw; } }