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>
|
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
|
* UI/WebServerResources/ContactsUI.js (initContacts): fixed a bug
|
||||||
causing a null exception error on IE7 when the window is not the
|
causing a null exception error on IE7 when the window is not the
|
||||||
main window, and is therefore missing the "uploadCancel" and
|
main window, and is therefore missing the "uploadCancel" and
|
||||||
|
|
|
@ -50,6 +50,12 @@
|
||||||
@class GCSFolder;
|
@class GCSFolder;
|
||||||
@class iCalCalendar;
|
@class iCalCalendar;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SOGoAppointmentProxyPermissionNone = 0,
|
||||||
|
SOGoAppointmentProxyPermissionRead = 1,
|
||||||
|
SOGoAppointmentProxyPermissionWrite = 2,
|
||||||
|
} SOGoAppointmentProxyPermission;
|
||||||
|
|
||||||
@interface SOGoAppointmentFolder : SOGoGCSFolder
|
@interface SOGoAppointmentFolder : SOGoGCSFolder
|
||||||
{
|
{
|
||||||
NSTimeZone *timeZone;
|
NSTimeZone *timeZone;
|
||||||
|
@ -138,9 +144,6 @@
|
||||||
- (BOOL) showCalendarTasks;
|
- (BOOL) showCalendarTasks;
|
||||||
- (void) setShowCalendarTasks: (BOOL) new;
|
- (void) setShowCalendarTasks: (BOOL) new;
|
||||||
|
|
||||||
- (BOOL) isProxied;
|
|
||||||
- (void) setIsProxied: (BOOL) isProxied;
|
|
||||||
|
|
||||||
- (NSString *) syncTag;
|
- (NSString *) syncTag;
|
||||||
- (void) setSyncTag: (NSString *) newSyncTag;
|
- (void) setSyncTag: (NSString *) newSyncTag;
|
||||||
|
|
||||||
|
@ -152,9 +155,10 @@
|
||||||
|
|
||||||
/* caldav proxy */
|
/* caldav proxy */
|
||||||
|
|
||||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
- (SOGoAppointmentProxyPermission)
|
||||||
remove: (BOOL) remove
|
proxyPermissionForUserWithLogin: (NSString *) login;
|
||||||
forWriteAccess: (BOOL) write;
|
|
||||||
|
- (NSArray *) aclUsersWithProxyWriteAccess: (BOOL) write;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -2906,47 +2906,6 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||||
return (![inactiveFolders containsObject: nameInContainer]);
|
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
|
- (BOOL) importComponent: (iCalEntityObject *) event
|
||||||
{
|
{
|
||||||
SOGoAppointmentObject *object;
|
SOGoAppointmentObject *object;
|
||||||
|
@ -3013,49 +2972,78 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||||
return aclsForUser;
|
return aclsForUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) requiredProxyRolesWithWriteAccess: (BOOL) hasWriteAccess
|
/* caldav-proxy */
|
||||||
|
- (SOGoAppointmentProxyPermission)
|
||||||
|
proxyPermissionForUserWithLogin: (NSString *) login
|
||||||
{
|
{
|
||||||
static NSArray *writeAccessRoles = nil;
|
SOGoAppointmentProxyPermission permission;
|
||||||
static NSArray *readAccessRoles = nil;
|
NSArray *roles;
|
||||||
|
static NSArray *readRoles = nil;
|
||||||
if (!writeAccessRoles)
|
static NSArray *writeRoles = nil;
|
||||||
|
|
||||||
|
if (!readRoles)
|
||||||
{
|
{
|
||||||
writeAccessRoles = [NSArray arrayWithObjects:
|
readRoles = [NSArray arrayWithObjects:
|
||||||
SOGoCalendarRole_ConfidentialModifier,
|
SOGoCalendarRole_ConfidentialViewer,
|
||||||
SOGoRole_ObjectCreator,
|
SOGoCalendarRole_ConfidentialDAndTViewer,
|
||||||
SOGoRole_ObjectEraser,
|
SOGoCalendarRole_PrivateViewer,
|
||||||
SOGoCalendarRole_PrivateModifier,
|
SOGoCalendarRole_PrivateDAndTViewer,
|
||||||
SOGoCalendarRole_PublicModifier,
|
SOGoCalendarRole_PublicViewer,
|
||||||
nil];
|
SOGoCalendarRole_PublicDAndTViewer,
|
||||||
[writeAccessRoles retain];
|
nil];
|
||||||
|
[readRoles retain];
|
||||||
}
|
}
|
||||||
|
if (!writeRoles)
|
||||||
if (!readAccessRoles)
|
|
||||||
{
|
{
|
||||||
readAccessRoles = [NSArray arrayWithObjects:
|
writeRoles = [NSArray arrayWithObjects:
|
||||||
SOGoCalendarRole_ConfidentialViewer,
|
SOGoRole_ObjectCreator,
|
||||||
SOGoCalendarRole_PrivateViewer,
|
SOGoRole_ObjectEraser,
|
||||||
SOGoCalendarRole_PublicViewer,
|
SOGoCalendarRole_ConfidentialModifier,
|
||||||
nil];
|
SOGoCalendarRole_ConfidentialResponder,
|
||||||
[readAccessRoles retain];
|
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
|
- (NSArray *) aclUsersWithProxyWriteAccess: (BOOL) write
|
||||||
remove: (BOOL) remove
|
|
||||||
forWriteAccess: (BOOL) write
|
|
||||||
{
|
{
|
||||||
NSArray *roles;
|
NSMutableArray *users;
|
||||||
|
NSArray *aclUsers;
|
||||||
|
NSString *aclUser;
|
||||||
|
SOGoAppointmentProxyPermission permission;
|
||||||
|
int count, max;
|
||||||
|
|
||||||
if (remove)
|
permission = (write
|
||||||
[self removeAclsForUsers: proxyUsers];
|
? SOGoAppointmentProxyPermissionWrite
|
||||||
else
|
: SOGoAppointmentProxyPermissionRead);
|
||||||
|
aclUsers = [self aclUsers];
|
||||||
|
max = [aclUsers count];
|
||||||
|
users = [NSMutableArray arrayWithCapacity: max];
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
{
|
{
|
||||||
roles = [self requiredProxyRolesWithWriteAccess: write];
|
aclUser = [aclUsers objectAtIndex: count];
|
||||||
[self setRoles: roles forUsers: proxyUsers];
|
if ([self proxyPermissionForUserWithLogin: aclUser]
|
||||||
|
== permission)
|
||||||
|
[users addObject: aclUser];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end /* SOGoAppointmentFolder */
|
@end /* SOGoAppointmentFolder */
|
||||||
|
|
|
@ -31,13 +31,15 @@
|
||||||
|
|
||||||
- (NSArray *) webCalendarIds;
|
- (NSArray *) webCalendarIds;
|
||||||
|
|
||||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
- (BOOL) hasProxyCalendarsWithWriteAccess: (BOOL) write
|
||||||
remove: (BOOL) remove
|
forUserWithLogin: (NSString *) userLogin;
|
||||||
forWriteAccess: (BOOL) write;
|
|
||||||
|
|
||||||
- (void) adjustProxySubscriptionsForUsers: (NSArray *) proxyUsers
|
- (NSArray *) proxySubscribersWithWriteAccess: (BOOL) write;
|
||||||
remove: (BOOL) remove
|
|
||||||
forWriteAccess: (BOOL) write;
|
- (void) addProxySubscribers: (NSArray *) proxySubscribers
|
||||||
|
withWriteAccess: (BOOL) write;
|
||||||
|
- (void) removeProxySubscribers: (NSArray *) proxySubscribers
|
||||||
|
withWriteAccess: (BOOL) write;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -79,13 +79,14 @@
|
||||||
{
|
{
|
||||||
NSMutableArray *keys;
|
NSMutableArray *keys;
|
||||||
NSEnumerator *sortedSubFolders;
|
NSEnumerator *sortedSubFolders;
|
||||||
SOGoGCSFolder *currentFolder;
|
SOGoAppointmentFolder *currentFolder;
|
||||||
|
SOGoUser *currentUser;
|
||||||
NSString *login;
|
NSString *login;
|
||||||
SOGoUser *ownerUser;
|
|
||||||
|
|
||||||
if ([[context request] isICal])
|
if ([[context request] isICal])
|
||||||
{
|
{
|
||||||
login = [[context activeUser] login];
|
currentUser = [context activeUser];
|
||||||
|
login = [currentUser login];
|
||||||
keys = [NSMutableArray array];
|
keys = [NSMutableArray array];
|
||||||
if ([owner isEqualToString: login])
|
if ([owner isEqualToString: login])
|
||||||
{
|
{
|
||||||
|
@ -100,9 +101,12 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ownerUser = [SOGoUser userWithLogin: owner];
|
sortedSubFolders = [[self subFolders] objectEnumerator];
|
||||||
keys = (NSMutableArray *) [[ownerUser userSettings]
|
while ((currentFolder = [sortedSubFolders nextObject]))
|
||||||
proxiedCalendars];
|
if ([currentUser hasSubscribedToCalendar: currentFolder]
|
||||||
|
&& ([currentFolder proxyPermissionForUserWithLogin: login]
|
||||||
|
!= SOGoAppointmentProxyPermissionNone))
|
||||||
|
[keys addObject: [currentFolder nameInContainer]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -369,50 +373,157 @@
|
||||||
withEquivalent: SoPerm_AddDocumentsImagesAndFiles
|
withEquivalent: SoPerm_AddDocumentsImagesAndFiles
|
||||||
asChildOf: davElement (@"write", XMLNS_WEBDAV)];
|
asChildOf: davElement (@"write", XMLNS_WEBDAV)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return aclManager;
|
return aclManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) adjustProxyRolesForUsers: (NSArray *) proxyUsers
|
- (BOOL) hasProxyCalendarsWithWriteAccess: (BOOL) write
|
||||||
remove: (BOOL) remove
|
forUserWithLogin: (NSString *) userLogin
|
||||||
forWriteAccess: (BOOL) write
|
|
||||||
{
|
{
|
||||||
NSArray *calendars;
|
NSEnumerator *sortedSubFolders;
|
||||||
SOGoUser *ownerUser;
|
SOGoAppointmentFolder *currentFolder;
|
||||||
SOGoAppointmentFolder *folder;
|
SOGoUser *currentUser;
|
||||||
int count, max;
|
SOGoAppointmentProxyPermission permission, curPermission, foundPermission;
|
||||||
|
BOOL rc;
|
||||||
|
|
||||||
ownerUser = [SOGoUser userWithLogin: owner];
|
if ([owner isEqualToString: userLogin])
|
||||||
calendars = [[ownerUser userSettings] proxiedCalendars];
|
rc = NO;
|
||||||
max = [calendars count];
|
else
|
||||||
for (count = 0; count < max; count++)
|
|
||||||
{
|
{
|
||||||
folder = [self lookupName: [calendars objectAtIndex: count]
|
foundPermission = SOGoAppointmentProxyPermissionNone;
|
||||||
inContext: context
|
permission = (write
|
||||||
acquire: NO];
|
? SOGoAppointmentProxyPermissionWrite
|
||||||
[folder adjustProxyRolesForUsers: proxyUsers
|
: SOGoAppointmentProxyPermissionRead);
|
||||||
remove: remove
|
currentUser = [SOGoUser userWithLogin: userLogin];
|
||||||
forWriteAccess: write];
|
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
|
- (void) removeProxySubscribers: (NSArray *) proxySubscribers
|
||||||
remove: (BOOL) remove
|
withWriteAccess: (BOOL) write
|
||||||
forWriteAccess: (BOOL) write
|
|
||||||
{
|
{
|
||||||
int count, max;
|
SOGoAppointmentFolder *currentFolder;
|
||||||
SOGoUser *proxyUser;
|
NSArray *subFolderNames;
|
||||||
|
NSMutableArray *subscribers;
|
||||||
|
int folderCount, folderMax, userCount, userMax;
|
||||||
|
|
||||||
max = [proxyUsers count];
|
subscribers = [NSMutableArray array];
|
||||||
for (count = 0; count < max; count++)
|
|
||||||
|
subFolderNames = [self subFolders];
|
||||||
|
folderMax = [subFolderNames count];
|
||||||
|
for (folderCount = 0; folderCount < folderMax; folderCount++)
|
||||||
{
|
{
|
||||||
proxyUser = [SOGoUser userWithLogin: [proxyUsers objectAtIndex: count]];
|
currentFolder = [subFolderNames objectAtIndex: folderCount];
|
||||||
if (proxyUser)
|
[currentFolder removeAclsForUsers: proxySubscribers];
|
||||||
[proxyUser adjustProxySubscriptionToUser: owner
|
|
||||||
remove: remove
|
userMax = [proxySubscribers count];
|
||||||
forWriteAccess: write];
|
for (userCount = 0; userCount < userMax; userCount++)
|
||||||
else
|
[currentFolder
|
||||||
[self warnWithFormat: @"(%@) user '%@' is invalid (ignored)",
|
subscribeUser: [proxySubscribers objectAtIndex: userCount]
|
||||||
NSStringFromSelector (_cmd), [proxyUser login]];
|
reallyDo: NO];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,21 +71,20 @@
|
||||||
- (NSArray *) davGroupMemberSet
|
- (NSArray *) davGroupMemberSet
|
||||||
{
|
{
|
||||||
NSMutableArray *members;
|
NSMutableArray *members;
|
||||||
NSArray *proxyUsers, *member;
|
NSArray *proxySubscribers, *member;
|
||||||
SOGoUser *ownerUser;
|
|
||||||
NSString *appName, *proxyUser;
|
NSString *appName, *proxyUser;
|
||||||
int count, max;
|
int count, max;
|
||||||
|
|
||||||
appName = [[context request] applicationName];
|
appName = [[context request] applicationName];
|
||||||
|
|
||||||
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]];
|
proxySubscribers
|
||||||
proxyUsers = [[ownerUser userSettings]
|
= [[container lookupName: @"Calendar" inContext: context acquire: NO]
|
||||||
calendarProxyUsersWithWriteAccess: hasWriteAccess];
|
proxySubscribersWithWriteAccess: hasWriteAccess];
|
||||||
max = [proxyUsers count];
|
max = [proxySubscribers count];
|
||||||
members = [NSMutableArray arrayWithCapacity: max];
|
members = [NSMutableArray arrayWithCapacity: max];
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
{
|
{
|
||||||
proxyUser = [proxyUsers objectAtIndex: count];
|
proxyUser = [proxySubscribers objectAtIndex: count];
|
||||||
member = [NSArray arrayWithObjects: @"href", XMLNS_WEBDAV, @"D",
|
member = [NSArray arrayWithObjects: @"href", XMLNS_WEBDAV, @"D",
|
||||||
[NSString stringWithFormat: @"/%@/dav/%@/",
|
[NSString stringWithFormat: @"/%@/dav/%@/",
|
||||||
appName, proxyUser],
|
appName, proxyUser],
|
||||||
|
@ -141,46 +140,35 @@
|
||||||
{
|
{
|
||||||
SOGoUser *ownerUser;
|
SOGoUser *ownerUser;
|
||||||
SOGoUserSettings *us;
|
SOGoUserSettings *us;
|
||||||
NSMutableArray *addedUsers, *removedUsers;
|
NSMutableArray *addedSubscribers, *removedSubscribers;
|
||||||
NSArray *oldProxyUsers, *newProxyUsers;
|
NSArray *oldProxySubscribers, *newProxySubscribers;
|
||||||
NSString *login;
|
NSString *login;
|
||||||
SOGoAppointmentFolders *folders;
|
SOGoAppointmentFolders *folders;
|
||||||
|
|
||||||
login = [self ownerInContext: context];
|
login = [self ownerInContext: context];
|
||||||
ownerUser = [SOGoUser userWithLogin: login roles: nil];
|
ownerUser = [SOGoUser userWithLogin: login roles: nil];
|
||||||
us = [ownerUser userSettings];
|
us = [ownerUser userSettings];
|
||||||
oldProxyUsers = [us calendarProxyUsersWithWriteAccess: hasWriteAccess];
|
folders = [container lookupName: @"Calendar"
|
||||||
if (!oldProxyUsers)
|
inContext: context acquire: NO];
|
||||||
oldProxyUsers = [NSMutableArray array];
|
oldProxySubscribers
|
||||||
newProxyUsers = [self _parseSubscribers: memberSet];
|
= [folders proxySubscribersWithWriteAccess: hasWriteAccess];
|
||||||
if (!newProxyUsers)
|
if (!oldProxySubscribers)
|
||||||
newProxyUsers = [NSMutableArray array];
|
oldProxySubscribers = [NSMutableArray array];
|
||||||
[us setCalendarProxyUsers: newProxyUsers
|
newProxySubscribers = [self _parseSubscribers: memberSet];
|
||||||
withWriteAccess: hasWriteAccess];
|
if (!newProxySubscribers)
|
||||||
|
newProxySubscribers = [NSMutableArray array];
|
||||||
|
|
||||||
folders = [container lookupName: @"Calendar" inContext: context
|
addedSubscribers = [newProxySubscribers mutableCopy];
|
||||||
acquire: NO];
|
[addedSubscribers removeObjectsInArray: oldProxySubscribers];
|
||||||
addedUsers = [newProxyUsers mutableCopy];
|
[addedSubscribers autorelease];
|
||||||
[addedUsers removeObjectsInArray: oldProxyUsers];
|
[folders addProxySubscribers: addedSubscribers
|
||||||
[folders adjustProxyRolesForUsers: addedUsers
|
withWriteAccess: hasWriteAccess];
|
||||||
remove: NO
|
|
||||||
forWriteAccess: hasWriteAccess];
|
|
||||||
[folders adjustProxySubscriptionsForUsers: addedUsers
|
|
||||||
remove: NO
|
|
||||||
forWriteAccess: hasWriteAccess];
|
|
||||||
[addedUsers autorelease];
|
|
||||||
|
|
||||||
removedUsers = [oldProxyUsers mutableCopy];
|
removedSubscribers = [oldProxySubscribers mutableCopy];
|
||||||
[removedUsers removeObjectsInArray: newProxyUsers];
|
[removedSubscribers removeObjectsInArray: newProxySubscribers];
|
||||||
[folders adjustProxyRolesForUsers: removedUsers
|
[removedSubscribers autorelease];
|
||||||
remove: YES
|
[folders removeProxySubscribers: removedSubscribers
|
||||||
forWriteAccess: hasWriteAccess];
|
withWriteAccess: hasWriteAccess];
|
||||||
[folders adjustProxySubscriptionsForUsers: removedUsers
|
|
||||||
remove: YES
|
|
||||||
forWriteAccess: hasWriteAccess];
|
|
||||||
[removedUsers autorelease];
|
|
||||||
|
|
||||||
[us synchronize];
|
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
|
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
|
|
||||||
|
@class SOGoAppointmentFolder;
|
||||||
|
|
||||||
@interface SOGoUser (SOGoCalDAVSupport)
|
@interface SOGoUser (SOGoCalDAVSupport)
|
||||||
|
|
||||||
- (void) adjustProxySubscriptionToUser: (NSString *) ownerUser
|
- (BOOL) hasSubscribedToCalendar: (SOGoAppointmentFolder *) calendar;
|
||||||
remove: (BOOL) remove
|
|
||||||
forWriteAccess: (BOOL) write;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -23,52 +23,22 @@
|
||||||
#import <SOGo/NSArray+Utilities.h>
|
#import <SOGo/NSArray+Utilities.h>
|
||||||
#import <SOGo/SOGoUserSettings.h>
|
#import <SOGo/SOGoUserSettings.h>
|
||||||
|
|
||||||
|
#import "SOGoAppointmentFolder.h"
|
||||||
|
|
||||||
#import "SOGoUser+Appointments.h"
|
#import "SOGoUser+Appointments.h"
|
||||||
|
|
||||||
@implementation SOGoUser (SOGoCalDAVSupport)
|
@implementation SOGoUser (SOGoCalDAVSupport)
|
||||||
|
|
||||||
- (void) adjustProxySubscriptionToUser: (NSString *) ownerUser
|
#warning duplicate of [SOGoGCSFolder userIsSubscriber:]
|
||||||
remove: (BOOL) remove
|
- (BOOL) hasSubscribedToCalendar: (SOGoAppointmentFolder *) calendar
|
||||||
forWriteAccess: (BOOL) write
|
|
||||||
{
|
{
|
||||||
SOGoUserSettings *us;
|
NSArray *subscriptions;
|
||||||
NSMutableArray *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
|
return [subscriptions containsObject: reference];
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSEnumerator.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
|
#import <Foundation/NSValue.h>
|
||||||
|
|
||||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
#import <NGObjWeb/WOResponse.h>
|
#import <NGObjWeb/WOResponse.h>
|
||||||
|
@ -137,25 +138,42 @@
|
||||||
|
|
||||||
- (NSArray *) _calendarProxiedUsersWithWriteAccess: (BOOL) write
|
- (NSArray *) _calendarProxiedUsersWithWriteAccess: (BOOL) write
|
||||||
{
|
{
|
||||||
NSMutableArray *proxiedUsers;
|
NSMutableDictionary *proxiedUsers;
|
||||||
SOGoUser *ownerUser;
|
NSArray *references, *elements;
|
||||||
NSArray *subscriptions;
|
NSString *currentLogin;
|
||||||
NSString *ownerLogin, *currentLogin;
|
NSNumber *yesNumber;
|
||||||
|
SOGoAppointmentFolders *parentFolder;
|
||||||
|
SOGoUserSettings *us;
|
||||||
int count, max;
|
int count, max;
|
||||||
|
|
||||||
ownerLogin = [self ownerInContext: nil];
|
yesNumber = [NSNumber numberWithBool: YES];
|
||||||
ownerUser = [SOGoUser userWithLogin: ownerLogin];
|
|
||||||
subscriptions = [[ownerUser userSettings]
|
us = [[SOGoUser userWithLogin: owner] userSettings];
|
||||||
calendarProxySubscriptionUsersWithWriteAccess: write];
|
references = [us subscribedCalendars];
|
||||||
max = [subscriptions count];
|
max = [references count];
|
||||||
proxiedUsers = [NSMutableArray arrayWithCapacity: max];
|
proxiedUsers = [NSMutableDictionary dictionaryWithCapacity: max];
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
{
|
{
|
||||||
currentLogin = [subscriptions objectAtIndex: count];
|
elements = [[references objectAtIndex: count]
|
||||||
[proxiedUsers addObject: currentLogin];
|
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
|
- (void) _addGroupMembershipToArray: (NSMutableArray *) groups
|
||||||
|
|
|
@ -336,7 +336,7 @@ static SoSecurityManager *sm = nil;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSException *) initSubFolders;
|
- (NSException *) initSubFolders
|
||||||
{
|
{
|
||||||
NSException *error;
|
NSException *error;
|
||||||
|
|
||||||
|
@ -435,10 +435,10 @@ static SoSecurityManager *sm = nil;
|
||||||
error = [self initSubFolders];
|
error = [self initSubFolders];
|
||||||
if (error && isPropfind)
|
if (error && isPropfind)
|
||||||
{
|
{
|
||||||
/* We exceptionnally raise the exception here because doPROPFIND:
|
/* We exceptionnally raise the exception here because doPROPFIND: will
|
||||||
will not care for errors in its response from
|
not care for errors in its response from toManyRelationShipKeys,
|
||||||
toManyRelationShipKeys, which may in turn trigger the
|
which may in turn trigger the disappearance of user folders in the
|
||||||
disappearance of user folders in the SOGo extensions. */
|
SOGo extensions. */
|
||||||
[error raise];
|
[error raise];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,19 +32,8 @@
|
||||||
|
|
||||||
+ (SOGoUserSettings *) settingsForUser: (NSString *) userId;
|
+ (SOGoUserSettings *) settingsForUser: (NSString *) userId;
|
||||||
|
|
||||||
/* the calendars that we publish to our proxy subscribers */
|
- (NSArray *) subscribedCalendars;
|
||||||
- (void) setProxiedCalendars: (NSArray *) proxiedCalendars;
|
- (NSArray *) subscribedAddressBooks;
|
||||||
- (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;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -55,65 +55,19 @@ static Class SOGoUserProfileKlass = Nil;
|
||||||
return ud;
|
return ud;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the calendars that we publish to our proxy subscribers */
|
- (NSArray *) _subscribedFoldersForModule: (NSString *) module
|
||||||
- (void) setProxiedCalendars: (NSArray *) proxiedCalendars
|
|
||||||
{
|
{
|
||||||
[self setObject: proxiedCalendars forKey: @"ProxiedCalendars"];
|
return [[self dictionaryForKey: module] objectForKey: @"SubscribedFolders"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) proxiedCalendars
|
- (NSArray *) subscribedCalendars
|
||||||
{
|
{
|
||||||
NSArray *proxiedCalendars;
|
return [self _subscribedFoldersForModule: @"Calendar"];
|
||||||
|
|
||||||
proxiedCalendars = [self arrayForKey: @"ProxiedCalendars"];
|
|
||||||
if (!proxiedCalendars)
|
|
||||||
proxiedCalendars = [NSArray arrayWithObject: @"personal"];
|
|
||||||
|
|
||||||
return proxiedCalendars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the users that we have subscribed us as a proxy to our calendars */
|
- (NSArray *) subscribedAddressBooks
|
||||||
- (void) setCalendarProxyUsers: (NSArray *) proxyUsers
|
|
||||||
withWriteAccess: (BOOL) writeAccess
|
|
||||||
{
|
{
|
||||||
NSString *key;
|
return [self _subscribedFoldersForModule: @"Contacts"];
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from config import hostname, port, username, password, subscriber_username
|
from config import hostname, port, username, password, subscriber_username
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import utilities
|
||||||
import webdavlib
|
import webdavlib
|
||||||
|
|
||||||
class iCalTest(unittest.TestCase):
|
class iCalTest(unittest.TestCase):
|
||||||
|
@ -121,5 +122,85 @@ class iCalTest(unittest.TestCase):
|
||||||
"'%s' expected to be %s proxy for %s: %s"
|
"'%s' expected to be %s proxy for %s: %s"
|
||||||
% (users[1], perm, users[0], proxyFor))
|
% (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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -49,7 +49,7 @@ class WebdavSyncTest(unittest.TestCase):
|
||||||
token = int(token_node.childNodes[0].nodeValue)
|
token = int(token_node.childNodes[0].nodeValue)
|
||||||
|
|
||||||
self.assertTrue(token > 0)
|
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
|
# we make sure that any token is invalid when the collection is empty
|
||||||
query2 = webdavlib.WebDAVSyncQuery(resource, "1234", [ "getetag" ])
|
query2 = webdavlib.WebDAVSyncQuery(resource, "1234", [ "getetag" ])
|
||||||
|
|
|
@ -33,28 +33,34 @@ class TestACLUtility(TestUtility):
|
||||||
TestUtility.__init__(self, client)
|
TestUtility.__init__(self, client)
|
||||||
self.resource = resource
|
self.resource = resource
|
||||||
|
|
||||||
def subscribe(self, subscribers=None):
|
def _subscriptionOperation(self, subscribers, operation):
|
||||||
rights_str = "".join(["<%s/>" % x
|
|
||||||
for x in self.rightsToSOGoRights(rights) ])
|
|
||||||
subscribeQuery = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
subscribeQuery = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
+ "<subscribe"
|
+ "<%s" % operation
|
||||||
+ " xmlns=\"urn:inverse:params:xml:ns:inverse-dav\"")
|
+ " xmlns=\"urn:inverse:params:xml:ns:inverse-dav\"")
|
||||||
if (subscribers is not None):
|
if (subscribers is not None):
|
||||||
subscribeQuery = (subscribeQuery
|
subscribeQuery = (subscribeQuery
|
||||||
+ " users=\"%s\"" % subscribers.join(","))
|
+ " users=\"%s\"" % ",".join(subscribers))
|
||||||
subscribeQuery = subscribeQuery + "/>"
|
subscribeQuery = subscribeQuery + "/>"
|
||||||
post = webdavlib.HTTPPOST(self.resource, subscribeQuery)
|
post = webdavlib.HTTPPOST(self.resource, subscribeQuery)
|
||||||
post.content_type = "application/xml; charset=\"utf-8\""
|
post.content_type = "application/xml; charset=\"utf-8\""
|
||||||
self.client.execute(post)
|
self.client.execute(post)
|
||||||
self.assertEquals(post.response["status"], 204,
|
self.assertEquals(post.response["status"], 204,
|
||||||
"subscribtion failure to set '%s' (status: %d)"
|
"subscribtion failure to '%s' for '%s' (status: %d)"
|
||||||
% (rights_str, post.response["status"]))
|
% (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):
|
def rightsToSOGoRights(self, rights):
|
||||||
self.fail("subclass must implement this method")
|
self.fail("subclass must implement this method")
|
||||||
|
|
||||||
def setupRights(self, username, rights):
|
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"
|
aclQuery = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
+ "<acl-query"
|
+ "<acl-query"
|
||||||
+ " xmlns=\"urn:inverse:params:xml:ns:inverse-dav\">"
|
+ " xmlns=\"urn:inverse:params:xml:ns:inverse-dav\">"
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"Publish the Free/Busy information" = "Divulgar a informação Livre/Ocupado";
|
"Publish the Free/Busy information" = "Divulgar a informação Livre/Ocupado";
|
||||||
|
|
||||||
"Default Roles" = "Papéis Padrão";
|
"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.";
|
"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ý";
|
"Publish the Free/Busy information" = "Zveřejni informace o Volný/Zaneprázdněný";
|
||||||
|
|
||||||
"Default Roles" = "Výchozí role";
|
"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.";
|
"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";
|
"Publish the Free/Busy information" = "Beschikbaarheidsinformatie publiceren";
|
||||||
|
|
||||||
"Default Roles" = "Standaardmachtigingen";
|
"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.";
|
"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";
|
"Publish the Free/Busy information" = "Publish the Free/Busy information";
|
||||||
|
|
||||||
"Default Roles" = "Default Roles";
|
"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.";
|
"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";
|
"Publish the Free/Busy information" = "Publier l'occupation du temps";
|
||||||
|
|
||||||
"Default Roles" = "Rôles par défaut";
|
"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.";
|
"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";
|
"Publish the Free/Busy information" = "Verfügbarkeitsinformationen veröffentlichen";
|
||||||
|
|
||||||
"Default Roles" = "Standardrechte";
|
"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.";
|
"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";
|
"Publish the Free/Busy information" = "Foglaltsági információ nyilvánossá tétele";
|
||||||
|
|
||||||
"Default Roles" = "Alapértelmezett jogok";
|
"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.";
|
"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)";
|
"Publish the Free/Busy information" = "Pubblica le informazioni sullo stato (libero/impegnato)";
|
||||||
|
|
||||||
"Default Roles" = "Permessi predefiniti";
|
"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.";
|
"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" = "Публиковать информацию о занятом/свободном времени";
|
"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" = "Publicar información de disponibilidad";
|
"Publish the Free/Busy information" = "Publicar información de disponibilidad";
|
||||||
|
|
||||||
"Default Roles" = "Roles por defecto";
|
"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.";
|
"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";
|
"Publish the Free/Busy information" = "Publisera ledig/upptagen information";
|
||||||
|
|
||||||
"Default Roles" = "Standardroller";
|
"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.";
|
"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/WORequest.h>
|
||||||
#import <NGObjWeb/SoSecurityManager.h>
|
#import <NGObjWeb/SoSecurityManager.h>
|
||||||
#import <NGCards/iCalPerson.h>
|
#import <NGCards/iCalPerson.h>
|
||||||
#import <SoObjects/SOGo/SOGoUserManager.h>
|
#import <SOGo/NSArray+Utilities.h>
|
||||||
#import <SoObjects/SOGo/SOGoContentObject.h>
|
#import <SOGo/SOGoContentObject.h>
|
||||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
#import <SOGo/SOGoGCSFolder.h>
|
||||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
#import <SOGo/SOGoPermissions.h>
|
||||||
#import <SoObjects/SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUserManager.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
|
||||||
#import "UIxAclEditor.h"
|
#import "UIxAclEditor.h"
|
||||||
|
|
||||||
|
@ -158,6 +159,16 @@
|
||||||
return [self _displayNameForUID: currentUser];
|
return [self _displayNameForUID: currentUser];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) currentUserIsSubscribed
|
||||||
|
{
|
||||||
|
SOGoGCSFolder *folder;
|
||||||
|
|
||||||
|
folder = [self clientObject];
|
||||||
|
|
||||||
|
return ([folder respondsToSelector: @selector (userIsSubscriber:)]
|
||||||
|
&& [folder userIsSubscriber: currentUser]);
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setUserUIDS: (NSString *) retainedUsers
|
- (void) setUserUIDS: (NSString *) retainedUsers
|
||||||
{
|
{
|
||||||
if ([retainedUsers length] > 0)
|
if ([retainedUsers length] > 0)
|
||||||
|
@ -169,6 +180,11 @@
|
||||||
savedUIDs = [NSArray new];
|
savedUIDs = [NSArray new];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) folderID
|
||||||
|
{
|
||||||
|
return [[self clientObject] nameInContainer];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
|
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
|
||||||
inContext: (WOContext *) context
|
inContext: (WOContext *) context
|
||||||
{
|
{
|
||||||
|
|
|
@ -313,23 +313,21 @@
|
||||||
NSException *ex;
|
NSException *ex;
|
||||||
|
|
||||||
request = [context request];
|
request = [context request];
|
||||||
ex = nil;
|
|
||||||
|
|
||||||
if ((destinationFolderId = [request formValueForKey: @"folder"]) &&
|
if ((destinationFolderId = [request formValueForKey: @"folder"]) &&
|
||||||
(contactsId = [request formValuesForKey: @"uid"]))
|
(contactsId = [request formValuesForKey: @"uid"]))
|
||||||
{
|
ex = [self _moveContacts: contactsId
|
||||||
ex = [self _moveContacts: contactsId
|
toFolder: destinationFolderId
|
||||||
toFolder: destinationFolderId
|
|
||||||
andKeepCopy: YES];
|
andKeepCopy: YES];
|
||||||
if (ex != nil)
|
|
||||||
response = (id)ex;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
response = [NSException exceptionWithHTTPStatus: 400
|
ex = [NSException exceptionWithHTTPStatus: 400
|
||||||
reason: @"missing 'folder' and/or 'uid' parameter"];
|
reason: (@"missing 'folder' and/or"
|
||||||
|
@" 'uid' parameter")];
|
||||||
|
|
||||||
if (ex == nil)
|
if (ex)
|
||||||
response = [self responseWith204];
|
response = (id) ex;
|
||||||
|
else
|
||||||
|
response = [self responseWith204];
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -343,25 +341,55 @@
|
||||||
NSException *ex;
|
NSException *ex;
|
||||||
|
|
||||||
request = [context request];
|
request = [context request];
|
||||||
ex = nil;
|
|
||||||
|
|
||||||
if ((destinationFolderId = [request formValueForKey: @"folder"]) &&
|
if ((destinationFolderId = [request formValueForKey: @"folder"])
|
||||||
(contactsId = [request formValuesForKey: @"uid"]))
|
&& (contactsId = [request formValuesForKey: @"uid"]))
|
||||||
{
|
ex = [self _moveContacts: contactsId
|
||||||
ex = [self _moveContacts: contactsId
|
toFolder: destinationFolderId
|
||||||
toFolder: destinationFolderId
|
|
||||||
andKeepCopy: NO];
|
andKeepCopy: NO];
|
||||||
if (ex != nil)
|
else
|
||||||
response = (id)ex;
|
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
|
else
|
||||||
response = [NSException exceptionWithHTTPStatus: 400
|
ex = [NSException exceptionWithHTTPStatus: 400
|
||||||
reason: @"missing 'folder' and/or 'uid' parameter"];
|
reason: @"missing 'uids' parameter"];
|
||||||
|
|
||||||
if (ex == nil)
|
if (ex)
|
||||||
response = [self responseWith204];
|
response = (id <WOActionResults>) ex;
|
||||||
|
else
|
||||||
return response;
|
response = [self responseWith204];
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"Publish the Free/Busy information" = "Cyhoddwch y wybodaeth Rhydd/Brysur";
|
"Publish the Free/Busy information" = "Cyhoddwch y wybodaeth Rhydd/Brysur";
|
||||||
|
|
||||||
"Default Roles" = "Rolau Gwreiddiol";
|
"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.";
|
"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";
|
actionClass = "UIxFolderActions";
|
||||||
actionName = "deactivateFolder";
|
actionName = "deactivateFolder";
|
||||||
};
|
};
|
||||||
|
subscribeUsers = {
|
||||||
|
protectedBy = "Change Permissions";
|
||||||
|
actionClass = "UIxFolderActions";
|
||||||
|
actionName = "subscribeUsers";
|
||||||
|
};
|
||||||
renameFolder = {
|
renameFolder = {
|
||||||
protectedBy = "Change Permissions";
|
protectedBy = "Change Permissions";
|
||||||
actionClass = "UIxFolderActions";
|
actionClass = "UIxFolderActions";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tarefa Confidencial)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Marca:";
|
"Tag:" = "Marca:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Důvěrný úkol)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Štítek:";
|
"Tag:" = "Štítek:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Vertrouwelijke taak)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Markering:";
|
"Tag:" = "Markering:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Confidential task)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Tag:";
|
"Tag:" = "Tag:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tâche confidentielle)";
|
||||||
"Synchronize" = "Synchroniser";
|
"Synchronize" = "Synchroniser";
|
||||||
"Tag:" = "Label :";
|
"Tag:" = "Label :";
|
||||||
|
|
||||||
"iCal Delegation" = "Délégation iCal";
|
|
||||||
"Shared when account is delegated" = "Inclure cet agenda lors de la délégation";
|
|
||||||
|
|
||||||
"Display" = "Affichage";
|
"Display" = "Affichage";
|
||||||
"Show alarms" = "Afficher les alarmes";
|
"Show alarms" = "Afficher les alarmes";
|
||||||
"Show tasks" = "Afficher les tâches";
|
"Show tasks" = "Afficher les tâches";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Tag:";
|
"Tag:" = "Tag:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Bizalmas feladat)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Cimke:";
|
"Tag:" = "Cimke:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Attività confidenziale)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Etichetta:";
|
"Tag:" = "Etichetta:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Confidential task)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Tag:";
|
"Tag:" = "Tag:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tarea confidencial)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Redacción:";
|
"Tag:" = "Redacción:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Konfidentiell uppgift)";
|
||||||
"Synchronize" = "Synkronisera";
|
"Synchronize" = "Synkronisera";
|
||||||
"Tag:" = "Etikett:";
|
"Tag:" = "Etikett:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Visa";
|
"Display" = "Visa";
|
||||||
"Show alarms" = "Visa alarm";
|
"Show alarms" = "Visa alarm";
|
||||||
"Show tasks" = "Visa uppgifter";
|
"Show tasks" = "Visa uppgifter";
|
||||||
|
|
|
@ -51,7 +51,4 @@
|
||||||
- (NSString *) calendarSyncTag;
|
- (NSString *) calendarSyncTag;
|
||||||
- (void) setCalendarSyncTag: (NSString *) newTag;
|
- (void) setCalendarSyncTag: (NSString *) newTag;
|
||||||
|
|
||||||
- (BOOL) isProxied;
|
|
||||||
- (void) setIsProxied: (BOOL) isProxied;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -149,17 +149,6 @@
|
||||||
[calendar setSyncTag: newTag];
|
[calendar setSyncTag: newTag];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DAV: calendar-proxy protocol */
|
|
||||||
- (BOOL) isProxied
|
|
||||||
{
|
|
||||||
return [calendar isProxied];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setIsProxied: (BOOL) isProxied
|
|
||||||
{
|
|
||||||
[calendar setIsProxied: isProxied];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) showCalendarAlarms
|
- (BOOL) showCalendarAlarms
|
||||||
{
|
{
|
||||||
return [calendar showCalendarAlarms];
|
return [calendar showCalendarAlarms];
|
||||||
|
|
|
@ -512,9 +512,6 @@ vtodo_class2 = "(Tasg gyhoeddus)";
|
||||||
"Synchronize" = "Synchronize";
|
"Synchronize" = "Synchronize";
|
||||||
"Tag:" = "Tag:";
|
"Tag:" = "Tag:";
|
||||||
|
|
||||||
"iCal Delegation" = "iCal Delegation";
|
|
||||||
"Shared when account is delegated" = "Shared when account is delegated";
|
|
||||||
|
|
||||||
"Display" = "Display";
|
"Display" = "Display";
|
||||||
"Show alarms" = "Show alarms";
|
"Show alarms" = "Show alarms";
|
||||||
"Show tasks" = "Show tasks";
|
"Show tasks" = "Show tasks";
|
||||||
|
|
|
@ -70,16 +70,6 @@
|
||||||
/></div></var:if>
|
/></div></var:if>
|
||||||
</fieldset>
|
</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>
|
<fieldset>
|
||||||
<legend><var:string label:value="Display"/></legend>
|
<legend><var:string label:value="Display"/></legend>
|
||||||
<div><label
|
<div><label
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
<input type="hidden" name="defaultUserID" id="defaultUserID"
|
<input type="hidden" name="defaultUserID" id="defaultUserID"
|
||||||
var:value="defaultUserID"/>
|
var:value="defaultUserID"/>
|
||||||
<input type="hidden" name="action" value="saveAcls"/>
|
<input type="hidden" name="action" value="saveAcls"/>
|
||||||
<input type="hidden" id="userUIDS" name="userUIDS"
|
<input type="hidden" name="folderID" id="folderID" var:value="folderID"/>
|
||||||
var:value="userUIDS"/>
|
|
||||||
<var:if condition="hasOwner">
|
<var:if condition="hasOwner">
|
||||||
<label><var:string label:value="Owner:"/>
|
<label><var:string label:value="Owner:"/>
|
||||||
<span class="value"><strong><var:string value="ownerName"/></strong></span></label>
|
<span class="value"><strong><var:string value="ownerName"/></strong></span></label>
|
||||||
|
@ -38,9 +37,14 @@
|
||||||
<ul id="userList" multiselect="yes">
|
<ul id="userList" multiselect="yes">
|
||||||
<var:foreach list="usersForObject" item="currentUser"
|
<var:foreach list="usersForObject" item="currentUser"
|
||||||
><li var:id="currentUser">
|
><li var:id="currentUser">
|
||||||
<img rsrc:src="abcard.gif"/>
|
<span class="userFullName"><img rsrc:src="abcard.gif"/>
|
||||||
<var:string value="currentUserDisplayName"/></li>
|
<var:string value="currentUserDisplayName"
|
||||||
</var:foreach>
|
/></span
|
||||||
|
><label class="subscriptionArea"><input type="checkbox"
|
||||||
|
var:checked="currentUserIsSubscribed"
|
||||||
|
var:disabled="currentUserIsSubscribed"
|
||||||
|
/><var:string label:value="Subscribe User"/></label
|
||||||
|
></li></var:foreach>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1891,17 +1891,20 @@ function onCalendarModify(event) {
|
||||||
var url = ApplicationBaseURL + calendarID + "/properties";
|
var url = ApplicationBaseURL + calendarID + "/properties";
|
||||||
var windowID = sanitizeWindowName(calendarID + " properties");
|
var windowID = sanitizeWindowName(calendarID + " properties");
|
||||||
var width = 310;
|
var width = 310;
|
||||||
var height = 310;
|
var height = 260;
|
||||||
var isWebCalendar = false;
|
var isWebCalendar = false;
|
||||||
if (UserSettings['Calendar']
|
if (UserSettings['Calendar']
|
||||||
&& UserSettings['Calendar']['WebCalendars']) {
|
&& UserSettings['Calendar']['WebCalendars']) {
|
||||||
var webCalendars = UserSettings['Calendar']['WebCalendars'];
|
var webCalendars = UserSettings['Calendar']['WebCalendars'];
|
||||||
var realID = calendarID.substr (1, calendarID.length - 1);
|
var realID = calendarID.substr (1, calendarID.length - 1);
|
||||||
if (webCalendars[realID])
|
if (webCalendars[realID]) {
|
||||||
isWebCalendar = true;
|
isWebCalendar = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (isWebCalendar || calendarID == "/personal")
|
if (isWebCalendar)
|
||||||
height -= 25;
|
height += 25;
|
||||||
|
else if (calendarID == "/personal")
|
||||||
|
height -= 25;
|
||||||
|
|
||||||
var properties = window.open(url, windowID,
|
var properties = window.open(url, windowID,
|
||||||
"width="+width+",height="+height+",resizable=0");
|
"width="+width+",height="+height+",resizable=0");
|
||||||
|
|
|
@ -57,8 +57,16 @@ UL#userList
|
||||||
list-style-image: none; }
|
list-style-image: none; }
|
||||||
|
|
||||||
UL#userList LI
|
UL#userList LI
|
||||||
{ cursor: pointer;
|
{ clear: both;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: right;
|
||||||
padding-left: 3px; }
|
padding-left: 3px; }
|
||||||
|
|
||||||
|
SPAN.userFullName
|
||||||
|
{ float: left; }
|
||||||
|
|
||||||
DIV#userSelectorButtons A.smallToolbarButton
|
DIV#userSelectorButtons A.smallToolbarButton
|
||||||
{ float: left; }
|
{ float: left; }
|
||||||
|
|
||||||
|
LABEL.subscriptionArea
|
||||||
|
{ padding-right: 5px; }
|
||||||
|
|
|
@ -7,6 +7,8 @@ var AclEditor = {
|
||||||
userRightsWidth: null
|
userRightsWidth: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var usersToSubscribe = [];
|
||||||
|
|
||||||
function addUser(userName, userID) {
|
function addUser(userName, userID) {
|
||||||
var result = false;
|
var result = false;
|
||||||
if (!$(userID)) {
|
if (!$(userID)) {
|
||||||
|
@ -32,19 +34,49 @@ function setEventsOnUserNode(node) {
|
||||||
n.observe("selectstart", listRowMouseDownHandler);
|
n.observe("selectstart", listRowMouseDownHandler);
|
||||||
n.observe("dblclick", onOpenUserRights);
|
n.observe("dblclick", onOpenUserRights);
|
||||||
n.observe("click", onRowClick);
|
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) {
|
function nodeForUser(userName, userId) {
|
||||||
var node = document.createElement("li");
|
var node = $(document.createElement("li"));
|
||||||
node.setAttribute("id", userId);
|
node.setAttribute("id", userId);
|
||||||
node.setAttribute("class", "");
|
|
||||||
setEventsOnUserNode(node);
|
|
||||||
|
|
||||||
|
var span = $(document.createElement("span"));
|
||||||
|
span.addClassName("userFullName");
|
||||||
var image = document.createElement("img");
|
var image = document.createElement("img");
|
||||||
image.setAttribute("src", ResourcesURL + "/abcard.gif");
|
image.setAttribute("src", ResourcesURL + "/abcard.gif");
|
||||||
|
span.appendChild(image);
|
||||||
|
span.appendChild(document.createTextNode(" " + userName));
|
||||||
|
node.appendChild(span);
|
||||||
|
|
||||||
node.appendChild(image);
|
var label = $(document.createElement("label"));
|
||||||
node.appendChild(document.createTextNode(" " + userName));
|
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;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -156,6 +188,24 @@ function onAclLoadHandler() {
|
||||||
|
|
||||||
AclEditor['userRightsHeight'] = window.opener.getUsersRightsWindowHeight();
|
AclEditor['userRightsHeight'] = window.opener.getUsersRightsWindowHeight();
|
||||||
AclEditor['userRightsWidth'] = window.opener.getUsersRightsWindowWidth();
|
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);
|
document.observe("dom:loaded", onAclLoadHandler);
|
||||||
|
|
Loading…
Reference in New Issue