From 80f757d7f217ae836f6c8de60134bc2a5d005687 Mon Sep 17 00:00:00 2001 From: mltownsend Date: Tue, 11 Aug 2009 17:00:46 +0000 Subject: User Manager feature --- Interfaces/English.lproj/MainMenu.xib | 73 +- Interfaces/English.lproj/UserManagerView.xib | 3788 ++++++++++++++++++++++++++ Source/SPArrayAdditions.h | 1 + Source/SPArrayAdditions.m | 15 + Source/SPStringAdditions.h | 2 + Source/SPStringAdditions.m | 36 + Source/SPUserMO.h | 41 + Source/SPUserMO.m | 72 + Source/SPUserManager.h | 73 + Source/SPUserManager.m | 680 +++++ Source/SPUserManager.xcdatamodel/elements | Bin 0 -> 50142 bytes Source/SPUserManager.xcdatamodel/layout | Bin 0 -> 5707 bytes Source/TableDocument.h | 4 +- Source/TableDocument.m | 23 +- sequel-pro.xcodeproj/project.pbxproj | 28 + 15 files changed, 4832 insertions(+), 4 deletions(-) create mode 100644 Interfaces/English.lproj/UserManagerView.xib create mode 100644 Source/SPUserMO.h create mode 100644 Source/SPUserMO.m create mode 100644 Source/SPUserManager.h create mode 100644 Source/SPUserManager.m create mode 100644 Source/SPUserManager.xcdatamodel/elements create mode 100644 Source/SPUserManager.xcdatamodel/layout diff --git a/Interfaces/English.lproj/MainMenu.xib b/Interfaces/English.lproj/MainMenu.xib index ed410904..81335a21 100644 --- a/Interfaces/English.lproj/MainMenu.xib +++ b/Interfaces/English.lproj/MainMenu.xib @@ -8,6 +8,7 @@ 353.00 YES + YES @@ -1449,6 +1450,30 @@ + + + Tools + + 2147483647 + + + submenuAction: + + + + YES + + + User Manager + u + 1048576 + 2147483647 + + + + + + Table @@ -2521,6 +2546,14 @@ 949 + + + showUserManager: + + + + 955 + @@ -2564,6 +2597,7 @@ + MainMenu @@ -3744,6 +3778,29 @@ + + 950 + + + YES + + + + + + 951 + + + YES + + + + + + 952 + + + @@ -4086,6 +4143,10 @@ 941.IBPluginDependency 943.IBPluginDependency 944.IBPluginDependency + 950.IBPluginDependency + 951.IBEditorWindowLastContentRect + 951.IBPluginDependency + 952.IBPluginDependency YES @@ -4179,7 +4240,7 @@ com.apple.InterfaceBuilder.CocoaPlugin {{449, 1007}, {197, 53}} - {{455, 703}, {511, 20}} + {{300, 703}, {567, 20}} com.apple.InterfaceBuilder.CocoaPlugin {{506, 836}, {511, 20}} @@ -4468,6 +4529,10 @@ w6gg4oaSIGZhY2FkZV0 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{623, 680}, {172, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin @@ -4490,7 +4555,7 @@ w6gg4oaSIGZhY2FkZV0 - 949 + 955 @@ -4890,6 +4955,7 @@ w6gg4oaSIGZhY2FkZV0 setDatabases: showCreateTableSyntax: showMySQLHelp: + showUserManager: showVariables: viewContent: viewQuery: @@ -4931,6 +4997,7 @@ w6gg4oaSIGZhY2FkZV0 id id id + id @@ -4976,6 +5043,7 @@ w6gg4oaSIGZhY2FkZV0 titleAccessoryView titleImageView titleStringView + userManagerInstance variablesCountTextField variablesSearchField variablesSheet @@ -5022,6 +5090,7 @@ w6gg4oaSIGZhY2FkZV0 id id id + id NSTextField NSSearchField id diff --git a/Interfaces/English.lproj/UserManagerView.xib b/Interfaces/English.lproj/UserManagerView.xib new file mode 100644 index 00000000..5e91154e --- /dev/null +++ b/Interfaces/English.lproj/UserManagerView.xib @@ -0,0 +1,3788 @@ + + + + 1050 + 9L30 + 677 + 949.54 + 353.00 + + YES + + + + YES + com.brandonwalkin.BWToolkit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + SPUserManager + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{376, 491}, {752, 506}} + 1677721600 + User Managment + NSWindow + + {3.40282e+38, 3.40282e+38} + + + 256 + + YES + + + 274 + + YES + + + 256 + + YES + + + 274 + + YES + + + 2304 + + YES + + + 4352 + {194, 467} + + YES + + + 256 + {194, 17} + + + + + + -2147483392 + {{-26, 0}, {16, 17}} + + + + YES + + NameColumn + 1.910000e+02 + 1.600000e+01 + 1.000000e+03 + + 75628032 + 0 + Accounts + + LucidaGrande + 1.100000e+01 + 3100 + + + 3 + MC4zMzMzMzI5OQA + + + 6 + System + headerTextColor + + 3 + MAA + + + + + 337772096 + 2048 + Text Cell + + LucidaGrande + 1.300000e+01 + 1044 + + + + 6 + System + controlBackgroundColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + + + 3 + YES + YES + + + displayName + YES + compare: + + + + 3.000000e+00 + + 6 + System + _sourceListBackgroundColor + + 1 + MC44MzkyMTU3IDAuODY2NjY2NjcgMC44OTgwMzkyMgA + + + + 6 + System + gridColor + + 3 + MC41AA + + + 2.000000e+01 + 1379926016 + 4 + 15 + 0 + YES + 1 + 1.400000e+01 + + + {{0, 17}, {194, 467}} + + + + + 4 + + + + -2147483392 + {{246, 17}, {15, 308}} + + + _doScroller: + 9.969040e-01 + + + + -2147483392 + {{1, 325}, {245, 15}} + + 1 + + _doScroller: + 9.961686e-01 + + + + 2304 + + YES + + + {194, 17} + + + + + 4 + + + + {{0, 22}, {194, 484}} + + + 560 + + + + + + QSAAAEEgAABBoAAAQaAAAA + + + + 290 + + YES + + + 292 + {{-1, -1}, {32, 24}} + + YES + + 67239424 + 134348800 + + + + -2033434369 + 163 + + NSImage + NSAddTemplate + + + + 200 + 25 + + + + + 292 + {{30, -1}, {32, 24}} + + YES + + 67239424 + 134348800 + + + + -2033434369 + 163 + + NSImage + NSRemoveTemplate + + + + 200 + 25 + + + + + 292 + {{61, -1}, {32, 24}} + + YES + + -2076049856 + 134350848 + + + -2038284033 + 163 + + + 400 + 75 + + + YES + + + 1048576 + 2147483647 + + NSImage + NSActionTemplate + + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + Add Host + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Remove Host + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + YES + 1 + YES + YES + 2 + + + + {194, 23} + + YES + YES + NO + 0 + + + {194, 506} + + NSView + + + + 256 + + YES + + + 274 + {{13, 40}, {531, 460}} + + + YES + + General + + + 256 + + YES + + + 13 + + YES + + + 256 + + YES + + + 268 + {{15, 42}, {71, 17}} + + YES + + 68288064 + 71304192 + Username: + + + + 6 + System + controlColor + + + + + + + + 268 + {{15, 12}, {71, 17}} + + YES + + 68288064 + 71304192 + Password: + + + + + + + + + 268 + {{91, 42}, {147, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + + + + + + 268 + {{91, 12}, {147, 22}} + + YES + + 343014976 + 272630784 + + + + YES + + + + YES + NSAllRomanInputSourcesLocaleIdentifier + + + + + {{1, 1}, {254, 72}} + + + + {{147, 312}, {256, 88}} + + {0, 0} + + 67239424 + 0 + Login Information + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 0 + 2 + NO + + + {{10, 33}, {511, 414}} + + + General + + + + + Global Privileges + + + 274 + + YES + + + 269 + + YES + + + 9 + + YES + + + 256 + + YES + + + 268 + {{16, 72}, {133, 18}} + + YES + + 67239424 + 0 + Replication Client + + + 1211912703 + 130 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{16, 52}, {133, 18}} + + YES + + 67239424 + 0 + Replication Slave + + + 1211912703 + 130 + + + + + 200 + 25 + + + + {{1, 1}, {175, 98}} + + + + {{252, 128}, {177, 114}} + + {0, 0} + + 67239424 + 0 + Replications + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 0 + 2 + NO + + + + 12 + + YES + + + 256 + + YES + + + 268 + {{16, 190}, {65, 18}} + + YES + + 67239424 + 0 + Reload + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 170}, {85, 18}} + + YES + + 67239424 + 0 + Shutdown + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 150}, {65, 18}} + + YES + + 67239424 + 0 + File + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 130}, {70, 18}} + + YES + + 67239424 + 0 + Process + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 110}, {70, 18}} + + YES + + 67239424 + 0 + Super + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 90}, {142, 18}} + + YES + + 67239424 + 0 + Create Temp Table + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 70}, {142, 18}} + + YES + + 67239424 + 0 + Lock Tables + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 50}, {142, 18}} + + YES + + 67239424 + 0 + Show Databases + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 30}, {142, 18}} + + YES + + 67239424 + 0 + Create User + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 10}, {142, 18}} + + YES + + 67239424 + 0 + Grant + + + 1211912703 + 130 + + + + + 200 + 25 + + + + {{1, 1}, {231, 216}} + + + + {{17, 10}, {233, 232}} + + {0, 0} + + 67239424 + 0 + Administration + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 0 + 2 + NO + + + + 289 + {{318, 84}, {114, 32}} + + YES + + 67239424 + 134217728 + Check All + + + -2038284033 + 129 + + + 200 + 25 + + + + + 12 + + YES + + + 256 + + YES + + + 268 + {{16, 92}, {63, 18}} + + YES + + 67239424 + 0 + Select + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 72}, {63, 18}} + + YES + + 67239424 + 0 + Insert + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 52}, {67, 18}} + + YES + + 67239424 + 0 + Update + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 32}, {63, 18}} + + YES + + 67239424 + 0 + Delete + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 12}, {91, 18}} + + YES + + 67239424 + 0 + References + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{152, 92}, {63, 18}} + + YES + + 67239424 + 0 + Create + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{152, 72}, {63, 18}} + + YES + + 67239424 + 0 + Drop + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{152, 52}, {63, 18}} + + YES + + 67239424 + 0 + Alter + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{152, 32}, {63, 18}} + + YES + + 67239424 + 0 + Index + + + 1211912703 + 130 + + + + + 200 + 25 + + + + {{1, 1}, {231, 118}} + + + + {{17, 246}, {233, 134}} + + {0, 0} + + 67239424 + 0 + Database and Tables + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 0 + 2 + NO + + + + 289 + {{318, 52}, {114, 32}} + + YES + + 67239424 + 134217728 + Uncheck All + + + -2038284033 + 129 + + + 200 + 25 + + + + + 9 + + YES + + + 256 + + YES + + + 268 + {{16, 92}, {97, 18}} + + YES + + 67239424 + 0 + Create View + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 72}, {97, 18}} + + YES + + 67239424 + 0 + Show View + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 52}, {116, 18}} + + YES + + 67239424 + 0 + Create Routine + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 32}, {105, 18}} + + YES + + 67239424 + 0 + Alter Routine + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{16, 12}, {97, 18}} + + YES + + 67239424 + 0 + Execute + + + 1211912703 + 130 + + + + + 200 + 25 + + + + {{1, 1}, {175, 118}} + + + + {{252, 246}, {177, 134}} + + {0, 0} + + 67239424 + 0 + Views and Procedures + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 0 + 2 + NO + + + {{17, 11}, {446, 400}} + + NSView + + + {{10, 33}, {511, 414}} + + Global Privileges + + + + + Resources + + + 256 + + YES + + + 269 + + YES + + + 256 + + YES + + + 4364 + {{18, 14}, {218, 82}} + + YES + 3 + 1 + + YES + + -1804468671 + -2143288320 + + + + + YES + + YES + allowsFloats + formatterBehavior + minimum + + + YES + + + + + + # + # + + + + + + + + + + NaN + + YES + + YES + + + YES + + + + + + 0 + 0 + YES + NO + 1 + AAAAAAAAAAAAAAAAAAAAAA + + + 3 + YES + YES + YES + + . + , + NO + YES + NO + + + 1.168931e+02 + + 67239424 + 67108864 + Max Updates: + + + + + -1804468671 + -1941961728 + + + + + YES + + YES + allowsFloats + formatterBehavior + minimum + + + YES + + + + + + # + # + + + + + + + + + + NaN + + + + + + 3 + YES + YES + YES + + . + , + NO + YES + NO + + 1 + + 1.168931e+02 + + 67239424 + 67108864 + Max Connections: + + + + + 343014976 + -1941961728 + + + + + YES + + YES + allowsFloats + formatterBehavior + minimum + + + YES + + + + + + # + # + + + + + + + + + + NaN + + + + + + 3 + YES + YES + YES + + . + , + NO + YES + NO + + + 1.168931e+02 + + 67239424 + 67108864 + Max Questions: + + + + + {218, 22} + {1, 8} + 524288 + NSActionCell + + 343014976 + 205521920 + + + 1.168931e+02 + + 67239424 + 67108864 + Field: + + + + -1 + -1 + + + + + + {{1, 1}, {254, 106}} + + + + {{127, 244}, {256, 122}} + + {0, 0} + + 67239424 + 0 + Resource Limits for the User + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 0 + 2 + NO + + + {{10, 33}, {511, 414}} + + Resources + + + + + + + 0 + YES + + YES + + + + + + 289 + {{467, 12}, {76, 32}} + + YES + + -2080244224 + 134217728 + Apply + + + -2038021889 + 129 + + + + 400 + 75 + + + + + 289 + {{385, 12}, {82, 32}} + + YES + + -2080244224 + 134217728 + Cancel + + + -2038021889 + 129 + + + + 400 + 75 + + + + {{195, 0}, {557, 506}} + + NSView + + + {752, 506} + + YES + 2 + + + {752, 506} + + + {{0, 0}, {1920, 1178}} + {3.40282e+38, 3.40282e+38} + + + + YES + username + children + host + itemTitle + password + globalPrivileges + globalPrivileges.Select_priv + globalPrivileges.Insert_priv + globalPrivileges.Update_priv + globalPrivileges.Delete_priv + globalPrivileges.Create_priv + globalPrivileges.Drop_priv + globalPrivileges.Reload_priv + globalPrivileges.Shutdown_priv + globalPrivileges.Process_priv + globalPrivileges.File_priv + globalPrivileges.Grant_priv + globalPrivileges.References_priv + globalPrivileges.Index_priv + globalPrivileges.Alter_priv + globalPrivileges.Show_db_priv + globalPrivileges.Super_priv + globalPrivileges.Create_tmp_table_priv + globalPrivileges.Lock_tables_priv + globalPrivileges.Execute_priv + globalPrivileges.Repl_slav_priv + globalPrivileges.Repl_client_priv + globalPrivileges.Create_view_priv + globalPrivileges.Show_view_priv + globalPrivileges.Create_routine_priv + globalPrivileges.Alter_routine_priv + globalPrivileges.Create_user_priv + globalPrivileges.Event_pri + user + content + contents + hosts.Select_priv + hosts.Insert_priv + displayName + create_priv + delete_priv + drop_priv + insert_priv + reload_priv + select_priv + update_priv + maxUserConnections + maxConnections + maxQuestions + max_user_connections + max_connections + max_questions + references_priv + alter_priv + index_priv + create_view_priv + show_view_priv + create_routine_priv + alter_routine_priv + execute_priv + shutdown_priv + file_priv + process_priv + super_priv + create_temporary_table_priv + lock_table_priv + lock_tables_priv + show_databases_priv + create_user_priv + grant_option_priv + replication_client_priv + replication_slave_priv + parent + + SPUserItem + YES + YES + + SPUser + + + 3 + valueForKey: + + 1 + + + YES + + 10 + parent + + + + + 0 + + + + 4 + 0 + NO + + + + YES + YES + YES + YES + children + + + + + YES + + + treeController + + + + 101 + + + + outlineView + + + + 102 + + + + tabView + + + + 103 + + + + delegate + + + + 168 + + + + window + + + + 169 + + + + managedObjectContext: managedObjectContext + + + + + + managedObjectContext: managedObjectContext + managedObjectContext + managedObjectContext + 2 + + + 355 + + + + doApply: + + + + 399 + + + + doCancel: + + + + 400 + + + + value: selection.max_user_connections + + + + + + value: selection.max_user_connections + value + selection.max_user_connections + 2 + + + 434 + + + + value: selection.max_connections + + + + + + value: selection.max_connections + value + selection.max_connections + 2 + + + 435 + + + + value: selection.max_questions + + + + + + value: selection.max_questions + value + selection.max_questions + 2 + + + 436 + + + + value: selection.user + + + + + + value: selection.user + value + selection.user + + YES + + YES + NSNoSelectionPlaceholder + NSNotApplicablePlaceholder + NSRaisesForNotApplicableKeys + + + YES + No Selection + User Not Selected + + + + 2 + + + 446 + + + + delegate + + + + 447 + + + + value: selection.select_priv + + + + + + value: selection.select_priv + value + selection.select_priv + 2 + + + 514 + + + + value: selection.insert_priv + + + + + + value: selection.insert_priv + value + selection.insert_priv + 2 + + + 516 + + + + value: selection.update_priv + + + + + + value: selection.update_priv + value + selection.update_priv + 2 + + + 518 + + + + value: selection.delete_priv + + + + + + value: selection.delete_priv + value + selection.delete_priv + 2 + + + 519 + + + + value: selection.references_priv + + + + + + value: selection.references_priv + value + selection.references_priv + 2 + + + 520 + + + + value: selection.create_priv + + + + + + value: selection.create_priv + value + selection.create_priv + 2 + + + 521 + + + + value: selection.drop_priv + + + + + + value: selection.drop_priv + value + selection.drop_priv + 2 + + + 522 + + + + value: selection.alter_priv + + + + + + value: selection.alter_priv + value + selection.alter_priv + 2 + + + 523 + + + + value: selection.index_priv + + + + + + value: selection.index_priv + value + selection.index_priv + 2 + + + 524 + + + + value: selection.create_view_priv + + + + + + value: selection.create_view_priv + value + selection.create_view_priv + 2 + + + 525 + + + + value: selection.show_view_priv + + + + + + value: selection.show_view_priv + value + selection.show_view_priv + 2 + + + 526 + + + + value: selection.create_routine_priv + + + + + + value: selection.create_routine_priv + value + selection.create_routine_priv + 2 + + + 527 + + + + value: selection.alter_routine_priv + + + + + + value: selection.alter_routine_priv + value + selection.alter_routine_priv + 2 + + + 528 + + + + value: selection.execute_priv + + + + + + value: selection.execute_priv + value + selection.execute_priv + 2 + + + 529 + + + + value: selection.reload_priv + + + + + + value: selection.reload_priv + value + selection.reload_priv + 2 + + + 530 + + + + value: selection.shutdown_priv + + + + + + value: selection.shutdown_priv + value + selection.shutdown_priv + 2 + + + 531 + + + + value: selection.file_priv + + + + + + value: selection.file_priv + value + selection.file_priv + 2 + + + 532 + + + + value: selection.process_priv + + + + + + value: selection.process_priv + value + selection.process_priv + 2 + + + 533 + + + + value: selection.super_priv + + + + + + value: selection.super_priv + value + selection.super_priv + 2 + + + 534 + + + + value: selection.create_temporary_table_priv + + + + + + value: selection.create_temporary_table_priv + value + selection.create_temporary_table_priv + 2 + + + 535 + + + + value: selection.lock_tables_priv + + + + + + value: selection.lock_tables_priv + value + selection.lock_tables_priv + 2 + + + 537 + + + + value: selection.show_databases_priv + + + + + + value: selection.show_databases_priv + value + selection.show_databases_priv + 2 + + + 538 + + + + value: selection.create_user_priv + + + + + + value: selection.create_user_priv + value + selection.create_user_priv + 2 + + + 539 + + + + value: selection.grant_option_priv + + + + + + value: selection.grant_option_priv + value + selection.grant_option_priv + 2 + + + 540 + + + + value: selection.replication_client_priv + + + + + + value: selection.replication_client_priv + value + selection.replication_client_priv + 2 + + + 541 + + + + value: selection.replication_slave_priv + + + + + + value: selection.replication_slave_priv + value + selection.replication_slave_priv + 2 + + + 542 + + + + value: selection.password + + + + + + value: selection.password + value + selection.password + + YES + + YES + NSConditionallySetsHidden + NSNoSelectionPlaceholder + NSRaisesForNotApplicableKeys + NSValidatesImmediately + + + YES + + No Selection + + + + + 2 + + + 576 + + + + addUser: + + + + 590 + + + + removeUser: + + + + 591 + + + + addHost: + + + + 594 + + + + removeHost: + + + + 595 + + + + enabled: selection.parent + + + + + + enabled: selection.parent + enabled + selection.parent + + NSValueTransformerName + NSIsNil + + 2 + + + 600 + + + + enabled: selection.parent + + + + + + enabled: selection.parent + enabled + selection.parent + + NSValueTransformerName + NSIsNil + + 2 + + + 603 + + + + value: arrangedObjects.displayName + + + + + + value: arrangedObjects.displayName + value + arrangedObjects.displayName + + YES + + YES + NSAllowsEditingMultipleValuesSelection + NSValidatesImmediately + + + YES + + + + + 2 + + + 604 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 3 + + + YES + + + + UserManagerView + + + 4 + + + YES + + + + + + 25 + + + YES + + + + + + + 27 + + + YES + + + + + + + + 48 + + + + + 122 + + + YES + + + + + + 123 + + + + + 124 + + + YES + + + + + + 125 + + + + + 37 + + + YES + + + + + + + + 189 + + + YES + + + + + + 190 + + + YES + + + + + + 42 + + + YES + + + + + + 43 + + + YES + + + + + + 38 + + + YES + + + + + + 41 + + + YES + + + + + + 44 + + + YES + + + + + + + + + 116 + + + YES + + + + + + 117 + + + + + 114 + + + YES + + + + + + 115 + + + + + 112 + + + YES + + + + + + 113 + + + + + 110 + + + YES + + + + + + 111 + + + + + 26 + + + YES + + + + + + + 28 + + + YES + + + + + + + + + 31 + + + YES + + + + + + 33 + + + YES + + + + + + 36 + + + + + 30 + + + + + 29 + + + + + 578 + + + + + 579 + + + YES + + + + + + + + 580 + + + YES + + + + + + 581 + + + + + 582 + + + YES + + + + + + 583 + + + + + 584 + + + YES + + + + + + 585 + + + YES + + + + + + 586 + + + YES + + + + + + + + 587 + + + + + 588 + + + + + 589 + + + + + 592 + + + YES + + + + + + + + + + + 454 + + + YES + + + + + + + 485 + + + YES + + + + + + 483 + + + YES + + + + + + 484 + + + + + 486 + + + + + 453 + + + YES + + + + + + + + + + + + + + + 505 + + + YES + + + + + + 503 + + + YES + + + + + + 501 + + + YES + + + + + + 499 + + + YES + + + + + + 497 + + + YES + + + + + + 495 + + + YES + + + + + + 493 + + + YES + + + + + + 491 + + + YES + + + + + + 489 + + + YES + + + + + + 487 + + + YES + + + + + + 488 + + + + + 490 + + + + + 492 + + + + + 494 + + + + + 496 + + + + + 498 + + + + + 500 + + + + + 502 + + + + + 504 + + + + + 506 + + + + + 509 + + + YES + + + + + + 510 + + + + + 451 + + + YES + + + + + + + + + + + + + + 471 + + + YES + + + + + + 469 + + + YES + + + + + + 467 + + + YES + + + + + + 465 + + + YES + + + + + + 463 + + + YES + + + + + + 461 + + + YES + + + + + + 459 + + + YES + + + + + + 457 + + + YES + + + + + + 455 + + + YES + + + + + + 456 + + + + + 458 + + + + + 460 + + + + + 462 + + + + + 464 + + + + + 466 + + + + + 468 + + + + + 470 + + + + + 472 + + + + + 511 + + + YES + + + + + + 512 + + + + + 452 + + + YES + + + + + + + + + + 477 + + + YES + + + + + + 475 + + + YES + + + + + + 473 + + + YES + + + + + + 481 + + + YES + + + + + + 479 + + + YES + + + + + + 480 + + + + + 482 + + + + + 474 + + + + + 476 + + + + + 478 + + + + + 593 + + + YES + + + + + + 288 + + + YES + + + + + + + + + 289 + + + YES + + + + + + 290 + + + YES + + + + + + 291 + + + + + 292 + + + YES + + + + + + 545 + + + + + 544 + + + + + 543 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 110.IBPluginDependency + 111.IBPluginDependency + 112.IBPluginDependency + 113.IBPluginDependency + 114.IBPluginDependency + 115.IBPluginDependency + 116.IBPluginDependency + 117.IBPluginDependency + 122.IBPluginDependency + 123.IBPluginDependency + 124.IBPluginDependency + 125.IBPluginDependency + 25.IBPluginDependency + 26.IBPluginDependency + 27.IBPluginDependency + 28.IBPluginDependency + 288.IBPluginDependency + 289.IBPluginDependency + 29.IBPluginDependency + 290.IBPluginDependency + 291.IBPluginDependency + 3.IBEditorWindowLastContentRect + 3.IBPluginDependency + 3.IBViewEditorWindowController.showingBoundsRectangles + 3.IBViewEditorWindowController.showingLayoutRectangles + 3.IBWindowTemplateEditedContentRect + 3.NSWindowTemplate.visibleAtLaunch + 30.IBPluginDependency + 31.IBPluginDependency + 33.IBPluginDependency + 36.IBPluginDependency + 37.IBAttributePlaceholdersKey + 37.IBPluginDependency + 38.IBPluginDependency + 4.IBPluginDependency + 41.IBPluginDependency + 44.IBPluginDependency + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 457.IBPluginDependency + 458.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 461.IBPluginDependency + 462.IBPluginDependency + 463.IBPluginDependency + 464.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 467.IBPluginDependency + 468.IBPluginDependency + 469.IBPluginDependency + 470.IBPluginDependency + 471.IBPluginDependency + 472.IBPluginDependency + 473.IBPluginDependency + 474.IBPluginDependency + 475.IBPluginDependency + 476.IBPluginDependency + 477.IBPluginDependency + 478.IBPluginDependency + 479.IBPluginDependency + 48.IBPluginDependency + 480.IBPluginDependency + 481.IBPluginDependency + 482.IBPluginDependency + 483.IBPluginDependency + 484.IBPluginDependency + 485.IBPluginDependency + 486.IBPluginDependency + 487.IBPluginDependency + 488.IBPluginDependency + 489.IBPluginDependency + 490.IBPluginDependency + 491.IBPluginDependency + 492.IBPluginDependency + 493.IBPluginDependency + 494.IBPluginDependency + 495.IBPluginDependency + 496.IBPluginDependency + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 543.IBPluginDependency + 544.IBPluginDependency + 545.IBPluginDependency + 579.IBPluginDependency + 580.IBAttributePlaceholdersKey + 580.IBPluginDependency + 581.IBPluginDependency + 582.IBAttributePlaceholdersKey + 582.IBPluginDependency + 583.IBPluginDependency + 584.IBPluginDependency + 585.IBPluginDependency + 586.IBEditorWindowLastContentRect + 586.IBPluginDependency + 587.IBPluginDependency + 588.IBPluginDependency + 589.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{59, 255}, {752, 506}} + com.apple.InterfaceBuilder.CocoaPlugin + + + {{59, 255}, {752, 506}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + InitialTabViewItem + + InitialTabViewItem + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Add User + + + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Remove User + + + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + {{476, 47}, {133, 54}} + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 604 + + + + YES + + NSObject + + IBProjectSource + Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h + + + + NSObject + + IBProjectSource + Frameworks/MCPKit/MCPFoundationKit/MCPNull.h + + + + NSObject + + IBProjectSource + Source/CMImageView.h + + + + NSObject + + IBProjectSource + Source/SPConnectionController.h + + + + NSObject + + toggleCollapse: + id + + + IBProjectSource + Source/TablesList.h + + + + NSWindow + + IBProjectSource + Source/SPWindowAdditions.h + + + + SPUserManager + NSObject + + YES + + YES + addHost: + addUser: + doApply: + doCancel: + removeHost: + removeUser: + + + YES + id + id + id + id + id + id + + + + YES + + YES + addHostSheet + outlineView + tabView + treeController + window + + + YES + NSPanel + NSOutlineView + NSTabView + NSTreeController + NSWindow + + + + IBProjectSource + Source/SPUserManager.h + + + + + 0 + ../../sequel-pro.xcodeproj + 3 + + diff --git a/Source/SPArrayAdditions.h b/Source/SPArrayAdditions.h index 45b81e03..473740fc 100644 --- a/Source/SPArrayAdditions.h +++ b/Source/SPArrayAdditions.h @@ -31,6 +31,7 @@ static inline id NSArrayObjectAtIndex(NSArray* self, NSUInteger i) { @interface NSArray (SPArrayAdditions) - (NSString *)componentsJoinedAndBacktickQuoted; +- (NSString *)componentsJoinedByCommas; - (NSArray *)subarrayWithIndexes:(NSIndexSet *)indexes; @end diff --git a/Source/SPArrayAdditions.m b/Source/SPArrayAdditions.m index 853421e0..37b1ba62 100644 --- a/Source/SPArrayAdditions.m +++ b/Source/SPArrayAdditions.m @@ -42,6 +42,21 @@ return result; } +- (NSString *)componentsJoinedByCommas +{ + NSString *result = [NSString string]; + for (NSString *component in self) + { + if ([result length]) + { + result = [result stringByAppendingString:@","]; + } + + result = [result stringByAppendingString:component]; + } + return result; +} + - (NSArray *)subarrayWithIndexes:(NSIndexSet *)indexes { NSMutableArray *subArray = [NSMutableArray arrayWithCapacity:[indexes count]]; diff --git a/Source/SPStringAdditions.h b/Source/SPStringAdditions.h index 764e6b24..6ee941c2 100644 --- a/Source/SPStringAdditions.h +++ b/Source/SPStringAdditions.h @@ -44,6 +44,8 @@ static inline const char* NSStringUTF8String(NSString* self) { + (NSString *)stringForTimeInterval:(float)timeInterval; - (NSString *)backtickQuotedString; +- (NSString *)tickQuotedString; +- (NSString *)replaceUnderscoreWithSpace; - (NSArray *)lineRangesForRange:(NSRange)aRange; - (NSString *)createViewSyntaxPrettifier; diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m index 81c501f9..5ddc14f3 100644 --- a/Source/SPStringAdditions.m +++ b/Source/SPStringAdditions.m @@ -163,6 +163,42 @@ return quotedString; } +// ------------------------------------------------------------------------------- +// tickQuotedString +// +// Returns the string quoted with ticks as required for MySQL identifiers +// eg.: tablename => 'tablename' +// my'table => 'my''table' +// ------------------------------------------------------------------------------- +- (NSString *)tickQuotedString +{ + // mutableCopy automatically retains the returned string, so don't forget to release it later... + NSMutableString *workingCopy = [self mutableCopy]; + + // First double all backticks in the string to escape them + // I don't want to use "stringByReplacingOccurrencesOfString:withString:" because it's only available in 10.5 + [workingCopy replaceOccurrencesOfString: @"'" + withString: @"''" + options: NSLiteralSearch + range: NSMakeRange(0, [workingCopy length]) ]; + + // Add the quotes around the string + NSString *quotedString = [NSString stringWithFormat: @"'%@'", workingCopy]; + + [workingCopy release]; + + return quotedString; +} + +- (NSString *)replaceUnderscoreWithSpace +{ + NSMutableString *workingCopy = [self mutableCopy]; + [workingCopy replaceOccurrencesOfString:@"_" + withString:@" " + options:NSLiteralSearch + range:NSMakeRange(0, [workingCopy length])]; + return [workingCopy autorelease]; +} // ------------------------------------------------------------------------------- // createViewSyntaxPrettifier diff --git a/Source/SPUserMO.h b/Source/SPUserMO.h new file mode 100644 index 00000000..13837921 --- /dev/null +++ b/Source/SPUserMO.h @@ -0,0 +1,41 @@ +// +// $Id: SPUserMO.h 856 2009-06-12 05:31:39Z mltownsend $ +// +// SPUserMO.h +// sequel-pro +// +// Created by Mark Townsend on Jan 01, 2009 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at + +#import + +@interface NSManagedObject (CoreDataGeneratedAccessors) + +@property(nonatomic, retain) NSString *user; +@property(nonatomic, retain) NSString *host; +@property(nonatomic, retain) NSManagedObject *parent; +@property (nonatomic, retain) NSSet *children; + +- (NSString *)displayName; +- (void)setDisplayName:(NSString *)value; + +// Access to-many relationship via -[NSObject mutableSetValueForKey:] +- (void)addChildrenObject:(NSManagedObject *)value; +- (void)removeChildrenObject:(NSManagedObject *)value; + +@end \ No newline at end of file diff --git a/Source/SPUserMO.m b/Source/SPUserMO.m new file mode 100644 index 00000000..05d699ae --- /dev/null +++ b/Source/SPUserMO.m @@ -0,0 +1,72 @@ +// +// $Id: SPUserMO.m 856 2009-06-12 05:31:39Z mltownsend $ +// +// SPUserMO.m +// sequel-pro +// +// Created by Mark Townsend on Jan 01, 2009 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at + +#import "SPUserMO.h" + +@implementation NSManagedObject (CoreDataGeneratedAccessors) + +@dynamic user, host; +@dynamic parent; +@dynamic children; + +- (NSString *)displayName +{ + if ([self valueForKey:@"parent"] == nil) { + return self.user; + } else { + return self.host; + } +} + +- (void)setDisplayName:(NSString *)value +{ + [self setValue:value forKey:@"host"]; +} + +- (void)addChildrenObject:(NSManagedObject *)value +{ + NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1]; + + [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; + [[self primitiveValueForKey:@"children"] addObject:value]; + [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; + + [changedObjects release]; + value.user = self.user; +} + +- (void)removeChildrenObject:(NSManagedObject *)value +{ + NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1]; + + [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects]; + [[self primitiveValueForKey:@"children"] removeObject:value]; + [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects]; + + [changedObjects release]; +} +@end + + + diff --git a/Source/SPUserManager.h b/Source/SPUserManager.h new file mode 100644 index 00000000..febeb472 --- /dev/null +++ b/Source/SPUserManager.h @@ -0,0 +1,73 @@ +// +// $Id: SPUserManager.h 856 2009-06-12 05:31:39Z mltownsend $ +// +// SPUserManager.h +// sequel-pro +// +// Created by Mark Townsend on Jan 01, 2009 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at + +#import + +@class MCPConnection; + +@interface SPUserManager : NSObject { + + NSPersistentStoreCoordinator *persistentStoreCoordinator; + NSManagedObjectModel *managedObjectModel; + NSManagedObjectContext *managedObjectContext; + NSDictionary *privColumnsMODict; + + BOOL isInitializing; + + MCPConnection* mySqlConnection; + + IBOutlet NSOutlineView* outlineView; + IBOutlet NSTabView *tabView; + IBOutlet NSTreeController *treeController; + IBOutlet NSWindow *window; + IBOutlet NSPanel *addHostSheet; +} + +- (NSPersistentStoreCoordinator *)persistentStoreCoordinator; +- (NSManagedObjectModel *)managedObjectModel; +- (NSManagedObjectContext *)managedObjectContext; + +- (id)initWithConnection:(MCPConnection *)connection; +- (void)setConnection:(MCPConnection *)connection; +- (MCPConnection *)connection; +- (void)show; +- (void)initializeChild:(NSManagedObject *)child withItem:(NSDictionary *)item; + +// Add/Remove Users +- (IBAction)addUser:(id)sender; +- (IBAction)removeUser:(id)sender; +- (IBAction)addHost:(id)sender; +- (IBAction)removeHost:(id)sender; + +// General +- (IBAction)doCancel:(id)sender; +- (IBAction)doApply:(id)sender; + +// Core Data Notifications +- (void)contextDidSave:(NSNotification *)notification; +- (BOOL)insertUsers:(NSArray *)insertedUsers; +- (BOOL)deleteUsers:(NSArray *)deletedUsers; +- (BOOL)updateUsers:(NSArray *)updatedUsers; +- (BOOL)grantPrivilegesToUser:(NSManagedObject *)user; +@end diff --git a/Source/SPUserManager.m b/Source/SPUserManager.m new file mode 100644 index 00000000..9ef3e8ba --- /dev/null +++ b/Source/SPUserManager.m @@ -0,0 +1,680 @@ +// +// $Id: SPUserManager.m 856 2009-06-12 05:31:39Z mltownsend $ +// +// SPUserManager.m +// sequel-pro +// +// Created by Mark Townsend on Jan 01, 2009 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at + +#import "SPUserManager.h" +#import "MCPConnection.h" +#import "SPUserMO.h" +#import "MCPResult.h" +#import "ImageAndTextCell.h" +#import "SPArrayAdditions.h" +#import "SPStringAdditions.h" + +#define COLUMNIDNAME @"NameColumn" + +@interface SPUserManager (PrivateMethods) +- (void)_initializeTree:(NSArray *)items; +- (void)_initializeUsers; +- (void)_selectParentFromSelection; +- (NSArray *)_fetchUserWithUserName:(NSString *)username; +- (NSManagedObject *)_createNewSPUser; +- (BOOL)checkAndDisplayMySqlError; +- (void)_clearData; +@end + +@implementation SPUserManager + +- (id)init +{ + [self dealloc]; + @throw [NSException exceptionWithName:@"BadInitCall" reason:@"Can't call init here" userInfo:nil]; + return nil; +} + +- (id)initWithConnection:(MCPConnection*) connection +{ + if (![super init]) { + return nil; + } + + [self setConnection:connection]; + + + privColumnsMODict = [[[NSDictionary alloc] initWithObjectsAndKeys: + @"grant_option_priv",@"Grant_priv", + @"show_databases_priv",@"Show_db_priv", + @"create_temporary_table_priv",@"Create_tmp_table_priv", + @"Replication_slave_priv",@"Repl_slave_priv", + @"Replication_client_priv",@"Repl_client_priv",nil] retain]; + + if (!outlineView) { + [NSBundle loadNibNamed:@"UserManagerView" owner:self]; + } + + return self; +} + +- (void)dealloc +{ + NSLog(@"SPUserManager dealloc."); + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [managedObjectContext release], managedObjectContext = nil; + [persistentStoreCoordinator release], persistentStoreCoordinator = nil; + [managedObjectModel release], managedObjectModel = nil; + [privColumnsMODict release], privColumnsMODict = nil; + + [mySqlConnection release]; + [super dealloc]; +} + +- (void)awakeFromNib +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(contextDidSave:) + name:NSManagedObjectContextDidSaveNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(contextDidChange:) + name:NSManagedObjectContextObjectsDidChangeNotification + object:nil]; + [tabView selectTabViewItemAtIndex:0]; + + NSTableColumn *tableColumn = [outlineView tableColumnWithIdentifier:COLUMNIDNAME]; + ImageAndTextCell *imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease]; + + [imageAndTextCell setEditable:NO]; + [tableColumn setDataCell:imageAndTextCell]; + + [NSThread detachNewThreadSelector:@selector(_initializeUsers) toTarget:self withObject:nil]; +} + +- (void)_initializeUsers +{ + isInitializing = TRUE; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSMutableArray *resultAsArray = [NSMutableArray array]; + NSMutableArray *usersResultArray = [NSMutableArray array]; + + [[self connection] selectDB:@"mysql"]; + MCPResult *result = [[[self connection] queryString:@"select * from user order by user"] retain]; + int rows = [result numOfRows]; + if (rows > 0) + { + // Go to the beginning + [result dataSeek:0]; + } + + for(int i = 0; i < rows; i++) + { + [resultAsArray addObject:[result fetchRowAsDictionary]]; + } + + [usersResultArray addObjectsFromArray:resultAsArray]; + + [self _initializeTree:usersResultArray]; + + [result release]; + [pool release]; + isInitializing = FALSE; +} + +- (void)_initializeTree:(NSArray *)items +{ + + for(int i = 0; i < [items count]; i++) + { + NSString *username = [[items objectAtIndex:i] objectForKey:@"User"]; + NSArray *array = [[self _fetchUserWithUserName:username] retain]; + NSDictionary *item = [items objectAtIndex:i]; + + if (array != nil && [array count] > 0) + { + // Add Children + NSManagedObject *parent = [array objectAtIndex:0]; + NSManagedObject *child = [self _createNewSPUser]; + [child setParent:parent]; + [parent addChildrenObject:child]; + + [self initializeChild:child withItem:item]; + + } else { + // Add Parent + NSManagedObject *parent = [self _createNewSPUser]; + NSManagedObject *child = [self _createNewSPUser]; + + [parent setValue:username forKey:@"user"]; + [parent setValue:[item objectForKey:@"Password"] forKey:@"password"]; + [parent addChildrenObject:child]; + [child setParent:parent]; + + [self initializeChild:child withItem:item]; + } + // Save the initialized objects so that any new changes will be tracked. + NSError *error = nil; + [[self managedObjectContext] save:&error]; + if (error != nil) + { + [[NSApplication sharedApplication] presentError:error]; + } + [array release]; + } +} + +- (void)initializeChild:(NSManagedObject *)child withItem:(NSDictionary *)item +{ + for (NSString *key in item) + { + NS_DURING + if ([key hasSuffix:@"_priv"]) + { + // Special case keys + if ([privColumnsMODict objectForKey:key] != nil) + { + key = [privColumnsMODict objectForKey:key]; + } + + BOOL value = [[item objectForKey:key] boolValue]; + [child setValue:[NSNumber numberWithBool:value] forKey:key]; + } + else if ([key hasPrefix:@"max"]) + { + NSNumber *value = [NSNumber numberWithInt:[[item objectForKey:key] intValue]]; + [child setValue:value forKey:key]; + } + else if (![key isEqualToString:@"User"] && ![key isEqualToString:@"Password"]) + { + NSString *value = [item objectForKey:key]; + [child setValue:value forKey:key]; + } + NS_HANDLER + NSLog(@"%@ not implemented yet.", key); + NS_ENDHANDLER + } + +} + +/** + Creates, retains, and returns the managed object model for the application + by merging all of the models found in the application bundle. + */ + +- (NSManagedObjectModel *)managedObjectModel { + + if (managedObjectModel != nil) { + return managedObjectModel; + } + + managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain]; + return managedObjectModel; +} + +/** + Returns the persistent store coordinator for the application. This + implementation will create and return a coordinator, having added the + store for the application to it. (The folder for the store is created, + if necessary.) + */ + +- (NSPersistentStoreCoordinator *) persistentStoreCoordinator { + + if (persistentStoreCoordinator != nil) { + return persistentStoreCoordinator; + } + + NSError *error; + + persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; + if (![persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&error]) + { + [[NSApplication sharedApplication] presentError:error]; + } + + return persistentStoreCoordinator; +} + +/** + Returns the managed object context for the application (which is already + bound to the persistent store coordinator for the application.) + */ + +- (NSManagedObjectContext *) managedObjectContext { + + if (managedObjectContext != nil) { + return managedObjectContext; + } + + NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; + if (coordinator != nil) { + managedObjectContext = [[NSManagedObjectContext alloc] init]; + [managedObjectContext setPersistentStoreCoordinator: coordinator]; + } + + return managedObjectContext; +} + +- (void)setConnection:(MCPConnection *)connection +{ + [connection retain]; + [mySqlConnection release]; + mySqlConnection = connection; +} + +- (MCPConnection* )connection +{ + return mySqlConnection; +} + +- (void)show +{ +// [NSThread detachNewThreadSelector:@selector(_initializeUsers) toTarget:self withObject:nil]; + [window makeKeyAndOrderFront:nil]; +} + +#pragma mark - +#pragma mark OutlineView Delegate Methods +- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + if ([cell isKindOfClass:[ImageAndTextCell class]]) + { + if ([(NSManagedObject *)[item representedObject] parent] != nil) + { + NSImage *image1 = [[NSImage imageNamed:NSImageNameNetwork] retain]; + [image1 setScalesWhenResized:YES]; + [image1 setSize:(NSSize){16,16}]; + [(ImageAndTextCell*)cell setImage:image1]; + [image1 release]; + + } + else + { + NSImage *image1 = [[NSImage imageNamed:NSImageNameUser] retain]; + [image1 setScalesWhenResized:YES]; + [image1 setSize:(NSSize){16,16}]; + [(ImageAndTextCell*)cell setImage:image1]; + [image1 release]; + } + } +} + +- (BOOL)outlineView:(NSOutlineView *)olv isGroupItem:(id)item +{ + return FALSE; +} + +- (BOOL)outlineView:(NSOutlineView *)olv shouldSelectItem:(id)item +{ + return TRUE; +} + +- (BOOL)outlineView:(NSOutlineView *)olv shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + if ([[[item representedObject] children] count] == 0) + { + return TRUE; + } + return FALSE; + +} + +- (void)outlineViewSelectionDidChange:(NSNotification *)notification +{ + id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; + if ([selectedObject parent] == nil && !([[[tabView selectedTabViewItem] identifier] isEqualToString:@"General"])) + { + [tabView selectTabViewItemWithIdentifier:@"General"]; + } + else + { + if ([[[tabView selectedTabViewItem] identifier] isEqualToString:@"General"]) + { + [tabView selectTabViewItemWithIdentifier:@"Global Privileges"]; + } + } +} + +// General Action Methods +- (IBAction)doCancel:(id)sender +{ + [[self managedObjectContext] rollback]; + [window close]; +} + +- (IBAction)doApply:(id)sender +{ + NSError *error = nil; + [[self managedObjectContext] save:&error]; + if (error != nil) + { + [[NSApplication sharedApplication] presentError:error]; + } + else + { + [window close]; + } +// [self _clearData]; +} + +- (IBAction)addUser:(id)sender +{ + if ([[treeController selectedObjects] count] > 0) + { + if ([[[treeController selectedObjects] objectAtIndex:0] parent] != nil) + { + [self _selectParentFromSelection]; + } + } + NSManagedObject *newItem = [self _createNewSPUser]; + NSManagedObject *newChild = [self _createNewSPUser]; + [newChild setValue:@"localhost" forKey:@"host"]; + [newItem addChildrenObject:newChild]; + + [treeController addObject:newItem]; + [outlineView expandItem:[outlineView itemAtRow:[outlineView selectedRow]]]; +} + +- (IBAction)removeUser:(id)sender +{ + [treeController remove:sender]; +} + +- (IBAction)addHost:(id)sender +{ + if ([[treeController selectedObjects] count] > 0) + { + if ([[[treeController selectedObjects] objectAtIndex:0] parent] != nil) + { + [self _selectParentFromSelection]; + } + } + [treeController addChild:sender]; + // Need to figure out how to do this right. I want to be able to have the newly + // added item be in edit mode to change the host name. +// [outlineView editColumn:0 row:[outlineView selectedRow] withEvent:nil select:TRUE]; +} + +- (IBAction)removeHost:(id)sender +{ + [treeController remove:sender]; +} + + +- (void)_clearData +{ + [managedObjectContext reset]; + [managedObjectContext release]; + managedObjectContext = nil; +} + +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + if ([menuItem action] == @selector(addHost:) || + [menuItem action] == @selector(removeHost:)) + { + return (([[treeController selectedObjects] count] > 0) && + [[[treeController selectedObjects] objectAtIndex:0] parent] != nil); + } + return TRUE; +} + +- (void)_selectParentFromSelection +{ + if ([[treeController selectedObjects] count] > 0) + { + NSTreeNode *firstSelectedNode = [[treeController selectedNodes] objectAtIndex:0]; + NSTreeNode *parentNode = [firstSelectedNode parentNode]; + if (parentNode) + { + NSIndexPath *parentIndex = [parentNode indexPath]; + [treeController setSelectionIndexPath:parentIndex]; + } + else + { + NSArray *selectedIndexPaths = [treeController selectionIndexPaths]; + [treeController removeSelectionIndexPaths:selectedIndexPaths]; + } + } +} + +#pragma mark - +#pragma mark Notifications +- (void)contextDidSave:(NSNotification *)notification +{ + if (!isInitializing) + { + NSArray *updated = [[notification userInfo] valueForKey:NSUpdatedObjectsKey]; + NSArray *inserted = [[notification userInfo] valueForKey:NSInsertedObjectsKey]; + NSArray *deleted = [[notification userInfo] valueForKey:NSDeletedObjectsKey]; + + if ([inserted count] > 0) + { + [self insertUsers:inserted]; + } + + if ([updated count] > 0) + { + [self updateUsers:updated]; + } + + if ([deleted count] > 0) + { + [self deleteUsers:deleted]; + } + } +} + +- (void)contextDidChange:(NSNotification *)notification +{ + NSLog(@"contextDidChange:"); + + if (!isInitializing) + { + [outlineView reloadData]; + } +} + +- (BOOL)updateUsers:(NSArray *)updatedUsers +{ + for (NSManagedObject *user in updatedUsers) { + [self grantPrivilegesToUser:user]; + } + return TRUE; +} + +- (BOOL)deleteUsers:(NSArray *)deletedUsers +{ + [[self connection] selectDB:@"mysql"]; + NSMutableString *droppedUsers = [NSMutableString string]; + for (NSManagedObject *user in deletedUsers) + { + if ([user host] != nil) + { + [droppedUsers appendString:[NSString stringWithFormat:@"%@@%@, ", + [[user valueForKey:@"user"] backtickQuotedString], + [[user valueForKey:@"host"] backtickQuotedString]]]; + } + + } + droppedUsers = [[droppedUsers substringToIndex:[droppedUsers length]-2] mutableCopy]; + [[self connection] queryString:[NSString stringWithFormat:@"DROP USER %@", droppedUsers]]; + + return TRUE; +} + +- (BOOL)insertUsers:(NSArray *)insertedUsers +{ + [[self connection] selectDB:@"mysql"]; + for(NSManagedObject *user in insertedUsers) + { + NSString *createStatement = [NSString stringWithFormat:@"CREATE USER %@@%@ IDENTIFIED BY %@;", + [[[user parent] valueForKey:@"user"] tickQuotedString], + [[user valueForKey:@"host"] tickQuotedString], + [[[user parent] valueForKey:@"password"] tickQuotedString]]; + // Create user in database + [[self connection] queryString:[NSString stringWithFormat:createStatement]]; + + if ([self checkAndDisplayMySqlError]) + { + [self grantPrivilegesToUser:user]; + } + } + + return TRUE; + +} + +// Grant or Revoke privileges to the given user +- (BOOL)grantPrivilegesToUser:(NSManagedObject *)user +{ + if ([user valueForKey:@"parent"] != nil) + { + NSDictionary *attributesDict = [[user entity] attributesByName]; + NSMutableArray *grantPrivileges = [NSMutableArray array]; + NSMutableArray *revokePrivileges = [NSMutableArray array]; + + for(NSString *key in [attributesDict allKeys]) + { + if ([key hasSuffix:@"_priv"]) + { + NSString *privilege = [key stringByReplacingOccurrencesOfString:@"_priv" withString:@""]; + + if ([[user valueForKey:key] boolValue] == TRUE) + { + [grantPrivileges addObject:[NSString stringWithFormat:@"%@", [privilege replaceUnderscoreWithSpace]]]; + } + else + { + [revokePrivileges addObject:[NSString stringWithFormat:@"%@", [privilege replaceUnderscoreWithSpace]]]; + } + } + } + // Grant privileges + if ([grantPrivileges count] > 0) + { + NSString *grantStatement = [NSString stringWithFormat:@"GRANT %@ ON *.* TO %@@%@;", + [grantPrivileges componentsJoinedByCommas], + [[[user parent] valueForKey:@"user"] tickQuotedString], + [[user valueForKey:@"host"] tickQuotedString]]; + NSLog(@"%@", grantStatement); + [[self connection] queryString:[NSString stringWithFormat:grantStatement]]; + [self checkAndDisplayMySqlError]; + } + + // Revoke privileges + if ([revokePrivileges count] > 0) + { + NSString *revokeStatement = [NSString stringWithFormat:@"REVOKE %@ ON *.* TO %@@%@;", + [revokePrivileges componentsJoinedByCommas], + [[[user parent] valueForKey:@"user"] tickQuotedString], + [[user valueForKey:@"host"] tickQuotedString]]; + NSLog(@"%@", revokeStatement); + [[self connection] queryString:[NSString stringWithFormat:revokeStatement]]; + [self checkAndDisplayMySqlError]; + } + } + return TRUE; +} +- (NSArray *)_fetchUserWithUserName:(NSString *)username +{ + NSManagedObjectContext *moc = [self managedObjectContext]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@ AND parent == nil", username]; + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"SPUser" + inManagedObjectContext:moc]; + NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; + + [request setEntity:entityDescription]; + [request setPredicate:predicate]; + + NSError *error = nil; + NSArray *array = [moc executeFetchRequest:request error:&error]; + if (error != nil) + { + [[NSApplication sharedApplication] presentError:error]; + } + + return array; +} + +- (NSManagedObject *)_createNewSPUser +{ + NSManagedObject *user = [[NSEntityDescription insertNewObjectForEntityForName:@"SPUser" + inManagedObjectContext:[self managedObjectContext]] autorelease]; + + return user; +} + +- (BOOL)checkAndDisplayMySqlError +{ + if (![[[self connection] getLastErrorMessage] isEqualToString:@""]) + { + NSBeginAlertSheet(@"MySQL Error", + nil, + nil, + nil, + window, + self, + NULL, + NULL, + nil, + [[self connection] getLastErrorMessage]); + return FALSE; + } else { + return TRUE; + } +} + +#pragma mark - +#pragma mark Tab View Delegate methods +- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem +{ + if ([[treeController selectedObjects] count] == 0) + return FALSE; + + id selectedObject = [[treeController selectedObjects] objectAtIndex:0]; + if ([[tabViewItem identifier] isEqualToString:@"General"]) + { + if ([selectedObject parent] == nil) { + return TRUE; + } else { + return FALSE; + } + } + else if ([[tabViewItem identifier] isEqualToString:@"Global Privileges"] || + [[tabViewItem identifier] isEqualToString:@"Resources"]) + { + if ([selectedObject parent] != nil) + { + return TRUE; + } + else + { + return FALSE; + } + } + + return TRUE; +} +@end diff --git a/Source/SPUserManager.xcdatamodel/elements b/Source/SPUserManager.xcdatamodel/elements new file mode 100644 index 00000000..6766bed3 Binary files /dev/null and b/Source/SPUserManager.xcdatamodel/elements differ diff --git a/Source/SPUserManager.xcdatamodel/layout b/Source/SPUserManager.xcdatamodel/layout new file mode 100644 index 00000000..07b18bfd Binary files /dev/null and b/Source/SPUserManager.xcdatamodel/layout differ diff --git a/Source/TableDocument.h b/Source/TableDocument.h index 42be9e5a..480ef810 100644 --- a/Source/TableDocument.h +++ b/Source/TableDocument.h @@ -53,6 +53,8 @@ enum { IBOutlet id databaseDataInstance; IBOutlet id spHistoryControllerInstance; IBOutlet id spExportControllerInstance; + IBOutlet id userManagerInstance; + IBOutlet NSSearchField *listFilterField; @@ -126,8 +128,8 @@ enum { - (NSString *)getHTMLforPrint; +- (IBAction)showUserManager:(id)sender; - (void)initQueryEditorWithString:(NSString *)query; - // Connection callback and methods - (void) setConnection:(MCPConnection *)theConnection; - (void)setShouldAutomaticallyConnect:(BOOL)shouldAutomaticallyConnect; diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 02212647..ee314b65 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -47,6 +47,7 @@ #import "SPPreferenceController.h" #import "SPPrintAccessory.h" #import "QLPreviewPanel.h" +#import "SPUserManager.h" // Used for printing #import "MGTemplateEngine.h" @@ -2174,7 +2175,15 @@ [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(viewRelations:)]; - + } else if ([itemIdentifier isEqualToString:@"SwitchToUserManagerToolbarItemIdentifier"]) { + [toolbarItem setLabel:NSLocalizedString(@"Users", @"toolbar item label for switching to the User Manager tab")]; + [toolbarItem setPaletteLabel:NSLocalizedString(@"Users", @"toolbar item label for switching to the User Manager tab")]; + //set up tooltip and image + [toolbarItem setToolTip:NSLocalizedString(@"Switch to the User Manager tab", @"tooltip for toolbar item for switching to the User Manager tab")]; + [toolbarItem setImage:[NSImage imageNamed:NSImageNameEveryone]]; + //set up the target action + [toolbarItem setTarget:self]; + [toolbarItem setAction:@selector(showUserManager:)]; } else { //itemIdentifier refered to a toolbar item that is not provided or supported by us or cocoa toolbarItem = nil; @@ -2199,6 +2208,7 @@ @"SwitchToRunQueryToolbarItemIdentifier", @"SwitchToTableInfoToolbarItemIdentifier", @"SwitchToTableRelationsToolbarItemIdentifier", + @"SwitchToUserManagerToolbarItemIdentifier", NSToolbarCustomizeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, @@ -2220,6 +2230,7 @@ @"SwitchToRunQueryToolbarItemIdentifier", NSToolbarFlexibleSpaceItemIdentifier, @"HistoryNavigationToolbarItemIdentifier", + @"SwitchToUserManagerToolbarItemIdentifier", @"ShowConsoleIdentifier", nil]; } @@ -2542,6 +2553,16 @@ if(queryEditorInitString) [queryEditorInitString release]; [super dealloc]; } + +- (void)showUserManager:(id)sender +{ + if (userManagerInstance == nil) + { + userManagerInstance = [[SPUserManager alloc] initWithConnection:mySQLConnection]; + } else { + [userManagerInstance show]; + } +} @end diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index aa5d4aa0..06ce19ec 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -123,6 +123,10 @@ 384582C40FB95FF800DDACB6 /* func-small.png in Resources */ = {isa = PBXBuildFile; fileRef = 384582C30FB95FF800DDACB6 /* func-small.png */; }; 384582C70FB9603600DDACB6 /* proc-small.png in Resources */ = {isa = PBXBuildFile; fileRef = 384582C60FB9603600DDACB6 /* proc-small.png */; }; 387BBBA80FBCB6CB00B31746 /* SPTableRelations.m in Sources */ = {isa = PBXBuildFile; fileRef = 387BBBA70FBCB6CB00B31746 /* SPTableRelations.m */; }; + 4D90B79A101E0CDF00D116A1 /* SPUserManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D90B799101E0CDF00D116A1 /* SPUserManager.m */; }; + 4D90B79E101E0CF200D116A1 /* SPUserManager.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = 4D90B79B101E0CF200D116A1 /* SPUserManager.xcdatamodel */; }; + 4D90B79F101E0CF200D116A1 /* SPUserMO.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D90B79D101E0CF200D116A1 /* SPUserMO.m */; }; + 4D90B7A2101E0D1500D116A1 /* UserManagerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4D90B7A0101E0D1500D116A1 /* UserManagerView.xib */; }; 4DECC3350EC2A170008D359E /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3320EC2A170008D359E /* Sparkle.framework */; }; 4DECC3370EC2A170008D359E /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3340EC2A170008D359E /* Growl.framework */; }; 4DECC48F0EC2B436008D359E /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4DECC3320EC2A170008D359E /* Sparkle.framework */; }; @@ -474,6 +478,12 @@ 384582C60FB9603600DDACB6 /* proc-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "proc-small.png"; sourceTree = ""; }; 387BBBA60FBCB6CB00B31746 /* SPTableRelations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPTableRelations.h; sourceTree = ""; }; 387BBBA70FBCB6CB00B31746 /* SPTableRelations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPTableRelations.m; sourceTree = ""; }; + 4D90B798101E0CDF00D116A1 /* SPUserManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUserManager.h; sourceTree = ""; }; + 4D90B799101E0CDF00D116A1 /* SPUserManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPUserManager.m; sourceTree = ""; }; + 4D90B79B101E0CF200D116A1 /* SPUserManager.xcdatamodel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.xcdatamodel; path = SPUserManager.xcdatamodel; sourceTree = ""; }; + 4D90B79C101E0CF200D116A1 /* SPUserMO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUserMO.h; sourceTree = ""; }; + 4D90B79D101E0CF200D116A1 /* SPUserMO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPUserMO.m; sourceTree = ""; }; + 4D90B7A1101E0D1500D116A1 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/UserManagerView.xib; sourceTree = ""; }; 4DECC3320EC2A170008D359E /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Frameworks/Sparkle.framework; sourceTree = ""; }; 4DECC3340EC2A170008D359E /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = Frameworks/Growl.framework; sourceTree = ""; }; 581068B51015411B0068C6E2 /* link-arrow-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "link-arrow-highlighted.png"; sourceTree = ""; }; @@ -897,6 +907,8 @@ 58FEF57D0F3B4E9700518E8E /* SPTableData.m */, 387BBBA60FBCB6CB00B31746 /* SPTableRelations.h */, 387BBBA70FBCB6CB00B31746 /* SPTableRelations.m */, + 4D90B798101E0CDF00D116A1 /* SPUserManager.h */, + 4D90B799101E0CDF00D116A1 /* SPUserManager.m */, 17E6414E0EF01EF6001BC333 /* TableContent.h */, 17E6414F0EF01EF6001BC333 /* TableContent.m */, 17E641500EF01EF6001BC333 /* TableDocument.h */, @@ -912,6 +924,9 @@ 17E6415D0EF01EF9001BC333 /* Model */ = { isa = PBXGroup; children = ( + 4D90B79B101E0CF200D116A1 /* SPUserManager.xcdatamodel */, + 4D90B79C101E0CF200D116A1 /* SPUserMO.h */, + 4D90B79D101E0CF200D116A1 /* SPUserMO.m */, 172A650F0F7BED7A001E861A /* SPConsoleMessage.h */, 172A65100F7BED7A001E861A /* SPConsoleMessage.m */, 177E7A210FCB6A2E00E9E122 /* SPExtendedTableInfo.h */, @@ -1078,6 +1093,7 @@ 17E642050EF020A3001BC333 /* Interfaces */ = { isa = PBXGroup; children = ( + 4D90B7A0101E0D1500D116A1 /* UserManagerView.xib */, B52460D90F8EF93B00171639 /* Console.xib */, BCA6F62F100FA7D700E80253 /* FieldEditorSheet.xib */, 17E642060EF020CB001BC333 /* DBView.xib */, @@ -1464,6 +1480,7 @@ BC688D811012462600D35128 /* borderlessbackground.png in Resources */, 581068B61015411B0068C6E2 /* link-arrow-highlighted.png in Resources */, 581069B410167EC10068C6E2 /* SequelProTunnelAssistant in Resources */, + 4D90B7A2101E0D1500D116A1 /* UserManagerView.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1596,6 +1613,9 @@ BC9F0881100FCF2C00A80D32 /* SPFieldEditorController.m in Sources */, 58D2E229101222670063EF1D /* SPTextAndLinkCell.m in Sources */, BC05F1C5101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m in Sources */, + 4D90B79A101E0CDF00D116A1 /* SPUserManager.m in Sources */, + 4D90B79E101E0CF200D116A1 /* SPUserManager.xcdatamodel in Sources */, + 4D90B79F101E0CF200D116A1 /* SPUserMO.m in Sources */, 584192A1101E57BB0089807F /* NSMutableArray-MultipleSort.m in Sources */, 589235321020C1230011DE00 /* SPHistoryController.m in Sources */, BCA6271C1031B9D40047E5D5 /* SPTooltip.m in Sources */, @@ -1673,6 +1693,14 @@ name = Localizable.strings; sourceTree = ""; }; + 4D90B7A0101E0D1500D116A1 /* UserManagerView.xib */ = { + isa = PBXVariantGroup; + children = ( + 4D90B7A1101E0D1500D116A1 /* English */, + ); + name = UserManagerView.xib; + sourceTree = ""; + }; 58186D1F0F4CB38900851FE9 /* ConnectionErrorDialog.xib */ = { isa = PBXVariantGroup; children = ( -- cgit v1.2.3