// // EditPermissionsViewController.m // pithos-ios // // Copyright 2011 GRNET S.A. All rights reserved. // // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the following // conditions are met: // // 1. Redistributions of source code must retain the above // copyright notice, this list of conditions and the following // disclaimer. // // 2. Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and // documentation are those of the authors and should not be // interpreted as representing official policies, either expressed // or implied, of GRNET S.A. #import "EditPermissionsViewController.h" #import "AccountManager.h" #import "UIViewController+Conveniences.h" #import "FolderViewController.h" #import "Folder.h" #import "PithosUtilities.h" #import "APICallback.h" #define kUser 0 #define kPermissions 1 #define kSavePermissions 2 #define kRemovePermissions 3 @implementation EditPermissionsViewController @synthesize account, container, object; @synthesize user, readPermissionSelected, writePermissionSelected, permissions; @synthesize oldPermissionsString; @synthesize newPermissionsEntry, removePermissionsEnabled; @synthesize folderViewController, objectIsFolder; - (void)dealloc { [account release]; [container release]; [object release]; [user release]; [permissions release]; [oldPermissionsString release]; [activityIndicatorView release]; [super dealloc]; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidUnload { [super viewDidUnload]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { if (removePermissionsEnabled) return 4; else return 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == kPermissions) return 2; else return 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } if (indexPath.section == kUser) { UITextField *textField = nil; for (id subView in cell.contentView.subviews) { if ([subView isKindOfClass:[UITextField class]]) { textField = (UITextField *)subView; } } if (textField == nil) { CGRect bounds = [cell.contentView bounds]; CGRect rect = CGRectInset(bounds, 10.0, 10.0); textField = [[UITextField alloc] initWithFrame:rect]; [textField setFrame:rect]; } [textField setClearButtonMode:UITextFieldViewModeWhileEditing]; [textField setBackgroundColor:[UIColor clearColor]]; [textField setOpaque:YES]; [textField setAutocorrectionType:UITextAutocorrectionTypeNo]; [textField setAutocapitalizationType:UITextAutocapitalizationTypeNone]; [textField setDelegate:self]; textField.placeholder = @"User or User:Group"; textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; textField.text = self.user; cell.selectionStyle = UITableViewCellSelectionStyleNone; [cell.contentView addSubview:textField]; cell.selectionStyle = UITableViewCellSelectionStyleNone; } else if (indexPath.section == kPermissions) { cell.selectionStyle = UITableViewCellSelectionStyleNone; if (indexPath.row == 0) { cell.textLabel.text = @"Read Only"; if (readPermissionSelected) cell.accessoryType = UITableViewCellAccessoryCheckmark; else cell.accessoryType = UITableViewCellAccessoryNone; } else { cell.textLabel.text = @"Read/Write"; if (writePermissionSelected) cell.accessoryType = UITableViewCellAccessoryCheckmark; else cell.accessoryType = UITableViewCellAccessoryNone; } } else if (indexPath.section == kSavePermissions) { cell.textLabel.text = @"Save"; cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleBlue; } else if (indexPath.section == kRemovePermissions) { cell.textLabel.text = @"Remove"; cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleBlue; } return cell; } #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section != kUser) [self.view endEditing:YES]; NSString *newUserName; NSIndexPath *userCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kUser]; UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:userCellIndexPath]; UITextField *textField = [[cell.contentView subviews] objectAtIndex:0]; newUserName = textField.text; if (![self userInputIsValid:newUserName]) { [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; return; } if (indexPath.section == kPermissions) { UITableViewCell *readPermissionsCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kPermissions]]; UITableViewCell *writePermissionsCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:kPermissions]]; if (indexPath.row == 0) { if (!readPermissionSelected) { readPermissionSelected = YES; if (writePermissionSelected) { writePermissionSelected = FALSE; writePermissionsCell.accessoryType = UITableViewCellAccessoryNone; } readPermissionsCell.accessoryType = UITableViewCellAccessoryCheckmark; } } else if (indexPath.row == 1) { if (!writePermissionSelected) { writePermissionSelected = YES; if (readPermissionSelected) { readPermissionSelected = FALSE; readPermissionsCell.accessoryType = UITableViewCellAccessoryNone; } writePermissionsCell.accessoryType = UITableViewCellAccessoryCheckmark; } } } else if (indexPath.section == kSavePermissions) { if (!readPermissionSelected && !writePermissionSelected) { [self alert:@"Cannot save permissions" message:@"Please select permissions type"]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; return; } [self.permissions removeObjectForKey:self.user]; if (readPermissionSelected) [self.permissions setObject:@"read" forKey:newUserName]; else if (writePermissionSelected) [self.permissions setObject:@"write" forKey:newUserName]; self.user = newUserName; self.oldPermissionsString = object.sharing; object.sharing = [self buildPermissionsString]; if (objectIsFolder && ![PithosUtilities isContentTypeDirectory:object.contentType]) { if (((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) && [folderViewController.parentFolderViewController.folder.objects objectForKey:object.name]) || ((UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) && [folderViewController.folder.objects objectForKey:object.name])) { NSString *alertMessage = [NSString stringWithFormat:@"In order to apply the changes in '%@', the object at the same path must be replaced. Continue?",object.name]; NSString *alertTitle = @"Apply changes"; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle message:alertMessage delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; [alert show]; [alert release]; return; } else { NSString *activityMessage = @"Applying permissions..."; [activityIndicatorView release]; activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage]; [activityIndicatorView addToView:self.view]; object.name = object.fullPath; object.contentType = @"application/directory"; object.data = [NSData data]; [self createNewFolder]; return; } } NSString *activityMessage = @"Applying permissions..."; [activityIndicatorView release]; activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage]; [activityIndicatorView addToView:self.view]; [[self.account.manager writeObjectMetadata:container object:object] success:^(OpenStackRequest *request) { [activityIndicatorView removeFromSuperview]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; removePermissionsEnabled = YES; [self.tableView reloadData]; if (objectIsFolder || (account.shared && ![oldPermissionsString isEqualToString:object.sharing])) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [self.folderViewController refreshButtonPressed:nil]; } else { self.folderViewController.needsRefreshing = YES; } } } failure:^(OpenStackRequest *request) { object.sharing = self.oldPermissionsString; readPermissionSelected = !readPermissionSelected; writePermissionSelected = !writePermissionSelected; if (readPermissionSelected) [self.permissions setObject:@"read" forKey:user]; else if (writePermissionSelected) [self.permissions setObject:@"write" forKey:user]; [activityIndicatorView removeFromSuperview]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; [self.tableView reloadData]; [self alert:@"There was a problem applying the permissions." request:request]; }]; } else if (indexPath.section == kRemovePermissions) { NSString *activityMessage = @"Removing permissions..."; [activityIndicatorView release]; activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage]; [activityIndicatorView addToView:self.view]; [permissions removeObjectForKey:user]; self.oldPermissionsString = object.sharing; object.sharing = [self buildPermissionsString]; [[self.account.manager writeObjectMetadata:container object:object] success:^(OpenStackRequest *request) { self.user = @""; self.readPermissionSelected = FALSE; self.writePermissionSelected = FALSE; removePermissionsEnabled = NO; [self.tableView reloadData]; [activityIndicatorView removeFromSuperview]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; if (objectIsFolder || (account.shared && ![oldPermissionsString isEqualToString:object.sharing])) { self.folderViewController.needsRefreshing = YES; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) [self.folderViewController refreshButtonPressed:nil]; else self.folderViewController.refreshWhenAppeared = YES; } } failure:^(OpenStackRequest *request) { object.sharing = self.oldPermissionsString; if (readPermissionSelected) [self.permissions setObject:@"read" forKey:user]; else if (writePermissionSelected) [self.permissions setObject:@"write" forKey:user]; [activityIndicatorView removeFromSuperview]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; [self.tableView reloadData]; [self alert:@"There was a problem removing the permissions." request:request]; }]; } } #pragma mark - Textfield delegate - (BOOL)textFieldShouldReturn:(UITextField *)textField { [self userInputIsValid:textField.text]; [textField resignFirstResponder]; return YES; } #pragma mark - Alertview delegate - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 1) { NSString *activityMessage = @"Applying permissions..."; [activityIndicatorView release]; activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage]; [activityIndicatorView addToView:self.view]; object.name = object.fullPath; object.contentType = @"application/directory"; object.data = [NSData data]; [self createNewFolder]; } else { [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; } } - (void)createNewFolder { [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:nil] success:^(OpenStackRequest *request) { Folder *newFolder = [[Folder alloc] init]; newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject]; newFolder.parent = folderViewController.folder; newFolder.sharing = folderViewController.folder.sharing; [folderViewController.folder addFolder:newFolder]; [activityIndicatorView removeFromSuperview]; [newFolder release]; [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; removePermissionsEnabled = YES; [self.tableView reloadData]; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [self.folderViewController refreshButtonPressed:nil]; } else { self.folderViewController.needsRefreshing = YES; self.folderViewController.refreshWhenAppeared = YES; } } failure:^(OpenStackRequest *request) { object.sharing = self.oldPermissionsString; readPermissionSelected = !readPermissionSelected; writePermissionSelected = !writePermissionSelected; if (readPermissionSelected) [self.permissions setObject:@"read" forKey:user]; else if (writePermissionSelected) [self.permissions setObject:@"write" forKey:user]; [activityIndicatorView removeFromSuperview]; [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; [self.tableView reloadData]; [self alert:@"There was a problem applying the permissions." request:request]; }]; } #pragma mark - helper methods - (NSString *)buildPermissionsString { NSString *readPermissionsString = @""; NSString *writePermissionsString = @""; for (NSString *aUser in [permissions allKeys]) { if ([[permissions objectForKey:aUser] isEqual:@"read"]) { if ([readPermissionsString length] == 0) readPermissionsString = [NSString stringWithFormat:@"read=%@", aUser]; else readPermissionsString = [NSString stringWithFormat:@"%@,%@", readPermissionsString ,aUser]; } else if ([[permissions objectForKey:aUser] isEqual:@"write"]) { if ([writePermissionsString length] == 0) writePermissionsString = [NSString stringWithFormat:@"write=%@", aUser]; else writePermissionsString = [NSString stringWithFormat:@"%@,%@", writePermissionsString, aUser]; } } if ([writePermissionsString length] == 0) return readPermissionsString; else if ([readPermissionsString length] == 0) return writePermissionsString; else return [NSString stringWithFormat:@"%@;%@", readPermissionsString, writePermissionsString]; } - (BOOL) userInputIsValid: (NSString *) input { if ([input length] == 0 || [[input stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0 ) { [self alert:@"Invalid input" message:@"User name cannot be empty"]; return NO; } else { NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"=,;"]; if ([input rangeOfCharacterFromSet:set].location != NSNotFound) { [self alert:@"Invalid input" message:@"User name cannot contain '=', ',' or ';'"]; return NO; } else { return YES; } } return YES; } @end