Added the SOGoUserManager class (not used right now) to cache user preferences. Fixed tons of bugs wrt invitations handling and more cleanup needs to be done.

Monotone-Parent: 56b6e4ca9c570a4e36d00e32127d539e82da7293
Monotone-Revision: db186d0ad7ef7cd1cab54a0ee31f87daa7c32085

Monotone-Author: ludovic@Sophos.ca
Monotone-Date: 2008-11-05T21:04:16
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Ludovic Marcotte
2008-11-05 21:04:16 +00:00
parent 5100d6611d
commit a57e885766
30 changed files with 628 additions and 112 deletions
@@ -1,5 +1,6 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2007-2008 Inverse inc.
This file is part of OpenGroupware.org.
@@ -62,6 +63,7 @@
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/SOGoPermissions.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserManager.h>
#import <SOGo/SOGoUserFolder.h>
#import <SOGo/SOGoWebDAVAclManager.h>
+117 -5
View File
@@ -40,6 +40,7 @@
#import <SoObjects/SOGo/SOGoObject.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoUserManager.h>
#import <SoObjects/SOGo/SOGoWebDAVAclManager.h>
#import <SoObjects/SOGo/SOGoWebDAVValue.h>
#import <SoObjects/SOGo/WORequest+SOGo.h>
@@ -169,7 +170,7 @@
possibleName = [folder resourceNameForEventUID: eventUID];
if (possibleName)
{
object = [folder lookupName: nameInContainer
object = [folder lookupName: possibleName
inContext: context acquire: NO];
if ([object isKindOfClass: [NSException class]])
object = nil;
@@ -362,9 +363,11 @@
}
- (NSException *) _updateAttendee: (iCalPerson *) attendee
ownerUser: (SOGoUser *) theOwnerUser
forEventUID: (NSString *) eventUID
withSequence: (NSNumber *) sequence
forUID: (NSString *) uid
shouldAddSentBy: (BOOL) b
{
SOGoAppointmentObject *eventObject;
iCalEvent *event;
@@ -381,8 +384,23 @@
if ([[event sequence] compare: sequence]
== NSOrderedSame)
{
otherAttendee = [event findParticipant: [context activeUser]];
SOGoUser *currentUser;
//otherAttendee = [event findParticipant: [context activeUser]];
otherAttendee = [event findParticipant: theOwnerUser];
[otherAttendee setPartStat: [attendee partStat]];
// If one has accepted / declined an invitation on behalf of
// the attendee, we add the user to the SENT-BY attribute.
currentUser = [context activeUser];
if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]])
{
NSString *currentEmail;
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
[otherAttendee addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
iCalString = [[event parent] versitString];
error = [eventObject saveContentString: iCalString];
}
@@ -392,10 +410,11 @@
}
- (NSException *) _handleAttendee: (iCalPerson *) attendee
ownerUser: (SOGoUser *) theOwnerUser
statusChange: (NSString *) newStatus
inEvent: (iCalEvent *) event
{
NSString *newContent, *currentStatus, *organizerUID;
NSString *newContent, *currentStatus, *currentUser, *organizerUID;
NSException *ex;
SOGoUser *ownerUser;
@@ -406,20 +425,70 @@
!= NSOrderedSame)
{
[attendee setPartStat: newStatus];
// If one has accepted / declined an invitation on behalf of
// the attendee, we add the user to the SENT-BY attribute.
currentUser = [context activeUser];
if (![[currentUser login] isEqualToString: [theOwnerUser login]])
{
NSString *currentEmail;
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
[attendee addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
// We generate the updated iCalendar file and we save it
// in the database.
newContent = [[event parent] versitString];
ex = [self saveContentString: newContent];
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
if (!(ex || [event userIsOrganizer: ownerUser]))
{
if ([[attendee rsvp] isEqualToString: @"true"]
&& [event isStillRelevant])
[self sendResponseToOrganizer: event];
organizerUID = [[event organizer] uid];
if (organizerUID)
ex = [self _updateAttendee: attendee
ownerUser: theOwnerUser
forEventUID: [event uid]
withSequence: [event sequence]
forUID: organizerUID];
forUID: organizerUID
shouldAddSentBy: YES];
}
// We update the calendar of all participants that are
// local to the system. This is useful in case user A accepts
// invitation from organizer B and users C, D, E who are also
// attendees need to verify if A has accepted.
NSArray *attendees;
iCalPerson *att;
NSString *uid;
int i;
attendees = [event attendees];
for (i = 0; i < [attendees count]; i++)
{
att = [attendees objectAtIndex: i];
if (att == attendee) continue;
uid = [[LDAPUserManager sharedUserManager]
getUIDForEmail: [att rfc822Email]];
if (uid)
{
[self _updateAttendee: attendee
ownerUser: theOwnerUser
forEventUID: [event uid]
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: YES];
}
}
}
@@ -512,6 +581,7 @@
{
iCalPerson *localAttendee;
iCalEvent *event;
SOGoUser *ownerUser;
event = [self component: NO secure: NO];
localAttendee = [event findParticipantWithEmail: [attendee rfc822Email]];
@@ -519,6 +589,46 @@
{
[localAttendee setPartStat: [attendee partStat]];
[self saveComponent: event];
/// TEST ///
NSArray *attendees;
iCalPerson *att;
NSString *uid;
int i;
// We update for the organizer
ownerUser = [context activeUser];
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
withSequence: [event sequence]
forUID: [[SOGoUser userWithLogin: owner roles: nil] login]
shouldAddSentBy: NO];
attendees = [event attendees];
for (i = 0; i < [attendees count]; i++)
{
att = [attendees objectAtIndex: i];
if (att == attendee) continue;
uid = [[LDAPUserManager sharedUserManager]
getUIDForEmail: [att rfc822Email]];
if (uid)
{
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: NO];
}
}
/// TEST ///
}
else
[self errorWithFormat: @"attendee not found: '%@'", attendee];
@@ -579,7 +689,9 @@
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
attendee = [event findParticipant: ownerUser];
if (attendee)
ex = [self _handleAttendee: attendee statusChange: _status
ex = [self _handleAttendee: attendee
ownerUser: ownerUser
statusChange: _status
inEvent: event];
else
ex = [NSException exceptionWithHTTPStatus: 404 /* Not Found */
@@ -1,2 +1,2 @@
<#IsSubject>Event Cancelled: <#summary/></#IsSubject>
<#IsBody><#organizer/> has cancelled this event: <#summary/>.</#IsBody>
<#IsBody><#organizer/> <#HasSentBy>(sent by <#sentBy/>) </#HasSentBy>has cancelled this event: <#summary/>.</#IsBody>
@@ -16,3 +16,12 @@ summary: WOString {
value = summary;
escapeHTML = NO;
}
HasSentBy: WOConditional {
condition = hasSentBy;
}
sentBy: WOString {
value = sentBy;
escapeHTML = NO;
}
@@ -1,2 +1,2 @@
<#IsSubject>Event Invitation Reply: <#summary/></#IsSubject>
<#IsBody><#attendee/> has <#HasAccepted>accepted</#HasAccepted><#HasDeclined>declined</#HasDeclined><#HasNotAcceptedNotDeclined>not yet decided upon</#HasNotAcceptedNotDeclined> your event invitation.</#IsBody>
<#IsBody><#attendee/> has <#HasSentBy>(sent by <#sentBy/>) </#HasSentBy><#HasAccepted>accepted</#HasAccepted><#HasDeclined>declined</#HasDeclined><#HasNotAcceptedNotDeclined>not yet decided upon</#HasNotAcceptedNotDeclined> your event invitation.</#IsBody>
@@ -28,3 +28,12 @@ HasDeclined: WOConditional {
HasNotAcceptedNotDeclined: WOConditional {
condition = hasNotAcceptedNotDeclined;
}
HasSentBy: WOConditional {
condition = hasSentBy;
}
sentBy: WOString {
value = sentBy;
escapeHTML = NO;
}
@@ -1,2 +1,2 @@
<#IsSubject>Event Invitation: <#summary/></#IsSubject>
<#IsBody><#organizer/> has invited you to <#summary/>.</#IsBody>
<#IsBody><#organizer/> <#HasSentBy>(sent by <#sentBy/>) </#HasSentBy>has invited you to <#summary/>.</#IsBody>
@@ -16,3 +16,12 @@ summary: WOString {
value = summary;
escapeHTML = NO;
}
HasSentBy: WOConditional {
condition = hasSentBy;
}
sentBy: WOString {
value = sentBy;
escapeHTML = NO;
}
+18 -1
View File
@@ -98,7 +98,24 @@ static NSCharacterSet *wsSet = nil;
- (NSString *) attendeeName
{
return [attendee cn];
NSString *name;
name = [attendee cn];
if (name && [name length])
return name;
return [attendee rfc822Email];
}
- (BOOL) hasSentBy
{
return [attendee hasSentBy];
}
- (NSString *) sentBy
{
return [attendee sentBy];
}
- (BOOL) hasAccepted
@@ -108,6 +108,16 @@ static NSTimeZone *UTC = nil;
return organizerName;
}
- (BOOL) hasSentBy
{
return [[apt organizer] hasSentBy];
}
- (NSString *) sentBy
{
return [[apt organizer] sentBy];
}
/* Helpers */
/* Generate Response */
+7 -20
View File
@@ -46,6 +46,7 @@
#import <SoObjects/SOGo/SOGoMailer.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoUserManager.h>
#import <SoObjects/SOGo/WORequest+SOGo.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
@@ -451,20 +452,6 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
return [[SOGoUser userWithLogin: uid roles: nil] timeZone];
}
- (void) _setupSentByIfNeeded: (iCalPerson *) person
{
SOGoUser *currentUser;
NSString *currentEmail;
currentUser = [context activeUser];
if (![[currentUser login] isEqualToString: owner])
{
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
[person addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"MAILTO:%@", currentEmail]];
}
}
- (void) sendEMailUsingTemplateNamed: (NSString *) newPageName
forObject: (iCalRepeatableEntityObject *) object
toAttendees: (NSArray *) attendees
@@ -491,11 +478,12 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
{
/* sender */
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
currentUser = [context activeUser];
shortSenderEmail = [[currentUser allEmails] objectAtIndex: 0];
senderEmail = [NSString stringWithFormat: @"%@ <%@>",
[ownerUser cn], shortSenderEmail];
[self _setupSentByIfNeeded: [object organizer]];
//currentUser = [context activeUser];
//shortSenderEmail = [[currentUser allEmails] objectAtIndex: 0];
// senderEmail = [NSString stringWithFormat: @"%@ <%@>",
// [ownerUser cn], shortSenderEmail];
shortSenderEmail = [[object organizer] rfc822Email];
senderEmail = [[object organizer] mailAddress];
// NSLog (@"sending '%@' from %@",
// [(iCalCalendar *) [object parent] method], senderEmail);
/* generate iCalString once */
@@ -695,7 +683,6 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
{
organizer = [event organizer];
attendee = [event findParticipant: ownerUser];
[self _setupSentByIfNeeded: attendee];
[event setAttendees: [NSArray arrayWithObject: attendee]];
[self sendIMIPReplyForEvent: event to: organizer];
}
@@ -31,6 +31,7 @@
#import <SaxObjC/XMLNamespaces.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserManager.h>
#import <SOGo/NSObject+DAV.h>
#import <SOGo/NSString+DAV.h>
+12 -4
View File
@@ -95,14 +95,22 @@ _computeAllDayOffset()
return isParticipant;
}
#warning user could be a delegate, we will need to handle that someday
- (BOOL) userIsOrganizer: (SOGoUser *) user
{
NSString *orgMail;
NSString *mail;
BOOL b;
orgMail = [[self organizer] rfc822Email];
mail = [[self organizer] rfc822Email];
b = [user hasEmail: mail];
if (b) return YES;
return [user hasEmail: orgMail];
// We check for the SENT-BY
mail = [[self organizer] sentBy];
if ([mail length])
return [user hasEmail: mail];
return NO;
}
- (NSArray *) attendeeUIDs
+2 -1
View File
@@ -1,6 +1,6 @@
/* iCalPerson+SOGo.h - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
* Copyright (C) 2007-2008 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@@ -33,6 +33,7 @@
- (NSString *) mailAddress;
- (NSString *) uid;
- (BOOL) hasSentBy;
@end
+27 -1
View File
@@ -1,6 +1,6 @@
/* iCalPerson+SOGo.m - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
* Copyright (C) 2007-2008 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@@ -50,4 +50,30 @@ static LDAPUserManager *um = nil;
return [um getUIDForEmail: [self rfc822Email]];
}
- (BOOL) hasSentBy
{
NSString *mail;
mail = [self value: 0 ofAttribute: @"SENT-BY"];
return ([mail length] > 7);
}
- (NSString *) sentBy
{
NSString *mail;
mail = [self value: 0 ofAttribute: @"SENT-BY"];
if ([mail length] > 7)
{
if ([mail characterAtIndex: 0] && [mail hasSuffix: @"\""])
mail = [mail substringWithRange: NSMakeRange(1, [mail length]-2)];
return [mail substringFromIndex: 7];
}
return @"";
}
@end
+2
View File
@@ -53,6 +53,7 @@ SOGo_HEADER_FILES = \
SOGoWebDAVValue.h \
SOGoMailer.h \
SOGoUser.h \
SOGoUserManager.h \
\
NSDictionary+BSJSONAdditions.h \
NSScanner+BSJSONAdditions.h \
@@ -98,6 +99,7 @@ SOGo_OBJC_FILES = \
SOGoWebDAVValue.m \
SOGoMailer.m \
SOGoUser.m \
SOGoUserManager.m \
\
NSDictionary+BSJSONAdditions.m \
NSScanner+BSJSONAdditions.m \
+1
View File
@@ -32,6 +32,7 @@
#import "LDAPUserManager.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoUserManager.h"
#import "SOGoDAVAuthenticator.h"
+1
View File
@@ -60,6 +60,7 @@
#import "SOGoParentFolder.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoUserManager.h"
#import "SOGoWebDAVAclManager.h"
#import "WORequest+SOGo.h"
+1
View File
@@ -61,6 +61,7 @@
#import "SOGoCache.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoUserManager.h"
#import "SOGoUserFolder.h"
#import "SOGoWebDAVAclManager.h"
#import "SOGoWebDAVValue.h"
+6 -2
View File
@@ -48,6 +48,7 @@
@class SOGoAppointmentFolder;
@class SOGoAppointmentFolders;
@class SOGoDateFormatter;
@class SOGoUserDefaults;
@class SOGoUserFolder;
extern NSString *SOGoWeekStartJanuary1;
@@ -62,8 +63,8 @@ extern NSString *SOGoWeekStartFirstFullWeek;
@interface SOGoUser : SoUser
{
NSUserDefaults *userDefaults;
NSUserDefaults *userSettings;
SOGoUserDefaults *userDefaults;
SOGoUserDefaults *userSettings;
NSArray *allEmails;
NSString *language;
NSString *currentPassword;
@@ -111,7 +112,10 @@ extern NSString *SOGoWeekStartFirstFullWeek;
/* defaults */
- (void) setUserDefaultsFromDictionary: (NSDictionary *) theDictionary;
- (NSUserDefaults *) userDefaults;
- (void) setUserSettingsFromDictionary: (NSDictionary *) theDictionary;
- (NSUserDefaults *) userSettings;
- (NSString *) language;
+17
View File
@@ -470,6 +470,14 @@ _timeValue (NSString *key)
}
/* defaults */
- (void) setUserDefaultsFromDictionary: (NSDictionary *) theDictionary
{
if (!userDefaults)
userDefaults = [[SOGoUserDefaults alloc] initWithTableURL: SOGoProfileURL
uid: login
fieldName: @"c_defaults"];
[userDefaults setValues: theDictionary];
}
- (NSUserDefaults *) userDefaults
{
@@ -493,6 +501,15 @@ _timeValue (NSString *key)
return userDefaults;
}
- (void) setUserSettingsFromDictionary: (NSDictionary *) theDictionary
{
if (!userSettings)
userSettings = [[SOGoUserDefaults alloc] initWithTableURL: SOGoProfileURL
uid: login
fieldName: @"c_settings"];
[userSettings setValues: theDictionary];
}
- (NSUserDefaults *) userSettings
{
if (!userSettings)
+1 -3
View File
@@ -36,12 +36,9 @@
@interface SOGoUserDefaults : NSObject
{
NSUserDefaults *parent;
NSURL *url;
NSString *uid;
NSString *fieldName;
NSArray *fieldNames;
NSMutableDictionary *values;
NSCalendarDate *lastFetch;
@@ -58,6 +55,7 @@
fieldName: (NSString *) fieldName;
/* value access */
- (void) setValues: (NSDictionary *) theValues;
- (void) setObject: (id) value
forKey: (NSString *) key;
+18 -7
View File
@@ -20,6 +20,7 @@
*/
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDistributedNotificationCenter.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSValue.h>
@@ -50,7 +51,6 @@ static NSString *uidColumnName = @"c_uid";
if (tableURL && [userID length] > 0
&& [defaultsFieldName length] > 0)
{
parent = [[NSUserDefaults standardUserDefaults] retain];
fieldName = [defaultsFieldName copy];
url = [tableURL copy];
uid = [userID copy];
@@ -77,7 +77,6 @@ static NSString *uidColumnName = @"c_uid";
{
[values release];
[lastFetch release];
[parent release];
[url release];
[uid release];
[fieldName release];
@@ -101,11 +100,6 @@ static NSString *uidColumnName = @"c_uid";
return fieldName;
}
- (NSUserDefaults *) parentDefaults
{
return parent;
}
/* operation */
- (BOOL) primaryFetchProfile
@@ -275,6 +269,18 @@ static NSString *uidColumnName = @"c_uid";
[self errorWithFormat: @"could not run SQL '%@': %@", sql, ex];
else
{
NSMutableDictionary *d;
d = [[NSMutableDictionary alloc] init];
[d addEntriesFromDictionary: values];
[d setObject: uid forKey: @"uid"];
[[NSDistributedNotificationCenter defaultCenter]
postNotificationName: ([fieldName isEqualToString: @"c_defaults"] ? @"SOGoUserDefaultsHaveChanged" : @"SOGoUserSettingsHaveChanged")
object: nil
userInfo: d];
[d release];
if ([[channel adaptorContext] hasOpenTransaction])
{
ex = [channel evaluateExpressionX: @"COMMIT TRANSACTION"];
@@ -315,6 +321,11 @@ static NSString *uidColumnName = @"c_uid";
}
/* value access */
- (void) setValues: (NSDictionary *) theValues
{
[values removeAllObjects];
[values addEntriesFromDictionary: theValues];
}
- (void) setObject: (id) value
forKey: (NSString *) key
+1
View File
@@ -52,6 +52,7 @@
#import "LDAPUserManager.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoUserManager.h"
#import "SOGoUserFolder.h"
+47
View File
@@ -0,0 +1,47 @@
/* SOGoUserManager.h - this file is part of SOGo
*
* Copyright (C) 2008 Inverse inc.
*
* Author: Ludovic Marcotte <lmarcotte@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
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef SOGOUSERMANAGER_H
#define SOGOUSERMANAGER_H
#import <Foundation/NSObject.h>
@class NSArray;
@class NSMutableDictionary;
@class NSString;
@class NSTimer;
@class SOGoUser;
@interface SOGoUserManager : NSObject
{
@private
NSMutableDictionary *_cache;
NSTimer *_cleanupTimer;
}
+ (id) sharedManager;
- (SOGoUser *) userWithLogin: (NSString *) theLogin
roles: (NSArray *) theRoles;
@end
#endif
+189
View File
@@ -0,0 +1,189 @@
/* SOGoUserManager.m - this file is part of SOGo
*
* Copyright (C) 2008 Inverse inc.
*
* Author: Ludovic Marcotte <lmarcotte@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
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "SOGoUserManager.h"
#include <Foundation/NSDictionary.h>
#include <Foundation/NSDistributedNotificationCenter.h>
#include <Foundation/NSEnumerator.h>
#include <Foundation/NSString.h>
#include <Foundation/NSTimer.h>
#include <Foundation/NSUserDefaults.h>
#import <NGExtensions/NSObject+Logs.h>
#include "SOGoUser.h"
// We define the default value for cleaning up cached
// users' preferences. This value should be relatively high
// to avoid useless database calls.
static NSTimeInterval cleanupInterval = 1800;
@implementation SOGoUserManager
- (id) init
{
NSString *cleanupSetting;
if ((self = [super init]))
{
_cache = [[NSMutableDictionary alloc] init];
}
// We register ourself for notifications
[[NSDistributedNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_userDefaultsHaveChanged:)
name: @"SOGoUserDefaultsHaveChanged"
object: nil];
[[NSDistributedNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_userSettingsHaveChanged:)
name: @"SOGoUserSettingsHaveChanged"
object: nil];
// We fire our timer that will cleanup cache entries
cleanupSetting = [[NSUserDefaults standardUserDefaults]
objectForKey: @"SOGoUserManagerCleanupInterval"];
if (cleanupSetting && [cleanupSetting doubleValue] > 0.0)
cleanupInterval = [cleanupSetting doubleValue];
_cleanupTimer = [NSTimer scheduledTimerWithTimeInterval: cleanupInterval
target: self
selector: @selector(_cleanupSources)
userInfo: nil
repeats: YES];
[self logWithFormat: @"cleanup interval set every %f seconds",
cleanupInterval];
return self;
}
- (void) dealloc
{
[_cache release];
[super dealloc];
}
+ (id) sharedManager
{
static id sharedManager = nil;
if (!sharedManager)
sharedManager = [self new];
return sharedManager;
}
- (SOGoUser *) userWithLogin: (NSString *) theLogin
roles: (NSArray *) theRoles
{
NSDate *cleanupDate;
SOGoUser *user;
id entry;
cleanupDate = [[NSDate date] addTimeInterval: cleanupInterval];
entry = [_cache objectForKey: theLogin];
if (!entry)
{
user = [SOGoUser userWithLogin: theLogin roles: theRoles];
entry = [NSMutableDictionary dictionaryWithObjectsAndKeys: user, @"user", cleanupDate, @"cleanupDate", nil];
[_cache setObject: entry forKey: theLogin];
}
else
{
[entry setObject: cleanupDate forKey: @"cleanupDate"];
user = [entry objectForKey: @"user"];
}
[user setPrimaryRoles: theRoles];
return user;
}
//
// Private stuff
//
- (void) _userDefaultsHaveChanged: (NSNotification *) theNotification
{
NSMutableDictionary *d;
SOGoUser *user;
d = [[NSMutableDictionary alloc] init];
[d addEntriesFromDictionary: [theNotification userInfo]];
user = [self userWithLogin: [d objectForKey: @"uid"]
roles: nil];
[d removeObjectForKey: @"uid"];
[user setUserDefaultsFromDictionary: d];
[d release];
}
- (void) _userSettingsHaveChanged: (NSNotification *) theNotification
{
NSMutableDictionary *d;
SOGoUser *user;
d = [[NSMutableDictionary alloc] init];
[d addEntriesFromDictionary: [theNotification userInfo]];
user = [self userWithLogin: [d objectForKey: @"uid"]
roles: nil];
[d removeObjectForKey: @"uid"];
[user setUserSettingsFromDictionary: d];
[d release];
}
- (void) _cleanupSources
{
NSEnumerator *userIDs;
NSString *currentID;
NSDictionary *currentUser;
NSDate *now;
unsigned int count;
now = [NSDate date];
count = 0;
userIDs = [[_cache allKeys] objectEnumerator];
while ((currentID = [userIDs nextObject]))
{
currentUser = [_cache objectForKey: currentID];
if ([now earlierDate:
[currentUser objectForKey: @"cleanupDate"]] == now)
{
[_cache removeObjectForKey: currentID];
count++;
}
}
if (count)
[self logWithFormat: @"cleaned %d users records from cache", count];
}
@end
+1
View File
@@ -40,6 +40,7 @@
#import "LDAPUserManager.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoUserManager.h"
#import "SOGoWebAuthenticator.h"
+3 -3
View File
@@ -1,6 +1,6 @@
/* UIxComponentEditor.h - this file is part of SOGo
*
* Copyright (C) 2006 Inverse inc.
* Copyright (C) 2006-2008 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@@ -41,8 +41,8 @@
NSString *saveURL;
NSMutableArray *calendarList;
NSMutableArray *organizerList;
NSDictionary *organizerIdentity;
//NSMutableArray *organizerList;
//NSDictionary *organizerIdentity;
/* individual values */
NSCalendarDate *cycleUntilDate;
+112 -60
View File
@@ -1,6 +1,6 @@
/* UIxComponentEditor.m - this file is part of SOGo
*
* Copyright (C) 2006 Inverse inc.
* Copyright (C) 2006-2008 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@@ -81,7 +81,7 @@ iRANGE(2);
#define REPEAT(X) \
- (NSString *) repeat##X { return repeat##X; } \
- (void) setRepeat##X: (NSString *) theValue { NSLog(@"setRepeat%d %@", X, theValue); ASSIGN(repeat##X, theValue); } \
- (void) setRepeat##X: (NSString *) theValue { ASSIGN(repeat##X, theValue); } \
#define RANGE(X) \
- (NSString *) range##X { return range##X; } \
@@ -98,7 +98,7 @@ iRANGE(2);
[self setIsCycleEndNever];
componentOwner = @"";
organizer = nil;
organizerIdentity = nil;
//organizerIdentity = nil;
attendeesNames = nil;
attendeesUIDs = nil;
attendeesEmails = nil;
@@ -128,7 +128,7 @@ iRANGE(2);
[title release];
[location release];
[organizer release];
[organizerIdentity release];
//[organizerIdentity release];
[comment release];
[priority release];
[categories release];
@@ -460,75 +460,101 @@ iRANGE(2);
return [organizer mailAddress];
}
- (BOOL) canBeOrganizer
{
NSString *owner;
SOGoObject <SOGoComponentOccurence> *co;
SOGoUser *currentUser;
BOOL hasOrganizer;
SoSecurityManager *sm;
// - (BOOL) canBeOrganizer
// {
// NSString *owner;
// SOGoObject <SOGoComponentOccurence> *co;
// SOGoUser *currentUser;
// BOOL hasOrganizer;
// SoSecurityManager *sm;
co = [self clientObject];
owner = [co ownerInContext: context];
currentUser = [context activeUser];
// co = [self clientObject];
// owner = [co ownerInContext: context];
// currentUser = [context activeUser];
hasOrganizer = ([[organizer value: 0] length] > 0);
// hasOrganizer = ([[organizer value: 0] length] > 0);
sm = [SoSecurityManager sharedSecurityManager];
// sm = [SoSecurityManager sharedSecurityManager];
return ([co isNew]
|| (([owner isEqualToString: [currentUser login]]
|| ![sm validatePermission: SOGoCalendarPerm_ModifyComponent
onObject: co
inContext: context])
&& (!hasOrganizer || [component userIsOrganizer: currentUser])));
}
// return ([co isNew]
// || (([owner isEqualToString: [currentUser login]]
// || ![sm validatePermission: SOGoCalendarPerm_ModifyComponent
// onObject: co
// inContext: context])
// && (!hasOrganizer || [component userIsOrganizer: currentUser])));
// }
- (BOOL) hasOrganizer
{
return ([[organizer value: 0] length] && ![self canBeOrganizer]);
}
// We check if there's an organizer and if it's not ourself
NSString *value;
- (void) setOrganizerIdentity: (NSDictionary *) newOrganizerIdentity
{
ASSIGN (organizerIdentity, newOrganizerIdentity);
}
value = [organizer rfc822Email];
- (NSDictionary *) organizerIdentity
{
NSArray *allIdentities;
NSEnumerator *identities;
NSDictionary *currentIdentity;
NSString *orgEmail;
orgEmail = [organizer rfc822Email];
if (!organizerIdentity)
if ([value length])
{
if ([orgEmail length])
{
allIdentities = [[context activeUser] allIdentities];
identities = [allIdentities objectEnumerator];
while (!organizerIdentity
&& ((currentIdentity = [identities nextObject])))
if ([[currentIdentity objectForKey: @"email"]
caseInsensitiveCompare: orgEmail]
== NSOrderedSame)
ASSIGN (organizerIdentity, currentIdentity);
}
NSDictionary *currentIdentity;
NSEnumerator *identities;
NSArray *allIdentities;
allIdentities = [[context activeUser] allIdentities];
identities = [allIdentities objectEnumerator];
currentIdentity = nil;
while ((currentIdentity = [identities nextObject]))
if ([[currentIdentity objectForKey: @"email"]
caseInsensitiveCompare: value]
== NSOrderedSame)
return NO;
return YES;
}
return organizerIdentity;
return NO;
//return ([[organizer value: 0] length] && ![self canBeOrganizer]);
}
- (NSArray *) organizerList
{
return [[context activeUser] allIdentities];
}
//- (void) setOrganizerIdentity: (NSDictionary *) newOrganizerIdentity
//{
// ASSIGN (organizerIdentity, newOrganizerIdentity);
//}
- (NSString *) itemOrganizerText
{
return [item keysWithFormat: @"%{fullName} <%{email}>"];
}
// - (NSDictionary *) organizerIdentity
// {
// NSArray *allIdentities;
// NSEnumerator *identities;
// NSDictionary *currentIdentity;
// NSString *orgEmail;
// orgEmail = [organizer rfc822Email];
// if (!organizerIdentity)
// {
// if ([orgEmail length])
// {
// allIdentities = [[context activeUser] allIdentities];
// identities = [allIdentities objectEnumerator];
// while (!organizerIdentity
// && ((currentIdentity = [identities nextObject])))
// if ([[currentIdentity objectForKey: @"email"]
// caseInsensitiveCompare: orgEmail]
// == NSOrderedSame)
// ASSIGN (organizerIdentity, currentIdentity);
// }
// }
// return organizerIdentity;
// }
//- (NSArray *) organizerList
//{
// return [[context activeUser] allIdentities];
//}
//- (NSString *) itemOrganizerText
//{
// return [item keysWithFormat: @"%{fullName} <%{email}>"];
//}
- (void) setAttendeesNames: (NSString *) newAttendeesNames
{
@@ -833,7 +859,7 @@ iRANGE(2);
- (void) setComponentCalendar: (SOGoAppointmentFolder *) _componentCalendar
{
ASSIGN (componentCalendar, _componentCalendar);
ASSIGN(componentCalendar, _componentCalendar);
}
/* priorities */
@@ -1286,13 +1312,38 @@ RANGE(2);
NSString *owner, *login;
BOOL isOwner, hasOrganizer, hasAttendees;
owner = [[self clientObject] ownerInContext: context];
//owner = [[self clientObject] ownerInContext: context];
owner = [componentCalendar ownerInContext: context];
login = [[context activeUser] login];
isOwner = [owner isEqualToString: login];
hasAttendees = ([[component attendees] count] > 0);
organizerEmail = [[component organizer] email];
hasOrganizer = ([organizerEmail length] > 0);
#if 1
ASSIGN (organizer, [iCalPerson elementWithTag: @"organizer"]);
[component setOrganizer: organizer];
if (hasAttendees)
{
SOGoUser *user;
id identity;
user = [SOGoUser userWithLogin: owner roles: nil];
identity = [user defaultIdentity];
[organizer setCn: [identity objectForKey: @"fullName"]];
[organizer setEmail: [identity objectForKey: @"email"]];
if (!isOwner)
{
NSString *currentEmail;
currentEmail = [[[context activeUser] allEmails] objectAtIndex: 0];
[organizer addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
}
#else
if (hasOrganizer)
{
if (isOwner && !hasAttendees)
@@ -1311,6 +1362,7 @@ RANGE(2);
[component setOrganizer: organizer];
}
}
#endif
}
- (void) _handleCustomRRule: (iCalRecurrenceRule *) theRule
@@ -61,12 +61,12 @@
/><span class="content"><var:string
value="organizerName"/></span></label>
</var:if>
<var:if condition="canBeOrganizer"
<!--<var:if condition="canBeOrganizer"
><label id="organizerListLabel"><var:string label:value="Organizer:"
/><span class="content"><var:popup list="organizerList"
item="item" string="itemOrganizerText"
var:selection="organizerIdentity"/>
</span></label></var:if>
</span></label></var:if>-->
<label id="attendeesLabel"><var:string label:value="Attendees:"
/><span class="content"
><a href="#" id="attendeesHref"><!-- space --></a></span></label>