diff --git a/ChangeLog b/ChangeLog index c175d605f..2f6ad60c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2008-02-22 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoObject.m ([SOGoObject -addUserInAcls:uid]): + new method. + ([SOGoObject -removeUserFromAcls:uid]): new methods (see below). + ([SOGoObject -davNamespaces]): declare the + "urn:inverse:params:xml:ns:inverse-dav" namespace. + ([SOGoObject -davRecordForUser:user]) + ([SOGoObject -davAclQuery:queryContext]): new methods to answer to + the "user-list", "roles", "set-roles", "add-user", "remove-user" + inverse DAV methods. + + * UI/Common/UIxObjectActions.m ([UIxObjectActions -addUserInAclsAction]) + ([UIxObjectActions -removeUserFromAclsAction]): moved the core of + those methods into SOGoObject and translate its result into an + appropriate HTTP status. + 2008-02-20 Wolfgang Sourdeau * SoObjects/SOGo/SOGoGCSFolder.m ([SOGoGCSFolder -davInverseACL]): diff --git a/SoObjects/SOGo/SOGoObject.h b/SoObjects/SOGo/SOGoObject.h index a6ff53d27..5c8f87b1e 100644 --- a/SoObjects/SOGo/SOGoObject.h +++ b/SoObjects/SOGo/SOGoObject.h @@ -113,6 +113,9 @@ - (NSArray *) subscriptionRoles; +- (BOOL) addUserInAcls: (NSString *) uid; +- (BOOL) removeUserFromAcls: (NSString *) uid; + - (NSArray *) aclUsers; - (NSArray *) aclsForUser: (NSString *) uid; - (void) setRoles: (NSArray *) roles @@ -126,6 +129,10 @@ - (NSString *) httpURLForAdvisoryToUser: (NSString *) uid; - (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid; +/* dav */ +- (NSArray *) davNamespaces; +- (NSString *) davRecordForUser: (NSString *) user; + /* description */ - (void) appendAttributesToDescription:(NSMutableString *)_ms; diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 748461d97..7fbace9f9 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -46,27 +46,31 @@ #import #import #import +#import +#import #import #import #import -#import "SOGoPermissions.h" -#import "SOGoUser.h" -#import "SOGoDAVAuthenticator.h" -#import "SOGoUserFolder.h" - -#import "SOGoDAVRendererTypes.h" - +#import "LDAPUserManager.h" #import "NSArray+Utilities.h" #import "NSCalendarDate+SOGo.h" #import "NSDictionary+Utilities.h" #import "NSString+Utilities.h" - #import "SOGoCache.h" +#import "SOGoDAVAuthenticator.h" +#import "SOGoDAVRendererTypes.h" +#import "SOGoPermissions.h" +#import "SOGoUser.h" +#import "SOGoUserFolder.h" + #import "SOGoObject.h" +static BOOL kontactGroupDAV = YES; +static BOOL sendACLAdvisories = NO; + @interface SOGoObject(Content) -- (NSString *)contentAsString; +- (NSString *) contentAsString; @end @interface SoClassSecurityInfo (SOGoAcls) @@ -160,18 +164,13 @@ @implementation SOGoObject -static BOOL kontactGroupDAV = YES; - -+ (int)version { - return 0; -} - + (void) initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + NSUserDefaults *ud; - kontactGroupDAV = - [ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"] ? NO : YES; + ud = [NSUserDefaults standardUserDefaults]; + kontactGroupDAV = ![ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"]; + sendACLAdvisories = [ud boolForKey: @"SOGoACLsSendEMailNotifications"]; // SoClass security declarations @@ -201,7 +200,7 @@ static BOOL kontactGroupDAV = YES; float f; if (pid == 0) - { /* break if we fork ;-) */ + { pid = getpid(); rndm = random(); } @@ -889,6 +888,44 @@ static BOOL kontactGroupDAV = YES; return [container subscriptionRoles]; } +- (BOOL) addUserInAcls: (NSString *) uid +{ + BOOL result; + + if ([uid length] + && ![uid isEqualToString: [self ownerInContext: nil]] + && [[LDAPUserManager sharedUserManager] + contactInfosForUserWithUIDorEmail: uid]) + { + [self setRoles: [self aclsForUser: uid] + forUser: uid]; + if (sendACLAdvisories) + [self sendACLAdditionAdvisoryToUser: uid]; + result = YES; + } + else + result = NO; + + return result; +} + +- (BOOL) removeUserFromAcls: (NSString *) uid +{ + BOOL result; + + if ([uid length]) + { + [self removeAclsForUsers: [NSArray arrayWithObject: uid]]; + if (sendACLAdvisories) + [self sendACLRemovalAdvisoryToUser: uid]; + result = YES; + } + else + result = NO; + + return result; +} + - (NSArray *) aclUsers { [self subclassResponsibility: _cmd]; @@ -1111,4 +1148,184 @@ static BOOL kontactGroupDAV = YES; return newClasses; } +/* dav acls */ +- (NSArray *) davNamespaces +{ + return [NSArray arrayWithObject: + @"urn:inverse:params:xml:ns:inverse-dav"]; +} + +- (NSString *) davRecordForUser: (NSString *) user +{ + NSMutableString *userRecord; + SOGoUser *sogoUser; + NSString *cn, *email; + + userRecord = [NSMutableString string]; + + [userRecord appendFormat: @"%@", + [user stringByEscapingXMLString]]; + sogoUser = [SOGoUser userWithLogin: user roles: nil]; + cn = [sogoUser cn]; + if (!cn) + cn = user; + [userRecord appendFormat: @"%@", + [cn stringByEscapingXMLString]]; + email = [[sogoUser allEmails] objectAtIndex: 0]; + if (email) + [userRecord appendFormat: @"%@", + [email stringByEscapingXMLString]]; + + return userRecord; +} + +- (NSString *) _davAclUserListQuery +{ + NSMutableString *userList; + NSString *defaultUserID, *currentUserID; + NSEnumerator *users; + + userList = [NSMutableString string]; + + defaultUserID = [self defaultUserID]; + if ([defaultUserID length]) + [userList appendFormat: @"%@", + [defaultUserID stringByEscapingXMLString]]; + users = [[self aclUsers] objectEnumerator]; + while ((currentUserID = [users nextObject])) + if (![currentUserID isEqualToString: defaultUserID]) + [userList appendFormat: @"%@", + [self davRecordForUser: currentUserID]]; + + return userList; +} + +- (NSString *) _davAclUserRoles: (NSString *) userName +{ + NSArray *roles; + + roles = [[self aclsForUser: userName] stringsWithFormat: @"<%@/>"]; + + return [roles componentsJoinedByString: @""]; +} + +- (NSArray *) _davGetRolesFromRequest: (id ) node +{ + NSMutableArray *roles; + id childNodes; + NSString *currentRole; + unsigned int count, max; + + roles = [NSMutableArray array]; + childNodes = [node childNodes]; + max = [childNodes length]; + for (count = 0; count < max; count++) + { + currentRole = [[childNodes objectAtIndex: count] nodeName]; + [roles addObject: currentRole]; + } + + return roles; +} + +- (NSString *) _davAclActionFromQuery: (id ) document +{ + id node, userAttr; + id attrs; + NSString *nodeName, *result, *response, *user; + + node = [[document documentElement] firstChild]; + nodeName = [node nodeName]; + if ([nodeName isEqualToString: @"user-list"]) + result = [self _davAclUserListQuery]; + else if ([nodeName isEqualToString: @"roles"]) + { + attrs = [node attributes]; + userAttr = [attrs namedItem: @"user"]; + user = [userAttr nodeValue]; + if ([user length]) + result = [self _davAclUserRoles: user]; + else + result = nil; + } + else if ([nodeName isEqualToString: @"set-roles"]) + { + attrs = [node attributes]; + userAttr = [attrs namedItem: @"user"]; + user = [userAttr nodeValue]; + if ([user length]) + { + [self setRoles: [self _davGetRolesFromRequest: node] + forUser: user]; + result = @""; + } + else + result = nil; + } + else if ([nodeName isEqualToString: @"add-user"]) + { + attrs = [node attributes]; + userAttr = [attrs namedItem: @"user"]; + user = [userAttr nodeValue]; + if ([self addUserInAcls: user]) + result = @""; + else + result = nil; + } + else if ([nodeName isEqualToString: @"remove-user"]) + { + attrs = [node attributes]; + userAttr = [attrs namedItem: @"user"]; + user = [userAttr nodeValue]; + if ([self removeUserFromAcls: user]) + result = @""; + else + result = nil; + } + else + result = nil; + + if (result) + { + if ([result length]) + response = [NSString stringWithFormat: @"<%@>%@", + nodeName, result, nodeName]; + else + response = @""; + } + else + response = nil; + + return response; +} + +- (id) davAclQuery: (WOContext *) queryContext +{ + WOResponse *r; + id document; + NSString *content; + + r = [queryContext response]; + [r setContentEncoding: NSUTF8StringEncoding]; + [r setHeader: @"text/xml; charset=\"utf-8\"" forKey: @"content-type"]; + [r setHeader: @"no-cache" forKey: @"pragma"]; + [r setHeader: @"no-cache" forKey: @"cache-control"]; + + document = [[context request] contentAsDOMDocument]; + content = [self _davAclActionFromQuery: document]; + if (content) + { + [r setStatus: 207]; + if ([content length]) + { + [r appendContentString: @"\r\n"]; + [r appendContentString: content]; + } + } + else + [r setStatus: 400]; + + return r; +} + @end /* SOGoObject */ diff --git a/UI/Common/UIxObjectActions.m b/UI/Common/UIxObjectActions.m index 05dd40a2c..dec91048a 100644 --- a/UI/Common/UIxObjectActions.m +++ b/UI/Common/UIxObjectActions.m @@ -33,43 +33,19 @@ #import "UIxObjectActions.h" -static BOOL sendACLAdvisories = NO; - @implementation UIxObjectActions -+ (void) initialize -{ - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - sendACLAdvisories = [ud boolForKey: @"SOGoACLsSendEMailNotifications"]; -} - - (WOResponse *) addUserInAclsAction { WOResponse *response; - WORequest *request; NSString *uid; unsigned int code; - LDAPUserManager *um; - SOGoObject *clientObject; - code = 403; - request = [context request]; - uid = [request formValueForKey: @"uid"]; - if ([uid length] > 0) - { - um = [LDAPUserManager sharedUserManager]; - if ([um contactInfosForUserWithUIDorEmail: uid]) - { - clientObject = [self clientObject]; - [clientObject setRoles: [clientObject aclsForUser: uid] - forUser: uid]; - if (sendACLAdvisories) - [clientObject sendACLAdditionAdvisoryToUser: uid]; - code = 204; - } - } + uid = [[context request] formValueForKey: @"uid"]; + if ([[self clientObject] addUserInAcls: uid]) + code = 204; + else + code = 403; response = [context response]; [response setStatus: code]; @@ -80,27 +56,14 @@ static BOOL sendACLAdvisories = NO; - (WOResponse *) removeUserFromAclsAction { WOResponse *response; - WORequest *request; NSString *uid; unsigned int code; - LDAPUserManager *um; - SOGoObject *co; - code = 403; - request = [context request]; - uid = [request formValueForKey: @"uid"]; - if ([uid length] > 0) - { - um = [LDAPUserManager sharedUserManager]; - if ([um contactInfosForUserWithUIDorEmail: uid]) - { - co = [self clientObject]; - [co removeAclsForUsers: [NSArray arrayWithObject: uid]]; - if (sendACLAdvisories) - [co sendACLRemovalAdvisoryToUser: uid]; - code = 204; - } - } + uid = [[context request] formValueForKey: @"uid"]; + if ([[self clientObject] removeUserFromAcls: uid]) + code = 204; + else + code = 403; response = [context response]; [response setStatus: code];