Skip to content

Commit

Permalink
fix(core): added back instance caching for LDAP members
Browse files Browse the repository at this point in the history
  • Loading branch information
extrafu committed Jun 3, 2020
1 parent 4d42e3f commit b94175c
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 84 deletions.
1 change: 1 addition & 0 deletions SoObjects/SOGo/LDAPSource.h
Expand Up @@ -72,6 +72,7 @@
NSDictionary *_contactMapping;
NSArray *_contactObjectClasses;
NSArray *_groupObjectClasses;
NSMutableArray *_members;

NSDictionary *_modulesConstraints;

Expand Down
191 changes: 107 additions & 84 deletions SoObjects/SOGo/LDAPSource.m
Expand Up @@ -98,6 +98,7 @@ - (id) init
// "name" expands to sn, displayname and cn
_searchFields = [[NSArray arrayWithObjects: @"name", @"mail", @"telephonenumber", nil] retain];
_groupObjectClasses = [[NSArray arrayWithObjects: @"group", @"groupofnames", @"groupofuniquenames", @"posixgroup", nil] retain];
_members = nil;
_IMAPHostField = nil;
_IMAPLoginField = nil;
_SieveHostField = nil;
Expand Down Expand Up @@ -142,6 +143,7 @@ - (void) dealloc
[_mailFields release];
[_searchFields release];
[_groupObjectClasses release];
[_members release];
[_IMAPHostField release];
[_IMAPLoginField release];
[_SieveHostField release];
Expand Down Expand Up @@ -2033,90 +2035,92 @@ - (NSArray *) membersForGroupWithUID: (NSString *) uid
NSAutoreleasePool *pool;
int i, c;
NGLdapEntry *entry;
NSMutableArray *members = nil;

if ([uid hasPrefix: @"@"])
uid = [uid substringFromIndex: 1];
if (!_members)
{
if ([uid hasPrefix: @"@"])
uid = [uid substringFromIndex: 1];

entry = [self lookupGroupEntryByUID: uid inDomain: nil];
entry = [self lookupGroupEntryByUID: uid inDomain: nil];

if (entry)
{
members = [NSMutableArray new];
uids = [NSMutableArray array];
dns = [NSMutableArray array];
logins = [NSMutableArray array];

// We check if it's a static group
// Fetch "members" - we get DNs
d = [entry asDictionary];
o = [d objectForKey: @"member"];
CHECK_CLASS(o);
if (o) [dns addObjectsFromArray: o];

// Fetch "uniqueMembers" - we get DNs
o = [d objectForKey: @"uniquemember"];
CHECK_CLASS(o);
if (o) [dns addObjectsFromArray: o];

// Fetch "memberUid" - we get UID (like login names)
o = [d objectForKey: @"memberuid"];
CHECK_CLASS(o);
if (o) [uids addObjectsFromArray: o];

c = [dns count] + [uids count];

// We deal with a static group, let's add the members
if (c)
if (entry)
{
um = [SOGoUserManager sharedUserManager];

// We add members for whom we have their associated DN
for (i = 0; i < [dns count]; i++)
_members = [[NSMutableArray alloc] init];
uids = [NSMutableArray array];
dns = [NSMutableArray array];
logins = [NSMutableArray array];

// We check if it's a static group
// Fetch "members" - we get DNs
d = [entry asDictionary];
o = [d objectForKey: @"member"];
CHECK_CLASS(o);
if (o) [dns addObjectsFromArray: o];

// Fetch "uniqueMembers" - we get DNs
o = [d objectForKey: @"uniquemember"];
CHECK_CLASS(o);
if (o) [dns addObjectsFromArray: o];

// Fetch "memberUid" - we get UID (like login names)
o = [d objectForKey: @"memberuid"];
CHECK_CLASS(o);
if (o) [uids addObjectsFromArray: o];

c = [dns count] + [uids count];

// We deal with a static group, let's add the members
if (c)
{
pool = [NSAutoreleasePool new];
dn = [dns objectAtIndex: i];
login = [um getLoginForDN: [dn lowercaseString]];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
um = [SOGoUserManager sharedUserManager];

// We add members for whom we have their associated DN
for (i = 0; i < [dns count]; i++)
{
[logins addObject: login];
[members addObject: [NSDictionary dictionaryWithObject: login
forKey: @"c_uid"]];
pool = [NSAutoreleasePool new];
dn = [dns objectAtIndex: i];
login = [um getLoginForDN: [dn lowercaseString]];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
{
[logins addObject: login];
[_members addObject: [NSDictionary dictionaryWithObject: login
forKey: @"c_uid"]];
}
[pool release];
}
[pool release];
}

// We add members for whom we have their associated login name
for (i = 0; i < [uids count]; i++)
{
pool = [NSAutoreleasePool new];
login = [uids objectAtIndex: i];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
// We add members for whom we have their associated login name
for (i = 0; i < [uids count]; i++)
{
[logins addObject: login];
[members addObject: [NSDictionary dictionaryWithObject: login
forKey: @"c_uid"]];
pool = [NSAutoreleasePool new];
login = [uids objectAtIndex: i];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
{
[logins addObject: login];
[_members addObject: [NSDictionary dictionaryWithObject: login
forKey: @"c_uid"]];
}
[pool release];
}
[pool release];
}


// We are done fetching members, let's cache the members of the group
// (ie., their UIDs) in memcached to speed up -hasMemberWithUID.
[[SOGoCache sharedCache] setValue: [logins componentsJoinedByString: @","]
forKey: [NSString stringWithFormat: @"%@+%@", uid, _domain]];
}
else
{
// We deal with a dynamic group, let's search all users for whom
// memberOf is equal to our group's DN.
// We also need to look for labelelURI?
// We are done fetching members, let's cache the members of the group
// (ie., their UIDs) in memcached to speed up -hasMemberWithUID.
[[SOGoCache sharedCache] setValue: [logins componentsJoinedByString: @","]
forKey: [NSString stringWithFormat: @"%@+%@", uid, _domain]];
}
else
{
// We deal with a dynamic group, let's search all users for whom
// memberOf is equal to our group's DN.
// We also need to look for labelelURI?
}
}
}

return members;
return _members;
}

//
Expand All @@ -2125,29 +2129,48 @@ - (NSArray *) membersForGroupWithUID: (NSString *) uid
- (BOOL) groupWithUIDHasMemberWithUID: (NSString *) uid
memberUid: (NSString *) memberUid
{

BOOL rc;
NSString *key, *value;;
NSArray *a;

rc = NO;

if ([uid hasPrefix: @"@"])
uid = [uid substringFromIndex: 1];

key = [NSString stringWithFormat: @"%@+%@", uid, _domain];
value = [[SOGoCache sharedCache] valueForKey: key];
// If _members is initialized, we use it as it's very accurate.
// Otherwise, we fallback on memcached in order to avoid
// decomposing the group all the time just to see if a user
// is a member of it.
if (_members)
{
NSString *currentUID;
int count, max;

// If the value isn't in memcached, that probably means -members was never called.
// We call it only once here.
if (!value)
max = [_members count];
for (count = 0; !rc && count < max; count++)
{
currentUID = [[_members objectAtIndex: count] objectForKey: @"c_uid"];
rc = [memberUid isEqualToString: currentUID];
}
}
else
{
[self membersForGroupWithUID: uid];
NSString *key, *value;
NSArray *a;

if ([uid hasPrefix: @"@"])
uid = [uid substringFromIndex: 1];

key = [NSString stringWithFormat: @"%@+%@", uid, _domain];
value = [[SOGoCache sharedCache] valueForKey: key];
}

a = [value componentsSeparatedByString: @","];
rc = [a containsObject: memberUid];
// If the value isn't in memcached, that probably means -members was never called.
// We call it only once here.
if (!value)
{
[self membersForGroupWithUID: uid];
value = [[SOGoCache sharedCache] valueForKey: key];
}

a = [value componentsSeparatedByString: @","];
rc = [a containsObject: memberUid];
}

return rc;
}
Expand Down

0 comments on commit b94175c

Please sign in to comment.