oc-calendar: Add edit/delete own and Folder Contact/Owner sharing perm

By storing these custom MAPI roles in the ACL.

The extension field 'X-SOGO-COMPONENT-CREATED-BY' is used to store the
event creator when it is done from Outlook. It is the same field SOGo
uses when an event is created from a shared folder in the webmail.

The creator and the organizer/owner of the event can be different and it can
be used from external sources by checking the organizer field. This matches
the specification from [MS-OXOCAL] Section 1.1 which defines the organizer
as the owner or creator of the event.
This commit is contained in:
Enrique J. Hernández Blasco
2016-02-09 16:34:04 +01:00
parent 12ac1d30de
commit dd32c659f6
7 changed files with 111 additions and 29 deletions

View File

@@ -68,6 +68,9 @@
- (void) fillMessageData: (struct mapistore_message *) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (NSString *) creator;
- (NSString *) owner;
- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (enum mapistore_error) getPidTagSenderAddressType: (void **) data

View File

@@ -1023,6 +1023,63 @@ static NSCharacterSet *hexCharacterSet = nil;
inMemCtx: memCtx];
}
/* creator (only if created from Outlook/SOGo or organizer as fallback */
- (NSString *) creator
{
iCalPerson *person;
NSDictionary *contactInfos;
NSString *creator = nil, *email;
SOGoUserManager *mgr;
creator = [[event uniqueChildWithTag: @"x-sogo-component-created-by"]
flattenedValuesForKey: @""];
if ([creator length] == 0)
{
person = [event organizer];
if (person)
{
email = [person rfc822Email];
if ([email length] > 0)
{
mgr = [SOGoUserManager sharedUserManager];
contactInfos = [mgr contactInfosForUserWithUIDorEmail: email];
if (contactInfos)
creator = [contactInfos objectForKey: @"sAMAccountName"];
}
}
}
return creator;
}
/* owner is the organizer of the event, if none, try with the creator
who has saved only from Outlook or SOGo */
- (NSString *) owner
{
iCalPerson *person;
NSDictionary *contactInfos;
NSString *email, *owner = nil;
SOGoUserManager *mgr;
person = [event organizer];
if (person)
{
email = [person rfc822Email];
if ([email length] > 0)
{
mgr = [SOGoUserManager sharedUserManager];
contactInfos = [mgr contactInfosForUserWithUIDorEmail: email];
if (contactInfos)
owner = [contactInfos objectForKey: @"sAMAccountName"];
}
}
if (!owner)
owner = [[event uniqueChildWithTag: @"x-sogo-component-created-by"]
flattenedValuesForKey: @""];
return owner;
}
/* sender representing */
- (enum mapistore_error) getPidTagSentRepresentingEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx

View File

@@ -208,6 +208,7 @@
[[container event] updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser
isNew: NO
inMemCtx: memCtx];
}

View File

@@ -81,11 +81,7 @@
Following rights are not supported by SOGo specifically:
- DeleteOwned : Delete only own objects
- EditOwned : Edit only own objects
- CreateSubfolders: No calendar subfolders
- FolderOwner: No sharing folder ownership?
- FolderContact: No support to store this information
- FolderVisible: It is inferred by other rights when extracting
*/
NSMutableArray *roles;
@@ -95,26 +91,35 @@
[roles addObject: SOGoRole_ObjectCreator];
if (rights & RightsDeleteAll)
[roles addObject: SOGoRole_ObjectEraser];
if (rights & RightsDeleteOwn)
[roles addObject: MAPIStoreRightDeleteOwn];
if (rights & RightsEditAll)
{
[roles addObject: SOGoCalendarRole_PublicModifier];
[roles addObject: SOGoCalendarRole_PrivateModifier];
[roles addObject: SOGoCalendarRole_ConfidentialModifier];
}
else if (rights & RightsReadItems)
if (rights & RightsEditOwn)
[roles addObject: MAPIStoreRightEditOwn];
if (rights & RightsReadItems)
{
[roles addObject: SOGoCalendarRole_PublicViewer];
[roles addObject: SOGoCalendarRole_PrivateViewer];
[roles addObject: SOGoCalendarRole_ConfidentialViewer];
}
if (rights & RightsFreeBusySimple)
{
[roles addObject: SOGoCalendarRole_PublicDAndTViewer];
}
[roles addObject: SOGoCalendarRole_PublicDAndTViewer];
if (rights & RightsFreeBusyDetailed)
{
[roles addObject: SOGoCalendarRole_ConfidentialDAndTViewer];
}
[roles addObject: SOGoCalendarRole_ConfidentialDAndTViewer];
if (rights & RightsFolderOwner)
[roles addObject: MAPIStoreRightFolderOwner];
if (rights & RightsFolderContact)
[roles addObject: MAPIStoreRightFolderContact];
// [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles];
@@ -136,19 +141,28 @@
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
// We have to set by hand other rights as only the highest role is returned
// See SOGoAppointmentFolder.m:aclsForUser for details
rights |= RightsReadItems | RightsFreeBusySimple | RightsFreeBusyDetailed;
rights |= RightsReadItems;
if ([roles containsObject: MAPIStoreRightEditOwn])
rights |= RightsEditOwn;
if ([roles containsObject: MAPIStoreRightDeleteOwn])
rights |= RightsDeleteOwn;
if ([roles containsObject: SOGoCalendarRole_PublicDAndTViewer])
rights |= RightsFreeBusySimple;
if ([roles containsObject: SOGoCalendarRole_ConfidentialDAndTViewer])
rights |= RightsFreeBusyDetailed;
rights |= RightsFreeBusySimple | RightsFreeBusyDetailed;
if ((rights & RightsReadItems) != 0 || (rights & RightsCreateItems) != 0 || (rights & RightsDeleteAll) != 0)
rights |= RoleNone; /* actually "folder visible" */
if ([roles containsObject: MAPIStoreRightFolderOwner])
rights |= RightsFolderOwner | RoleNone;
if ([roles containsObject: MAPIStoreRightFolderContact])
rights |= RightsFolderContact;
// [self logWithFormat: @"rights for roles (%@) = %.8x", roles, rights];
return rights;

View File

@@ -528,6 +528,16 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
ASSIGN (sogoObject, newObject);
}
- (NSString *) creator
{
return [[self _appointmentWrapper] creator];
}
- (NSString *) owner
{
return [[self _appointmentWrapper] owner];
}
- (BOOL) subscriberCanReadMessage
{
NSArray *roles;
@@ -539,20 +549,6 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
|| [self subscriberCanModifyMessage]);
}
- (BOOL) subscriberCanModifyMessage
{
BOOL rc;
NSArray *roles = [self activeUserRoles];
if (isNew)
rc = [roles containsObject: SOGoRole_ObjectCreator];
else
rc = ([roles containsObject: SOGoCalendarRole_ComponentModifier]
|| [roles containsObject: SOGoCalendarRole_ComponentResponder]);
return rc;
}
- (void) _updateAttachedEvents
{
NSArray *allAttachments;
@@ -632,6 +628,7 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
[masterEvent updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser
isNew: isNew
inMemCtx: memCtx];
[self _updateAttachedEvents];
[[self userContext] activate];

View File

@@ -37,6 +37,7 @@
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser
isNew: (BOOL) isNew
inMemCtx: (TALLOC_CTX *) memCtx;
@end

View File

@@ -247,6 +247,7 @@
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser
isNew: (BOOL) isNew
inMemCtx: (TALLOC_CTX *) memCtx
{
BOOL isAllDay;
@@ -573,6 +574,14 @@
}
}
}
// Creator (with sharing purposes)
if (isNew)
{
value = [properties objectForKey: MAPIPropertyKey (PidTagLastModifierName)];
if (value)
[[self uniqueChildWithTag: @"x-sogo-component-created-by"] setSingleValue: value
forKey: @""];
}
}
@end