diff options
-rw-r--r-- | Source/SPUserManager.m | 307 | ||||
-rw-r--r-- | Source/SPUserManagerDataSource.h | 35 | ||||
-rw-r--r-- | Source/SPUserManagerDataSource.m | 51 | ||||
-rw-r--r-- | Source/SPUserManagerDelegate.h | 35 | ||||
-rw-r--r-- | Source/SPUserManagerDelegate.m | 335 | ||||
-rw-r--r-- | sequel-pro.xcodeproj/project.pbxproj | 12 |
6 files changed, 307 insertions, 468 deletions
diff --git a/Source/SPUserManager.m b/Source/SPUserManager.m index c06025d2..397275cb 100644 --- a/Source/SPUserManager.m +++ b/Source/SPUserManager.m @@ -44,6 +44,12 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; +static NSString *SPGeneralTabIdentifier = @"General"; +static NSString *SPGlobalPrivilegesTabIdentifier = @"Global Privileges"; +static NSString *SPResourcesTabIdentifier = @"Resources"; +static NSString *SPSchemaPrivilegesTabIdentifier = @"Schema Privileges"; + + @interface SPUserManager () - (void)_initializeTree:(NSArray *)items; @@ -64,6 +70,7 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; - (BOOL)_renameUserFrom:(NSString *)originalUser host:(NSString *)originalHost to:(NSString *)newUser host:(NSString *)newHost; - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void*)context; - (void)contextWillSave:(NSNotification *)notice; +- (void)_selectFirstChildOfParentNode; @end @@ -1520,6 +1527,306 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; return YES; } +#pragma mark - SPUserManagerDelegate + +#pragma mark TableView Delegate Methods + +- (void)tableViewSelectionDidChange:(NSNotification *)notification +{ + id object = [notification object]; + + if (object == schemasTableView) { + [grantedSchemaPrivs removeAllObjects]; + [grantedTableView reloadData]; + + [self _initializeAvailablePrivs]; + + if ([[treeController selectedObjects] count] > 0 && [[schemasTableView selectedRowIndexes] count] > 0) { + SPUserMO *user = [[treeController selectedObjects] objectAtIndex:0]; + + // Check to see if the user host node was selected + if ([user valueForKey:@"host"]) { + NSString *selectedSchema = [schemas objectAtIndex:[schemasTableView selectedRow]]; + + NSArray *results = [self _fetchPrivsWithUser:[[user parent] valueForKey:@"user"] + schema:[selectedSchema stringByReplacingOccurrencesOfString:@"_" withString:@"\\_"] + 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]) + { + NSString *displayName = [[[property name] stringByReplacingOccurrencesOfString:@"_priv" withString:@""] replaceUnderscoreWithSpace]; + NSDictionary *newDict = [NSDictionary dictionaryWithObjectsAndKeys:displayName, @"displayName", [property name], @"name", nil]; + [grantedController addObject:newDict]; + + // Remove items from available so they can't be added twice. + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"displayName like[cd] %@", displayName]; + NSArray *previousObjects = [[availableController arrangedObjects] filteredArrayUsingPredicate:predicate]; + + for (NSDictionary *dict in previousObjects) + { + [availableController removeObject:dict]; + } + } + } + } + + [availableTableView setEnabled:YES]; + } + } + else { + [availableTableView setEnabled:NO]; + } + } + else if (object == grantedTableView) { + [removeSchemaPrivButton setEnabled:[[grantedController selectedObjects] count] > 0]; + } + else if (object == availableTableView) { + [addSchemaPrivButton setEnabled:[[availableController selectedObjects] count] > 0]; + } +} + +- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex +{ + if (tableView == schemasTableView) { + NSString *schemaName = [schemas objectAtIndex:rowIndex]; + + // Gray out the "all database" entries + if ([schemaName isEqualToString:@""] || [schemaName isEqualToString:@"%"]) { + [cell setTextColor:[NSColor lightGrayColor]]; + } else { + [cell setTextColor:[NSColor blackColor]]; + } + + // If the schema has permissions set, highlight with a yellow background + BOOL enabledPermissions = NO; + SPUserMO *user = [[treeController selectedObjects] objectAtIndex:0]; + NSArray *results = [self _fetchPrivsWithUser:[[user parent] valueForKey:@"user"] + schema:[schemaName stringByReplacingOccurrencesOfString:@"_" withString:@"\\_"] + host:[user valueForKey:@"host"]]; + if ([results count]) { + NSManagedObject *schemaPrivs = [results objectAtIndex:0]; + for (NSString *itemKey in [[[schemaPrivs entity] attributesByName] allKeys]) { + if ([itemKey hasSuffix:@"_priv"] && [[schemaPrivs valueForKey:itemKey] boolValue]) { + enabledPermissions = YES; + break; + } + } + } + + if (enabledPermissions) { + [cell setDrawsBackground:YES]; + [cell setBackgroundColor:[NSColor colorWithDeviceRed:1.f green:1.f blue:0.f alpha:0.2]]; + } else { + [cell setDrawsBackground:NO]; + } + } +} + +#pragma mark - +#pragma mark Tab View Delegate methods + +- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem +{ + BOOL retVal = YES; + + if ([[treeController selectedObjects] count] == 0) return NO; + + if (![treeController commitEditing]) { + return NO; + } + + // Currently selected object in tree + id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; + + // If we are selecting a tab view that requires there be a child, + // make sure there is a child to select. If not, don't allow it. + if ([[tabViewItem identifier] isEqualToString:SPGlobalPrivilegesTabIdentifier] || + [[tabViewItem identifier] isEqualToString:SPResourcesTabIdentifier] || + [[tabViewItem identifier] isEqualToString:SPSchemaPrivilegesTabIdentifier]) { + + id parent = [selectedObject parent]; + + retVal = parent ? ([[parent children] count] > 0) : ([[selectedObject children] count] > 0); + + if (!retVal) { + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"User has no hosts", @"user has no hosts message") + defaultButton:NSLocalizedString(@"Add Host", @"Add Host") + alternateButton:NSLocalizedString(@"Cancel", @"cancel button") + otherButton:nil + informativeTextWithFormat:NSLocalizedString(@"This user doesn't have any hosts associated with it. It will be deleted unless one is added", @"user has no hosts informative message")]; + + if ([alert runModal] == NSAlertDefaultReturn) { + [self addHost:nil]; + } + } + + // If this is the resources tab, enable or disable the controls based on the server's support for them + if ([[tabViewItem identifier] isEqualToString:SPResourcesTabIdentifier]) { + + BOOL serverSupportsUserMaxVars = [serverSupport supportsUserMaxVars]; + + // Disable the fields according to the version + [maxUpdatesTextField setEnabled:serverSupportsUserMaxVars]; + [maxConnectionsTextField setEnabled:serverSupportsUserMaxVars]; + [maxQuestionsTextField setEnabled:serverSupportsUserMaxVars]; + } + } + + return retVal; +} + +- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem +{ + if ([[treeController selectedObjects] count] == 0) return; + + id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; + + // If the selected tab is General and a child is selected, select the + // parent (user info). + if ([[tabViewItem identifier] isEqualToString:SPGeneralTabIdentifier]) { + if ([selectedObject parent]) { + [self _selectParentFromSelection]; + } + } + else if ([[tabViewItem identifier] isEqualToString:SPGlobalPrivilegesTabIdentifier] || + [[tabViewItem identifier] isEqualToString:SPResourcesTabIdentifier] || + [[tabViewItem identifier] isEqualToString:SPSchemaPrivilegesTabIdentifier]) { + // If the tab is either Global Privs or Resources and we have a user + // selected, then open tree and select first child node. + [self _selectFirstChildOfParentNode]; + } +} + +#pragma mark - +#pragma mark Outline view Delegate Methods + +- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + if ([cell isKindOfClass:[ImageAndTextCell class]]) + { + // Determines which Image to display depending on parent or child object + NSImage *image = [[NSImage imageNamed:[(SPUserMO *)[item representedObject] parent] ? NSImageNameNetwork : NSImageNameUser] retain]; + + [image setSize:(NSSize){16, 16}]; + [(ImageAndTextCell *)cell setImage:image]; + [image release]; + } +} + +- (BOOL)outlineView:(NSOutlineView *)olv isGroupItem:(id)item +{ + return NO; +} + +- (BOOL)outlineView:(NSOutlineView *)olv shouldSelectItem:(id)item +{ + return YES; +} + +- (BOOL)outlineView:(NSOutlineView *)olv shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + return ([[[item representedObject] children] count] == 0); +} + +- (void)outlineViewSelectionDidChange:(NSNotification *)notification +{ + if ([[treeController selectedObjects] count] == 0) return; + + id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; + + if ([selectedObject parent] == nil && !([[[tabView selectedTabViewItem] identifier] isEqualToString:@"General"])) { + [tabView selectTabViewItemWithIdentifier:SPGeneralTabIdentifier]; + } + else { + if ([selectedObject parent] != nil && [[[tabView selectedTabViewItem] identifier] isEqualToString:@"General"]) { + [tabView selectTabViewItemWithIdentifier:SPGlobalPrivilegesTabIdentifier]; + } + } + + if ([selectedObject parent] != nil && [selectedObject host] == nil) + { + [selectedObject setValue:@"%" forKey:@"host"]; + [outlineView reloadItem:selectedObject]; + } + + [schemasTableView deselectAll:nil]; + [schemasTableView setNeedsDisplay:YES]; + [grantedTableView deselectAll:nil]; + [availableTableView deselectAll:nil]; +} + +- (BOOL)selectionShouldChangeInOutlineView:(NSOutlineView *)olv +{ + if ([[treeController selectedObjects] count] > 0) + { + id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; + + // Check parents + if ([selectedObject valueForKey:@"parent"] == nil) + { + NSString *name = [selectedObject valueForKey:@"user"]; + NSArray *results = [self _fetchUserWithUserName:name]; + + if ([results count] > 1) { + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Duplicate User", @"duplicate user message") + defaultButton:NSLocalizedString(@"OK", @"OK button") + alternateButton:nil + otherButton:nil + informativeTextWithFormat:NSLocalizedString(@"A user with the name '%@' already exists", @"duplicate user informative message"), name]; + [alert runModal]; + + return NO; + } + } + else + { + NSArray *children = [selectedObject valueForKeyPath:@"parent.children"]; + NSString *host = [selectedObject valueForKey:@"host"]; + + for (NSManagedObject *child in children) + { + if (![selectedObject isEqual:child] && [[child valueForKey:@"host"] isEqualToString:host]) + { + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Duplicate Host", @"duplicate host message") + defaultButton:NSLocalizedString(@"OK", @"OK button") + alternateButton:nil + otherButton:nil + informativeTextWithFormat:NSLocalizedString(@"A user with the host '%@' already exists", @"duplicate host informative message"), host]; + + [alert runModal]; + + return NO; + } + } + } + } + + return YES; +} + +#pragma mark - SPUserManagerDataSource + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView +{ + return [schemas count]; +} + +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex +{ + NSString *databaseName = [schemas objectAtIndex:rowIndex]; + if ([databaseName isEqualToString:@""]) { + databaseName = NSLocalizedString(@"All Databases", @"All databases placeholder"); + } else if ([databaseName isEqualToString:@"%"]) { + databaseName = NSLocalizedString(@"All Databases (%)", @"All databases (%) placeholder"); + } + return databaseName; +} + #pragma mark - - (void)dealloc diff --git a/Source/SPUserManagerDataSource.h b/Source/SPUserManagerDataSource.h deleted file mode 100644 index f441c156..00000000 --- a/Source/SPUserManagerDataSource.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// SPUserManagerDataSource.h -// sequel-pro -// -// Created by Rowan Beentje on March 8, 2013. -// Copyright (c) 2013 Rowan Beentje. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at <https://github.com/sequelpro/sequelpro> - -#import "SPUserManager.h" - -@interface SPUserManager (SPUserManagerDataSource) - -@end diff --git a/Source/SPUserManagerDataSource.m b/Source/SPUserManagerDataSource.m deleted file mode 100644 index 95ec6b68..00000000 --- a/Source/SPUserManagerDataSource.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// SPUserManagerDataSource.m -// sequel-pro -// -// Created by Rowan Beentje on March 8, 2013. -// Copyright (c) 2013 Rowan Beentje. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at <https://github.com/sequelpro/sequelpro> - -#import "SPUserManagerDataSource.h" - -@implementation SPUserManager (SPUserManagerDataSource) - -- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView -{ - return [schemas count]; -} - -- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex -{ - NSString *databaseName = [schemas objectAtIndex:rowIndex]; - if ([databaseName isEqualToString:@""]) { - databaseName = NSLocalizedString(@"All Databases", @"All databases placeholder"); - } else if ([databaseName isEqualToString:@"%"]) { - databaseName = NSLocalizedString(@"All Databases (%)", @"All databases (%) placeholder"); - } - return databaseName; -} - -@end diff --git a/Source/SPUserManagerDelegate.h b/Source/SPUserManagerDelegate.h deleted file mode 100644 index 14581148..00000000 --- a/Source/SPUserManagerDelegate.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// SPUserManagerDelegate.h -// sequel-pro -// -// Created by Mark Townsend on Jan 1, 2009. -// Copyright (c) 2009 Mark Townsend. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at <https://github.com/sequelpro/sequelpro> - -#import "SPUserManager.h" - -@interface SPUserManager (SPUserManagerDelegate) - -@end diff --git a/Source/SPUserManagerDelegate.m b/Source/SPUserManagerDelegate.m deleted file mode 100644 index cefe7f2e..00000000 --- a/Source/SPUserManagerDelegate.m +++ /dev/null @@ -1,335 +0,0 @@ -// -// SPUserManagerDelegate.m -// sequel-pro -// -// Created by Mark Townsend on Jan 1, 2009. -// Copyright (c) 2009 Mark Townsend. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at <https://github.com/sequelpro/sequelpro> - -#import "SPUserManagerDelegate.h" -#import "SPUserMO.h" -#import "SPServerSupport.h" -#import "ImageAndTextCell.h" - -static NSString *SPGeneralTabIdentifier = @"General"; -static NSString *SPGlobalPrivilegesTabIdentifier = @"Global Privileges"; -static NSString *SPResourcesTabIdentifier = @"Resources"; -static NSString *SPSchemaPrivilegesTabIdentifier = @"Schema Privileges"; - -@interface SPUserManager (DeclaredAPI) - -- (void)_initializeAvailablePrivs; -- (void)_selectParentFromSelection; -- (void)_selectFirstChildOfParentNode; -- (NSArray *)_fetchUserWithUserName:(NSString *)username; - -- (NSArray *)_fetchPrivsWithUser:(NSString *)username schema:(NSString *)selectedSchema host:(NSString *)host; - -@end - -@implementation SPUserManager (SPUserManagerDelegate) - -#pragma mark - -#pragma mark TableView Delegate Methods - -- (void)tableViewSelectionDidChange:(NSNotification *)notification -{ - id object = [notification object]; - - if (object == schemasTableView) { - [grantedSchemaPrivs removeAllObjects]; - [grantedTableView reloadData]; - - [self _initializeAvailablePrivs]; - - if ([[treeController selectedObjects] count] > 0 && [[schemasTableView selectedRowIndexes] count] > 0) { - SPUserMO *user = [[treeController selectedObjects] objectAtIndex:0]; - - // Check to see if the user host node was selected - if ([user valueForKey:@"host"]) { - NSString *selectedSchema = [schemas objectAtIndex:[schemasTableView selectedRow]]; - - NSArray *results = [self _fetchPrivsWithUser:[[user parent] valueForKey:@"user"] - schema:[selectedSchema stringByReplacingOccurrencesOfString:@"_" withString:@"\\_"] - 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]) - { - NSString *displayName = [[[property name] stringByReplacingOccurrencesOfString:@"_priv" withString:@""] replaceUnderscoreWithSpace]; - NSDictionary *newDict = [NSDictionary dictionaryWithObjectsAndKeys:displayName, @"displayName", [property name], @"name", nil]; - [grantedController addObject:newDict]; - - // Remove items from available so they can't be added twice. - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"displayName like[cd] %@", displayName]; - NSArray *previousObjects = [[availableController arrangedObjects] filteredArrayUsingPredicate:predicate]; - - for (NSDictionary *dict in previousObjects) - { - [availableController removeObject:dict]; - } - } - } - } - - [availableTableView setEnabled:YES]; - } - } - else { - [availableTableView setEnabled:NO]; - } - } - else if (object == grantedTableView) { - [removeSchemaPrivButton setEnabled:[[grantedController selectedObjects] count] > 0]; - } - else if (object == availableTableView) { - [addSchemaPrivButton setEnabled:[[availableController selectedObjects] count] > 0]; - } -} - -- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex -{ - if (tableView == schemasTableView) { - NSString *schemaName = [schemas objectAtIndex:rowIndex]; - - // Gray out the "all database" entries - if ([schemaName isEqualToString:@""] || [schemaName isEqualToString:@"%"]) { - [cell setTextColor:[NSColor lightGrayColor]]; - } else { - [cell setTextColor:[NSColor blackColor]]; - } - - // If the schema has permissions set, highlight with a yellow background - BOOL enabledPermissions = NO; - SPUserMO *user = [[treeController selectedObjects] objectAtIndex:0]; - NSArray *results = [self _fetchPrivsWithUser:[[user parent] valueForKey:@"user"] - schema:[schemaName stringByReplacingOccurrencesOfString:@"_" withString:@"\\_"] - host:[user valueForKey:@"host"]]; - if ([results count]) { - NSManagedObject *schemaPrivs = [results objectAtIndex:0]; - for (NSString *itemKey in [[[schemaPrivs entity] attributesByName] allKeys]) { - if ([itemKey hasSuffix:@"_priv"] && [[schemaPrivs valueForKey:itemKey] boolValue]) { - enabledPermissions = YES; - break; - } - } - } - - if (enabledPermissions) { - [cell setDrawsBackground:YES]; - [cell setBackgroundColor:[NSColor colorWithDeviceRed:1.f green:1.f blue:0.f alpha:0.2]]; - } else { - [cell setDrawsBackground:NO]; - } - } -} - -#pragma mark - -#pragma mark Tab View Delegate methods - -- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - BOOL retVal = YES; - - if ([[treeController selectedObjects] count] == 0) return NO; - - if (![treeController commitEditing]) { - return NO; - } - - // Currently selected object in tree - id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; - - // If we are selecting a tab view that requires there be a child, - // make sure there is a child to select. If not, don't allow it. - if ([[tabViewItem identifier] isEqualToString:SPGlobalPrivilegesTabIdentifier] || - [[tabViewItem identifier] isEqualToString:SPResourcesTabIdentifier] || - [[tabViewItem identifier] isEqualToString:SPSchemaPrivilegesTabIdentifier]) { - - id parent = [selectedObject parent]; - - retVal = parent ? ([[parent children] count] > 0) : ([[selectedObject children] count] > 0); - - if (!retVal) { - NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"User has no hosts", @"user has no hosts message") - defaultButton:NSLocalizedString(@"Add Host", @"Add Host") - alternateButton:NSLocalizedString(@"Cancel", @"cancel button") - otherButton:nil - informativeTextWithFormat:NSLocalizedString(@"This user doesn't have any hosts associated with it. It will be deleted unless one is added", @"user has no hosts informative message")]; - - if ([alert runModal] == NSAlertDefaultReturn) { - [self addHost:nil]; - } - } - - // If this is the resources tab, enable or disable the controls based on the server's support for them - if ([[tabViewItem identifier] isEqualToString:SPResourcesTabIdentifier]) { - - BOOL serverSupportsUserMaxVars = [serverSupport supportsUserMaxVars]; - - // Disable the fields according to the version - [maxUpdatesTextField setEnabled:serverSupportsUserMaxVars]; - [maxConnectionsTextField setEnabled:serverSupportsUserMaxVars]; - [maxQuestionsTextField setEnabled:serverSupportsUserMaxVars]; - } - } - - return retVal; -} - -- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[treeController selectedObjects] count] == 0) return; - - id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; - - // If the selected tab is General and a child is selected, select the - // parent (user info). - if ([[tabViewItem identifier] isEqualToString:SPGeneralTabIdentifier]) { - if ([selectedObject parent]) { - [self _selectParentFromSelection]; - } - } - else if ([[tabViewItem identifier] isEqualToString:SPGlobalPrivilegesTabIdentifier] || - [[tabViewItem identifier] isEqualToString:SPResourcesTabIdentifier] || - [[tabViewItem identifier] isEqualToString:SPSchemaPrivilegesTabIdentifier]) { - // If the tab is either Global Privs or Resources and we have a user - // selected, then open tree and select first child node. - [self _selectFirstChildOfParentNode]; - } -} - -#pragma mark - -#pragma mark Outline view Delegate Methods - -- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - if ([cell isKindOfClass:[ImageAndTextCell class]]) - { - // Determines which Image to display depending on parent or child object - NSImage *image = [[NSImage imageNamed:[(SPUserMO *)[item representedObject] parent] ? NSImageNameNetwork : NSImageNameUser] retain]; - - [image setSize:(NSSize){16, 16}]; - [(ImageAndTextCell *)cell setImage:image]; - [image release]; - } -} - -- (BOOL)outlineView:(NSOutlineView *)olv isGroupItem:(id)item -{ - return NO; -} - -- (BOOL)outlineView:(NSOutlineView *)olv shouldSelectItem:(id)item -{ - return YES; -} - -- (BOOL)outlineView:(NSOutlineView *)olv shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - return ([[[item representedObject] children] count] == 0); -} - -- (void)outlineViewSelectionDidChange:(NSNotification *)notification -{ - if ([[treeController selectedObjects] count] == 0) return; - - id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; - - if ([selectedObject parent] == nil && !([[[tabView selectedTabViewItem] identifier] isEqualToString:@"General"])) { - [tabView selectTabViewItemWithIdentifier:SPGeneralTabIdentifier]; - } - else { - if ([selectedObject parent] != nil && [[[tabView selectedTabViewItem] identifier] isEqualToString:@"General"]) { - [tabView selectTabViewItemWithIdentifier:SPGlobalPrivilegesTabIdentifier]; - } - } - - if ([selectedObject parent] != nil && [selectedObject host] == nil) - { - [selectedObject setValue:@"%" forKey:@"host"]; - [outlineView reloadItem:selectedObject]; - } - - [schemasTableView deselectAll:nil]; - [schemasTableView setNeedsDisplay:YES]; - [grantedTableView deselectAll:nil]; - [availableTableView deselectAll:nil]; -} - -- (BOOL)selectionShouldChangeInOutlineView:(NSOutlineView *)olv -{ - if ([[treeController selectedObjects] count] > 0) - { - id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; - - // Check parents - if ([selectedObject valueForKey:@"parent"] == nil) - { - NSString *name = [selectedObject valueForKey:@"user"]; - NSArray *results = [self _fetchUserWithUserName:name]; - - if ([results count] > 1) { - NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Duplicate User", @"duplicate user message") - defaultButton:NSLocalizedString(@"OK", @"OK button") - alternateButton:nil - otherButton:nil - informativeTextWithFormat:NSLocalizedString(@"A user with the name '%@' already exists", @"duplicate user informative message"), name]; - [alert runModal]; - - return NO; - } - } - else - { - NSArray *children = [selectedObject valueForKeyPath:@"parent.children"]; - NSString *host = [selectedObject valueForKey:@"host"]; - - for (NSManagedObject *child in children) - { - if (![selectedObject isEqual:child] && [[child valueForKey:@"host"] isEqualToString:host]) - { - NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Duplicate Host", @"duplicate host message") - defaultButton:NSLocalizedString(@"OK", @"OK button") - alternateButton:nil - otherButton:nil - informativeTextWithFormat:NSLocalizedString(@"A user with the host '%@' already exists", @"duplicate host informative message"), host]; - - [alert runModal]; - - return NO; - } - } - } - } - - return YES; -} - -@end diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 9f8f46b2..5bc97dc1 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -37,7 +37,6 @@ 172A65110F7BED7A001E861A /* SPConsoleMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 172A65100F7BED7A001E861A /* SPConsoleMessage.m */; }; 173284EA1088FEDE0062E892 /* SPConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 173284E91088FEDE0062E892 /* SPConstants.m */; }; 1734696B11C1167000AB3D16 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; }; - 17381856151FB34E0078FFE2 /* SPUserManagerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 17381855151FB34E0078FFE2 /* SPUserManagerDelegate.m */; }; 173C4362104455CA001F3A30 /* QueryFavoriteManager.xib in Resources */ = {isa = PBXBuildFile; fileRef = 173C4360104455CA001F3A30 /* QueryFavoriteManager.xib */; }; 173C4366104455E0001F3A30 /* SPQueryFavoriteManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 173C4365104455E0001F3A30 /* SPQueryFavoriteManager.m */; }; 173C44D81044A6B0001F3A30 /* SPOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 173C44D71044A6B0001F3A30 /* SPOutlineView.m */; }; @@ -384,7 +383,6 @@ 58CDB3400FCE13EF00F8ACA3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5EAC0FC0EC87FF900CC579C /* Security.framework */; }; 58CDB3410FCE141900F8ACA3 /* SequelProTunnelAssistant.m in Sources */ = {isa = PBXBuildFile; fileRef = 58CDB3310FCE139C00F8ACA3 /* SequelProTunnelAssistant.m */; }; 58CDB3420FCE142500F8ACA3 /* SPKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E641740EF01F80001BC333 /* SPKeychain.m */; }; - 58D29FE016E96306002EB401 /* SPUserManagerDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D29FDF16E96306002EB401 /* SPUserManagerDataSource.m */; }; 58D2A6A716FBDEFF002EB401 /* SPComboPopupButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D2A6A616FBDEFF002EB401 /* SPComboPopupButton.m */; }; 58D2E229101222670063EF1D /* SPTextAndLinkCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D2E227101222670063EF1D /* SPTextAndLinkCell.m */; }; 58D2E22E101222870063EF1D /* link-arrow-clicked.png in Resources */ = {isa = PBXBuildFile; fileRef = 58D2E22B101222870063EF1D /* link-arrow-clicked.png */; }; @@ -661,8 +659,6 @@ 172A65100F7BED7A001E861A /* SPConsoleMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPConsoleMessage.m; sourceTree = "<group>"; }; 173284E81088FEDE0062E892 /* SPConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPConstants.h; sourceTree = "<group>"; }; 173284E91088FEDE0062E892 /* SPConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPConstants.m; sourceTree = "<group>"; }; - 17381854151FB34E0078FFE2 /* SPUserManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUserManagerDelegate.h; sourceTree = "<group>"; }; - 17381855151FB34E0078FFE2 /* SPUserManagerDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPUserManagerDelegate.m; sourceTree = "<group>"; }; 173C4361104455CA001F3A30 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/QueryFavoriteManager.xib; sourceTree = "<group>"; }; 173C4364104455E0001F3A30 /* SPQueryFavoriteManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPQueryFavoriteManager.h; sourceTree = "<group>"; }; 173C4365104455E0001F3A30 /* SPQueryFavoriteManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPQueryFavoriteManager.m; sourceTree = "<group>"; }; @@ -1144,8 +1140,6 @@ 58CDB32F0FCE138D00F8ACA3 /* SPSSHTunnel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPSSHTunnel.m; sourceTree = "<group>"; }; 58CDB3310FCE139C00F8ACA3 /* SequelProTunnelAssistant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SequelProTunnelAssistant.m; sourceTree = "<group>"; }; 58CDB3360FCE13C900F8ACA3 /* SequelProTunnelAssistant */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SequelProTunnelAssistant; sourceTree = BUILT_PRODUCTS_DIR; }; - 58D29FDE16E96306002EB401 /* SPUserManagerDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUserManagerDataSource.h; sourceTree = "<group>"; }; - 58D29FDF16E96306002EB401 /* SPUserManagerDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPUserManagerDataSource.m; sourceTree = "<group>"; }; 58D2A6A516FBDEFF002EB401 /* SPComboPopupButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPComboPopupButton.h; sourceTree = "<group>"; }; 58D2A6A616FBDEFF002EB401 /* SPComboPopupButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPComboPopupButton.m; sourceTree = "<group>"; }; 58D2E227101222670063EF1D /* SPTextAndLinkCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPTextAndLinkCell.m; sourceTree = "<group>"; }; @@ -1499,10 +1493,6 @@ children = ( 4D90B798101E0CDF00D116A1 /* SPUserManager.h */, 4D90B799101E0CDF00D116A1 /* SPUserManager.m */, - 17381854151FB34E0078FFE2 /* SPUserManagerDelegate.h */, - 17381855151FB34E0078FFE2 /* SPUserManagerDelegate.m */, - 58D29FDE16E96306002EB401 /* SPUserManagerDataSource.h */, - 58D29FDF16E96306002EB401 /* SPUserManagerDataSource.m */, ); name = "User Manager"; sourceTree = "<group>"; @@ -3352,7 +3342,6 @@ 584D87921514101E00F24774 /* SPDatabaseStructure.m in Sources */, 584D88A91515034200F24774 /* NSNotificationCenterThreadingAdditions.m in Sources */, 584D899D15162CBE00F24774 /* SPDataBase64EncodingAdditions.m in Sources */, - 17381856151FB34E0078FFE2 /* SPUserManagerDelegate.m in Sources */, 17BA2A3215275D8600389803 /* SPExportInterfaceController.m in Sources */, 1798F1871550175B004B0AB8 /* SPFavoritesExporter.m in Sources */, 1798F1881550175B004B0AB8 /* SPFavoritesImporter.m in Sources */, @@ -3366,7 +3355,6 @@ 58DF9F7315AB8509003B4330 /* SPSplitView.m in Sources */, 58DFC91615CB3501003B4330 /* BGHUDButtonCell.m in Sources */, 5843E247162B555B00EAA6D1 /* SPThreadAdditions.m in Sources */, - 58D29FE016E96306002EB401 /* SPUserManagerDataSource.m in Sources */, 58D2A6A716FBDEFF002EB401 /* SPComboPopupButton.m in Sources */, 17846BA4170C962E00414499 /* SPProcessListControllerDataSource.m in Sources */, 501B1D181728A3DA0017C92E /* SPCharsetCollationHelper.m in Sources */, |