From d7ebbe9b1e17c69a35e7ff05b5fa265e180fcebf Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Mon, 3 May 2010 19:16:10 +0000 Subject: - Merge in fixes from trunk for final release - incoporates r2175, r2177, r2184, r2198, r2200, r2203, r2205 and r2206. --- Interfaces/English.lproj/UserManagerView.xib | 112 +++++++++++++++++---------- Source/SPExtendedTableInfo.m | 3 +- Source/SPSSHTunnel.m | 4 + Source/SPUserManager.m | 95 ++++++++++++++++++----- Source/SPUserManager.xcdatamodel/elements | Bin 127771 -> 131784 bytes Source/SPUserManager.xcdatamodel/layout | Bin 9663 -> 9663 bytes Source/TableContent.m | 18 +++-- Source/TableSource.m | 14 +++- 8 files changed, 172 insertions(+), 74 deletions(-) diff --git a/Interfaces/English.lproj/UserManagerView.xib b/Interfaces/English.lproj/UserManagerView.xib index 36c8dd39..d28c0761 100644 --- a/Interfaces/English.lproj/UserManagerView.xib +++ b/Interfaces/English.lproj/UserManagerView.xib @@ -2,10 +2,10 @@ 1050 - 10C540 - 740 - 1038.25 - 458.00 + 10D2094 + 762 + 1038.29 + 460.00 YES @@ -15,18 +15,17 @@ YES - 740 - 1.2.2 + 762 + 1.2.5 YES - YES - com.brandonwalkin.BWToolkit com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit YES @@ -56,10 +55,10 @@ User Managment NSWindow - {3.40282e+38, 3.40282e+38} + {1.79769e+308, 1.79769e+308} {752, 506} - + 256 YES @@ -148,7 +147,7 @@ controlBackgroundColor 3 - MC42NjY2NjY2ODY1AA + MC42NjY2NjY2NjY3AA @@ -204,7 +203,6 @@ {{0, 17}, {194, 467}} - 4 @@ -238,7 +236,6 @@ {194, 17} - 4 @@ -247,7 +244,6 @@ {{0, 22}, {194, 484}} - 560 @@ -400,6 +396,7 @@ + 4 YES 1 YES @@ -435,7 +432,7 @@ General - + 256 YES @@ -564,7 +561,6 @@ {{10, 33}, {511, 414}} - General @@ -1398,7 +1394,7 @@ Schema Privileges - + 256 YES @@ -1480,7 +1476,6 @@ {{1, 17}, {130, 363}} - 4 @@ -1515,7 +1510,6 @@ {{1, 0}, {130, 17}} - 4 @@ -1524,7 +1518,6 @@ {{17, 17}, {132, 381}} - 562 @@ -1611,7 +1604,6 @@ {{1, 17}, {130, 363}} - 4 @@ -1645,7 +1637,6 @@ {{1, 0}, {130, 17}} - 4 @@ -1654,7 +1645,6 @@ {{157, 17}, {132, 381}} - 562 @@ -1740,7 +1730,6 @@ {{1, 17}, {130, 363}} - 4 @@ -1775,7 +1764,6 @@ {{1, 0}, {130, 17}} - 4 @@ -1784,7 +1772,6 @@ {{362, 17}, {132, 381}} - 562 @@ -1843,6 +1830,7 @@ {{10, 33}, {511, 414}} + Schema Privileges @@ -2119,13 +2107,13 @@ - + 0 YES YES - + @@ -2183,11 +2171,10 @@ {752, 506} - {{0, 0}, {1680, 1028}} {752, 528} - {3.40282e+38, 3.40282e+38} + {1.79769e+308, 1.79769e+308} @@ -2508,14 +2495,6 @@ 436 - - - delegate - - - - 447 - value: selection.select_priv @@ -4071,6 +4050,22 @@ 922 + + + delegate + + + + 924 + + + + refresh: + + + + 925 + @@ -5483,11 +5478,11 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{240, 174}, {752, 506}} + {{152, 121}, {752, 506}} com.apple.InterfaceBuilder.CocoaPlugin - {{240, 174}, {752, 506}} + {{152, 121}, {752, 506}} {752, 506} @@ -5601,7 +5596,7 @@ com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit - {{511, 95}, {130, 81}} + {{202, 63}, {130, 81}} com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit @@ -5666,7 +5661,7 @@ - 923 + 925 @@ -5713,6 +5708,13 @@ Source/SPContentFilterManager.h + + NSObject + + IBProjectSource + Source/SPMainThreadTrampoline.h + + NSObject @@ -6626,6 +6628,7 @@ 0 + IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx @@ -6641,5 +6644,30 @@ YES ../../sequel-pro.xcodeproj 3 + + YES + + YES + NSActionTemplate + NSAddTemplate + NSLeftFacingTriangleTemplate + NSMenuCheckmark + NSMenuMixedState + NSRemoveTemplate + NSRightFacingTriangleTemplate + NSSwitch + + + YES + {10, 10} + {8, 8} + {9, 9} + {9, 8} + {7, 2} + {8, 8} + {9, 9} + {15, 15} + + diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m index fe89d563..d58e731e 100644 --- a/Source/SPExtendedTableInfo.m +++ b/Source/SPExtendedTableInfo.m @@ -436,9 +436,10 @@ - (void)textDidEndEditing:(NSNotification *)notification { id object = [notification object]; + if ((object == tableCommentsTextView) && ([object isEditable]) && ([selectedTable length] > 0)) { - NSString *currentComment = [tableDataInstance statusValueForKey:@"Comment"]; + NSString *currentComment = [[tableDataInstance statusValueForKey:@"Comment"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSString *newComment = [[tableCommentsTextView string] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; // Check that the user actually changed the tables comment diff --git a/Source/SPSSHTunnel.m b/Source/SPSSHTunnel.m index eeef83d2..2b7c31fb 100644 --- a/Source/SPSSHTunnel.m +++ b/Source/SPSSHTunnel.m @@ -352,6 +352,10 @@ [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NSFileHandleDataAvailableNotification" object:nil]; + + // Run the run loop for a short time to ensure all task/pipe callbacks are dealt with + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; + [task release], task = nil; [standardError release], standardError = nil; [taskEnvironment release], taskEnvironment = nil; diff --git a/Source/SPUserManager.m b/Source/SPUserManager.m index cad74193..90cc426d 100644 --- a/Source/SPUserManager.m +++ b/Source/SPUserManager.m @@ -208,9 +208,12 @@ NSManagedObject *parent = [self _createNewSPUser]; NSManagedObject *child = [self _createNewSPUser]; - // We only care about setting the user and password keys on the parent + // We only care about setting the user and password keys on the parent, together with their + // original values for comparison purposes [parent setValue:username forKey:@"user"]; + [parent setValue:username forKey:@"originaluser"]; [parent setValue:[item objectForKey:@"Password"] forKey:@"password"]; + [parent setValue:[item objectForKey:@"Password"] forKey:@"originalpassword"]; [self _initializeChild:child withItem:item]; @@ -265,6 +268,8 @@ - (void)_initializeSchemaPrivs { // Initialize Databases + [schemas removeAllObjects]; + MCPResult *results = [self.mySqlConnection listDBs]; if ([results numOfRows]) { @@ -328,8 +333,8 @@ // Assumes that the child has already been initialized with values from the // global user table. // Select rows from the db table that contains schema privs for each user/host - NSString *queryString = [NSString stringWithFormat:@"SELECT * from `mysql`.`db` d WHERE d.user = '%@' and d.host = '%@'", - [[child parent] valueForKey:@"user"], [child valueForKey:@"host"]]; + NSString *queryString = [NSString stringWithFormat:@"SELECT * from `mysql`.`db` d WHERE d.user = %@ and d.host = %@", + [[[child parent] valueForKey:@"user"] tickQuotedString], [[child valueForKey:@"host"] tickQuotedString]]; MCPResult *queryResults = [self.mySqlConnection queryString:queryString]; if ([queryResults numOfRows] > 0) { @@ -634,14 +639,21 @@ - (IBAction)removeUser:(id)sender { NSString *username = [[[treeController selectedObjects] objectAtIndex:0] - valueForKey:@"user"]; + valueForKey:@"originaluser"]; NSArray *children = [[[treeController selectedObjects] objectAtIndex:0] valueForKey:@"children"]; + + + // On all the children - host entries - set the username to be deleted, + // for later query contruction. for(NSManagedObject *child in children) { [child setPrimitiveValue:username forKey:@"user"]; } + // Unset the host on the user, so that only the host entries are dropped + [[[treeController selectedObjects] objectAtIndex:0] setPrimitiveValue:nil forKey:@"host"]; + [treeController remove:sender]; } @@ -748,6 +760,19 @@ [grantedTableView reloadData]; [self _initializeAvailablePrivs]; [treeController fetch:nil]; + + // After the reset, ensure all original password and user values are up-to-date. + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"SPUser" + inManagedObjectContext:self.managedObjectContext]; + NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; + [request setEntity:entityDescription]; + NSArray *userArray = [self.managedObjectContext executeFetchRequest:request error:nil]; + for (NSManagedObject *user in userArray) { + if (![user parent]) { + [user setValue:[user valueForKey:@"user"] forKey:@"originaluser"]; + [user setValue:[user valueForKey:@"password"] forKey:@"originalpassword"]; + } + } } - (void)_setSchemaPrivValues:(NSArray *)objects enabled:(BOOL)enabled @@ -864,6 +889,7 @@ - (void)contextDidSave:(NSNotification *)notification { NSManagedObjectContext *notificationContext = (NSManagedObjectContext *)[notification object]; + // If there are multiple user manager windows open, it's possible to get this // notification from foreign windows. Ignore those notifications. if (notificationContext != self.managedObjectContext) return; @@ -905,22 +931,39 @@ if ([[[user entity] name] isEqualToString:@"Privileges"]) { [self grantDbPrivilegesWithPrivilege:user]; + + + // If the parent user has changed, either the username or password have been edited. } - else if (![user host]) + else if (![user parent]) { - // Just the user password was changed. - // Change password to be the same on all hosts. NSArray *hosts = [user valueForKey:@"children"]; - - for(NSManagedObject *child in hosts) - { - NSString *changePasswordStatement = [NSString stringWithFormat: - @"SET PASSWORD FOR %@@%@ = PASSWORD('%@')", - [[user valueForKey:@"user"] tickQuotedString], - [[child host] tickQuotedString], - [user valueForKey:@"password"]]; - [self.mySqlConnection queryString:changePasswordStatement]; - [self checkAndDisplayMySqlError]; + + // If the user has been changed, update the username on all hosts. Don't check for errors, as some + // hosts may be new. + if (![[user valueForKey:@"user"] isEqualToString:[user valueForKey:@"originaluser"]]) { + for (NSManagedObject *child in hosts) { + NSString *renameUserStatement = [NSString stringWithFormat: + @"RENAME USER %@@%@ TO %@@%@", + [[user valueForKey:@"originaluser"] tickQuotedString], + [[child host] tickQuotedString], + [[user valueForKey:@"user"] tickQuotedString], + [[child host] tickQuotedString]]; + [self.mySqlConnection queryString:renameUserStatement]; + } + } + + // If the password has been changed, use the same password on all hosts + if (![[user valueForKey:@"password"] isEqualToString:[user valueForKey:@"originalpassword"]]) { + for (NSManagedObject *child in hosts) { + NSString *changePasswordStatement = [NSString stringWithFormat: + @"SET PASSWORD FOR %@@%@ = PASSWORD(%@)", + [[user valueForKey:@"user"] tickQuotedString], + [[child host] tickQuotedString], + [[user valueForKey:@"password"] tickQuotedString]]; + [self.mySqlConnection queryString:changePasswordStatement]; + [self checkAndDisplayMySqlError]; + } } } else { [self grantPrivilegesToUser:user]; @@ -939,8 +982,8 @@ if (![[[user entity] name] isEqualToString:@"Privileges"] && [user valueForKey:@"host"] != nil) { [droppedUsers appendString:[NSString stringWithFormat:@"%@@%@, ", - [[user valueForKey:@"user"] backtickQuotedString], - [[user valueForKey:@"host"] backtickQuotedString]]]; + [[user valueForKey:@"user"] tickQuotedString], + [[user valueForKey:@"host"] tickQuotedString]]]; } } @@ -1025,7 +1068,7 @@ { NSString *grantStatement = [NSString stringWithFormat:@"GRANT %@ ON %@.* TO %@@%@", [[grantPrivileges componentsJoinedByCommas] uppercaseString], - dbName, + [dbName backtickQuotedString], [[schemaPriv valueForKeyPath:@"user.parent.user"] tickQuotedString], [[schemaPriv valueForKeyPath:@"user.host"] tickQuotedString]]; DLog(@"%@", grantStatement); @@ -1038,7 +1081,7 @@ { NSString *revokeStatement = [NSString stringWithFormat:@"REVOKE %@ ON %@.* FROM %@@%@", [[revokePrivileges componentsJoinedByCommas] uppercaseString], - dbName, + [dbName backtickQuotedString], [[schemaPriv valueForKeyPath:@"user.parent.user"] tickQuotedString], [[schemaPriv valueForKeyPath:@"user.host"] tickQuotedString]]; DLog(@"%@", revokeStatement); @@ -1304,6 +1347,16 @@ } } +#pragma mark - +#pragma mark Tab view delegate methods + +- (void)tabView:(NSTabView *)usersTabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem +{ + if ([[tabViewItem identifier] isEqualToString:@"Schema Privileges"]) { + [self _initializeSchemaPrivs]; + } +} + #pragma mark - /** diff --git a/Source/SPUserManager.xcdatamodel/elements b/Source/SPUserManager.xcdatamodel/elements index 33881efc..22c2c418 100644 Binary files a/Source/SPUserManager.xcdatamodel/elements and b/Source/SPUserManager.xcdatamodel/elements differ diff --git a/Source/SPUserManager.xcdatamodel/layout b/Source/SPUserManager.xcdatamodel/layout index 14b1545d..60630b61 100644 Binary files a/Source/SPUserManager.xcdatamodel/layout and b/Source/SPUserManager.xcdatamodel/layout differ diff --git a/Source/TableContent.m b/Source/TableContent.m index 4710abef..90fbe5d1 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -2188,7 +2188,7 @@ } else { [self performSelector:@selector(showErrorSheetWith:) withObject:[NSArray arrayWithObjects:NSLocalizedString(@"Error", @"error"), - [NSString stringWithFormat:NSLocalizedString(@"Couldn't remove rows.\nMySQL said: %@", @"message of panel when field cannot be removed"), + [NSString stringWithFormat:NSLocalizedString(@"Couldn't remove rows.\n\nMySQL said: %@", @"message of panel when field cannot be removed"), [mySQLConnection getLastErrorMessage]], nil] afterDelay:0.3]; @@ -2335,7 +2335,8 @@ // Remember affected rows for error checking affectedRows += [mySQLConnection affectedRows]; } - errors = [selectedRows count] - affectedRows; + + errors = (affectedRows > 0) ? [selectedRows count] - affectedRows : [selectedRows count]; } else { // if table has more than one PRIMARY KEY // delete the row by using all PRIMARY KEYs in an OR clause @@ -2390,21 +2391,23 @@ // Remember affected rows for error checking affectedRows += [mySQLConnection affectedRows]; } - errors = [selectedRows count] - affectedRows; + + errors = (affectedRows > 0) ? [selectedRows count] - affectedRows : [selectedRows count]; } // Restore Console Log window's updating bahaviour [[SPQueryController sharedQueryController] setAllowConsoleUpdate:consoleUpdateStatus]; - if ( errors ) { + if (errors) { NSArray *message; //TODO: The following three messages are NOT localisable! - if(errors < 0) { + if (errors < 0) { message = [NSArray arrayWithObjects:NSLocalizedString(@"Warning", @"warning"), [NSString stringWithFormat:NSLocalizedString(@"%ld row%@ more %@ removed! Please check the Console and inform the Sequel Pro team!", @"message of panel when more rows were deleted"), (long)(errors*-1), ((errors*-1)>1)?@"s":@"", (errors>1)?@"were":@"was"], nil]; - } else { - if(primaryKeyFieldNames == nil) + } + else { + if (primaryKeyFieldNames == nil) message = [NSArray arrayWithObjects:NSLocalizedString(@"Warning", @"warning"), [NSString stringWithFormat:NSLocalizedString(@"%ld row%@ ha%@ not been removed. Reload the table to be sure that the rows exist and use a primary key for your table.", @"message of panel when not all selected fields have been deleted"), (long)errors, (errors>1)?@"s":@"", (errors>1)?@"ve":@"s"], nil]; @@ -2413,6 +2416,7 @@ [NSString stringWithFormat:NSLocalizedString(@"%ld row%@ ha%@ not been removed. Reload the table to be sure that the rows exist and check the Console for possible errors inside the primary key%@ for your table.", @"message of panel when not all selected fields have been deleted by using primary keys"), (long)errors, (errors>1)?@"s":@"", (errors>1)?@"ve":@"s", (errors>1)?@"s":@""], nil]; } + [self performSelector:@selector(showErrorSheetWith:) withObject:message afterDelay:0.3]; diff --git a/Source/TableSource.m b/Source/TableSource.m index 6ff0d971..1e3bee8f 100644 --- a/Source/TableSource.m +++ b/Source/TableSource.m @@ -347,6 +347,10 @@ // Check whether a save of the current row is required. if (![self saveRowOnDeselect]) return; + NSInteger index = [tableSourceView selectedRow]; + + if ((index == -1) || (index > ([tableFields count] - 1))) return; + // Check if the user tries to delete the last defined field in table // Note that because of better menu item validation, this check will now never evaluate to true. if ([tableSourceView numberOfRows] < 2) { @@ -362,7 +366,7 @@ } - NSString *field = [[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"Field"]; + NSString *field = [[tableFields objectAtIndex:index] objectForKey:@"Field"]; BOOL hasForeignKey = NO; NSString *referencedTable = @""; @@ -409,8 +413,12 @@ // Check whether a save of the current fields row is required. if (![self saveRowOnDeselect]) return; - NSString *keyName = [[indexes objectAtIndex:[indexView selectedRow]] objectForKey:@"Key_name"]; - NSString *columnName = [[indexes objectAtIndex:[indexView selectedRow]] objectForKey:@"Column_name"]; + NSInteger index = [indexView selectedRow]; + + if ((index == -1) || (index > ([indexes count] - 1))) return; + + NSString *keyName = [[indexes objectAtIndex:index] objectForKey:@"Key_name"]; + NSString *columnName = [[indexes objectAtIndex:index] objectForKey:@"Column_name"]; BOOL hasForeignKey = NO; NSString *constraintName = @""; -- cgit v1.2.3