mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-05-23 04:15:26 +00:00
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:
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
- (BOOL) canSubscribeUsers
|
||||
{
|
||||
return [[self clientObject]
|
||||
respondsToSelector: @selector (subscribeUser:reallyDo:)];
|
||||
respondsToSelector: @selector (subscribeUserOrGroup:reallyDo:)];
|
||||
}
|
||||
|
||||
- (BOOL) currentUserIsSubscribed
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user