Example #1
0
        public void CacheKeyMatches_DifferentInstancesInKey( )
        {
            StructuredQuery sq1          = new StructuredQuery( );
            StructuredQuery sq2          = new StructuredQuery( );
            QuerySettings   settings1    = new QuerySettings( );
            QuerySettings   settings2    = new QuerySettings( );
            UserRuleSet     userRuleSet1 = new UserRuleSet(new List <long> {
                1, 2
            });
            UserRuleSet userRuleSet2 = new UserRuleSet(new List <long> {
                1, 2
            });
            long userId = 0;

            var key1 = new CachingQueryRunnerKey(sq1, settings1, userRuleSet1, userId);
            var key2 = new CachingQueryRunnerKey(sq2, settings2, userRuleSet2, userId);

            Assert.That(key1, Is.EqualTo(key2));
            Assert.That(key1, Is.Not.SameAs(key2));

            ConcurrentDictionary <CachingQueryRunnerKey, long> dict = new ConcurrentDictionary <CachingQueryRunnerKey, long>( );

            dict.AddOrUpdate(key1, 1, (k, v) => 1);
            long value;
            bool exists = dict.TryGetValue(key2, out value);

            Assert.That(exists, Is.True);
        }
        private int GenerateHashCode()
        {
            unchecked
            {
                int hashCode = 17;

                if (CacheKeyTokens != null)
                {
                    hashCode = hashCode * 92821 + CacheKeyTokens.GetHashCode( );
                }

                if (UserRuleSet != null)
                {
                    hashCode = hashCode * 92821 + UserRuleSet.GetHashCode( );
                }

                hashCode = hashCode * 92821 + Bools.GetHashCode( );

                if (TimeZoneName != null)
                {
                    hashCode = hashCode * 92821 + TimeZoneName.GetHashCode( );
                }

                return(hashCode);
            }
        }
 internal CachingQuerySqlBuilderKey(StructuredQuery query, QuerySqlBuilderSettings settings, UserRuleSet userRuleSet)
 {
     CacheKeyTokens = GetCacheKeyTokens(query, settings); // Uninspired, but adequate
     Bools          = PackBools(settings);
     UserRuleSet    = userRuleSet;                        // Users may share a query plan if they have the same set of security rules
     TimeZoneName   = query.TimeZoneName;                 // TimeZoneName: Ideally this could be removed from the cache key, but it will be some effort for negligable short-term benefit
     _hashCode      = GenerateHashCode();
 }
        public void Test_Empty( )
        {
            var set1 = new UserRuleSet(new List <long>( ));
            var set2 = new UserRuleSet(new List <long>( ));

            Assert.That(set1, Is.EqualTo(set2));
            Assert.That(set1.GetHashCode(), Is.EqualTo(set2.GetHashCode()));
        }
            public UserRuleSet GetUserRuleSet(long userId, EntityRef permission)
            {
                var         key = new Tuple <long, EntityRef>(userId, permission);
                UserRuleSet rs;

                if (!base.TryGetValue(key, out rs))
                {
                    rs = new UserRuleSet(new List <long>());
                }

                return(rs);
            }
Example #6
0
        public void CacheKeyMatches( )
        {
            StructuredQuery sq          = new StructuredQuery( );
            QuerySettings   settings    = new QuerySettings( );
            UserRuleSet     userRuleSet = new UserRuleSet(new List <long>( ));
            long            userId      = 0;

            var key1 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId);
            var key2 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId);

            Assert.That(key1, Is.EqualTo(key2));
            Assert.That(key1, Is.Not.SameAs(key2));
        }
        public void Test_Equals( )
        {
            var set1 = new UserRuleSet(new List <long>( )
            {
                1, 2, 3
            });
            var set2 = new UserRuleSet(new List <long>( )
            {
                1, 2, 3
            });

            Assert.That(Equals(set1, set2), Is.True);
        }
        public void Test_Different( )
        {
            var set1 = new UserRuleSet(new List <long>( )
            {
                1, 2, 4
            });
            var set2 = new UserRuleSet(new List <long>( )
            {
                1, 2, 3
            });

            Assert.That(set1, Is.Not.EqualTo(set2));
        }
Example #9
0
        public void CacheKeyDifferent_User( )
        {
            StructuredQuery sq          = new StructuredQuery( );
            QuerySettings   settings    = new QuerySettings( );
            UserRuleSet     userRuleSet = new UserRuleSet(new List <long>( ));
            long            userId1     = 1;
            long            userId2     = 2;

            var key1 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId1);

            var key2 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId2);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #10
0
        public void Test_OutOfOrder( )
        {
            var set1 = new UserRuleSet(new List <long>( )
            {
                3, 2, 1
            });
            var set2 = new UserRuleSet(new List <long>( )
            {
                2, 3, 1
            });

            Assert.That(set1, Is.EqualTo(set2));
            Assert.That(set1.GetHashCode( ), Is.EqualTo(set2.GetHashCode( )));
        }
        public void ReadAndWriteSetsDifferent()
        {
            var rs = new UserRuleSet(new List <long> {
                100, 101
            });
            var prov = new DummyRuleSetProvider();

            prov.Add(1, Permissions.Read, rs);
            prov.Add(2, Permissions.Modify, rs);

            var hasher = new UserRuleSetsHasher(prov);

            Assert.That(hasher.GetUserRuleSetsHash(1), Is.Not.EqualTo(hasher.GetUserRuleSetsHash(2)));
        }
Example #12
0
        public void CacheKeyDifferent_TimeZoneName( )
        {
            StructuredQuery         sq          = new StructuredQuery( );
            QuerySqlBuilderSettings settings    = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet = new UserRuleSet(new List <long>( ));

            settings.RunAsUser = 0;

            var key1 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            sq.TimeZoneName = "asdf";
            var key2 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #13
0
        public void CacheKeyDifferent_StructuredQuery( )
        {
            StructuredQuery         sq          = new StructuredQuery( );
            QuerySqlBuilderSettings settings    = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet = new UserRuleSet(new List <long>( ));

            settings.RunAsUser = 0;

            var key1 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            sq.RootEntity = new ResourceEntity( );
            var key2 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #14
0
        public void CacheKeyDifferent_FullAggregateClustering( )
        {
            StructuredQuery         sq          = new StructuredQuery( );
            QuerySqlBuilderSettings settings    = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet = new UserRuleSet(new List <long>( ));

            settings.RunAsUser = 0;

            settings.FullAggregateClustering = false;
            var key1 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            settings.FullAggregateClustering = true;
            var key2 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
        public void CacheKeyMatches( )
        {
            StructuredQuery sq = new StructuredQuery( );

            sq.RootEntity = new ResourceEntity(new EDC.ReadiNow.Model.EntityRef("test:person"));

            QuerySettings settings    = new QuerySettings( );
            UserRuleSet   userRuleSet = new UserRuleSet(new List <long>( ));

            IQueryRunnerCacheKeyProvider provider = Factory.Current.Resolve <IQueryRunnerCacheKeyProvider>( );
            var key1 = provider.CreateCacheKey(sq, settings);
            var key2 = provider.CreateCacheKey(sq, settings);

            Assert.That(key1, Is.EqualTo(key2));
            Assert.That(key1, Is.Not.SameAs(key2));
        }
Example #16
0
        public void CacheKeyDifferent_SupportQuickSearch( )
        {
            StructuredQuery         sq          = new StructuredQuery( );
            QuerySqlBuilderSettings settings    = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet = new UserRuleSet(new List <long>( ));

            settings.RunAsUser = 0;

            settings.SupportQuickSearch = false;
            var key1 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            settings.SupportQuickSearch = true;
            var key2 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #17
0
        public void CacheKeyDifferent_ResultSchemaOnly( )
        {
            StructuredQuery sq          = new StructuredQuery( );
            QuerySettings   settings    = new QuerySettings( );
            UserRuleSet     userRuleSet = new UserRuleSet(new List <long>( ));
            long            userId      = 0;

            settings.RunAsUser = 0;

            settings.ResultSchemaOnly = false;
            var key1 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId);

            settings.ResultSchemaOnly = true;
            var key2 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #18
0
        public void CacheKeyDifferent_TargetResource( )
        {
            StructuredQuery sq          = new StructuredQuery( );
            QuerySettings   settings    = new QuerySettings( );
            UserRuleSet     userRuleSet = new UserRuleSet(new List <long>( ));
            long            userId      = 0;

            settings.RunAsUser = 0;

            settings.TargetResource = 1;
            var key1 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId);

            settings.TargetResource = 2;
            var key2 = new CachingQueryRunnerKey(sq, settings, userRuleSet, userId);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #19
0
        public void CacheKeyDifferent_ClientAggregates( )
        {
            StructuredQuery         sq          = new StructuredQuery( );
            QuerySqlBuilderSettings settings    = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet = new UserRuleSet(new List <long>( ));

            settings.RunAsUser = 0;
            settings.SupportClientAggregate = true;
            settings.ClientAggregate        = new ClientAggregate( );

            var key1 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            settings.ClientAggregate.GroupedColumns.Add(new EDC.ReadiNow.Metadata.Reporting.ReportGroupField( ));
            var key2 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #20
0
        public void CacheKeyDifferent_RunAsUserRuleSet( )
        {
            StructuredQuery         sq           = new StructuredQuery( );
            QuerySqlBuilderSettings settings     = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet1 = new UserRuleSet(new List <long> {
                22, 33
            });
            UserRuleSet userRuleSet2 = new UserRuleSet(new List <long> {
                44, 55
            });

            settings.RunAsUser = 1;
            var key1 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet1);

            settings.RunAsUser = 2;
            var key2 = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet2);

            Assert.That(key1, Is.Not.EqualTo(key2));
        }
Example #21
0
        public void Test_AddingNewRole( )
        {
            EntityType           entityType1;
            EntityType           entityType2;
            UserAccount          userAccount;
            Role                 role1;
            Role                 role2;
            IUserRuleSetProvider userRuleSetProvider;
            UserRuleSet          userRuleSet1;

            using (var ctx = DatabaseContext.GetContext(true, preventPostSaveActionsPropagating: true))
            {
                entityType1 = EDC.ReadiNow.Model.Entity.Create <EntityType>();
                entityType1.Save();
                entityType2 = EDC.ReadiNow.Model.Entity.Create <EntityType>();
                entityType2.Save();

                role1 = new Role();
                role1.Save();
                role2 = new Role();
                role2.Save();

                userAccount = new UserAccount();
                userAccount.UserHasRole.Add(role1);
                userAccount.Save();

                new AccessRuleFactory().AddAllowReadQuery(role1.As <Subject>(), entityType1.As <SecurableEntity>(), TestQueries.Entities(entityType1).ToReport());
                new AccessRuleFactory().AddAllowReadQuery(role2.As <Subject>(), entityType2.As <SecurableEntity>(), TestQueries.Entities(entityType2).ToReport());

                userRuleSetProvider = Factory.UserRuleSetProvider;
                userRuleSet1        = userRuleSetProvider.GetUserRuleSet(userAccount.Id, Permissions.Read);

                // Add a new role
                userAccount.UserHasRole.Add(role2);
                userAccount.Save();

                ctx.CommitTransaction();
            }

            UserRuleSet userRuleSet2 = userRuleSetProvider.GetUserRuleSet(userAccount.Id, Permissions.Read);

            Assert.That(userRuleSet1, Is.Not.EqualTo(userRuleSet2));
        }
Example #22
0
        public void CacheKeyMatches_Match_With_Different_Instances(bool differentUsers, bool concurrent)
        {
            Func <int, CachingQuerySqlBuilderKey> makeKey = ( int userId ) =>
            {
                StructuredQuery sq = new StructuredQuery( );
                sq.SelectColumns.Add(new SelectColumn( ));
                sq.SelectColumns.Add(new SelectColumn( ));
                QuerySqlBuilderSettings settings    = new QuerySqlBuilderSettings( );
                UserRuleSet             userRuleSet = new UserRuleSet(new List <long> {
                    1, 2, 3
                });
                settings.RunAsUser = userId;
                settings.SupportClientAggregate = true;
                settings.ClientAggregate        = new ClientAggregate( );
                settings.ClientAggregate.AggregatedColumns.Add(new EDC.ReadiNow.Metadata.Reporting.ReportAggregateField {
                    ReportColumnId = sq.SelectColumns [0].ColumnId
                });
                settings.ClientAggregate.GroupedColumns.Add(new EDC.ReadiNow.Metadata.Reporting.ReportGroupField {
                    ReportColumnId = sq.SelectColumns [1].ColumnId
                });
                var key = new CachingQuerySqlBuilderKey(sq, settings, userRuleSet);
                return(key);
            };

            CachingQuerySqlBuilderKey key1 = null;
            CachingQuerySqlBuilderKey key2 = null;

            if (concurrent)
            {
                Task.WaitAll(
                    Task.Factory.StartNew(() => { key1 = makeKey(111); }),
                    Task.Factory.StartNew(() => { key2 = makeKey(differentUsers ? 222 : 111); })
                    );
            }
            else
            {
                key1 = makeKey(111);
                key2 = makeKey(differentUsers ? 222 : 111);
            }

            Assert.That(key1, Is.EqualTo(key2));
            Assert.That(key1, Is.Not.SameAs(key2));
        }
Example #23
0
        public void CacheKeyMatches_MatchingRuleSets( )
        {
            StructuredQuery         sq           = new StructuredQuery( );
            QuerySqlBuilderSettings settings1    = new QuerySqlBuilderSettings( );
            QuerySqlBuilderSettings settings2    = new QuerySqlBuilderSettings( );
            UserRuleSet             userRuleSet1 = new UserRuleSet(new List <long> {
                1, 2, 3
            });
            UserRuleSet userRuleSet2 = new UserRuleSet(new List <long> {
                1, 2, 3
            });

            settings1.RunAsUser = 111;
            settings2.RunAsUser = 222;

            var key1 = new CachingQuerySqlBuilderKey(sq, settings1, userRuleSet1);
            var key2 = new CachingQuerySqlBuilderKey(sq, settings2, userRuleSet2);

            Assert.That(key1, Is.EqualTo(key2));
            Assert.That(key1, Is.Not.SameAs(key2));
        }
Example #24
0
        /// <summary>
        /// Create cache keys
        /// </summary>
        /// <param name="query">The query</param>
        /// <param name="settings">The query settings</param>
        /// <param name="perUserKey">True if the key is for a specific user; or false if it is to be shared across users.</param>
        /// <returns>The cache key</returns>
        private CachingQueryRunnerKey CreateCacheKeyImpl(StructuredQuery query, QuerySettings settings, bool perUserKey)
        {
            // Get a user-set key
            // (Users may share the same report SQL if they have the same set of read-rules)
            UserRuleSet userRuleSet = null;

            if (settings.RunAsUser != 0)
            {
                userRuleSet = UserRuleSetProvider.GetUserRuleSet(settings.RunAsUser, Permissions.Read);
                if (userRuleSet == null)
                {
                    throw new InvalidOperationException("Expected userRuleSet");   // Assert false
                }
            }

            // Create cache key
            // Cached with userId = -1 if the user
            long userId = perUserKey ? settings.RunAsUser : ShareAcrossUsersCacheKey;
            var  key    = new CachingQueryRunnerKey(query, settings, userRuleSet, userId);

            return(key);
        }
        public void Test_TwoUsersSameTwoRoles_OneHasOwnRule( )
        {
            long       user1       = 1;
            long       user2       = 2;
            long       role1       = 3;
            long       role2       = 4;
            AccessRule accessRule1 = new AccessRule( );
            AccessRule accessRule2 = new AccessRule( );
            AccessRule accessRule3 = new AccessRule( );
            AccessRule accessRule4 = new AccessRule( );
            Mock <IUserRoleRepository> mockRoles = new Mock <IUserRoleRepository>(MockBehavior.Strict);
            Mock <IRuleRepository>     mockRules = new Mock <IRuleRepository>(MockBehavior.Strict);

            mockRoles.Setup(x => x.GetUserRoles(user1)).Returns(new HashSet <long> {
                role1, role2
            });
            mockRoles.Setup(x => x.GetUserRoles(user2)).Returns(new HashSet <long> {
                role1, role2
            });
            mockRules.Setup(x => x.GetAccessRules(user1, Permissions.Read, null)).Returns(new List <AccessRule> {
            });
            mockRules.Setup(x => x.GetAccessRules(user2, Permissions.Read, null)).Returns(new List <AccessRule> {
                accessRule4
            });
            mockRules.Setup(x => x.GetAccessRules(role1, Permissions.Read, null)).Returns(new List <AccessRule> {
                accessRule1
            });
            mockRules.Setup(x => x.GetAccessRules(role2, Permissions.Read, null)).Returns(new List <AccessRule> {
                accessRule2, accessRule3
            });

            UserRuleSetProvider userRuleSetprovider = new UserRuleSetProvider(mockRoles.Object, mockRules.Object);

            UserRuleSet userRuleSet1 = userRuleSetprovider.GetUserRuleSet(user1, Permissions.Read);
            UserRuleSet userRuleSet2 = userRuleSetprovider.GetUserRuleSet(user2, Permissions.Read);

            Assert.That(userRuleSet1, Is.Not.EqualTo(userRuleSet2));
        }
            public void Add(long userId, EntityRef permission, UserRuleSet rs)
            {
                var key = new Tuple <long, EntityRef>(userId, permission);

                base.Add(key, rs);
            }
Example #27
0
        /// <summary>
        /// Build the SQL, or collect it from cache.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public QueryBuild BuildSql(StructuredQuery query, QuerySqlBuilderSettings settings)
        {
            // Validate
            if (query == null)
            {
                throw new ArgumentNullException("query");
            }
            if (QuerySqlBuilder == null)
            {
                throw new InvalidOperationException("QuerySqlBuilder not set.");
            }
            if (settings == null)
            {
                settings = new QuerySqlBuilderSettings( );
            }

            // Check if query can even participate in cache
            if (!CachingQuerySqlBuilderKey.DoesRequestAllowForCaching(query, settings))
            {
                return(BuildSqlImpl(query, settings));
            }

            // Get a user-set key
            // (Users may share the same report SQL if they have the same set of read-rules)
            UserRuleSet userRuleSet = null;

            if (settings.RunAsUser != 0)
            {
                userRuleSet = UserRuleSetProvider.GetUserRuleSet(settings.RunAsUser, Permissions.Read);
                if (userRuleSet == null)
                {
                    throw new InvalidOperationException("Expected userRuleSet");   // Assert false
                }
            }

            // Create cache key
            CachingQuerySqlBuilderKey   key = new CachingQuerySqlBuilderKey(query, settings, userRuleSet);
            CachingQuerySqlBuilderValue cacheValue;

            using (MessageContext msg = new MessageContext("Reports"))
            {
                // Check for force recalculation
                if (settings.RefreshCachedSql)
                {
                    msg.Append(() => "CachingQuerySqlBuilder refreshed forced");
                    _cacheInvalidator.DebugInvalidations.Add(key);
                    Cache.Remove(key);
                }

                // In some circumstances, a result will be uncacheable, so we just return 'null' in the delegate instead.
                // However, on the first access, we will still be doing the calculation, so store it here.
                CachingQuerySqlBuilderValue calculatedOnThisAccess = null;

                // Check cache
                bool fromCache = TryGetOrAdd(key, msg, out cacheValue, callbackKey =>
                {
                    // This callback is called if we have a cache miss

                    using (CacheContext cacheContext = new CacheContext( ))
                    {
                        QueryBuild queryResult = BuildSqlImpl(query, settings);
                        cacheValue             = new CachingQuerySqlBuilderValue(query, queryResult);
                        calculatedOnThisAccess = cacheValue;

                        if (queryResult.SqlIsUncacheable)
                        {
                            return(null);
                        }
                        else
                        {
                            // Add the cache context entries to the appropriate CacheInvalidator
                            _cacheInvalidator.AddInvalidations(cacheContext, callbackKey);
                            return(cacheValue);
                        }
                    }
                });

                // cacheValue will be null if the result was uncacheable
                if (cacheValue == null)
                {
                    if (calculatedOnThisAccess != null)
                    {
                        // In this path, the result was uncacheable, so the cache returned a 'null',
                        // but it was the initial calculation run anyway, so we can get the value from callbackValue.
                        cacheValue = calculatedOnThisAccess;
                    }
                    else
                    {
                        // In this path, the result was uncacheable, but someone had asked previously, and stored
                        // the null, so we need to actually build the SQL again for this scenario.
                        // Note: don't need to do anything with cache context, because this cache is not participating.
                        // And if there's a parent context set, then the call to BuildSqlImpl will just talk directly to that context.
                        QueryBuild queryResult = BuildSqlImpl(query, settings);
                        cacheValue = new CachingQuerySqlBuilderValue(query, queryResult);
                    }
                }
                else if (fromCache && CacheContext.IsSet( ))
                {
                    // Add the already stored changes that should invalidate this cache
                    // entry to any outer or containing cache contexts.
                    using (CacheContext cacheContext = CacheContext.GetContext( ))
                    {
                        cacheContext.AddInvalidationsFor(_cacheInvalidator, key);
                    }
                }
            }

            if (cacheValue == null)
            {
                throw new Exception("Assert false");
            }

            // Mutate returned result to be suitable for current query
            QueryBuild result;

            if (cacheValue.OriginalQuery == query)
            {
                result = cacheValue.QueryResult;
            }
            else
            {
                result = MutateResultToMatchCurrentQuery(cacheValue, query);
            }

            return(result);
        }
Example #28
0
 internal CachingQueryRunnerKey(StructuredQuery query, QuerySettings settings, UserRuleSet userRuleSet, long runAsUser)
 {
     Key            = new CachingQuerySqlBuilderKey(query, settings, userRuleSet);
     Bools          = PackBools(settings);
     PageSize       = settings.PageSize;
     User           = runAsUser;
     TargetResource = settings.TargetResource;
     _hashCode      = GenerateHashCode();
 }