From e07734fa5f57325a92ea70bcb4410b73340aa026 Mon Sep 17 00:00:00 2001 From: Jean Raby Date: Fri, 29 Mar 2013 10:38:52 -0400 Subject: [PATCH] Filter sql source entries based on the user domain When using dynamic domains with SQL sources (DomainFieldName), let WebUI and dav lookups return entries from current domain and other domains visible from the originating domain. Fixes #2269 SQLSource.m: _visibleDomainsQualifierFromDomain: returns a EOQualifier OR'ing all visible domains from specified domain (including specified domain) SQLSource.m: allEntryIDsVisibleFromDomain Replacement for allEntryIDs. Instead of returning all entries from the sql source, only return the entries visible from the specified domain. SoObjects/SOGo/SQLSource.m: allEntryIDs Changed to call allEntryIDsVisibleFromDomain with an empty domain. SQLSource.m fetchContactsMatching:inDomain: Use _visibleDomainsQualifierFromDomain to filter entries LDAPSource.m: allEntryIDsVisibleFromDomain Simply call allEntryIDs, discarding the domain. LDAP does need to do the extra domain filtering SOGoContactSourceFolder.m: toOneRelationshipKeys Call new method: allEntryIDsVisibleFromDomain --- SoObjects/Contacts/SOGoContactSourceFolder.m | 5 +- SoObjects/SOGo/LDAPSource.m | 7 ++ SoObjects/SOGo/SOGoSource.h | 1 + SoObjects/SOGo/SQLSource.m | 106 +++++++++++++++++-- 4 files changed, 109 insertions(+), 10 deletions(-) diff --git a/SoObjects/Contacts/SOGoContactSourceFolder.m b/SoObjects/Contacts/SOGoContactSourceFolder.m index b270460c1..faa4f5ed5 100644 --- a/SoObjects/Contacts/SOGoContactSourceFolder.m +++ b/SoObjects/Contacts/SOGoContactSourceFolder.m @@ -200,7 +200,10 @@ - (NSArray *) toOneRelationshipKeys { - return [source allEntryIDs]; + NSString *userDomain; + + userDomain = [[context activeUser] domain]; + return [source allEntryIDsVisibleFromDomain: userDomain]; } - (NSException *) saveLDIFEntry: (SOGoContactLDIFEntry *) ldifEntry diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index 302944673..0abf57afa 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -779,6 +779,13 @@ static Class NSStringK; return fields; } +/* This is required for SQL sources when DomainFieldName is enabled. + * For LDAP, simply discard the domain and call the original method */ +- (NSArray *) allEntryIDsVisibleFromDomain: (NSString *) domain +{ + return [self allEntryIDs]; +} + - (NSArray *) allEntryIDs { NSEnumerator *entries; diff --git a/SoObjects/SOGo/SOGoSource.h b/SoObjects/SOGo/SOGoSource.h index ebf085200..2415f408c 100644 --- a/SoObjects/SOGo/SOGoSource.h +++ b/SoObjects/SOGo/SOGoSource.h @@ -61,6 +61,7 @@ inDomain: (NSString *) domain; - (NSArray *) allEntryIDs; +- (NSArray *) allEntryIDsVisibleFromDomain: (NSString *) domain; - (NSArray *) fetchContactsMatching: (NSString *) filter inDomain: (NSString *) domain; diff --git a/SoObjects/SOGo/SQLSource.m b/SoObjects/SOGo/SQLSource.m index c2db99f7d..7d0de6c07 100644 --- a/SoObjects/SOGo/SQLSource.m +++ b/SoObjects/SOGo/SQLSource.m @@ -37,6 +37,8 @@ #import #import +#import + #import "SOGoConstants.h" #import "NSString+Utilities.h" #import "NSString+Crypto.h" @@ -626,23 +628,94 @@ return [self _lookupContactEntry: entryID considerEmail: YES inDomain: domain]; } -- (NSArray *) allEntryIDs +/* Returns an EOQualifier of the following form: + * (_domainField = domain OR _domainField = visibleDomain1 [...]) + * Should only be called on SQL sources using _domainField name. + */ +- (EOQualifier *) _visibleDomainsQualifierFromDomain: (NSString *) domain +{ + int i; + EOQualifier *qualifier, *domainQualifier; + NSArray *visibleDomains; + NSMutableArray *qualifiers; + NSString *currentDomain; + + SOGoSystemDefaults *sd; + + /* Return early if no domain or if being called on a 'static' sql source */ + if (!domain || !_domainField) + return nil; + + sd = [SOGoSystemDefaults sharedSystemDefaults]; + visibleDomains = [sd visibleDomainsForDomain: domain]; + qualifier = nil; + + domainQualifier = + [[EOKeyValueQualifier alloc] initWithKey: _domainField + operatorSelector: EOQualifierOperatorEqual + value: domain]; + [domainQualifier autorelease]; + + if ([visibleDomains count]) + { + qualifiers = [NSMutableArray arrayWithCapacity: [visibleDomains count] + 1]; + [qualifiers addObject: domainQualifier]; + for(i = 0; i < [visibleDomains count]; i++) + { + currentDomain = [visibleDomains objectAtIndex: i]; + qualifier = + [[EOKeyValueQualifier alloc] initWithKey: _domainField + operatorSelector: EOQualifierOperatorEqual + value: currentDomain]; + [qualifier autorelease]; + [qualifiers addObject: qualifier]; + } + qualifier = [[EOOrQualifier alloc] initWithQualifierArray: qualifiers]; + [qualifier autorelease]; + } + + return qualifier ? qualifier : domainQualifier; +} + + +- (NSArray *) allEntryIDsVisibleFromDomain: (NSString *) domain { EOAdaptorChannel *channel; - NSMutableArray *results; + EOQualifier *domainQualifier; GCSChannelManager *cm; NSException *ex; - NSString *sql; - + NSMutableArray *results; + NSMutableString *sql; + results = [NSMutableArray array]; cm = [GCSChannelManager defaultChannelManager]; channel = [cm acquireOpenChannelForURL: _viewURL]; if (channel) { - sql = [NSString stringWithFormat: @"SELECT c_uid FROM %@", + sql = [NSMutableString stringWithFormat: @"SELECT c_uid FROM %@", [_viewURL gcsTableName]]; + if (_domainField) + { + if ([domain length]) + { + domainQualifier = + [self _visibleDomainsQualifierFromDomain: domain]; + if (domainQualifier) + { + [sql appendString: @" WHERE "]; + [domainQualifier _gcsAppendToString: sql]; + } + } + else + { + /* Should not happen but avoid returning the whole table + * if a domain should have been defined */ + [sql appendFormat: @" WHERE %@ is NULL", _domainField]; + } + } + ex = [channel evaluateExpressionX: sql]; if (!ex) { @@ -671,6 +744,11 @@ return results; } +- (NSArray *) allEntryIDs +{ + return [self allEntryIDsVisibleFromDomain: nil]; +} + - (NSArray *) fetchContactsMatching: (NSString *) filter inDomain: (NSString *) domain { @@ -699,16 +777,26 @@ lowerFilter, lowerFilter]; if (_mailFields && [_mailFields count] > 0) - { - [sql appendString: [self _whereClauseFromArray: _mailFields value: lowerFilter exact: NO]]; - } + { + [sql appendString: [self _whereClauseFromArray: _mailFields value: lowerFilter exact: NO]]; + } [sql appendString: @")"]; if (_domainField) { if ([domain length]) - [sql appendFormat: @" AND %@ = '%@'", _domainField, domain]; + { + EOQualifier *domainQualifier; + domainQualifier = + [self _visibleDomainsQualifierFromDomain: domain]; + if (domainQualifier) + { + [sql appendFormat: @" AND ("]; + [domainQualifier _gcsAppendToString: sql]; + [sql appendFormat: @")"]; + } + } else [sql appendFormat: @" AND %@ IS NULL", _domainField]; }