See ChangeLog

Monotone-Parent: 8ff4e6d2b420caded81d7317c1170ff6ce35249e
Monotone-Revision: 2b7803f8e993e96ff4490197722ef0a2a5faad70

Monotone-Author: ludovic@Sophos.ca
Monotone-Date: 2012-04-18T17:39:11
This commit is contained in:
Ludovic Marcotte
2012-04-18 17:39:11 +00:00
parent 045363c72e
commit dbd99fac84
12 changed files with 170 additions and 43 deletions
+26
View File
@@ -1,3 +1,29 @@
2012-04-18 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentObject.m (-_handleResourcesConflicts: ...):
We now handle recurring appointments by fetching the freebusy information for one full
year from the date of the event. Also improved the conflict
reporting messages.
* SoObjects/Appointments/SOGoAppointmentObject.m (-PUTAction:):
update the versit string in the request when updating the event, in
case a resource auto-accepted the event
* SoObjects/SOGo/SOGoGCSFolder.m: renamed -subscribeUser:reallydo: to
subscribeUserOrGroup:reallydo and we now handle group subscriptions.
Refactored all callers.
* SoObjects/SOGo/SOGoParentFolder.m (-_appendSubscribedSource:): now returns a
BOOL if the permission are still valid or not
* SoObjects/SOGo/SOGoParentFolder.m (-appendSubscribedSources): consumes the
returned value from -_appendSubscribedSource: and cleans up SubscribedFolders
and FolderDisplayNames accordingly in the user's settings.
* SoObjects/SOGo/SOGoUserManager.m (-_fillContactInfosForUser: ...): we now
set the isGroup attribute as we need this for quick groups
resolving.
2012-04-18 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/WebServerResources/generic.js (showAuthenticationDialog): new
@@ -67,4 +67,4 @@ vtodo_class2 = "(Confidential task)";
= "%{Attendee} %{SentByText}has not yet decided upon your event invitation.";
/* Resources */
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\".";
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}.";
@@ -725,8 +725,8 @@ static SoSecurityManager *sm = nil;
userMax = [proxySubscribers count];
for (userCount = 0; userCount < userMax; userCount++)
[currentFolder
subscribeUser: [proxySubscribers objectAtIndex: userCount]
reallyDo: YES];
subscribeUserOrGroup: [proxySubscribers objectAtIndex: userCount]
reallyDo: YES];
}
}
}
@@ -750,8 +750,8 @@ static SoSecurityManager *sm = nil;
userMax = [proxySubscribers count];
for (userCount = 0; userCount < userMax; userCount++)
[currentFolder
subscribeUser: [proxySubscribers objectAtIndex: userCount]
reallyDo: NO];
subscribeUserOrGroup: [proxySubscribers objectAtIndex: userCount]
reallyDo: NO];
}
}
}
+19 -3
View File
@@ -459,8 +459,10 @@
NSMutableArray *fbInfo;
int i;
// We get the start/end date for our conflict range. If the event to be added is recurring, we
// check for at least a year to start with.
start = [[theEvent startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: 1];
end = [[theEvent endDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -1];
end = [[theEvent endDate] dateByAddingYears: ([theEvent isRecurrent] ? 1 : 0) months: 0 days: 0 hours: 0 minutes: 0 seconds: -1];
folder = [[SOGoUser userWithLogin: currentUID]
personalCalendarFolderInContext: context];
@@ -488,16 +490,23 @@
[currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
else
{
iCalCalendar *calendar;
NSDictionary *values;
NSString *reason;
iCalEvent *event;
calendar = [iCalCalendar parseSingleFromSource: [[fbInfo objectAtIndex: 0] objectForKey: @"c_content"]];
event = [[calendar events] lastObject];
values = [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat: @"%d", [user numberOfSimultaneousBookings]], @"NumberOfSimultaneousBookings",
[user cn], @"Cn",
[user systemEmail], @"SystemEmail",
([event summary] ? [event summary] : @""), @"EventTitle",
[[fbInfo objectAtIndex: 0] objectForKey: @"startDate"], @"StartDate",
nil];
reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"."]];
reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}."]];
return [NSException exceptionWithHTTPStatus:403
reason: reason];
@@ -1668,7 +1677,7 @@
else
{
// We might have auto-accepted resources here. If that's the
// case, let's regerate the versitstring and replace the
// case, let's regenerate the versitstring and replace the
// one from the request.
[rq setContent: [[[event parent] versitString] dataUsingEncoding: [rq contentEncoding]]];
}
@@ -1815,6 +1824,13 @@
{
if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]))
return ex;
else
{
// We might have auto-accepted resources here. If that's the
// case, let's regenerate the versitstring and replace the
// one from the request.
[rq setContent: [[[newEvent parent] versitString] dataUsingEncoding: [rq contentEncoding]]];
}
// A RECURRENCE-ID was removed so there has to be a change in the master event
// We could also have an EXDATE added in the master component of the attendees
+2 -2
View File
@@ -102,8 +102,8 @@
- (void) removeFolderSettings: (NSMutableDictionary *) moduleSettings
withReference: (NSString *) reference;
- (BOOL) subscribeUser: (NSString *) subscribingUser
reallyDo: (BOOL) reallyDo;
- (BOOL) subscribeUserOrGroup: (NSString *) theIdentifier
reallyDo: (BOOL) reallyDo;
- (BOOL) userIsSubscriber: (NSString *) subscribingUser;
- (void) initializeQuickTablesAclsInContext: (WOContext *) localContext;
+39 -11
View File
@@ -840,19 +840,48 @@ static NSArray *childRecordFields = nil;
return [folderSubscription containsObject: [self folderReference]];
}
- (BOOL) subscribeUser: (NSString *) subscribingUser
reallyDo: (BOOL) reallyDo
- (BOOL) subscribeUserOrGroup: (NSString *) theIdentifier
reallyDo: (BOOL) reallyDo
{
NSMutableDictionary *moduleSettings;
NSMutableArray *folderSubscription;
NSString *subscriptionPointer;
NSMutableArray *allUsers;
SOGoUserSettings *us;
NSMutableDictionary *moduleSettings;
NSDictionary *dict;
SOGoUser *sogoUser;
BOOL rc;
int i;
sogoUser = [SOGoUser userWithLogin: subscribingUser roles: nil];
if (sogoUser)
dict = [[SOGoUserManager sharedUserManager] contactInfosForUserWithUIDorEmail: theIdentifier];
if ([[dict objectForKey: @"isGroup"] boolValue])
{
SOGoGroup *aGroup;
aGroup = [SOGoGroup groupWithIdentifier: theIdentifier
inDomain: [[context activeUser] domain]];
allUsers = [NSMutableArray arrayWithArray: [aGroup members]];
// We remove the active user from the group (if present) in order to
// not subscribe him to his own resource!
[allUsers removeObject: [context activeUser]];
}
else
{
sogoUser = [SOGoUser userWithLogin: theIdentifier roles: nil];
if (sogoUser)
allUsers = [NSArray arrayWithObject: sogoUser];
else
allUsers = [NSArray array];
}
rc = NO;
for (i = 0; i < [allUsers count]; i++)
{
sogoUser = [allUsers objectAtIndex: i];
us = [sogoUser userSettings];
moduleSettings = [us objectForKey: [container nameInContainer]];
if (!(moduleSettings
@@ -883,14 +912,13 @@ static NSArray *childRecordFields = nil;
[self removeFolderSettings: moduleSettings
withReference: subscriptionPointer];
[folderSubscription removeObject: subscriptionPointer];
}
}
[us synchronize];
rc = YES;
}
else
rc = NO;
return rc;
}
@@ -945,8 +973,8 @@ static NSArray *childRecordFields = nil;
LDAP call but more importantly, cache propagation calls that will
create contention on GDNC. */
for (count = 0; count < max; count++)
[self subscribeUser: [delegatedUsers objectAtIndex: count]
reallyDo: reallyDo];
[self subscribeUserOrGroup: [delegatedUsers objectAtIndex: count]
reallyDo: reallyDo];
}
else
{
@@ -965,7 +993,7 @@ static NSArray *childRecordFields = nil;
@"You cannot (un)subscribe to a folder that you own!"];
}
else
[self subscribeUser: userLogin reallyDo: reallyDo];
[self subscribeUserOrGroup: userLogin reallyDo: reallyDo];
}
return response;
+10 -1
View File
@@ -23,7 +23,6 @@
/*
Here are some group samples:
[ POSIX group ]
dn: cn=it-staff,ou=Group,dc=zzz,dc=xxx,dc=yyy
@@ -43,6 +42,16 @@
memberUid: hbt
memberUid: hossein
dn: cn=inverse,ou=groups,dc=inverse,dc=ca
objectClass: groupOfUniqueNames
objectClass: top
objectClass: extensibleObject
uniqueMember: uid=flachapelle,ou=users,dc=inverse,dc=ca
uniqueMember: uid=lmarcotte,ou=users,dc=inverse,dc=ca
uniqueMember: uid=wsourdeau,ou=users,dc=inverse,dc=ca
cn: inverse
mail: inverse@inverse.ca
*/
#include "SOGoGroup.h"
+48 -13
View File
@@ -251,7 +251,7 @@ static SoSecurityManager *sm = nil;
return nil;
}
- (void) _appendSubscribedSource: (NSString *) sourceKey
- (BOOL) _appendSubscribedSource: (NSString *) sourceKey
{
SOGoGCSFolder *subscribedFolder;
@@ -262,32 +262,67 @@ static SoSecurityManager *sm = nil;
&& ![sm validatePermission: SOGoPerm_AccessObject
onObject: subscribedFolder
inContext: context])
[subscribedSubFolders setObject: subscribedFolder
forKey: [subscribedFolder nameInContainer]];
{
[subscribedSubFolders setObject: subscribedFolder
forKey: [subscribedFolder nameInContainer]];
return YES;
}
return NO;
}
- (NSException *) appendSubscribedSources
{
NSArray *subscribedReferences;
SOGoUser *ownerUser;
NSMutableDictionary *folderDisplayNames;
NSMutableArray *subscribedReferences;
SOGoUserSettings *settings;
NSEnumerator *allKeys;
NSString *currentKey;
SOGoUser *ownerUser;
NSException *error;
id o;
BOOL dirty;
error = nil; /* we ignore non-DB errors at this time... */
dirty = NO;
ownerUser = [SOGoUser userWithLogin: owner];
settings = [ownerUser userSettings];
subscribedReferences = [[settings objectForKey: nameInContainer]
objectForKey: @"SubscribedFolders"];
if ([subscribedReferences isKindOfClass: [NSArray class]])
{
allKeys = [subscribedReferences objectEnumerator];
while ((currentKey = [allKeys nextObject]))
[self _appendSubscribedSource: currentKey];
}
subscribedReferences = [NSMutableArray arrayWithArray: [[settings objectForKey: nameInContainer]
objectForKey: @"SubscribedFolders"]];
o = [[settings objectForKey: nameInContainer] objectForKey: @"FolderDisplayNames"];
folderDisplayNames = nil;
if (o)
folderDisplayNames = [NSMutableDictionary dictionaryWithDictionary: o];
allKeys = [subscribedReferences objectEnumerator];
while ((currentKey = [allKeys nextObject]))
{
if (![self _appendSubscribedSource: currentKey])
{
// We no longer have access to this subscription, let's
// remove it from the current list.
[subscribedReferences removeObject: currentKey];
[folderDisplayNames removeObjectForKey: currentKey];
dirty = YES;
}
}
// If we changed the folder subscribtion list, we must sync it
if (dirty)
{
id o;
[[settings objectForKey: nameInContainer] setObject: subscribedReferences
forKey: @"SubscribedFolders"];
[[settings objectForKey: nameInContainer] setObject: folderDisplayNames
forKey: @"FolderDisplayNames"];
}
return error;
}
+4
View File
@@ -306,6 +306,10 @@
return allEmails;
}
//
// We always return the last object among our list of email addresses. This value
// is always added in SOGoUserManager: -_fillContactMailRecords:
//
- (NSString *) systemEmail
{
if (!allEmails)
+13 -4
View File
@@ -572,6 +572,9 @@
= [NSString stringWithFormat: @"%@@%@", uid, [dd mailDomain]];
else
systemEmail = uid;
// We always add the system email, which will always be returned
// by SOGoUser -systemEmail.
[emails addObject: systemEmail];
[contact setObject: [emails objectAtIndex: 0] forKey: @"c_email"];
}
@@ -583,11 +586,12 @@
withUIDorEmail: (NSString *) uid
inDomain: (NSString *) domain
{
NSMutableArray *emails;
NSDictionary *userEntry;
NSEnumerator *sogoSources;
NSObject <SOGoSource> *currentSource;
NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname, *c_imaplogin;
NSObject <SOGoSource> *currentSource;
NSEnumerator *sogoSources;
NSDictionary *userEntry;
NSMutableArray *emails;
NSNumber *isGroup;
NSArray *c_emails;
BOOL access;
@@ -635,6 +639,11 @@
if (!access)
[currentUser setObject: [NSNumber numberWithBool: NO]
forKey: @"MailAccess"];
// We check if it's a group
isGroup = [userEntry objectForKey: @"isGroup"];
if (isGroup)
[currentUser setObject: isGroup forKey: @"isGroup"];
// We also fill the resource attributes, if any
if ([userEntry objectForKey: @"isResource"])
+1 -1
View File
@@ -138,7 +138,7 @@
- (BOOL) canSubscribeUsers
{
return [[self clientObject]
respondsToSelector: @selector (subscribeUser:reallyDo:)];
respondsToSelector: @selector (subscribeUserOrGroup:reallyDo:)];
}
- (BOOL) currentUserIsSubscribed
+3 -3
View File
@@ -91,7 +91,7 @@
}
else
{
[clientObject subscribeUser: login reallyDo: reallyDo];
[clientObject subscribeUserOrGroup: login reallyDo: reallyDo];
if (isMailInvitation)
{
mailInvitationURL
@@ -376,8 +376,8 @@
folder = [self clientObject];
max = [userIDs count];
for (count = 0; count < max; count++)
[folder subscribeUser: [userIDs objectAtIndex: count]
reallyDo: YES];
[folder subscribeUserOrGroup: [userIDs objectAtIndex: count]
reallyDo: YES];
ex = nil;
}
else