Пример #1
0
        public override async Task <IdentityResult> UpdateAsync(Role role)
        {
            //TODO: Unstable method work, sometimes throws EF already being tracked exception
            //https://github.com/aspnet/Identity/issues/1807
            var result = await base.UpdateAsync(role);

            if (result.Succeeded && role.Permissions != null)
            {
                var sourcePermissionClaims = role.Permissions.Select(x => new Claim(PlatformConstants.Security.Claims.PermissionClaimType, x.Name)).ToList();
                var targetPermissionClaims = (await GetClaimsAsync(role)).Where(x => x.Type == PlatformConstants.Security.Claims.PermissionClaimType).ToList();
                var comparer = AnonymousComparer.Create((Claim x) => x.Value);
                //Add
                foreach (var sourceClaim in sourcePermissionClaims.Except(targetPermissionClaims, comparer))
                {
                    await base.AddClaimAsync(role, sourceClaim);
                }
                //Remove
                foreach (var targetClaim in targetPermissionClaims.Except(sourcePermissionClaims, comparer).ToArray())
                {
                    await base.RemoveClaimAsync(role, targetClaim);
                }

                SecurityCacheRegion.ExpireRegion();
            }
            return(result);
        }
        public async Task Invoke(HttpContext context)
        {
            var cacheKey = CacheKey.With(GetType(), "GetAllPlatformRoles");

            try
            {
                await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) =>
                {
                    cacheEntry.AddExpirationToken(SecurityCacheRegion.CreateChangeToken());
                    var allRolesIds = (await _platformSecurityApi.SearchRolesAsync(new RoleSearchCriteria {
                        Take = int.MaxValue
                    })).Roles.Select(x => x.Id).ToArray();
                    foreach (var role in SecurityConstants.Roles.AllRoles)
                    {
                        if (!allRolesIds.Contains(role.Id))
                        {
                            await _platformSecurityApi.UpdateRoleAsync(role.ToRoleDto());
                        }
                    }
                    return(allRolesIds);
                }, cacheNullValue : false);
            }
            catch (Exception ex)
            {
                _looger.LogError(ex, ex.Message);
            }

            await _next(context);
        }
Пример #3
0
        public override async Task <IdentityResult> CreateAsync(ApplicationUser user)
        {
            var changedEntries = new List <GenericChangedEntry <ApplicationUser> >
            {
                new GenericChangedEntry <ApplicationUser>(user, EntryState.Added)
            };
            await _eventPublisher.Publish(new UserChangingEvent(changedEntries));

            var result = await base.CreateAsync(user);

            if (result.Succeeded)
            {
                if (!user.Roles.IsNullOrEmpty())
                {
                    //Add
                    foreach (var newRole in user.Roles)
                    {
                        await AddToRoleAsync(user, newRole.Name);
                    }
                }

                // add external logins
                if (!user.Logins.IsNullOrEmpty())
                {
                    foreach (var login in user.Logins)
                    {
                        await AddLoginAsync(user, new UserLoginInfo(login.LoginProvider, login.ProviderKey, null));
                    }
                }

                SecurityCacheRegion.ExpireUser(user);
                await _eventPublisher.Publish(new UserChangedEvent(changedEntries));
            }
            return(result);
        }
Пример #4
0
        public override async Task <IdentityResult> UpdateAsync(ApplicationUser user)
        {
            var oldUser = await FindByIdAsync(user.Id);

            var changedEntries = new List <GenericChangedEntry <ApplicationUser> >
            {
                new GenericChangedEntry <ApplicationUser>(user, oldUser, EntryState.Modified)
            };
            await _eventPublisher.Publish(new UserChangingEvent(changedEntries));

            var result = await base.UpdateAsync(user);

            if (result.Succeeded)
            {
                await _eventPublisher.Publish(new UserChangedEvent(changedEntries));

                if (user.Roles != null)
                {
                    var targetRoles = (await GetRolesAsync(user));
                    var sourceRoles = user.Roles.Select(x => x.Name);
                    //Add
                    foreach (var newRole in sourceRoles.Except(targetRoles))
                    {
                        await AddToRoleAsync(user, newRole);
                    }
                    //Remove
                    foreach (var removeRole in targetRoles.Except(sourceRoles))
                    {
                        await RemoveFromRoleAsync(user, removeRole);
                    }
                }
                SecurityCacheRegion.ExpireUser(user);
            }
            return(result);
        }
Пример #5
0
        protected override async Task <IdentityResult> UpdateUserAsync(ApplicationUser user)
        {
            var existentUser = await LoadExistingUser(user);

            //We cant update not existing user
            if (existentUser == null)
            {
                return(IdentityResult.Failed(ErrorDescriber.DefaultError()));
            }

            var changedEntries = new List <GenericChangedEntry <ApplicationUser> >
            {
                new GenericChangedEntry <ApplicationUser>(user, (ApplicationUser)existentUser.Clone(), EntryState.Modified)
            };

            await _eventPublisher.Publish(new UserChangingEvent(changedEntries));

            //We need to use Patch method to update already tracked by DbContent entity, unless the UpdateAsync for passed user will throw exception
            //"The instance of entity type 'ApplicationUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached"
            user.Patch(existentUser);

            var result = await base.UpdateUserAsync(existentUser);

            if (result.Succeeded)
            {
                SecurityCacheRegion.ExpireUser(existentUser);
                var events = changedEntries.GenerateSecurityEventsByChanges();
                var tasks  = events.Select(x => _eventPublisher.Publish(x));
                await Task.WhenAll(tasks);
            }

            return(result);
        }
Пример #6
0
        public override async Task <IdentityResult> CreateAsync(ApplicationUser user)
        {
            var changedEntries = new List <GenericChangedEntry <ApplicationUser> >
            {
                new GenericChangedEntry <ApplicationUser>(user, EntryState.Added)
            };
            await _eventPublisher.Publish(new UserChangingEvent(changedEntries));

            var result = await base.CreateAsync(user);

            if (result.Succeeded)
            {
                await _eventPublisher.Publish(new UserChangedEvent(changedEntries));

                if (user.Roles != null)
                {
                    //Add
                    foreach (var newRole in user.Roles)
                    {
                        await AddToRoleAsync(user, newRole.Name);
                    }
                }
                SecurityCacheRegion.ExpireUser(user);
            }
            return(result);
        }
Пример #7
0
        public override async Task <IdentityResult> UpdateAsync(ApplicationUser user)
        {
            ApplicationUser existUser = null;

            if (!string.IsNullOrEmpty(user.Id))
            {
                //It is important to call base.FindByIdAsync method to avoid of update a cached user.
                existUser = await base.FindByIdAsync(user.Id);
            }
            if (existUser == null)
            {
                //It is important to call base.FindByNameAsync method to avoid of update a cached user.
                existUser = await base.FindByNameAsync(user.UserName);
            }

            //We cant update not existing user
            if (existUser == null)
            {
                return(IdentityResult.Failed(ErrorDescriber.DefaultError()));
            }

            await LoadUserDetailsAsync(existUser);

            var changedEntries = new List <GenericChangedEntry <ApplicationUser> >
            {
                new GenericChangedEntry <ApplicationUser>(user, existUser, EntryState.Modified)
            };
            await _eventPublisher.Publish(new UserChangingEvent(changedEntries));

            //We need to use Patch method to update already tracked by DbContent entity, unless the UpdateAsync for passed user will throw exception
            //"The instance of entity type 'ApplicationUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached"
            user.Patch(existUser);
            var result = await base.UpdateAsync(existUser);

            if (result.Succeeded)
            {
                await _eventPublisher.Publish(new UserChangedEvent(changedEntries));

                if (user.Roles != null)
                {
                    var targetRoles = (await GetRolesAsync(existUser));
                    var sourceRoles = user.Roles.Select(x => x.Name);
                    //Add
                    foreach (var newRole in sourceRoles.Except(targetRoles))
                    {
                        await AddToRoleAsync(existUser, newRole);
                    }
                    //Remove
                    foreach (var removeRole in targetRoles.Except(sourceRoles))
                    {
                        await RemoveFromRoleAsync(existUser, removeRole);
                    }
                }
                SecurityCacheRegion.ExpireUser(existUser);
            }
            return(result);
        }
Пример #8
0
        public virtual Task Handle(OrderPlacedEvent message)
        {
            // Need to expire cache for resetting 'IsFirstTimeBuyer' after order creation
            if (message.WorkContext.CurrentUser.IsFirstTimeBuyer)
            {
                SecurityCacheRegion.ExpireUser(message.WorkContext.CurrentUser.Id);
            }

            return(Task.CompletedTask);
        }
Пример #9
0
        public override async Task <IdentityResult> DeleteAsync(Role role)
        {
            var result = await base.DeleteAsync(role);

            if (result.Succeeded)
            {
                SecurityCacheRegion.ExpireRegion();
            }
            return(result);
        }
Пример #10
0
        public override async Task <IdentityResult> ChangePasswordAsync(ApplicationUser user, string currentPassword, string newPassword)
        {
            var result = await base.ChangePasswordAsync(user, currentPassword, newPassword);

            if (result == IdentityResult.Success)
            {
                SecurityCacheRegion.ExpireUser(user);
            }

            return(result);
        }
Пример #11
0
        public override async Task <IdentityResult> ResetPasswordAsync(ApplicationUser user, string token, string newPassword)
        {
            //It is important to call base.FindByIdAsync method to avoid of update a cached user.
            var existUser = await base.FindByIdAsync(user.Id);

            var result = await base.ResetPasswordAsync(existUser, token, newPassword);

            if (result == IdentityResult.Success)
            {
                SecurityCacheRegion.ExpireUser(user);
            }

            return(result);
        }
Пример #12
0
        public override async Task <IdentityResult> ChangePasswordAsync(ApplicationUser user, string currentPassword, string newPassword)
        {
            var result = await base.ChangePasswordAsync(user, currentPassword, newPassword);

            if (result == IdentityResult.Success)
            {
                SecurityCacheRegion.ExpireUser(user);
                // Calculate password hash for external hash storage. This provided as workaround until password hash storage would implemented
                var customPasswordHash = _userPasswordHasher.HashPassword(user, newPassword);
                await _eventPublisher.Publish(new UserPasswordChangedEvent(user.Id, customPasswordHash));
            }

            return(result);
        }
Пример #13
0
        public override async Task <IdentityResult> CreateAsync(Role role)
        {
            var result = await base.CreateAsync(role);

            if (result.Succeeded && !role.Permissions.IsNullOrEmpty())
            {
                var permissionRoleClaims = role.Permissions.Select(x => new Claim(PlatformConstants.Security.Claims.PermissionClaimType, x.Name));
                foreach (var claim in permissionRoleClaims)
                {
                    await base.AddClaimAsync(role, claim);
                }
                SecurityCacheRegion.ExpireRegion();
            }
            return(result);
        }
Пример #14
0
        public override async Task <Role> FindByIdAsync(string roleId)
        {
            var cacheKey = CacheKey.With(GetType(), "FindByIdAsync", roleId);
            var result   = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) =>
            {
                cacheEntry.AddExpirationToken(SecurityCacheRegion.CreateChangeToken());
                var role = await base.FindByIdAsync(roleId);
                if (role != null)
                {
                    await LoadRolePermissionsAsync(role);
                }
                return(role);
            }, cacheNullValue : false);

            return(result);
        }
Пример #15
0
        public override async Task <ApplicationUser> FindByLoginAsync(string loginProvider, string providerKey)
        {
            var cacheKey = CacheKey.With(GetType(), "FindByLoginAsync", loginProvider, providerKey);
            var result   = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) =>
            {
                var user = await base.FindByLoginAsync(loginProvider, providerKey);
                if (user != null)
                {
                    await LoadUserRolesAsync(user);
                    cacheEntry.AddExpirationToken(SecurityCacheRegion.CreateChangeTokenForUser(user));
                }
                return(user);
            }, cacheNullValue : false);

            return(result);
        }
Пример #16
0
        public override async Task <ApplicationUser> FindByIdAsync(string userId)
        {
            var cacheKey = CacheKey.With(GetType(), nameof(FindByIdAsync), userId);
            var result   = await _memoryCache.GetOrCreateExclusiveAsync(cacheKey, async (cacheEntry) =>
            {
                var user = await base.FindByIdAsync(userId);
                if (user != null)
                {
                    await LoadUserDetailsAsync(user);
                    cacheEntry.AddExpirationToken(SecurityCacheRegion.CreateChangeTokenForUser(user));
                }
                return(user);
            }, cacheNullValue : false);

            return(result);
        }
Пример #17
0
        public override async Task <IdentityResult> DeleteAsync(ApplicationUser user)
        {
            var changedEntries = new List <GenericChangedEntry <ApplicationUser> >
            {
                new GenericChangedEntry <ApplicationUser>(user, EntryState.Deleted)
            };
            await _eventPublisher.Publish(new UserChangingEvent(changedEntries));

            var result = await base.DeleteAsync(user);

            if (result.Succeeded)
            {
                SecurityCacheRegion.ExpireUser(user);
                await _eventPublisher.Publish(new UserChangedEvent(changedEntries));
            }
            return(result);
        }
Пример #18
0
        public override async Task <IdentityResult> ResetPasswordAsync(ApplicationUser user, string token, string newPassword)
        {
            //It is important to call base.FindByIdAsync method to avoid of update a cached user.
            var existUser = await base.FindByIdAsync(user.Id);

            var result = await base.ResetPasswordAsync(existUser, token, newPassword);

            if (result == IdentityResult.Success)
            {
                SecurityCacheRegion.ExpireUser(user);
                // Calculate password hash for external hash storage. This provided as workaround until password hash storage would implemented
                var customPasswordHash = _userPasswordHasher.HashPassword(user, newPassword);
                await _eventPublisher.Publish(new UserResetPasswordEvent(user.Id, customPasswordHash));
            }

            return(result);
        }
Пример #19
0
        public override async Task <IdentityResult> CreateAsync(Role role)
        {
            var result = await base.CreateAsync(role);

            if (result.Succeeded && !role.Permissions.IsNullOrEmpty())
            {
                var existRole = string.IsNullOrEmpty(role.Id) ?  await base.FindByNameAsync(role.Name) : await base.FindByIdAsync(role.Id);

                var permissionRoleClaims = role.Permissions.Select(x => new Claim(PlatformConstants.Security.Claims.PermissionClaimType, x.Name));
                foreach (var claim in permissionRoleClaims)
                {
                    //Need to use an existing tracked by EF entity in order to add permissions for role
                    await base.AddClaimAsync(existRole, claim);
                }
                SecurityCacheRegion.ExpireRegion();
            }
            return(result);
        }
Пример #20
0
        public override async Task <IdentityResult> UpdateAsync(Role updateRole)
        {
            if (updateRole == null)
            {
                throw new ArgumentNullException(nameof(updateRole));
            }
            Role existRole = null;

            if (!string.IsNullOrEmpty(updateRole.Id))
            {
                existRole = await base.FindByIdAsync(updateRole.Id);
            }
            if (existRole == null)
            {
                existRole = await base.FindByNameAsync(updateRole.Name);
            }
            if (existRole != null)
            {
                //Need to path exists tracked by EF  entity due to already being tracked exception
                //https://github.com/aspnet/Identity/issues/1807
                updateRole.Patch(existRole);
            }
            var result = await base.UpdateAsync(existRole);

            if (result.Succeeded && updateRole.Permissions != null)
            {
                var sourcePermissionClaims = updateRole.Permissions.Select(x => x.ToClaim(_jsonOptions.SerializerSettings)).ToList();
                var targetPermissionClaims = (await GetClaimsAsync(existRole)).Where(x => x.Type == PlatformConstants.Security.Claims.PermissionClaimType).ToList();
                var comparer = AnonymousComparer.Create((Claim x) => x.Value);
                //Add
                foreach (var sourceClaim in sourcePermissionClaims.Except(targetPermissionClaims, comparer))
                {
                    await base.AddClaimAsync(existRole, sourceClaim);
                }
                //Remove
                foreach (var targetClaim in targetPermissionClaims.Except(sourcePermissionClaims, comparer).ToArray())
                {
                    await base.RemoveClaimAsync(existRole, targetClaim);
                }
                SecurityCacheRegion.ExpireRegion();
            }
            return(result);
        }
Пример #21
0
        public ActionResult ResetCache()
        {
            //TODO: Replace to some other (maybe with using reflection)
            ThemeEngineCacheRegion.ExpireRegion();
            CartCacheRegion.ExpireRegion();
            CatalogCacheRegion.ExpireRegion();
            ContentBlobCacheRegion.ExpireRegion();
            CustomerCacheRegion.ExpireRegion();
            MarketingCacheRegion.ExpireRegion();
            PricingCacheRegion.ExpireRegion();
            QuoteCacheRegion.ExpireRegion();
            RecommendationsCacheRegion.ExpireRegion();
            StaticContentCacheRegion.ExpireRegion();
            StoreCacheRegion.ExpireRegion();
            TaxCacheRegion.ExpireRegion();
            SubscriptionCacheRegion.ExpireRegion();
            SecurityCacheRegion.ExpireRegion();

            return(StoreFrontRedirect("~/"));
        }