aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPExtendedTableInfo.m3
-rw-r--r--Source/SPSSHTunnel.m4
-rw-r--r--Source/SPUserManager.m95
-rw-r--r--Source/SPUserManager.xcdatamodel/elementsbin127771 -> 131784 bytes
-rw-r--r--Source/SPUserManager.xcdatamodel/layoutbin9663 -> 9663 bytes
-rw-r--r--Source/TableContent.m18
-rw-r--r--Source/TableSource.m14
7 files changed, 102 insertions, 32 deletions
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);
@@ -1305,6 +1348,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 -
/**
* Dealloc. Get rid of everything.
diff --git a/Source/SPUserManager.xcdatamodel/elements b/Source/SPUserManager.xcdatamodel/elements
index 33881efc..22c2c418 100644
--- a/Source/SPUserManager.xcdatamodel/elements
+++ b/Source/SPUserManager.xcdatamodel/elements
Binary files differ
diff --git a/Source/SPUserManager.xcdatamodel/layout b/Source/SPUserManager.xcdatamodel/layout
index 14b1545d..60630b61 100644
--- a/Source/SPUserManager.xcdatamodel/layout
+++ b/Source/SPUserManager.xcdatamodel/layout
Binary files 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 = @"";