Example #1
0
        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;
            }
        }