mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-05-22 03:45:25 +00:00
Added support for the parameter "IMAPLoginMailField" for SQL/LDAP sources, and the parameter "authenticationFilter" for SQL sources. See ChangeLog.
Monotone-Parent: 1cdaff22cdbdb961e1937dc8f1ac1936bd06dc99 Monotone-Revision: 36439821e42cfcb830bfff9081d7e1318f1e92ab Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-14T18:41:10 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -1,5 +1,28 @@
|
||||
2011-04-14 Francis Lachapelle <flachapelle@inverse.ca>
|
||||
|
||||
* SoObjects/SOGo/SOGoUserManager.m (-getImapLoginForUID:): we now
|
||||
consider the source parameter IMAPLoginFieldName. We continue to support
|
||||
SOGoForceIMAPLoginWithEmail at the domain/system level.
|
||||
|
||||
* SoObjects/SOGo/LDAPSource.m: we can now define a new parameter
|
||||
named IMAPLoginFieldName to specify which field to use for IMAP
|
||||
authentication. By default, we use the value of the UIDFieldName.
|
||||
|
||||
* SoObjects/SOGo/SQLSource.m
|
||||
(-checkLogin:password:perr:expire:grace:): if the defaults parameter
|
||||
authenticationFilter is defined, we add it to the SQL where clause.
|
||||
(_lookupContactEntry:considerEmail:): we add a new key
|
||||
(canAuthenticate) to the returned dictionary that specifies if the
|
||||
user can authenticate or not. We also add c_imaplogin when the
|
||||
user must authenticate with a different username to the IMAP server.
|
||||
|
||||
* SoObjects/SOGo/SOGoUser.m (-canAuthenticate): new method that
|
||||
returns true if the user can authenticate, based on the
|
||||
authentication filter associated to the source.
|
||||
|
||||
* SoObjects/SOGo/SOGoGCSFolder.m (-ocsFolder): don't automatically
|
||||
create the folder if the user can't authenticate.
|
||||
|
||||
* UI/Contacts/UIxContactsListActions.m: was
|
||||
UIxContactsListView.m. The new method contactsListAction now
|
||||
returns a JSON representation of the addressbook.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
* Francis Lachapelle <flachapelle@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -53,7 +54,7 @@
|
||||
NSString *CNField;
|
||||
NSString *UIDField;
|
||||
NSArray *mailFields, *searchFields;
|
||||
NSString *IMAPHostField;
|
||||
NSString *IMAPHostField, *IMAPLoginField;
|
||||
NSArray *bindFields;
|
||||
BOOL _bindAsCurrentUser;
|
||||
|
||||
@@ -83,6 +84,7 @@
|
||||
mailFields: (NSArray *) newMailFields
|
||||
searchFields: (NSArray *) newSearchFields
|
||||
IMAPHostField: (NSString *) newIMAPHostField
|
||||
IMAPLoginField: (NSString *) newIMAPLoginField
|
||||
andBindFields: (id) newBindFields;
|
||||
|
||||
- (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
* Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
* Francis Lachapelle <flachapelle@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -161,6 +162,7 @@ static NSArray *commonSearchFields;
|
||||
searchFields = [NSArray arrayWithObjects: @"sn", @"displayname", @"telephonenumber", nil];
|
||||
[searchFields retain];
|
||||
IMAPHostField = nil;
|
||||
IMAPLoginField = nil;
|
||||
bindFields = nil;
|
||||
_scope = @"sub";
|
||||
_filter = nil;
|
||||
@@ -188,6 +190,7 @@ static NSArray *commonSearchFields;
|
||||
[mailFields release];
|
||||
[searchFields release];
|
||||
[IMAPHostField release];
|
||||
[IMAPLoginField release];
|
||||
[bindFields release];
|
||||
[_filter release];
|
||||
[sourceID release];
|
||||
@@ -223,6 +226,7 @@ static NSArray *commonSearchFields;
|
||||
mailFields: [udSource objectForKey: @"MailFieldNames"]
|
||||
searchFields: [udSource objectForKey: @"SearchFieldNames"]
|
||||
IMAPHostField: [udSource objectForKey: @"IMAPHostFieldName"]
|
||||
IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"]
|
||||
andBindFields: [udSource objectForKey: @"bindFields"]];
|
||||
|
||||
if ([sourceDomain length])
|
||||
@@ -305,6 +309,7 @@ static NSArray *commonSearchFields;
|
||||
mailFields: (NSArray *) newMailFields
|
||||
searchFields: (NSArray *) newSearchFields
|
||||
IMAPHostField: (NSString *) newIMAPHostField
|
||||
IMAPLoginField: (NSString *) newIMAPLoginField
|
||||
andBindFields: (id) newBindFields
|
||||
{
|
||||
ASSIGN (baseDN, [newBaseDN lowercaseString]);
|
||||
@@ -316,6 +321,8 @@ static NSArray *commonSearchFields;
|
||||
ASSIGN (UIDField, newUIDField);
|
||||
if (newIMAPHostField)
|
||||
ASSIGN (IMAPHostField, newIMAPHostField);
|
||||
if (newIMAPLoginField)
|
||||
ASSIGN (IMAPLoginField, newIMAPLoginField);
|
||||
if (newMailFields)
|
||||
ASSIGN (mailFields, newMailFields);
|
||||
if (newSearchFields)
|
||||
@@ -694,6 +701,10 @@ static NSArray *commonSearchFields;
|
||||
// Add IMAP hostname from user defaults
|
||||
if ([IMAPHostField length])
|
||||
[searchAttributes addObjectUniquely: IMAPHostField];
|
||||
|
||||
// Add IMAP login from user defaults
|
||||
if ([IMAPLoginField length])
|
||||
[searchAttributes addObjectUniquely: IMAPLoginField];
|
||||
}
|
||||
|
||||
return searchAttributes;
|
||||
@@ -761,6 +772,13 @@ static NSArray *commonSearchFields;
|
||||
if ([ldapValue length] > 0)
|
||||
[contactEntry setObject: ldapValue forKey: @"c_imaphostname"];
|
||||
}
|
||||
|
||||
if (IMAPLoginField)
|
||||
{
|
||||
ldapValue = [[ldapEntry attributeWithName: IMAPLoginField] stringValueAtIndex: 0];
|
||||
if ([ldapValue length] > 0)
|
||||
[contactEntry setObject: ldapValue forKey: @"c_imaplogin"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _fillConstraints: (NGLdapEntry *) ldapEntry
|
||||
|
||||
@@ -480,14 +480,17 @@ static NSArray *childRecordFields = nil;
|
||||
- (GCSFolder *) ocsFolder
|
||||
{
|
||||
GCSFolder *folder;
|
||||
SOGoUser *user;
|
||||
NSString *userLogin;
|
||||
|
||||
if (!ocsFolder)
|
||||
{
|
||||
ocsFolder = [self ocsFolderForPath: [self ocsPath]];
|
||||
userLogin = [[context activeUser] login];
|
||||
user = [context activeUser];
|
||||
userLogin = [user login];
|
||||
if (!ocsFolder
|
||||
&& [userLogin isEqualToString: [self ownerInContext: context]]
|
||||
&& [user canAuthenticate]
|
||||
&& [self folderIsMandatory]
|
||||
&& [self create])
|
||||
ocsFolder = [self ocsFolderForPath: [self ocsPath]];
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
- (NSMutableDictionary *) defaultIdentity;
|
||||
|
||||
- (BOOL) isSuperUser;
|
||||
- (BOOL) canAuthenticate;
|
||||
|
||||
/* module access */
|
||||
- (BOOL) canAccessModule: (NSString *) module;
|
||||
|
||||
@@ -757,6 +757,15 @@
|
||||
return [[_domainDefaults superUsernames] containsObject: login];
|
||||
}
|
||||
|
||||
- (BOOL) canAuthenticate
|
||||
{
|
||||
id authValue;
|
||||
|
||||
authValue = [self _fetchFieldForUser: @"canAuthenticate"];
|
||||
|
||||
return [authValue boolValue];
|
||||
}
|
||||
|
||||
/* module access */
|
||||
- (BOOL) canAccessModule: (NSString *) module
|
||||
{
|
||||
|
||||
@@ -337,17 +337,23 @@
|
||||
- (NSString *) getImapLoginForUID: (NSString *) uid
|
||||
{
|
||||
NSDictionary *contactInfos;
|
||||
NSString *domain;
|
||||
NSString *domain, *login;
|
||||
SOGoDomainDefaults *dd;
|
||||
|
||||
contactInfos = [self contactInfosForUserWithUIDorEmail: uid];
|
||||
login = [contactInfos objectForKey: @"c_imaplogin"];
|
||||
domain = [contactInfos objectForKey: @"c_domain"];
|
||||
if ([domain length])
|
||||
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
||||
else
|
||||
dd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||
|
||||
return ([dd forceIMAPLoginWithEmail] ? [self getEmailForUID: uid] : uid);
|
||||
if (login == nil)
|
||||
{
|
||||
if ([domain length])
|
||||
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
||||
else
|
||||
dd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||
|
||||
login = [dd forceIMAPLoginWithEmail] ? [self getEmailForUID: uid] : uid;
|
||||
}
|
||||
|
||||
return login;
|
||||
}
|
||||
|
||||
- (NSString *) getUIDForEmail: (NSString *) email
|
||||
@@ -549,7 +555,7 @@
|
||||
NSDictionary *userEntry;
|
||||
NSEnumerator *sogoSources;
|
||||
NSObject <SOGoDNSource> *currentSource;
|
||||
NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname;
|
||||
NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname, *c_imaplogin;
|
||||
NSArray *c_emails;
|
||||
BOOL access;
|
||||
|
||||
@@ -558,6 +564,7 @@
|
||||
c_uid = nil;
|
||||
c_domain = nil;
|
||||
c_imaphostname = nil;
|
||||
c_imaplogin = nil;
|
||||
|
||||
[currentUser setObject: [NSNumber numberWithBool: YES]
|
||||
forKey: @"CalendarAccess"];
|
||||
@@ -583,6 +590,8 @@
|
||||
[emails addObjectsFromArray: c_emails];
|
||||
if (!c_imaphostname)
|
||||
c_imaphostname = [userEntry objectForKey: @"c_imaphostname"];
|
||||
if (!c_imaplogin)
|
||||
c_imaplogin = [userEntry objectForKey: @"c_imaplogin"];
|
||||
access = [[userEntry objectForKey: @"CalendarAccess"] boolValue];
|
||||
if (!access)
|
||||
[currentUser setObject: [NSNumber numberWithBool: NO]
|
||||
@@ -603,6 +612,8 @@
|
||||
|
||||
if (c_imaphostname)
|
||||
[currentUser setObject: c_imaphostname forKey: @"c_imaphostname"];
|
||||
if (c_imaplogin)
|
||||
[currentUser setObject: c_imaplogin forKey: @"c_imaplogin"];
|
||||
[currentUser setObject: emails forKey: @"emails"];
|
||||
[currentUser setObject: cn forKey: @"cn"];
|
||||
[currentUser setObject: c_uid forKey: @"c_uid"];
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* Copyright (C) 2009-2011 Inverse inc.
|
||||
*
|
||||
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
* Authors: Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
* Francis Lachapelle <flachapelle@invers.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -36,7 +37,9 @@
|
||||
{
|
||||
NSString *_sourceID;
|
||||
NSString *_domain;
|
||||
NSString *_authenticationFilter;
|
||||
NSArray *_mailFields;
|
||||
NSString *_imapLoginField;
|
||||
NSString *_userPasswordAlgorithm;
|
||||
NSURL *_viewURL;
|
||||
}
|
||||
|
||||
+88
-23
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* Copyright (C) 2009-2011 Inverse inc.
|
||||
*
|
||||
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
* Authors: Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
* Francis Lachapelle <flachapelle@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -31,9 +32,8 @@
|
||||
|
||||
#import <GDLContentStore/GCSChannelManager.h>
|
||||
#import <GDLContentStore/NSURL+GCS.h>
|
||||
#import <GDLContentStore/EOQualifier+GCS.h>
|
||||
#import <GDLAccess/EOAdaptorChannel.h>
|
||||
#import <GDLAccess/EOAdaptorContext.h>
|
||||
#import <GDLAccess/EOAttribute.h>
|
||||
|
||||
#import "SOGoConstants.h"
|
||||
#import "NSString+Utilities.h"
|
||||
@@ -79,6 +79,7 @@
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_sourceID = nil;
|
||||
_authenticationFilter = nil;
|
||||
_mailFields = nil;
|
||||
_userPasswordAlgorithm = nil;
|
||||
_viewURL = nil;
|
||||
@@ -90,6 +91,7 @@
|
||||
- (void) dealloc
|
||||
{
|
||||
[_sourceID release];
|
||||
[_authenticationFilter release];
|
||||
[_mailFields release];
|
||||
[_userPasswordAlgorithm release];
|
||||
[_viewURL release];
|
||||
@@ -103,8 +105,10 @@
|
||||
self = [self init];
|
||||
|
||||
ASSIGN(_sourceID, [udSource objectForKey: @"id"]);
|
||||
ASSIGN(_authenticationFilter, [udSource objectForKey: @"authenticationFilter"]);
|
||||
ASSIGN(_mailFields, [udSource objectForKey: @"MailFieldNames"]);
|
||||
ASSIGN(_userPasswordAlgorithm, [udSource objectForKey: @"userPasswordAlgorithm"]);
|
||||
ASSIGN(_imapLoginField, [udSource objectForKey: @"IMAPLoginFieldName"]);
|
||||
|
||||
if (!_userPasswordAlgorithm)
|
||||
_userPasswordAlgorithm = @"none";
|
||||
@@ -203,9 +207,10 @@
|
||||
grace: (int *) _grace
|
||||
{
|
||||
EOAdaptorChannel *channel;
|
||||
EOQualifier *qualifier;
|
||||
GCSChannelManager *cm;
|
||||
NSException *ex;
|
||||
NSString *sql;
|
||||
NSMutableString *sql;
|
||||
BOOL rc;
|
||||
|
||||
rc = NO;
|
||||
@@ -214,12 +219,25 @@
|
||||
cm = [GCSChannelManager defaultChannelManager];
|
||||
channel = [cm acquireOpenChannelForURL: _viewURL];
|
||||
if (channel)
|
||||
{
|
||||
sql = [NSString stringWithFormat: (@"SELECT c_password"
|
||||
@" FROM %@"
|
||||
@" WHERE c_uid = '%@'"),
|
||||
[_viewURL gcsTableName], _login];
|
||||
|
||||
{
|
||||
qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_uid"
|
||||
operatorSelector: EOQualifierOperatorEqual
|
||||
value: _login];
|
||||
[qualifier autorelease];
|
||||
sql = [NSMutableString stringWithFormat: @"SELECT c_password"
|
||||
@" FROM %@"
|
||||
@" WHERE ",
|
||||
[_viewURL gcsTableName]];
|
||||
if (_authenticationFilter)
|
||||
{
|
||||
qualifier = [[EOAndQualifier alloc] initWithQualifiers:
|
||||
qualifier,
|
||||
[EOQualifier qualifierWithQualifierFormat: _authenticationFilter],
|
||||
nil];
|
||||
[qualifier autorelease];
|
||||
}
|
||||
[qualifier _gcsAppendToString: sql];
|
||||
|
||||
ex = [channel evaluateExpressionX: sql];
|
||||
if (!ex)
|
||||
{
|
||||
@@ -235,7 +253,8 @@
|
||||
[channel cancelFetch];
|
||||
}
|
||||
else
|
||||
[self errorWithFormat: @"could not run SQL '%@': %@", sql, ex];
|
||||
[self errorWithFormat: @"could not run SQL '%@': %@", qualifier, ex];
|
||||
|
||||
[cm releaseChannel: channel];
|
||||
}
|
||||
else
|
||||
@@ -328,8 +347,10 @@
|
||||
{
|
||||
NSMutableDictionary *response;
|
||||
EOAdaptorChannel *channel;
|
||||
EOQualifier *qualifier;
|
||||
GCSChannelManager *cm;
|
||||
NSString *sql, *value;
|
||||
NSMutableString *sql;
|
||||
NSString *value;
|
||||
NSException *ex;
|
||||
|
||||
response = nil;
|
||||
@@ -340,21 +361,21 @@
|
||||
if (channel)
|
||||
{
|
||||
if (!b)
|
||||
sql = [NSString stringWithFormat: (@"SELECT *"
|
||||
@" FROM %@"
|
||||
@" WHERE c_uid = '%@'"),
|
||||
[_viewURL gcsTableName], theID];
|
||||
sql = [NSMutableString stringWithFormat: (@"SELECT *"
|
||||
@" FROM %@"
|
||||
@" WHERE c_uid = '%@'"),
|
||||
[_viewURL gcsTableName], theID];
|
||||
else
|
||||
{
|
||||
sql = [NSString stringWithFormat: (@"SELECT *"
|
||||
@" FROM %@"
|
||||
@" WHERE c_uid = '%@' OR"
|
||||
@" LOWER(mail) = '%@'"),
|
||||
[_viewURL gcsTableName], theID, [theID lowercaseString]];
|
||||
|
||||
sql = [NSMutableString stringWithFormat: (@"SELECT *"
|
||||
@" FROM %@"
|
||||
@" WHERE c_uid = '%@' OR"
|
||||
@" LOWER(mail) = '%@'"),
|
||||
[_viewURL gcsTableName], theID, [theID lowercaseString]];
|
||||
|
||||
if (_mailFields && [_mailFields count] > 0)
|
||||
{
|
||||
sql = [sql stringByAppendingString: [self _whereClauseFromArray: _mailFields value: [theID lowercaseString] exact: YES]];
|
||||
[sql appendString: [self _whereClauseFromArray: _mailFields value: [theID lowercaseString] exact: YES]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,6 +418,50 @@
|
||||
}
|
||||
|
||||
[response setObject: emails forKey: @"c_emails"];
|
||||
|
||||
// We check if the user can authenticate
|
||||
if (_authenticationFilter)
|
||||
{
|
||||
EOQualifier *q_uid, *q_auth;
|
||||
|
||||
sql = [NSMutableString stringWithFormat: @"SELECT c_uid"
|
||||
@" FROM %@"
|
||||
@" WHERE ",
|
||||
[_viewURL gcsTableName]];
|
||||
|
||||
q_auth = [EOQualifier qualifierWithQualifierFormat: _authenticationFilter];
|
||||
|
||||
q_uid = [[EOKeyValueQualifier alloc] initWithKey: @"c_uid"
|
||||
operatorSelector: EOQualifierOperatorEqual
|
||||
value: theID];
|
||||
[q_uid autorelease];
|
||||
|
||||
qualifier = [[EOAndQualifier alloc] initWithQualifiers: q_uid, q_auth, nil];
|
||||
[qualifier autorelease];
|
||||
[qualifier _gcsAppendToString: sql];
|
||||
|
||||
ex = [channel evaluateExpressionX: sql];
|
||||
if (!ex)
|
||||
{
|
||||
NSDictionary *authResponse;
|
||||
|
||||
authResponse = [channel fetchAttributes: [channel describeResults: NO] withZone: NULL];
|
||||
[response setObject: [NSNumber numberWithBool: [authResponse count] > 0] forKey: @"canAuthenticate"];
|
||||
[channel cancelFetch];
|
||||
}
|
||||
else
|
||||
[self errorWithFormat: @"could not run SQL '%@': %@", sql, ex];
|
||||
}
|
||||
else
|
||||
[response setObject: [NSNumber numberWithBool: YES] forKey: @"canAuthenticate"];
|
||||
|
||||
// We check if we should use a different login for IMAP
|
||||
if (_imapLoginField)
|
||||
{
|
||||
if ([response objectForKey: _imapLoginField])
|
||||
[response setObject: [response objectForKey: _imapLoginField] forKey: @"c_imaplogin"];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
[self errorWithFormat: @"could not run SQL '%@': %@", sql, ex];
|
||||
|
||||
Reference in New Issue
Block a user