Monotone-Parent: 538aedd7d01174f61f329561b71c913f2c048a26
Monotone-Revision: d4724feea77a2bfe4a1315b1572ab4ae3ea3afc9 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2010-01-19T12:28:10 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
943b044622
commit
4639bf6b99
39
ChangeLog
39
ChangeLog
|
@ -1,5 +1,44 @@
|
|||
2010-01-19 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* UI/Common/UIxFolderActions.m (-subscribeUsersAction): new web
|
||||
method that enables resource owners to subscribe other users to
|
||||
their resources from the acl editor.
|
||||
|
||||
* UI/Common/UIxAclEditor.m (-currentUserIsSubscribed)
|
||||
(-folderID): new accessors.
|
||||
|
||||
* Tests/utilities.py (TestACLUtility.(un)subscribe): added utility
|
||||
methods.
|
||||
|
||||
* Tests/test-ical.py (iCalTest.testCalendarProxy2): test the
|
||||
behaviour of the ical proxy mechanisms when subscriptions and
|
||||
access rights are modified.
|
||||
|
||||
* SoObjects/SOGo/SOGoUserSettings.m (-subscribedCalendars)
|
||||
(-subscribedAddressBooks): new accessors.
|
||||
(-setCalendarProxyUsers:withWriteAccess:)
|
||||
(-setCalendarProxySubscriptionUsers:withWriteAccess:) removed accessors.
|
||||
|
||||
* SoObjects/Appointments/SOGoUser+Appointments.m
|
||||
(-adjustProxySubscriptionToUser:remove:forWriteAccess:) removed
|
||||
methods.
|
||||
(-hasSubscribedToCalendar:): new method that returns whether a
|
||||
user has subscribed to a calendar resource. Might be a duplicate
|
||||
of [SOGoGCSFolder userIsSubscriber:].
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentFolders.m
|
||||
(-adjustProxyRolesForUsers:remove:forWriteAccess:)
|
||||
(-adjustProxySubscriptionsForUsers:remove:forWriteAccess:):
|
||||
removed methods.
|
||||
(-hasProxyCalendarsWithWriteAccess:forUserWithLogin:): new method
|
||||
that returns whether the user passed as parameter should be
|
||||
returned in the list of subscribers corresponding to the proper
|
||||
write access.
|
||||
(-proxySubscribersWithWriteAccess:) new method that returns the
|
||||
list of users that have a proxy access to the current account.
|
||||
(-addProxySubscribers:withWriteAccess:,-removeProxySubscribers:withWriteAccess:)
|
||||
setters for the above method.
|
||||
|
||||
* UI/WebServerResources/ContactsUI.js (initContacts): fixed a bug
|
||||
causing a null exception error on IE7 when the window is not the
|
||||
main window, and is therefore missing the "uploadCancel" and
|
||||
|
|
|
@ -50,6 +50,12 @@
|
|||
@class GCSFolder;
|
||||
@class iCalCalendar;
|
||||
|
||||
typedef enum {
|
||||
SOGoAppointmentProxyPermissionNone = 0,
|
||||
SOGoAppointmentProxyPermissionRead = 1,
|
||||
SOGoAppointmentProxyPermissionWrite = 2,
|
||||
} SOGoAppointmentProxyPermission;
|
||||
|
||||
@interface SOGoAppointmentFolder : SOGoGCSFolder
|
||||
{
|
||||
NSTimeZone *timeZone;
|
||||
|
@ -138,9 +144,6 @@
|
|||
- (BOOL) showCalendarTasks;
|
||||
- (void) setShowCalendarTasks: (BOOL) new;
|
||||
|
||||
- (BOOL) isProxied;
|
||||
- (void) setIsProxied: (BOOL) isProxied;
|
||||
|
||||
- (NSString *) syncTag;
|
||||
- (void) setSyncTag: (NSString *) newSyncTag;
|
||||
|
||||
|
@ -152,9 +155,10 @@
|
|||
|
||||
/* caldav proxy */
|
||||
|
||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write;
|
||||
- (SOGoAppointmentProxyPermission)
|
||||
proxyPermissionForUserWithLogin: (NSString *) login;
|
||||
|
||||
- (NSArray *) aclUsersWithProxyWriteAccess: (BOOL) write;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -2906,47 +2906,6 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
|||
return (![inactiveFolders containsObject: nameInContainer]);
|
||||
}
|
||||
|
||||
- (BOOL) isProxied
|
||||
{
|
||||
NSArray *proxiedCalendars;
|
||||
SOGoUser *ownerUser;
|
||||
|
||||
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: nil]];
|
||||
proxiedCalendars = [[ownerUser userSettings] proxiedCalendars];
|
||||
|
||||
return [proxiedCalendars containsObject: [self realNameInContainer]];
|
||||
}
|
||||
|
||||
- (void) setIsProxied: (BOOL) isProxied
|
||||
{
|
||||
NSMutableArray *proxiedCalendars;
|
||||
NSArray *subscriptionUsers;
|
||||
SOGoUser *ownerUser;
|
||||
SOGoUserSettings *us;
|
||||
|
||||
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: nil]];
|
||||
us = [ownerUser userSettings];
|
||||
proxiedCalendars = [[us proxiedCalendars] mutableCopy];
|
||||
if (isProxied)
|
||||
[proxiedCalendars addObjectUniquely: [self realNameInContainer]];
|
||||
else
|
||||
[proxiedCalendars removeObject: [self realNameInContainer]];
|
||||
|
||||
[us setProxiedCalendars: proxiedCalendars];
|
||||
|
||||
subscriptionUsers = [us calendarProxyUsersWithWriteAccess: YES];
|
||||
[self adjustProxyRolesForUsers: subscriptionUsers
|
||||
remove: !isProxied
|
||||
forWriteAccess: YES];
|
||||
subscriptionUsers = [us calendarProxyUsersWithWriteAccess: NO];
|
||||
[self adjustProxyRolesForUsers: subscriptionUsers
|
||||
remove: !isProxied
|
||||
forWriteAccess: NO];
|
||||
|
||||
[us synchronize];
|
||||
[proxiedCalendars autorelease];
|
||||
}
|
||||
|
||||
- (BOOL) importComponent: (iCalEntityObject *) event
|
||||
{
|
||||
SOGoAppointmentObject *object;
|
||||
|
@ -3013,49 +2972,78 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
|||
return aclsForUser;
|
||||
}
|
||||
|
||||
- (NSArray *) requiredProxyRolesWithWriteAccess: (BOOL) hasWriteAccess
|
||||
/* caldav-proxy */
|
||||
- (SOGoAppointmentProxyPermission)
|
||||
proxyPermissionForUserWithLogin: (NSString *) login
|
||||
{
|
||||
static NSArray *writeAccessRoles = nil;
|
||||
static NSArray *readAccessRoles = nil;
|
||||
|
||||
if (!writeAccessRoles)
|
||||
SOGoAppointmentProxyPermission permission;
|
||||
NSArray *roles;
|
||||
static NSArray *readRoles = nil;
|
||||
static NSArray *writeRoles = nil;
|
||||
|
||||
if (!readRoles)
|
||||
{
|
||||
writeAccessRoles = [NSArray arrayWithObjects:
|
||||
SOGoCalendarRole_ConfidentialModifier,
|
||||
SOGoRole_ObjectCreator,
|
||||
SOGoRole_ObjectEraser,
|
||||
SOGoCalendarRole_PrivateModifier,
|
||||
SOGoCalendarRole_PublicModifier,
|
||||
nil];
|
||||
[writeAccessRoles retain];
|
||||
readRoles = [NSArray arrayWithObjects:
|
||||
SOGoCalendarRole_ConfidentialViewer,
|
||||
SOGoCalendarRole_ConfidentialDAndTViewer,
|
||||
SOGoCalendarRole_PrivateViewer,
|
||||
SOGoCalendarRole_PrivateDAndTViewer,
|
||||
SOGoCalendarRole_PublicViewer,
|
||||
SOGoCalendarRole_PublicDAndTViewer,
|
||||
nil];
|
||||
[readRoles retain];
|
||||
}
|
||||
|
||||
if (!readAccessRoles)
|
||||
if (!writeRoles)
|
||||
{
|
||||
readAccessRoles = [NSArray arrayWithObjects:
|
||||
SOGoCalendarRole_ConfidentialViewer,
|
||||
SOGoCalendarRole_PrivateViewer,
|
||||
SOGoCalendarRole_PublicViewer,
|
||||
nil];
|
||||
[readAccessRoles retain];
|
||||
writeRoles = [NSArray arrayWithObjects:
|
||||
SOGoRole_ObjectCreator,
|
||||
SOGoRole_ObjectEraser,
|
||||
SOGoCalendarRole_ConfidentialModifier,
|
||||
SOGoCalendarRole_ConfidentialResponder,
|
||||
SOGoCalendarRole_PrivateModifier,
|
||||
SOGoCalendarRole_PrivateResponder,
|
||||
SOGoCalendarRole_PublicModifier,
|
||||
SOGoCalendarRole_PublicResponder,
|
||||
nil];
|
||||
[writeRoles retain];
|
||||
}
|
||||
|
||||
return (hasWriteAccess) ? writeAccessRoles : readAccessRoles;
|
||||
permission = SOGoAppointmentProxyPermissionNone;
|
||||
roles = [self aclsForUser: login];
|
||||
if ([roles count])
|
||||
{
|
||||
if ([roles firstObjectCommonWithArray: readRoles])
|
||||
permission = SOGoAppointmentProxyPermissionRead;
|
||||
if ([roles firstObjectCommonWithArray: writeRoles])
|
||||
permission = SOGoAppointmentProxyPermissionWrite;
|
||||
}
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write
|
||||
- (NSArray *) aclUsersWithProxyWriteAccess: (BOOL) write
|
||||
{
|
||||
NSArray *roles;
|
||||
NSMutableArray *users;
|
||||
NSArray *aclUsers;
|
||||
NSString *aclUser;
|
||||
SOGoAppointmentProxyPermission permission;
|
||||
int count, max;
|
||||
|
||||
if (remove)
|
||||
[self removeAclsForUsers: proxyUsers];
|
||||
else
|
||||
permission = (write
|
||||
? SOGoAppointmentProxyPermissionWrite
|
||||
: SOGoAppointmentProxyPermissionRead);
|
||||
aclUsers = [self aclUsers];
|
||||
max = [aclUsers count];
|
||||
users = [NSMutableArray arrayWithCapacity: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
roles = [self requiredProxyRolesWithWriteAccess: write];
|
||||
[self setRoles: roles forUsers: proxyUsers];
|
||||
aclUser = [aclUsers objectAtIndex: count];
|
||||
if ([self proxyPermissionForUserWithLogin: aclUser]
|
||||
== permission)
|
||||
[users addObject: aclUser];
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
@end /* SOGoAppointmentFolder */
|
||||
|
|
|
@ -31,13 +31,15 @@
|
|||
|
||||
- (NSArray *) webCalendarIds;
|
||||
|
||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write;
|
||||
- (BOOL) hasProxyCalendarsWithWriteAccess: (BOOL) write
|
||||
forUserWithLogin: (NSString *) userLogin;
|
||||
|
||||
- (void) adjustProxySubscriptionsForUsers: (NSArray *) proxyUsers
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write;
|
||||
- (NSArray *) proxySubscribersWithWriteAccess: (BOOL) write;
|
||||
|
||||
- (void) addProxySubscribers: (NSArray *) proxySubscribers
|
||||
withWriteAccess: (BOOL) write;
|
||||
- (void) removeProxySubscribers: (NSArray *) proxySubscribers
|
||||
withWriteAccess: (BOOL) write;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -79,13 +79,14 @@
|
|||
{
|
||||
NSMutableArray *keys;
|
||||
NSEnumerator *sortedSubFolders;
|
||||
SOGoGCSFolder *currentFolder;
|
||||
SOGoAppointmentFolder *currentFolder;
|
||||
SOGoUser *currentUser;
|
||||
NSString *login;
|
||||
SOGoUser *ownerUser;
|
||||
|
||||
if ([[context request] isICal])
|
||||
{
|
||||
login = [[context activeUser] login];
|
||||
currentUser = [context activeUser];
|
||||
login = [currentUser login];
|
||||
keys = [NSMutableArray array];
|
||||
if ([owner isEqualToString: login])
|
||||
{
|
||||
|
@ -100,9 +101,12 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
ownerUser = [SOGoUser userWithLogin: owner];
|
||||
keys = (NSMutableArray *) [[ownerUser userSettings]
|
||||
proxiedCalendars];
|
||||
sortedSubFolders = [[self subFolders] objectEnumerator];
|
||||
while ((currentFolder = [sortedSubFolders nextObject]))
|
||||
if ([currentUser hasSubscribedToCalendar: currentFolder]
|
||||
&& ([currentFolder proxyPermissionForUserWithLogin: login]
|
||||
!= SOGoAppointmentProxyPermissionNone))
|
||||
[keys addObject: [currentFolder nameInContainer]];
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -369,50 +373,157 @@
|
|||
withEquivalent: SoPerm_AddDocumentsImagesAndFiles
|
||||
asChildOf: davElement (@"write", XMLNS_WEBDAV)];
|
||||
}
|
||||
|
||||
return aclManager;
|
||||
}
|
||||
|
||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write
|
||||
- (BOOL) hasProxyCalendarsWithWriteAccess: (BOOL) write
|
||||
forUserWithLogin: (NSString *) userLogin
|
||||
{
|
||||
NSArray *calendars;
|
||||
SOGoUser *ownerUser;
|
||||
SOGoAppointmentFolder *folder;
|
||||
int count, max;
|
||||
NSEnumerator *sortedSubFolders;
|
||||
SOGoAppointmentFolder *currentFolder;
|
||||
SOGoUser *currentUser;
|
||||
SOGoAppointmentProxyPermission permission, curPermission, foundPermission;
|
||||
BOOL rc;
|
||||
|
||||
ownerUser = [SOGoUser userWithLogin: owner];
|
||||
calendars = [[ownerUser userSettings] proxiedCalendars];
|
||||
max = [calendars count];
|
||||
for (count = 0; count < max; count++)
|
||||
if ([owner isEqualToString: userLogin])
|
||||
rc = NO;
|
||||
else
|
||||
{
|
||||
folder = [self lookupName: [calendars objectAtIndex: count]
|
||||
inContext: context
|
||||
acquire: NO];
|
||||
[folder adjustProxyRolesForUsers: proxyUsers
|
||||
remove: remove
|
||||
forWriteAccess: write];
|
||||
foundPermission = SOGoAppointmentProxyPermissionNone;
|
||||
permission = (write
|
||||
? SOGoAppointmentProxyPermissionWrite
|
||||
: SOGoAppointmentProxyPermissionRead);
|
||||
currentUser = [SOGoUser userWithLogin: userLogin];
|
||||
sortedSubFolders = [[self subFolders] objectEnumerator];
|
||||
while ((currentFolder = [sortedSubFolders nextObject]))
|
||||
if ([currentUser hasSubscribedToCalendar: currentFolder])
|
||||
{
|
||||
curPermission = [currentFolder
|
||||
proxyPermissionForUserWithLogin: userLogin];
|
||||
if ((foundPermission == SOGoAppointmentProxyPermissionNone)
|
||||
|| (foundPermission == SOGoAppointmentProxyPermissionRead
|
||||
&& curPermission == SOGoAppointmentProxyPermissionWrite))
|
||||
foundPermission = curPermission;
|
||||
}
|
||||
rc = (foundPermission == permission);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
- (NSArray *) proxySubscribersWithWriteAccess: (BOOL) write
|
||||
{
|
||||
SOGoAppointmentFolder *currentFolder;
|
||||
SOGoUser *currentUser;
|
||||
NSArray *subFolderNames, *aclUsers;
|
||||
NSString *aclUser;
|
||||
NSMutableArray *subscribers;
|
||||
int folderCount, folderMax, userCount, userMax;
|
||||
|
||||
subscribers = [NSMutableArray array];
|
||||
|
||||
subFolderNames = [self subFolders];
|
||||
folderMax = [subFolderNames count];
|
||||
for (folderCount = 0; folderCount < folderMax; folderCount++)
|
||||
{
|
||||
currentFolder = [subFolderNames objectAtIndex: folderCount];
|
||||
aclUsers = [currentFolder aclUsersWithProxyWriteAccess: write];
|
||||
userMax = [aclUsers count];
|
||||
for (userCount = 0; userCount < userMax; userCount++)
|
||||
{
|
||||
aclUser = [aclUsers objectAtIndex: userCount];
|
||||
if (![subscribers containsObject: aclUser])
|
||||
{
|
||||
currentUser = [SOGoUser userWithLogin: aclUser];
|
||||
if ([currentUser hasSubscribedToCalendar: currentFolder])
|
||||
[subscribers addObject: aclUser];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subscribers;
|
||||
}
|
||||
|
||||
- (NSArray *) _requiredProxyRolesWithWriteAccess: (BOOL) hasWriteAccess
|
||||
{
|
||||
static NSArray *writeAccessRoles = nil;
|
||||
static NSArray *readAccessRoles = nil;
|
||||
|
||||
if (!writeAccessRoles)
|
||||
{
|
||||
writeAccessRoles = [NSArray arrayWithObjects:
|
||||
SOGoCalendarRole_ConfidentialModifier,
|
||||
SOGoRole_ObjectCreator,
|
||||
SOGoRole_ObjectEraser,
|
||||
SOGoCalendarRole_PrivateModifier,
|
||||
SOGoCalendarRole_PublicModifier,
|
||||
nil];
|
||||
[writeAccessRoles retain];
|
||||
}
|
||||
|
||||
if (!readAccessRoles)
|
||||
{
|
||||
readAccessRoles = [NSArray arrayWithObjects:
|
||||
SOGoCalendarRole_ConfidentialViewer,
|
||||
SOGoCalendarRole_PrivateViewer,
|
||||
SOGoCalendarRole_PublicViewer,
|
||||
nil];
|
||||
[readAccessRoles retain];
|
||||
}
|
||||
|
||||
return (hasWriteAccess) ? writeAccessRoles : readAccessRoles;
|
||||
}
|
||||
|
||||
- (void) addProxySubscribers: (NSArray *) proxySubscribers
|
||||
withWriteAccess: (BOOL) write
|
||||
{
|
||||
SOGoAppointmentFolder *currentFolder;
|
||||
NSArray *subFolderNames, *proxyRoles;
|
||||
NSMutableArray *subscribers;
|
||||
int folderCount, folderMax, userCount, userMax;
|
||||
|
||||
subscribers = [NSMutableArray array];
|
||||
|
||||
proxyRoles = [self _requiredProxyRolesWithWriteAccess: write];
|
||||
subFolderNames = [self subFolders];
|
||||
folderMax = [subFolderNames count];
|
||||
for (folderCount = 0; folderCount < folderMax; folderCount++)
|
||||
{
|
||||
currentFolder = [subFolderNames objectAtIndex: folderCount];
|
||||
[currentFolder setRoles: proxyRoles
|
||||
forUsers: proxySubscribers];
|
||||
|
||||
userMax = [proxySubscribers count];
|
||||
for (userCount = 0; userCount < userMax; userCount++)
|
||||
[currentFolder
|
||||
subscribeUser: [proxySubscribers objectAtIndex: userCount]
|
||||
reallyDo: YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) adjustProxySubscriptionsForUsers: (NSArray *) proxyUsers
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write
|
||||
- (void) removeProxySubscribers: (NSArray *) proxySubscribers
|
||||
withWriteAccess: (BOOL) write
|
||||
{
|
||||
int count, max;
|
||||
SOGoUser *proxyUser;
|
||||
SOGoAppointmentFolder *currentFolder;
|
||||
NSArray *subFolderNames;
|
||||
NSMutableArray *subscribers;
|
||||
int folderCount, folderMax, userCount, userMax;
|
||||
|
||||
max = [proxyUsers count];
|
||||
for (count = 0; count < max; count++)
|
||||
subscribers = [NSMutableArray array];
|
||||
|
||||
subFolderNames = [self subFolders];
|
||||
folderMax = [subFolderNames count];
|
||||
for (folderCount = 0; folderCount < folderMax; folderCount++)
|
||||
{
|
||||
proxyUser = [SOGoUser userWithLogin: [proxyUsers objectAtIndex: count]];
|
||||
if (proxyUser)
|
||||
[proxyUser adjustProxySubscriptionToUser: owner
|
||||
remove: remove
|
||||
forWriteAccess: write];
|
||||
else
|
||||
[self warnWithFormat: @"(%@) user '%@' is invalid (ignored)",
|
||||
NSStringFromSelector (_cmd), [proxyUser login]];
|
||||
currentFolder = [subFolderNames objectAtIndex: folderCount];
|
||||
[currentFolder removeAclsForUsers: proxySubscribers];
|
||||
|
||||
userMax = [proxySubscribers count];
|
||||
for (userCount = 0; userCount < userMax; userCount++)
|
||||
[currentFolder
|
||||
subscribeUser: [proxySubscribers objectAtIndex: userCount]
|
||||
reallyDo: NO];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,21 +71,20 @@
|
|||
- (NSArray *) davGroupMemberSet
|
||||
{
|
||||
NSMutableArray *members;
|
||||
NSArray *proxyUsers, *member;
|
||||
SOGoUser *ownerUser;
|
||||
NSArray *proxySubscribers, *member;
|
||||
NSString *appName, *proxyUser;
|
||||
int count, max;
|
||||
|
||||
appName = [[context request] applicationName];
|
||||
|
||||
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]];
|
||||
proxyUsers = [[ownerUser userSettings]
|
||||
calendarProxyUsersWithWriteAccess: hasWriteAccess];
|
||||
max = [proxyUsers count];
|
||||
proxySubscribers
|
||||
= [[container lookupName: @"Calendar" inContext: context acquire: NO]
|
||||
proxySubscribersWithWriteAccess: hasWriteAccess];
|
||||
max = [proxySubscribers count];
|
||||
members = [NSMutableArray arrayWithCapacity: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
proxyUser = [proxyUsers objectAtIndex: count];
|
||||
proxyUser = [proxySubscribers objectAtIndex: count];
|
||||
member = [NSArray arrayWithObjects: @"href", XMLNS_WEBDAV, @"D",
|
||||
[NSString stringWithFormat: @"/%@/dav/%@/",
|
||||
appName, proxyUser],
|
||||
|
@ -141,46 +140,35 @@
|
|||
{
|
||||
SOGoUser *ownerUser;
|
||||
SOGoUserSettings *us;
|
||||
NSMutableArray *addedUsers, *removedUsers;
|
||||
NSArray *oldProxyUsers, *newProxyUsers;
|
||||
NSMutableArray *addedSubscribers, *removedSubscribers;
|
||||
NSArray *oldProxySubscribers, *newProxySubscribers;
|
||||
NSString *login;
|
||||
SOGoAppointmentFolders *folders;
|
||||
|
||||
login = [self ownerInContext: context];
|
||||
ownerUser = [SOGoUser userWithLogin: login roles: nil];
|
||||
us = [ownerUser userSettings];
|
||||
oldProxyUsers = [us calendarProxyUsersWithWriteAccess: hasWriteAccess];
|
||||
if (!oldProxyUsers)
|
||||
oldProxyUsers = [NSMutableArray array];
|
||||
newProxyUsers = [self _parseSubscribers: memberSet];
|
||||
if (!newProxyUsers)
|
||||
newProxyUsers = [NSMutableArray array];
|
||||
[us setCalendarProxyUsers: newProxyUsers
|
||||
withWriteAccess: hasWriteAccess];
|
||||
folders = [container lookupName: @"Calendar"
|
||||
inContext: context acquire: NO];
|
||||
oldProxySubscribers
|
||||
= [folders proxySubscribersWithWriteAccess: hasWriteAccess];
|
||||
if (!oldProxySubscribers)
|
||||
oldProxySubscribers = [NSMutableArray array];
|
||||
newProxySubscribers = [self _parseSubscribers: memberSet];
|
||||
if (!newProxySubscribers)
|
||||
newProxySubscribers = [NSMutableArray array];
|
||||
|
||||
folders = [container lookupName: @"Calendar" inContext: context
|
||||
acquire: NO];
|
||||
addedUsers = [newProxyUsers mutableCopy];
|
||||
[addedUsers removeObjectsInArray: oldProxyUsers];
|
||||
[folders adjustProxyRolesForUsers: addedUsers
|
||||
remove: NO
|
||||
forWriteAccess: hasWriteAccess];
|
||||
[folders adjustProxySubscriptionsForUsers: addedUsers
|
||||
remove: NO
|
||||
forWriteAccess: hasWriteAccess];
|
||||
[addedUsers autorelease];
|
||||
addedSubscribers = [newProxySubscribers mutableCopy];
|
||||
[addedSubscribers removeObjectsInArray: oldProxySubscribers];
|
||||
[addedSubscribers autorelease];
|
||||
[folders addProxySubscribers: addedSubscribers
|
||||
withWriteAccess: hasWriteAccess];
|
||||
|
||||
removedUsers = [oldProxyUsers mutableCopy];
|
||||
[removedUsers removeObjectsInArray: newProxyUsers];
|
||||
[folders adjustProxyRolesForUsers: removedUsers
|
||||
remove: YES
|
||||
forWriteAccess: hasWriteAccess];
|
||||
[folders adjustProxySubscriptionsForUsers: removedUsers
|
||||
remove: YES
|
||||
forWriteAccess: hasWriteAccess];
|
||||
[removedUsers autorelease];
|
||||
|
||||
[us synchronize];
|
||||
removedSubscribers = [oldProxySubscribers mutableCopy];
|
||||
[removedSubscribers removeObjectsInArray: newProxySubscribers];
|
||||
[removedSubscribers autorelease];
|
||||
[folders removeProxySubscribers: removedSubscribers
|
||||
withWriteAccess: hasWriteAccess];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
||||
@class SOGoAppointmentFolder;
|
||||
|
||||
@interface SOGoUser (SOGoCalDAVSupport)
|
||||
|
||||
- (void) adjustProxySubscriptionToUser: (NSString *) ownerUser
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write;
|
||||
- (BOOL) hasSubscribedToCalendar: (SOGoAppointmentFolder *) calendar;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -23,52 +23,22 @@
|
|||
#import <SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/SOGoUserSettings.h>
|
||||
|
||||
#import "SOGoAppointmentFolder.h"
|
||||
|
||||
#import "SOGoUser+Appointments.h"
|
||||
|
||||
@implementation SOGoUser (SOGoCalDAVSupport)
|
||||
|
||||
- (void) adjustProxySubscriptionToUser: (NSString *) ownerUser
|
||||
remove: (BOOL) remove
|
||||
forWriteAccess: (BOOL) write
|
||||
#warning duplicate of [SOGoGCSFolder userIsSubscriber:]
|
||||
- (BOOL) hasSubscribedToCalendar: (SOGoAppointmentFolder *) calendar
|
||||
{
|
||||
SOGoUserSettings *us;
|
||||
NSMutableArray *subscriptions;
|
||||
NSArray *subscriptions;
|
||||
NSString *reference;
|
||||
|
||||
us = [self userSettings];
|
||||
subscriptions = [[self userSettings] subscribedCalendars];
|
||||
reference = [calendar folderReference];
|
||||
|
||||
/* first, we want to ensure the subscription does not appear in the
|
||||
opposite list... */
|
||||
if (!remove)
|
||||
{
|
||||
subscriptions
|
||||
= [[us calendarProxySubscriptionUsersWithWriteAccess: !write]
|
||||
mutableCopy];
|
||||
[subscriptions autorelease];
|
||||
if ([subscriptions containsObject: ownerUser])
|
||||
{
|
||||
[subscriptions removeObject: ownerUser];
|
||||
[us setCalendarProxySubscriptionUsers: subscriptions
|
||||
withWriteAccess: !write];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
subscriptions
|
||||
= [[us calendarProxySubscriptionUsersWithWriteAccess: write]
|
||||
mutableCopy];
|
||||
[subscriptions autorelease];
|
||||
if (remove)
|
||||
[subscriptions removeObject: ownerUser];
|
||||
else
|
||||
{
|
||||
if (!subscriptions)
|
||||
subscriptions = [NSMutableArray array];
|
||||
[subscriptions addObjectUniquely: ownerUser];
|
||||
}
|
||||
|
||||
[us setCalendarProxySubscriptionUsers: subscriptions
|
||||
withWriteAccess: write];
|
||||
[us synchronize];
|
||||
return [subscriptions containsObject: reference];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
|
@ -137,25 +138,42 @@
|
|||
|
||||
- (NSArray *) _calendarProxiedUsersWithWriteAccess: (BOOL) write
|
||||
{
|
||||
NSMutableArray *proxiedUsers;
|
||||
SOGoUser *ownerUser;
|
||||
NSArray *subscriptions;
|
||||
NSString *ownerLogin, *currentLogin;
|
||||
NSMutableDictionary *proxiedUsers;
|
||||
NSArray *references, *elements;
|
||||
NSString *currentLogin;
|
||||
NSNumber *yesNumber;
|
||||
SOGoAppointmentFolders *parentFolder;
|
||||
SOGoUserSettings *us;
|
||||
int count, max;
|
||||
|
||||
ownerLogin = [self ownerInContext: nil];
|
||||
ownerUser = [SOGoUser userWithLogin: ownerLogin];
|
||||
subscriptions = [[ownerUser userSettings]
|
||||
calendarProxySubscriptionUsersWithWriteAccess: write];
|
||||
max = [subscriptions count];
|
||||
proxiedUsers = [NSMutableArray arrayWithCapacity: max];
|
||||
yesNumber = [NSNumber numberWithBool: YES];
|
||||
|
||||
us = [[SOGoUser userWithLogin: owner] userSettings];
|
||||
references = [us subscribedCalendars];
|
||||
max = [references count];
|
||||
proxiedUsers = [NSMutableDictionary dictionaryWithCapacity: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentLogin = [subscriptions objectAtIndex: count];
|
||||
[proxiedUsers addObject: currentLogin];
|
||||
elements = [[references objectAtIndex: count]
|
||||
componentsSeparatedByString: @":"];
|
||||
if ([elements count])
|
||||
{
|
||||
currentLogin = [elements objectAtIndex: 0];
|
||||
if (![proxiedUsers objectForKey: currentLogin])
|
||||
{
|
||||
parentFolder = [[container lookupName: currentLogin
|
||||
inContext: context
|
||||
acquire: NO]
|
||||
lookupName: @"Calendar"
|
||||
inContext: context acquire: NO];
|
||||
if ([parentFolder hasProxyCalendarsWithWriteAccess: write
|
||||
forUserWithLogin: owner])
|
||||
[proxiedUsers setObject: yesNumber forKey: currentLogin];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return proxiedUsers;
|
||||
return [proxiedUsers allKeys];
|
||||
}
|
||||
|
||||
- (void) _addGroupMembershipToArray: (NSMutableArray *) groups
|
||||
|
|
|
@ -336,7 +336,7 @@ static SoSecurityManager *sm = nil;
|
|||
return error;
|
||||
}
|
||||
|
||||
- (NSException *) initSubFolders;
|
||||
- (NSException *) initSubFolders
|
||||
{
|
||||
NSException *error;
|
||||
|
||||
|
@ -435,10 +435,10 @@ static SoSecurityManager *sm = nil;
|
|||
error = [self initSubFolders];
|
||||
if (error && isPropfind)
|
||||
{
|
||||
/* We exceptionnally raise the exception here because doPROPFIND:
|
||||
will not care for errors in its response from
|
||||
toManyRelationShipKeys, which may in turn trigger the
|
||||
disappearance of user folders in the SOGo extensions. */
|
||||
/* We exceptionnally raise the exception here because doPROPFIND: will
|
||||
not care for errors in its response from toManyRelationShipKeys,
|
||||
which may in turn trigger the disappearance of user folders in the
|
||||
SOGo extensions. */
|
||||
[error raise];
|
||||
}
|
||||
|
||||
|
|
|
@ -32,19 +32,8 @@
|
|||
|
||||
+ (SOGoUserSettings *) settingsForUser: (NSString *) userId;
|
||||
|
||||
/* the calendars that we publish to our proxy subscribers */
|
||||
- (void) setProxiedCalendars: (NSArray *) proxiedCalendars;
|
||||
- (NSArray *) proxiedCalendars;
|
||||
|
||||
/* the users that we have subscribed us as a proxy to our calendars */
|
||||
- (void) setCalendarProxyUsers: (NSArray *) proxyUsers
|
||||
withWriteAccess: (BOOL) writeAccess;
|
||||
- (NSArray *) calendarProxyUsersWithWriteAccess: (BOOL) writeAccess;
|
||||
|
||||
/* the users that have subscribed us as a proxy to their calendars */
|
||||
- (void) setCalendarProxySubscriptionUsers: (NSArray *) subscriptionUsers
|
||||
withWriteAccess: (BOOL) writeAccess;
|
||||
- (NSArray *) calendarProxySubscriptionUsersWithWriteAccess: (BOOL) writeAccess;
|
||||
- (NSArray *) subscribedCalendars;
|
||||
- (NSArray *) subscribedAddressBooks;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -55,65 +55,19 @@ static Class SOGoUserProfileKlass = Nil;
|
|||
return ud;
|
||||
}
|
||||
|
||||
/* the calendars that we publish to our proxy subscribers */
|
||||
- (void) setProxiedCalendars: (NSArray *) proxiedCalendars
|
||||
- (NSArray *) _subscribedFoldersForModule: (NSString *) module
|
||||
{
|
||||
[self setObject: proxiedCalendars forKey: @"ProxiedCalendars"];
|
||||
return [[self dictionaryForKey: module] objectForKey: @"SubscribedFolders"];
|
||||
}
|
||||
|
||||
- (NSArray *) proxiedCalendars
|
||||
- (NSArray *) subscribedCalendars
|
||||
{
|
||||
NSArray *proxiedCalendars;
|
||||
|
||||
proxiedCalendars = [self arrayForKey: @"ProxiedCalendars"];
|
||||
if (!proxiedCalendars)
|
||||
proxiedCalendars = [NSArray arrayWithObject: @"personal"];
|
||||
|
||||
return proxiedCalendars;
|
||||
return [self _subscribedFoldersForModule: @"Calendar"];
|
||||
}
|
||||
|
||||
/* the users that we have subscribed us as a proxy to our calendars */
|
||||
- (void) setCalendarProxyUsers: (NSArray *) proxyUsers
|
||||
withWriteAccess: (BOOL) writeAccess
|
||||
- (NSArray *) subscribedAddressBooks
|
||||
{
|
||||
NSString *key;
|
||||
|
||||
key = [NSString stringWithFormat: @"CalendarProxy%@Users",
|
||||
(writeAccess ? @"Write" : @"Read")];
|
||||
|
||||
[self setObject: proxyUsers forKey: key];
|
||||
}
|
||||
|
||||
- (NSArray *) calendarProxyUsersWithWriteAccess: (BOOL) writeAccess
|
||||
{
|
||||
NSString *key;
|
||||
|
||||
key = [NSString stringWithFormat: @"CalendarProxy%@Users",
|
||||
(writeAccess ? @"Write" : @"Read")];
|
||||
|
||||
return [self arrayForKey: key];
|
||||
}
|
||||
|
||||
/* the users that have subscribed us as a proxy to their calendars */
|
||||
- (void) setCalendarProxySubscriptionUsers: (NSArray *) subscriptionUsers
|
||||
withWriteAccess: (BOOL) writeAccess
|
||||
{
|
||||
NSString *key;
|
||||
|
||||
key = [NSString stringWithFormat: @"CalendarProxy%@SubscriptionUsers",
|
||||
(writeAccess ? @"Write" : @"Read")];
|
||||
|
||||
[self setObject: subscriptionUsers forKey: key];
|
||||
}
|
||||
|
||||
- (NSArray *) calendarProxySubscriptionUsersWithWriteAccess: (BOOL) writeAccess
|
||||
{
|
||||
NSString *key;
|
||||
|
||||
key = [NSString stringWithFormat: @"CalendarProxy%@SubscriptionUsers",
|
||||
(writeAccess ? @"Write" : @"Read")];
|
||||
|
||||
return [self arrayForKey: key];
|
||||
return [self _subscribedFoldersForModule: @"Contacts"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
from config import hostname, port, username, password, subscriber_username
|
||||
|
||||
import unittest
|
||||
import utilities
|
||||
import webdavlib
|
||||
|
||||
class iCalTest(unittest.TestCase):
|
||||
|
@ -121,5 +122,85 @@ class iCalTest(unittest.TestCase):
|
|||
"'%s' expected to be %s proxy for %s: %s"
|
||||
% (users[1], perm, users[0], proxyFor))
|
||||
|
||||
def _testMapping(self, client, perm, resource, rights):
|
||||
dav_utility = utilities.TestCalendarACLUtility(client, resource)
|
||||
dav_utility.setupRights(subscriber_username, rights)
|
||||
|
||||
membership = self._getMembership(subscriber_username)
|
||||
self.assertEquals(['/SOGo/dav/%s/calendar-proxy-%s/'
|
||||
% (username, perm)],
|
||||
membership,
|
||||
"'%s' must have %s access to %s's calendars:\n%s"
|
||||
% (subscriber_username, perm, username, membership))
|
||||
proxyFor = self._getProxyFor(subscriber_username, perm)
|
||||
self.assertEquals([username], proxyFor,
|
||||
"'%s' expected to be %s proxy for %s: %s"
|
||||
% (subscriber_username, perm, username, proxyFor))
|
||||
|
||||
def testCalendarProxy2(self):
|
||||
"""calendar-proxy as used from SOGo"""
|
||||
client = webdavlib.WebDAVClient(hostname, port, username, password)
|
||||
client.user_agent = "DAVKit/4.0.1 (730); CalendarStore/4.0.1 (973); iCal/4.0.1 (1374); Mac OS X/10.6.2 (10C540)"
|
||||
personal_resource = "/SOGo/dav/%s/Calendar/personal/" % username
|
||||
dav_utility = utilities.TestCalendarACLUtility(client,
|
||||
personal_resource)
|
||||
dav_utility.setupRights(subscriber_username, {})
|
||||
dav_utility.subscribe([subscriber_username])
|
||||
|
||||
other_resource = ("/SOGo/dav/%s/Calendar/test-calendar-proxy2/"
|
||||
% username)
|
||||
delete = webdavlib.WebDAVDELETE(other_resource)
|
||||
client.execute(delete)
|
||||
mkcol = webdavlib.WebDAVMKCOL(other_resource)
|
||||
client.execute(mkcol)
|
||||
dav_utility = utilities.TestCalendarACLUtility(client,
|
||||
other_resource)
|
||||
dav_utility.setupRights(subscriber_username, {})
|
||||
dav_utility.subscribe([subscriber_username])
|
||||
|
||||
## we test the rights mapping
|
||||
# write: write on 'personal', none on 'test-calendar-proxy2'
|
||||
self._testMapping(client, "write", personal_resource,
|
||||
{ "c": True, "d": False, "pu": "v" })
|
||||
self._testMapping(client, "write", personal_resource,
|
||||
{ "c": False, "d": True, "pu": "v" })
|
||||
self._testMapping(client, "write", personal_resource,
|
||||
{ "c": False, "d": False, "pu": "m" })
|
||||
self._testMapping(client, "write", personal_resource,
|
||||
{ "c": False, "d": False, "pu": "r" })
|
||||
|
||||
# read: read on 'personal', none on 'test-calendar-proxy2'
|
||||
self._testMapping(client, "read", personal_resource,
|
||||
{ "c": False, "d": False, "pu": "d" })
|
||||
self._testMapping(client, "read", personal_resource,
|
||||
{ "c": False, "d": False, "pu": "v" })
|
||||
|
||||
# write: read on 'personal', write on 'test-calendar-proxy2'
|
||||
self._testMapping(client, "write", other_resource,
|
||||
{ "c": False, "d": False, "pu": "r" })
|
||||
|
||||
## we test the unsubscription
|
||||
# unsubscribed from personal, subscribed to 'test-calendar-proxy2'
|
||||
dav_utility = utilities.TestCalendarACLUtility(client,
|
||||
personal_resource)
|
||||
dav_utility.unsubscribe([subscriber_username])
|
||||
membership = self._getMembership(subscriber_username)
|
||||
self.assertEquals(['/SOGo/dav/%s/calendar-proxy-write/' % username],
|
||||
membership,
|
||||
"'%s' must have write access to %s's calendars"
|
||||
% (subscriber_username, username))
|
||||
# unsubscribed from personal, unsubscribed from 'test-calendar-proxy2'
|
||||
dav_utility = utilities.TestCalendarACLUtility(client,
|
||||
other_resource)
|
||||
dav_utility.unsubscribe([subscriber_username])
|
||||
membership = self._getMembership(subscriber_username)
|
||||
self.assertEquals([],
|
||||
membership,
|
||||
"'%s' must have no access to %s's calendars"
|
||||
% (subscriber_username, username))
|
||||
|
||||
delete = webdavlib.WebDAVDELETE(other_resource)
|
||||
client.execute(delete)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -49,7 +49,7 @@ class WebdavSyncTest(unittest.TestCase):
|
|||
token = int(token_node.childNodes[0].nodeValue)
|
||||
|
||||
self.assertTrue(token > 0)
|
||||
self.assertTrue(token < int(query1.start))
|
||||
self.assertTrue(token <= int(query1.start))
|
||||
|
||||
# we make sure that any token is invalid when the collection is empty
|
||||
query2 = webdavlib.WebDAVSyncQuery(resource, "1234", [ "getetag" ])
|
||||
|
|
|
@ -33,28 +33,34 @@ class TestACLUtility(TestUtility):
|
|||
TestUtility.__init__(self, client)
|
||||
self.resource = resource
|
||||
|
||||
def subscribe(self, subscribers=None):
|
||||
rights_str = "".join(["<%s/>" % x
|
||||
for x in self.rightsToSOGoRights(rights) ])
|
||||
def _subscriptionOperation(self, subscribers, operation):
|
||||
subscribeQuery = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<subscribe"
|
||||
+ "<%s" % operation
|
||||
+ " xmlns=\"urn:inverse:params:xml:ns:inverse-dav\"")
|
||||
if (subscribers is not None):
|
||||
subscribeQuery = (subscribeQuery
|
||||
+ " users=\"%s\"" % subscribers.join(","))
|
||||
+ " users=\"%s\"" % ",".join(subscribers))
|
||||
subscribeQuery = subscribeQuery + "/>"
|
||||
post = webdavlib.HTTPPOST(self.resource, subscribeQuery)
|
||||
post.content_type = "application/xml; charset=\"utf-8\""
|
||||
self.client.execute(post)
|
||||
self.assertEquals(post.response["status"], 204,
|
||||
"subscribtion failure to set '%s' (status: %d)"
|
||||
% (rights_str, post.response["status"]))
|
||||
"subscribtion failure to '%s' for '%s' (status: %d)"
|
||||
% (self.resource, "', '".join(subscribers),
|
||||
post.response["status"]))
|
||||
|
||||
def subscribe(self, subscribers=None):
|
||||
self._subscriptionOperation(subscribers, "subscribe")
|
||||
|
||||
def unsubscribe(self, subscribers=None):
|
||||
self._subscriptionOperation(subscribers, "unsubscribe")
|
||||
|
||||
def rightsToSOGoRights(self, rights):
|
||||
self.fail("subclass must implement this method")
|
||||
|
||||
def setupRights(self, username, rights):
|
||||
rights_str = "".join(["<%s/>" % x for x in self.rightsToSOGoRights(rights) ])
|
||||
rights_str = "".join(["<%s/>"
|
||||
% x for x in self.rightsToSOGoRights(rights) ])
|
||||
aclQuery = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<acl-query"
|
||||
+ " xmlns=\"urn:inverse:params:xml:ns:inverse-dav\">"
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Divulgar a informação Livre/Ocupado";
|
||||
|
||||
"Default Roles" = "Papéis Padrão";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Desculpe, os direitos de usuário não podem ser modificados para este objeto.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Zveřejni informace o Volný/Zaneprázdněný";
|
||||
|
||||
"Default Roles" = "Výchozí role";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Omlouváme se, ale uživatelská práva pro tento objekt nemohou být nastaveny.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Beschikbaarheidsinformatie publiceren";
|
||||
|
||||
"Default Roles" = "Standaardmachtigingen";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "De machtigingen kunnen niet worden ingesteld voor dit object.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Publish the Free/Busy information";
|
||||
|
||||
"Default Roles" = "Default Roles";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Sorry, the user rights can not be configured for that object.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Publier l'occupation du temps";
|
||||
|
||||
"Default Roles" = "Rôles par défaut";
|
||||
"Subscribe User" = "Abonner l'utilisateur";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Sorry, the user rights can not be configured for that object.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Verfügbarkeitsinformationen veröffentlichen";
|
||||
|
||||
"Default Roles" = "Standardrechte";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Leider können die Benutzerrechte für dieses Objekt nicht konfiguriert werden.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Foglaltsági információ nyilvánossá tétele";
|
||||
|
||||
"Default Roles" = "Alapértelmezett jogok";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Sajnálom, erre az objektumra nem állíthatók be felhasználói jogosultságok.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Pubblica le informazioni sullo stato (libero/impegnato)";
|
||||
|
||||
"Default Roles" = "Permessi predefiniti";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Non è possibile configurare i permessi per questo oggetto.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Публиковать информацию о занятом/свободном времени";
|
||||
|
||||
"Default Roles" = "Контроль доступа для всех";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Извините, для данного объекта невозможно настроить права доступа.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Publicar información de disponibilidad";
|
||||
|
||||
"Default Roles" = "Roles por defecto";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Sorry, the user rights can not be configured for that object.";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Publisera ledig/upptagen information";
|
||||
|
||||
"Default Roles" = "Standardroller";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Tyvärr, användarrättigheterna kan inte konfigureras för objektet.";
|
||||
|
||||
|
|
|
@ -29,11 +29,12 @@
|
|||
#import <NGObjWeb/WORequest.h>
|
||||
#import <NGObjWeb/SoSecurityManager.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <SoObjects/SOGo/SOGoUserManager.h>
|
||||
#import <SoObjects/SOGo/SOGoContentObject.h>
|
||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
#import <SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/SOGoContentObject.h>
|
||||
#import <SOGo/SOGoGCSFolder.h>
|
||||
#import <SOGo/SOGoPermissions.h>
|
||||
#import <SOGo/SOGoUserManager.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
||||
#import "UIxAclEditor.h"
|
||||
|
||||
|
@ -158,6 +159,16 @@
|
|||
return [self _displayNameForUID: currentUser];
|
||||
}
|
||||
|
||||
- (BOOL) currentUserIsSubscribed
|
||||
{
|
||||
SOGoGCSFolder *folder;
|
||||
|
||||
folder = [self clientObject];
|
||||
|
||||
return ([folder respondsToSelector: @selector (userIsSubscriber:)]
|
||||
&& [folder userIsSubscriber: currentUser]);
|
||||
}
|
||||
|
||||
- (void) setUserUIDS: (NSString *) retainedUsers
|
||||
{
|
||||
if ([retainedUsers length] > 0)
|
||||
|
@ -169,6 +180,11 @@
|
|||
savedUIDs = [NSArray new];
|
||||
}
|
||||
|
||||
- (NSString *) folderID
|
||||
{
|
||||
return [[self clientObject] nameInContainer];
|
||||
}
|
||||
|
||||
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
|
|
|
@ -313,23 +313,21 @@
|
|||
NSException *ex;
|
||||
|
||||
request = [context request];
|
||||
ex = nil;
|
||||
|
||||
if ((destinationFolderId = [request formValueForKey: @"folder"]) &&
|
||||
(contactsId = [request formValuesForKey: @"uid"]))
|
||||
{
|
||||
ex = [self _moveContacts: contactsId
|
||||
toFolder: destinationFolderId
|
||||
ex = [self _moveContacts: contactsId
|
||||
toFolder: destinationFolderId
|
||||
andKeepCopy: YES];
|
||||
if (ex != nil)
|
||||
response = (id)ex;
|
||||
}
|
||||
else
|
||||
response = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: @"missing 'folder' and/or 'uid' parameter"];
|
||||
ex = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: (@"missing 'folder' and/or"
|
||||
@" 'uid' parameter")];
|
||||
|
||||
if (ex == nil)
|
||||
response = [self responseWith204];
|
||||
if (ex)
|
||||
response = (id) ex;
|
||||
else
|
||||
response = [self responseWith204];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -343,25 +341,55 @@
|
|||
NSException *ex;
|
||||
|
||||
request = [context request];
|
||||
ex = nil;
|
||||
|
||||
if ((destinationFolderId = [request formValueForKey: @"folder"]) &&
|
||||
(contactsId = [request formValuesForKey: @"uid"]))
|
||||
{
|
||||
ex = [self _moveContacts: contactsId
|
||||
toFolder: destinationFolderId
|
||||
if ((destinationFolderId = [request formValueForKey: @"folder"])
|
||||
&& (contactsId = [request formValuesForKey: @"uid"]))
|
||||
ex = [self _moveContacts: contactsId
|
||||
toFolder: destinationFolderId
|
||||
andKeepCopy: NO];
|
||||
if (ex != nil)
|
||||
response = (id)ex;
|
||||
else
|
||||
ex = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: (@"missing 'folder' and/or"
|
||||
@"'uid' parameter")];
|
||||
|
||||
if (ex)
|
||||
response = (id <WOActionResults>) ex;
|
||||
else
|
||||
response = [self responseWith204];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) subscribeUsersAction
|
||||
{
|
||||
id <WOActionResults> response;
|
||||
NSString *uids;
|
||||
NSArray *userIDs;
|
||||
SOGoGCSFolder *folder;
|
||||
NSException *ex;
|
||||
int count, max;
|
||||
|
||||
uids = [[context request] formValueForKey: @"uids"];
|
||||
if ([uids length])
|
||||
{
|
||||
userIDs = [uids componentsSeparatedByString: @","];
|
||||
folder = [self clientObject];
|
||||
max = [userIDs count];
|
||||
for (count = 0; count < max; count++)
|
||||
[folder subscribeUser: [userIDs objectAtIndex: count]
|
||||
reallyDo: YES];
|
||||
ex = nil;
|
||||
}
|
||||
else
|
||||
response = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: @"missing 'folder' and/or 'uid' parameter"];
|
||||
ex = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: @"missing 'uids' parameter"];
|
||||
|
||||
if (ex == nil)
|
||||
response = [self responseWith204];
|
||||
|
||||
return response;
|
||||
if (ex)
|
||||
response = (id <WOActionResults>) ex;
|
||||
else
|
||||
response = [self responseWith204];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"Publish the Free/Busy information" = "Cyhoddwch y wybodaeth Rhydd/Brysur";
|
||||
|
||||
"Default Roles" = "Rolau Gwreiddiol";
|
||||
"Subscribe User" = "Subscribe User";
|
||||
|
||||
"Sorry, the user rights can not be configured for that object." = "Sori, ni all hawliau'r defnyddiwr cael ei newid ar gyfer y gwrthrych hwn.";
|
||||
|
||||
|
|
|
@ -101,6 +101,11 @@
|
|||
actionClass = "UIxFolderActions";
|
||||
actionName = "deactivateFolder";
|
||||
};
|
||||
subscribeUsers = {
|
||||
protectedBy = "Change Permissions";
|
||||
actionClass = "UIxFolderActions";
|
||||
actionName = "subscribeUsers";
|
||||
};
|
||||
renameFolder = {
|
||||
protectedBy = "Change Permissions";
|
||||
actionClass = "UIxFolderActions";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tarefa Confidencial)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Marca:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Důvěrný úkol)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Štítek:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Vertrouwelijke taak)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Markering:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Confidential task)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Tag:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tâche confidentielle)";
|
|||
"Synchronize" = "Synchroniser";
|
||||
"Tag:" = "Label :";
|
||||
|
||||
"iCal Delegation" = "Délégation iCal";
|
||||
"Shared when account is delegated" = "Inclure cet agenda lors de la délégation";
|
||||
|
||||
"Display" = "Affichage";
|
||||
"Show alarms" = "Afficher les alarmes";
|
||||
"Show tasks" = "Afficher les tâches";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Tag:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Bizalmas feladat)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Cimke:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Attività confidenziale)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Etichetta:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Confidential task)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Tag:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tarea confidencial)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Redacción:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Konfidentiell uppgift)";
|
|||
"Synchronize" = "Synkronisera";
|
||||
"Tag:" = "Etikett:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Visa";
|
||||
"Show alarms" = "Visa alarm";
|
||||
"Show tasks" = "Visa uppgifter";
|
||||
|
|
|
@ -51,7 +51,4 @@
|
|||
- (NSString *) calendarSyncTag;
|
||||
- (void) setCalendarSyncTag: (NSString *) newTag;
|
||||
|
||||
- (BOOL) isProxied;
|
||||
- (void) setIsProxied: (BOOL) isProxied;
|
||||
|
||||
@end
|
||||
|
|
|
@ -149,17 +149,6 @@
|
|||
[calendar setSyncTag: newTag];
|
||||
}
|
||||
|
||||
/* DAV: calendar-proxy protocol */
|
||||
- (BOOL) isProxied
|
||||
{
|
||||
return [calendar isProxied];
|
||||
}
|
||||
|
||||
- (void) setIsProxied: (BOOL) isProxied
|
||||
{
|
||||
[calendar setIsProxied: isProxied];
|
||||
}
|
||||
|
||||
- (BOOL) showCalendarAlarms
|
||||
{
|
||||
return [calendar showCalendarAlarms];
|
||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tasg gyhoeddus)";
|
|||
"Synchronize" = "Synchronize";
|
||||
"Tag:" = "Tag:";
|
||||
|
||||
"iCal Delegation" = "iCal Delegation";
|
||||
"Shared when account is delegated" = "Shared when account is delegated";
|
||||
|
||||
"Display" = "Display";
|
||||
"Show alarms" = "Show alarms";
|
||||
"Show tasks" = "Show tasks";
|
||||
|
|
|
@ -70,16 +70,6 @@
|
|||
/></div></var:if>
|
||||
</fieldset>
|
||||
|
||||
<var:if condition="isWebCalendar" const:negate="YES"
|
||||
><fieldset>
|
||||
<legend><var:string label:value="iCal Delegation"/></legend>
|
||||
<div><label
|
||||
><input type="checkbox" const:class="checkBox" id="isProxied"
|
||||
var:checked="isProxied"
|
||||
/><var:string label:value="Shared when account is delegated"
|
||||
/></label></div>
|
||||
</fieldset></var:if>
|
||||
|
||||
<fieldset>
|
||||
<legend><var:string label:value="Display"/></legend>
|
||||
<div><label
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
<input type="hidden" name="defaultUserID" id="defaultUserID"
|
||||
var:value="defaultUserID"/>
|
||||
<input type="hidden" name="action" value="saveAcls"/>
|
||||
<input type="hidden" id="userUIDS" name="userUIDS"
|
||||
var:value="userUIDS"/>
|
||||
<input type="hidden" name="folderID" id="folderID" var:value="folderID"/>
|
||||
<var:if condition="hasOwner">
|
||||
<label><var:string label:value="Owner:"/>
|
||||
<span class="value"><strong><var:string value="ownerName"/></strong></span></label>
|
||||
|
@ -38,9 +37,14 @@
|
|||
<ul id="userList" multiselect="yes">
|
||||
<var:foreach list="usersForObject" item="currentUser"
|
||||
><li var:id="currentUser">
|
||||
<img rsrc:src="abcard.gif"/>
|
||||
<var:string value="currentUserDisplayName"/></li>
|
||||
</var:foreach>
|
||||
<span class="userFullName"><img rsrc:src="abcard.gif"/>
|
||||
<var:string value="currentUserDisplayName"
|
||||
/></span
|
||||
><label class="subscriptionArea"><input type="checkbox"
|
||||
var:checked="currentUserIsSubscribed"
|
||||
var:disabled="currentUserIsSubscribed"
|
||||
/><var:string label:value="Subscribe User"/></label
|
||||
></li></var:foreach>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1891,17 +1891,20 @@ function onCalendarModify(event) {
|
|||
var url = ApplicationBaseURL + calendarID + "/properties";
|
||||
var windowID = sanitizeWindowName(calendarID + " properties");
|
||||
var width = 310;
|
||||
var height = 310;
|
||||
var height = 260;
|
||||
var isWebCalendar = false;
|
||||
if (UserSettings['Calendar']
|
||||
&& UserSettings['Calendar']['WebCalendars']) {
|
||||
var webCalendars = UserSettings['Calendar']['WebCalendars'];
|
||||
var realID = calendarID.substr (1, calendarID.length - 1);
|
||||
if (webCalendars[realID])
|
||||
if (webCalendars[realID]) {
|
||||
isWebCalendar = true;
|
||||
}
|
||||
}
|
||||
if (isWebCalendar || calendarID == "/personal")
|
||||
height -= 25;
|
||||
if (isWebCalendar)
|
||||
height += 25;
|
||||
else if (calendarID == "/personal")
|
||||
height -= 25;
|
||||
|
||||
var properties = window.open(url, windowID,
|
||||
"width="+width+",height="+height+",resizable=0");
|
||||
|
|
|
@ -57,8 +57,16 @@ UL#userList
|
|||
list-style-image: none; }
|
||||
|
||||
UL#userList LI
|
||||
{ cursor: pointer;
|
||||
{ clear: both;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
padding-left: 3px; }
|
||||
|
||||
SPAN.userFullName
|
||||
{ float: left; }
|
||||
|
||||
DIV#userSelectorButtons A.smallToolbarButton
|
||||
{ float: left; }
|
||||
|
||||
LABEL.subscriptionArea
|
||||
{ padding-right: 5px; }
|
||||
|
|
|
@ -7,6 +7,8 @@ var AclEditor = {
|
|||
userRightsWidth: null
|
||||
};
|
||||
|
||||
var usersToSubscribe = [];
|
||||
|
||||
function addUser(userName, userID) {
|
||||
var result = false;
|
||||
if (!$(userID)) {
|
||||
|
@ -32,19 +34,49 @@ function setEventsOnUserNode(node) {
|
|||
n.observe("selectstart", listRowMouseDownHandler);
|
||||
n.observe("dblclick", onOpenUserRights);
|
||||
n.observe("click", onRowClick);
|
||||
|
||||
var cbParents = n.childNodesWithTag("label");
|
||||
if (cbParents && cbParents.length) {
|
||||
var cbParent = $(cbParents[0]);
|
||||
var checkbox = cbParent.childNodesWithTag("input")[0];
|
||||
$(checkbox).observe("change", onSubscriptionChange);
|
||||
}
|
||||
}
|
||||
|
||||
function onSubscriptionChange(event) {
|
||||
var li = this.parentNode.parentNode;
|
||||
var username = li.getAttribute("id");
|
||||
var idx = usersToSubscribe.indexOf(username);
|
||||
if (this.checked) {
|
||||
if (idx < 0)
|
||||
usersToSubscribe.push(username);
|
||||
} else {
|
||||
if (idx > -1)
|
||||
usersToSubscribe.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function nodeForUser(userName, userId) {
|
||||
var node = document.createElement("li");
|
||||
var node = $(document.createElement("li"));
|
||||
node.setAttribute("id", userId);
|
||||
node.setAttribute("class", "");
|
||||
setEventsOnUserNode(node);
|
||||
|
||||
var span = $(document.createElement("span"));
|
||||
span.addClassName("userFullName");
|
||||
var image = document.createElement("img");
|
||||
image.setAttribute("src", ResourcesURL + "/abcard.gif");
|
||||
span.appendChild(image);
|
||||
span.appendChild(document.createTextNode(" " + userName));
|
||||
node.appendChild(span);
|
||||
|
||||
node.appendChild(image);
|
||||
node.appendChild(document.createTextNode(" " + userName));
|
||||
var label = $(document.createElement("label"));
|
||||
label.addClassName("class", "subscriptionArea");
|
||||
var cb = document.createElement("input");
|
||||
cb.type = "checkbox";
|
||||
label.appendChild(cb);
|
||||
label.appendChild(document.createTextNode(getLabel("Subscribe User")));
|
||||
node.appendChild(label);
|
||||
|
||||
setEventsOnUserNode(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -156,6 +188,24 @@ function onAclLoadHandler() {
|
|||
|
||||
AclEditor['userRightsHeight'] = window.opener.getUsersRightsWindowHeight();
|
||||
AclEditor['userRightsWidth'] = window.opener.getUsersRightsWindowWidth();
|
||||
|
||||
Event.observe(window, "beforeunload", onAclCloseHandler);
|
||||
}
|
||||
|
||||
function onAclCloseHandler(event) {
|
||||
if (usersToSubscribe.length) {
|
||||
var url = (URLForFolderID($("folderID").value)
|
||||
+ "/subscribeUsers?uids=" + usersToSubscribe.join(","));
|
||||
new Ajax.Request(url, {
|
||||
asynchronous: false,
|
||||
method: 'get',
|
||||
onFailure: function(transport) {
|
||||
log("Can't expunge current folder: " + transport.status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
document.observe("dom:loaded", onAclLoadHandler);
|
||||
|
|
Loading…
Reference in New Issue