From 2e77b3e6b1064403c8518d4c6bae6be8a7cdd3de Mon Sep 17 00:00:00 2001 From: stuconnolly Date: Tue, 9 Mar 2010 15:25:36 +0000 Subject: Fix an exception in the user manager caused by sorting the users list by making the user manager KVO compliant for the sort descriptors array. Also, add a bunch of comments and general tidy up on SPUserManager.m. --- Interfaces/English.lproj/UserManagerView.xib | 45 ++++--- Source/SPUserManager.h | 8 +- Source/SPUserManager.m | 176 ++++++++++++++++++--------- 3 files changed, 147 insertions(+), 82 deletions(-) diff --git a/Interfaces/English.lproj/UserManagerView.xib b/Interfaces/English.lproj/UserManagerView.xib index cd7a2ab2..36c8dd39 100644 --- a/Interfaces/English.lproj/UserManagerView.xib +++ b/Interfaces/English.lproj/UserManagerView.xib @@ -21,7 +21,7 @@ YES - + YES @@ -99,7 +99,7 @@ -2147483392 - {{-26, 0}, {16, 17}} + {{183, 0}, {12, 17}} @@ -134,7 +134,7 @@ 337772096 - 2048 + 2304 Text Cell LucidaGrande @@ -212,21 +212,22 @@ -2147483392 - {{246, 17}, {15, 308}} + {{183, 17}, {11, 456}} + 256 _doScroller: - 0.99690401554107666 + 0.96487605571746826 -2147483392 - {{1, 325}, {245, 15}} + {{0, 473}, {183, 11}} - 1 + 257 _doScroller: - 0.99616861343383789 + 0.99487179517745972 @@ -434,7 +435,7 @@ General - + 256 YES @@ -563,6 +564,7 @@ {{10, 33}, {511, 414}} + General @@ -1396,7 +1398,7 @@ Schema Privileges - + 256 YES @@ -1841,7 +1843,6 @@ {{10, 33}, {511, 414}} - Schema Privileges @@ -2118,13 +2119,13 @@ - + 0 YES YES - + @@ -4187,11 +4188,6 @@ - - 578 - - - 579 @@ -5279,6 +5275,11 @@ + + 923 + + + @@ -5398,7 +5399,6 @@ 544.IBPluginDependency 545.IBNumberFormatterLocalizesFormatMetadataKey 545.IBPluginDependency - 578.IBPluginDependency 579.IBPluginDependency 580.IBAttributePlaceholdersKey 580.IBPluginDependency @@ -5483,11 +5483,11 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{434, 346}, {752, 506}} + {{240, 174}, {752, 506}} com.apple.InterfaceBuilder.CocoaPlugin - {{434, 346}, {752, 506}} + {{240, 174}, {752, 506}} {752, 506} @@ -5578,7 +5578,6 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.brandonwalkin.BWToolkit ToolTip @@ -5667,7 +5666,7 @@ - 922 + 923 diff --git a/Source/SPUserManager.h b/Source/SPUserManager.h index 0bcc82bd..86c19664 100644 --- a/Source/SPUserManager.h +++ b/Source/SPUserManager.h @@ -55,10 +55,13 @@ IBOutlet NSTextField *userNameTextField; IBOutlet BWAnchoredButtonBar *splitViewButtonBar; - + NSMutableArray *schemas; NSMutableArray *grantedSchemaPrivs; NSMutableArray *availablePrivs; + + NSArray *treeSortDescriptors; + NSSortDescriptor *treeSortDescriptor; } @property (nonatomic, retain) MCPConnection *mySqlConnection; @@ -67,6 +70,7 @@ @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext; @property (nonatomic, retain) NSMutableDictionary *privsSupportedByServer; +@property (nonatomic, retain) NSArray *treeSortDescriptors; @property (nonatomic, retain) NSMutableArray *schemas; @property (nonatomic, retain) NSMutableArray *grantedSchemaPrivs; @property (nonatomic, retain) NSMutableArray *availablePrivs; @@ -99,6 +103,4 @@ - (BOOL)grantPrivilegesToUser:(NSManagedObject *)user; - (BOOL)grantDbPrivilegesWithPrivilege:(NSManagedObject *)user; -- (NSArray *)treeSortDescriptors; - @end diff --git a/Source/SPUserManager.m b/Source/SPUserManager.m index 0cc2b125..9ce7e5d4 100644 --- a/Source/SPUserManager.m +++ b/Source/SPUserManager.m @@ -62,6 +62,7 @@ @synthesize schemas; @synthesize grantedSchemaPrivs; @synthesize availablePrivs; +@synthesize treeSortDescriptors; - (id)init { @@ -88,27 +89,6 @@ return self; } -/** - * Dealloc. Get rid of everything. - */ -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSManagedObjectContextDidSaveNotification - object:nil]; - [managedObjectContext release]; - [persistentStoreCoordinator release]; - [managedObjectModel release]; - [privColumnToGrantMap release]; - [mySqlConnection release]; - [privsSupportedByServer release]; - [schemas release]; - [availablePrivs release]; - [grantedSchemaPrivs release]; - - [super dealloc]; -} - /** * UI specific items to set up when the window loads. This is different than awakeFromNib * as it's only called once. @@ -128,6 +108,11 @@ [self _initializeUsers]; [self _initializeSchemaPrivs]; + + treeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES]; + + [self setTreeSortDescriptors:[NSArray arrayWithObject:treeSortDescriptor]]; + [super windowDidLoad]; } @@ -193,11 +178,12 @@ isInitializing = FALSE; } +/** + * Initialize the outline view tree. The NSOutlineView gets it's data from a NSTreeController which gets + * it's data from the SPUser Entity objects in the current managedObjectContext. + */ - (void)_initializeTree:(NSArray *)items -{ - // The NSOutlineView gets it's data from a NSTreeController which gets - // it's data from the SPUser Entity objects in the current managedObjectContext. - +{ // Go through each item that contains a dictionary of key-value pairs // for each user currently in the database. for(NSInteger i = 0; i < [items count]; i++) @@ -243,12 +229,16 @@ } [parentResults release]; } + // Reload data of the outline view with the changes. [outlineView reloadData]; [treeController rearrangeObjects]; } -- (void) _initializeAvailablePrivs +/** + * Initialize the available user privileges. + */ +- (void)_initializeAvailablePrivs { // Initialize available privileges NSManagedObjectContext *moc = self.managedObjectContext; @@ -256,6 +246,7 @@ inManagedObjectContext:moc]; NSArray *props = [privEntityDescription attributeKeys]; [availablePrivs removeAllObjects]; + for (NSString *prop in props) { if ([prop hasSuffix:@"_priv"] && [[self.privsSupportedByServer objectForKey:prop] boolValue]) @@ -266,25 +257,31 @@ } } + [availableController rearrangeObjects]; - } + +/** + * Initialize the available schema privileges. + */ - (void)_initializeSchemaPrivs { // Initialize Databases MCPResult *results = [self.mySqlConnection listDBs]; + if ([results numOfRows]) { [results dataSeek:0]; } + for (int i = 0; i < [results numOfRows]; i++) { [schemas addObject:[results fetchRowAsDictionary]]; } - [schemaController rearrangeObjects]; - [self _initializeAvailablePrivs]; - + [schemaController rearrangeObjects]; + [self _initializeAvailablePrivs]; } + /** * Set NSManagedObject with values from the passed in dictionary. */ @@ -325,6 +322,9 @@ } } +/** + * Initialize the schema privileges for the supplied child object. + */ - (void)_initializeSchemaPrivsForChild:(NSManagedObject *)child { // Assumes that the child has already been initialized with values from the @@ -361,7 +361,6 @@ NSMutableSet *privs = [child mutableSetValueForKey:@"schema_privileges"]; [privs addObject:dbPriv]; } - } /** @@ -531,13 +530,6 @@ return YES; } -- (NSArray *)treeSortDescriptors -{ - NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES] autorelease]; - - return [NSArray arrayWithObject:descriptor]; -} - #pragma mark - #pragma mark General IBAction methods @@ -614,9 +606,11 @@ @catch (NSException * e) { } } - } +/** + * Adds a new user to the current database. + */ - (IBAction)addUser:(id)sender { // Adds a new SPUser objects to the managedObjectContext and sets default values @@ -636,6 +630,9 @@ [[self window] makeFirstResponder:userNameTextField]; } +/** + * Removes the currently selected user from the current database. + */ - (IBAction)removeUser:(id)sender { NSString *username = [[[treeController selectedObjects] objectAtIndex:0] @@ -646,9 +643,13 @@ { [child setPrimitiveValue:username forKey:@"user"]; } + [treeController remove:sender]; } +/** + * Adds a new host to the currently selected user. + */ - (IBAction)addHost:(id)sender { if ([[treeController selectedObjects] count] > 0) @@ -658,6 +659,7 @@ [self _selectParentFromSelection]; } } + [treeController addChild:sender]; // The newly added item will be selected as it is added, but only after the next iteration of the @@ -665,12 +667,17 @@ [self performSelector:@selector(editNewHost) withObject:nil afterDelay:0.1]; } -// Perform a deferred edit of the currently selected row. +/** + * Perform a deferred edit of the currently selected row. + */ - (void)editNewHost { [outlineView editColumn:0 row:[outlineView selectedRow] withEvent:nil select:TRUE]; } +/** + * Removes the currently selected host from it's parent user. + */ - (IBAction)removeHost:(id)sender { // Set the username on the child so that it's accessabile when building @@ -679,6 +686,7 @@ NSManagedObject *parent = [child valueForKey:@"parent"]; [child setPrimitiveValue:[[child valueForKey:@"parent"] valueForKey:@"user"] forKey:@"user"]; [treeController remove:sender]; + if ([[parent valueForKey:@"children"] count] == 0) { NSAlert *alert = [NSAlert alertWithMessageText:@"User doesn't have any hosts." @@ -690,6 +698,9 @@ } } +/** + * Adds a new schema privilege. + */ - (IBAction)addSchemaPriv:(id)sender { NSArray *selectedObjects = [availableController selectedObjects]; @@ -700,6 +711,9 @@ [self _setSchemaPrivValues:selectedObjects enabled:YES]; } +/** + * Removes a schema privilege. + */ - (IBAction)removeSchemaPriv:(id)sender { NSArray *selectedObjects = [grantedController selectedObjects]; @@ -708,9 +722,11 @@ [grantedController removeObjects:selectedObjects]; [grantedTableView reloadData]; [self _setSchemaPrivValues:selectedObjects enabled:NO]; - } +/** + * Refreshes the current list of users. + */ - (IBAction)refresh:(id)sender { if ([self.managedObjectContext hasChanges]) @@ -720,18 +736,20 @@ alternateButton:NSLocalizedString(@"Cancel", @"cancel button") otherButton:nil informativeTextWithFormat:@"Window has changes. All changes will be lost!"]; + [alert setAlertStyle:NSWarningAlertStyle]; + if ([alert runModal] == NSAlertAlternateReturn) // cancel { return; } } + [self.managedObjectContext reset]; [grantedSchemaPrivs removeAllObjects]; [grantedTableView reloadData]; [self _initializeAvailablePrivs]; [treeController fetch:nil]; - } - (void)_setSchemaPrivValues:(NSArray *)objects enabled:(BOOL)enabled @@ -770,8 +788,8 @@ NSMutableSet *privs = [selectedHost mutableSetValueForKey:@"schema_privileges"]; [privs addObject:priv]; } - } + - (void)_clearData { [managedObjectContext reset]; @@ -779,6 +797,9 @@ managedObjectContext = nil; } +/** + * Menu item validation. + */ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { // Only allow removing hosts of a host node is selected. @@ -881,7 +902,8 @@ - (BOOL)updateUsers:(NSArray *)updatedUsers { - for (NSManagedObject *user in updatedUsers) { + for (NSManagedObject *user in updatedUsers) + { if ([[[user entity] name] isEqualToString:@"Privileges"]) { [self grantDbPrivilegesWithPrivilege:user]; @@ -905,7 +927,6 @@ } else { [self grantPrivilegesToUser:user]; } - } return YES; @@ -914,6 +935,7 @@ - (BOOL)deleteUsers:(NSArray *)deletedUsers { NSMutableString *droppedUsers = [NSMutableString string]; + for (NSManagedObject *user in deletedUsers) { if (![[[user entity] name] isEqualToString:@"Privileges"] && [user valueForKey:@"host"] != nil) @@ -924,9 +946,11 @@ } } + droppedUsers = [[droppedUsers substringToIndex:[droppedUsers length]-2] mutableCopy]; [self.mySqlConnection queryString:[NSString stringWithFormat:@"DROP USER %@", droppedUsers]]; [droppedUsers release]; + return TRUE; } @@ -966,14 +990,13 @@ if ([self checkAndDisplayMySqlError]) [self grantPrivilegesToUser:user]; } - } + return YES; } /** - * Grant or revoke db privileges to the given user - * + * Grant or revoke DB privileges for the supplied user. */ - (BOOL)grantDbPrivilegesWithPrivilege:(NSManagedObject *)schemaPriv { @@ -981,6 +1004,7 @@ NSMutableArray *revokePrivileges = [NSMutableArray array]; NSString *dbName = [schemaPriv valueForKey:@"db"]; + for (NSString *key in self.privsSupportedByServer) { if (![key hasSuffix:@"_priv"]) continue; @@ -997,6 +1021,7 @@ @catch (NSException * e) { } } + // Grant privileges if ([grantPrivileges count] > 0) { @@ -1021,11 +1046,13 @@ DLog(@"%@", revokeStatement); [self.mySqlConnection queryString:revokeStatement]; [self checkAndDisplayMySqlError]; - } + } + return TRUE; } + /** - * Grant or revoke privileges to the given user + * Grant or revoke privileges for the supplied user. */ - (BOOL)grantPrivilegesToUser:(NSManagedObject *)user { @@ -1052,6 +1079,7 @@ @catch (NSException * e) { } } + // Grant privileges if ([grantPrivileges count] > 0) { @@ -1077,7 +1105,7 @@ } } - for(NSManagedObject *priv in [user valueForKey:@"schema_privileges"]) + for (NSManagedObject *priv in [user valueForKey:@"schema_privileges"]) { [self grantDbPrivilegesWithPrivilege:priv]; } @@ -1085,8 +1113,10 @@ return TRUE; } -// Gets any NSManagedObject (SPUser) from the managedObjectContext that may -// already exist with the given username. +/** + * Gets any NSManagedObject (SPUser) from the managedObjectContext that may + * already exist with the given username. + */ - (NSArray *)_fetchUserWithUserName:(NSString *)username { NSManagedObjectContext *moc = [self managedObjectContext]; @@ -1100,6 +1130,7 @@ NSError *error = nil; NSArray *array = [moc executeFetchRequest:request error:&error]; + if (error != nil) { [[NSApplication sharedApplication] presentError:error]; @@ -1120,15 +1151,18 @@ NSError *error = nil; NSArray *array = [moc executeFetchRequest:request error:&error]; + if (error != nil) { [[NSApplication sharedApplication] presentError:error]; } - return array; + return array; } -// Creates a new NSManagedObject and inserts it into the managedObjectContext. +/** + * Creates a new NSManagedObject and inserts it into the managedObjectContext. + */ - (NSManagedObject *)_createNewSPUser { NSManagedObject *user = [NSEntityDescription insertNewObjectForEntityForName:@"SPUser" @@ -1137,7 +1171,9 @@ return user; } -// Displays alert panel if there is an error condition currently on the mySqlConnection +/** + * Displays an alert panel if there was an error condition on the MySQL connection. + */ - (BOOL)checkAndDisplayMySqlError { if (![[self.mySqlConnection getLastErrorMessage] isEqualToString:@""]) { @@ -1208,14 +1244,18 @@ [grantedSchemaPrivs removeAllObjects]; [grantedTableView reloadData]; [self _initializeAvailablePrivs]; + if ([[treeController selectedObjects] count] > 0 && [[schemaController selectedObjects] count] > 0) { NSManagedObject *user = [[treeController selectedObjects] objectAtIndex:0]; + // Check to see if the user host node was selected if ([user valueForKey:@"host"]) { NSString *selectedSchema = [[[schemaController selectedObjects] objectAtIndex:0] valueForKey:@"Database"]; NSArray *results = [self _fetchPrivsWithUser:[[user parent] valueForKey:@"user"] schema:selectedSchema host:[user valueForKey:@"host"]]; + if ([results count] > 0) { NSManagedObject *priv = [results objectAtIndex:0]; + for (NSPropertyDescription *property in [priv entity]) { if ([[property name] hasSuffix:@"_priv"] && [[priv valueForKey:[property name]] boolValue]) @@ -1266,4 +1306,28 @@ } } +#pragma mark - + +/** + * Dealloc. Get rid of everything. + */ +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSManagedObjectContextDidSaveNotification + object:nil]; + [managedObjectContext release]; + [persistentStoreCoordinator release]; + [managedObjectModel release]; + [privColumnToGrantMap release]; + [mySqlConnection release]; + [privsSupportedByServer release]; + [schemas release]; + [availablePrivs release]; + [grantedSchemaPrivs release]; + [treeSortDescriptor release]; + + [super dealloc]; +} + @end -- cgit v1.2.3