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