Files
HeidiSQL/source/usermanager.pas
Ansgar Becker 4e23728aa2 - Move all hardcoded preferences names (registry) plus their default values to const.inc to fix inconsistencies like the one described here: http://www.heidisql.com/forum/viewtopic.php?p=1739
- Consequently use Mainform.GetRegValue() to read these values, an overloaded method with either Boolean, String or Integer result. These methods keep a global TRegistry object (regMain) open while the application runs, rather than creating a new one for each caller.
- Remove Mainform.SaveRegValue() which was used in one or two callers. Rather use a TRegistry object and do that by hand. There's no significant advantage in using a SaveRegValue method currently.
2008-02-06 00:00:52 +00:00

1029 lines
34 KiB
ObjectPascal

unit usermanager;
// -------------------------------------
// Usermanager
// -------------------------------------
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, CheckLst, ImgList, ExtCtrls, Registry, ZDataset, Db;
// winsock
type
TUserManagerForm = class(TForm)
PageControl1: TPageControl;
TabSheetAddUser: TTabSheet;
DBUserTree: TTreeView;
EditUser: TEdit;
EditPassword: TEdit;
EditHost: TEdit;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
CheckListBoxPrivileges: TCheckListBox;
CheckBoxAllPrivileges: TCheckBox;
Label8: TLabel;
CheckBoxWithGrant: TCheckBox;
Label9: TLabel;
Bevel1: TBevel;
CheckBoxCreateAccount: TCheckBox;
EditDescription: TEdit;
Label1: TLabel;
TabSheetEditUsers: TTabSheet;
Panel1: TPanel;
CheckListBoxPrivs: TCheckListBox;
Label13: TLabel;
LabelColumn: TLabel;
LabelTable: TLabel;
LabelDB: TLabel;
Label12: TLabel;
Label11: TLabel;
LabelPrivileges: TLabel;
Panel2: TPanel;
Label2: TLabel;
TreeViewUsers: TTreeView;
ButtonSelectAll: TButton;
ButtonSelectNone: TButton;
ButtonSet: TButton;
LabelPleaseSelect: TLabel;
LabelNoPrivs: TLabel;
ButtonSelectPrivileges: TButton;
Panel3: TPanel;
ButtonClose: TButton;
ButtonAddUser: TButton;
LabelUser: TLabel;
ButtonRevoke: TButton;
Panel4: TPanel;
ButtonEditUser: TButton;
Button1: TButton;
procedure DBUserTreeExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
procedure ButtonCloseClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure CheckBoxAllPrivilegesClick(Sender: TObject);
procedure ButtonAddUserClick(Sender: TObject);
procedure CheckBoxCreateAccountClick(Sender: TObject);
procedure TreeViewUsersDblClick(Sender: TObject);
procedure TreeViewUsersChange(Sender: TObject; Node: TTreeNode);
procedure PageControl1Change(Sender: TObject);
procedure ButtonSelectAllClick(Sender: TObject);
procedure ButtonSelectNoneClick(Sender: TObject);
procedure ShowPrivilegesControls(v,w,y: Boolean);
procedure ButtonSelectPrivilegesClick(Sender: TObject);
procedure ShowPrivs(node: TTreeNode);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ButtonSetClick(Sender: TObject);
procedure CheckListBoxPrivsClickCheck(Sender: TObject);
procedure ButtonRevokeClick(Sender: TObject);
procedure ButtonEditUserClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure GetResUsers;
procedure GetResDBs;
procedure GetResTables;
procedure GetResColumns;
function getColumnNamesOrValues( which: String = 'columns' ): TStringList;
function getPrivColumns( privtable: String ): TDataSet;
procedure clearCache;
private
{ Private declarations }
editcurrent : Boolean;
public
{ Public declarations }
User, Host : String; // Remember for setting privileges
ZQueryDBs, ZQueryTables, ZQueryColumns, ZQueryUsers: TDataSet;
ColumnsUsers, ColumnsDB, ColumnsTables, ColumnsColumns : TDataSet;
end;
function UserManagerWindow (AOwner : TComponent; Flags : String = '') : Boolean;
var
UserManagerForm: TUserManagerForm;
old_ActualDatabase : String;
implementation
uses
main, childwin, helpers, edituser;
{$I const.inc}
{$R *.DFM}
function UserManagerWindow (AOwner : TComponent; Flags : String = '') : Boolean;
var
f : TUserManagerForm;
test_result : String;
cwin : TMDIChild;
begin
// Test if we can access the privileges database and tables by
// A. Using the mysql-DB
cwin := Mainform.Childwin;
try
try
cwin.TemporaryDatabase := DBNAME_MYSQL;
cwin.EnsureDatabase;
except
MessageDlg('You have no access to the privileges database.', mtError, [mbOK], 0);
Result := false;
exit;
end;
// B. retrieving a count of all users.
test_result := cwin.GetVar( 'SELECT COUNT(*) FROM '+mainform.mask(PRIVTABLE_USERS), 0, true, false );
if test_result = '' then
begin
MessageDlg('You have no access to the privileges tables.', mtError, [mbOK], 0);
Result := false;
exit;
end;
f := TUserManagerForm.Create(AOwner);
// use this dirty trick to overcome limitations
UsermanagerForm := f;
// set flags ...
Result := (f.ShowModal = mrOK);
FreeAndNil (f);
UsermanagerForm := nil; // uhhh
finally
cwin.TemporaryDatabase := '';
end;
end;
procedure TUserManagerForm.ButtonCloseClick(Sender: TObject);
begin
close;
end;
procedure TUserManagerForm.FormShow(Sender: TObject);
var
i : Integer;
tntop, tn1, tnu1, tnu2 : TTreeNode;
// wsadat : WSAData;
// host : String;
// ph : PHostEnt;
begin
Screen.Cursor := crHourglass;
DBUserTree.Items.Clear;
TreeViewUsers.Items.Clear;
PageControl1.ActivePageIndex := 0;
ShowPrivilegesControls(false, true, false);
CheckBoxCreateAccount.Caption := 'Create connection account for ' + APPNAME;
tnu1 := DBUserTree.Items.Add(nil, 'Global Access');
tnu1.ImageIndex := 41;
tnu1.SelectedIndex := tnu1.ImageIndex;
tntop := Mainform.Childwin.tnodehost; // tnodehost on childwin
tn1 := tntop.GetFirstChild;
for i:=0 to tntop.Count-1 do
begin
tnu2 := DBUserTree.Items.AddChild(tnu1, tn1.Text);
tnu2.ImageIndex := tn1.ImageIndex;
tnu2.SelectedIndex := tn1.SelectedIndex;
DBUserTree.Items.AddChild( tnu2, DUMMY_NODE_TEXT );
tn1 := tntop.getNextChild(tn1);
end;
EditUser.Text := Mainform.Childwin.Conn.MysqlParams.User;
tnu1.Expand(false);
tnu1.Selected := true;
with CheckListBoxPrivileges do
for i:=0 to 8 do
Checked[i] := true;
PageControl1.OnChange(self);
{
// get users hostname
WSAStartup(MAKEWORD(1, 1), wsadat);
gethostname(pchar(host), 80);
ph := gethostbyname(pchar(host));
EditHost.Text := ph.h_name;
WSACleanup();
}
Screen.Cursor := crDefault;
end;
procedure TUserManagerForm.CheckBoxAllPrivilegesClick(Sender: TObject);
begin
CheckListBoxPrivileges.Enabled := not CheckBoxAllPrivileges.Checked;
end;
procedure TUserManagerForm.ButtonAddUserClick(Sender: TObject);
var
i : Integer;
priv, query, access, fromhost, pass, grant : String;
begin
// Account
if CheckBoxCreateAccount.Checked then
with TRegistry.Create do
begin
OpenKey(REGPATH + REGKEY_SESSIONS, false);
if KeyExists(EditDescription.Text) then
begin
MessageDlg('This Description (' + EditDescription.Text + ') is already used.' + CRLF + 'Please specify another description!', mtError, [mbOK], 0);
EditDescription.SetFocus;
exit;
end
else with TRegistry.Create do
begin
OpenKey(REGPATH + REGKEY_SESSIONS + EditDescription.Text, true);
WriteString(REGNAME_HOST, Mainform.Childwin.Conn.MysqlParams.Host);
WriteString(REGNAME_USER, EditUser.Text);
WriteString(REGNAME_PASSWORD, encrypt(EditPassword.Text));
WriteString(REGNAME_PORT, IntToStr(Mainform.Childwin.Conn.MysqlParams.Port));
WriteString(REGNAME_TIMEOUT, IntToStr(DEFAULT_TIMEOUT));
WriteBool(REGNAME_COMPRESSED, DEFAULT_COMPRESSED);
WriteString(REGNAME_ONLYDBS, '');
CloseKey;
Free;
end;
Free;
end;
priv := '';
if CheckBoxAllPrivileges.Checked then
priv := 'ALL PRIVILEGES'
else
with CheckListBoxPrivileges do
for i:=0 to Items.Count - 1 do
if Checked[i] then
begin
if priv <> '' then
priv := priv + ', ';
priv := priv + Items[i];
end;
if priv = '' then
priv := 'USAGE';
case DBUserTree.Selected.Level of
0 : access := '*.*';
1 : access := MainForm.Mask( DBUserTree.Selected.Text ) + '.*';
2 : access := MainForm.Mask( DBUserTree.Selected.Text );
end;
if EditHost.Text = '' then
fromhost := '%'
else
fromhost := EditHost.Text;
if EditPassWord.Text <> '' then
pass := ' IDENTIFIED BY ''' + EditPassWord.Text + '''';
if CheckBoxWithGrant.Checked then
grant := ' WITH GRANT OPTION';
query := 'GRANT ' + priv + ' ON ' + access + ' TO ''' + EditUser.Text + '''@''' + fromhost + '''' + pass + grant;
Mainform.Childwin.ExecUpdateQuery(query);
Mainform.Childwin.ExecUpdateQuery('FLUSH PRIVILEGES');
ShowMessage('User succesfully created.');
end;
procedure TUserManagerForm.CheckBoxCreateAccountClick(Sender: TObject);
begin
Label1.Enabled := CheckBoxCreateAccount.Checked;
EditDescription.Enabled := CheckBoxCreateAccount.Checked;
if (CheckBoxCreateAccount.Checked) and (EditDescription.Text = '') then
begin
EditDescription.Text := Mainform.Childwin.Caption;
EditDescription.SetFocus;
end;
end;
procedure TUserManagerForm.TreeViewUsersDblClick(Sender: TObject);
var
tnu, tndb : TTreeNode;
i : Integer;
TableNames : TStringList;
ZQueryColumnNames : TDataSet;
begin
// Add subitems to TreeNode:
Screen.Cursor := crHourGlass;
if not TreeViewUsers.Selected.HasChildren then
case TreeViewUsers.Selected.Level of
0 : // add dbs to user-node...
begin
tndb := Mainform.Childwin.tnodehost.GetFirstChild;
for i:=0 to Mainform.Childwin.tnodehost.Count-1 do
begin
tnu := TreeViewUsers.Items.AddChild(TreeViewUsers.Selected, tndb.Text);
tnu.ImageIndex := tndb.ImageIndex;
tnu.SelectedIndex := tndb.SelectedIndex;
tndb := Mainform.Childwin.tnodehost.getNextChild(tndb);
end;
end;
1 : // add tables to user-node...
begin
TableNames := Mainform.Childwin.GetCol( 'SHOW TABLES FROM ' + MainForm.mask(TreeViewUsers.Selected.Text) );
for i:=0 to TableNames.Count-1 do
begin
with TreeViewUsers.Items.AddChild( TreeViewUsers.Selected, TableNames[i] ) do
begin
ImageIndex := 39;
SelectedIndex := 40;
end;
end;
end;
2 : // add columns to user-node...
begin
// find fields from table
ZQueryColumnNames := Mainform.Childwin.GetResults( 'SHOW COLUMNS FROM ' + mainform.mask(TreeViewUsers.Selected.Parent.Text) + '.' + mainform.mask(TreeViewUsers.Selected.Text));
for i:=1 to ZQueryColumnNames.RecordCount do
begin
tnu := TreeViewUsers.Items.AddChild(TreeViewUsers.Selected, ZQueryColumnNames.Fields[0].AsString);
tnu.ImageIndex := ICONINDEX_FIELD;
tnu.SelectedIndex := ICONINDEX_FIELD;
ZQueryColumnNames.Next;
end;
ZQueryColumnNames.Close;
FreeAndNil( ZQueryColumnNames );
end;
end;
if not TreeViewUsers.Selected.Expanded then
TreeViewUsers.Selected.Expand(false);
Screen.Cursor := crDefault;
end;
procedure TUserManagerForm.TreeViewUsersChange(Sender: TObject;
Node: TTreeNode);
var
n : TTreeNode;
highlight : TColor;
begin
// Selecting a User, DB, Table or Column in TreeViewUsers
n := Node;
while n.Parent <> nil do
n := n.Parent;
// show controls:
ShowPrivilegesControls(false, false, true);
User := copy(n.Text, 0, pos('@', n.Text)-1);
Host := copy(n.Text, pos('@', n.Text)+1, length(n.text));
LabelUser.Caption := 'User ''' + User + ''' connecting from host ''' + Host + '''';
highlight := clNavy;
case Node.level of
0 : begin
LabelDB.Caption := '<All Databases>'; LabelDB.Font.Color := highlight;
LabelTable.Caption := '<All Tables>'; LabelTable.Font.Color := highlight;
LabelColumn.Caption := '<All Columns>'; LabelColumn.Font.Color := highlight;
ButtonEditUser.Enabled := true;
end;
1 : begin
LabelDB.Caption := Node.Text; LabelDB.Font.Color := clWindowText;
LabelTable.Caption := '<All Tables>'; LabelTable.Font.Color := highlight;
LabelColumn.Caption := '<All Columns>'; LabelColumn.Font.Color := highlight;
GetResDBs;
ButtonEditUser.Enabled := false;
end;
2 : begin
LabelDB.Caption := Node.Parent.Text; LabelDB.Font.Color := clWindowText;
LabelTable.Caption := Node.Text; LabelTable.Font.Color := clWindowText;
LabelColumn.Caption := '<All Columns>'; LabelColumn.Font.Color := highlight;
GetResTables;
ButtonEditUser.Enabled := false;
end;
3 : begin
LabelDB.Caption := Node.Parent.Parent.Text; LabelDB.Font.Color := clWindowText;
LabelTable.Caption := Node.Parent.Text; LabelTable.Font.Color := clWindowText;
LabelColumn.Caption := Node.Text; LabelColumn.Font.Color := clWindowText;
GetResColumns;
ButtonEditUser.Enabled := false;
end;
end;
editcurrent := true;
ShowPrivs(node);
end;
procedure TUserManagerForm.PageControl1Change(Sender: TObject);
var
i : Integer;
tn : TTreeNode;
begin
// Toggle Button Add User
ButtonAddUser.Visible := PageControl1.ActivePage = TabSheetAddUser;
// ---------------------
// Edit Users:
// Fill Tree with Registered Users:
if (PageControl1.ActivePage = TabSheetEditUsers) and
(TreeViewUsers.Items.Count = 0) then
begin
GetResUsers;
for i:=1 to ZQueryUsers.RecordCount do
begin
tn := TreeViewUsers.Items.AddChild(nil, ZQueryUsers.Fields[1].AsString + '@' + ZQueryUsers.Fields[0].AsString );
tn.ImageIndex := 61;
tn.SelectedIndex := 60;
ZQueryUsers.Next;
end;
end;
// ---------------------
end;
procedure TUserManagerForm.ButtonSelectAllClick(Sender: TObject);
begin
// Select all
ToggleCheckListBox(CheckListBoxPrivs, true);
CheckListBoxPrivs.OnClickCheck(self);
end;
procedure TUserManagerForm.ButtonSelectNoneClick(Sender: TObject);
begin
// Select none
ToggleCheckListBox(CheckListBoxPrivs, false);
CheckListBoxPrivs.OnClickCheck(self);
end;
procedure TUserManagerForm.ShowPrivilegesControls(v, w, y: Boolean);
function getPrivNames( privtable : String ): TStringList;
var
i,j : Byte;
q : TDataSet;
setlist : TStringList;
tmpstr : String;
begin
// Get cached dataset
q := getPrivColumns( privtable );
result := TStringList.Create;
for i := 0 to q.RecordCount-1 do
begin
if pos( '_priv', q.FieldByName('Field').AsString ) > 0 then
begin
// user + db are enum(Y,N)
if StrCmpBegin( 'enum', q.FieldByName('Type').AsString ) then
begin
result.add( q.FieldByName('Field').AsString );
result[result.count-1] := stringreplace( result[result.count-1], '_priv', '', [] );
end
// table + column are set(x,y,z)
else if StrCmpBegin( 'set', q.FieldByName('Type').AsString ) then
begin
tmpstr := getEnumValues(q.FieldByName('Type').AsString);
tmpstr := StringReplace( tmpstr, '''', '', [rfReplaceAll] );
setlist := explode(',', tmpstr );
for j:=0 to setlist.Count-1 do
begin
result.Add(q.FieldByName('Field').AsString+': '+setlist[j]);
result[result.count-1] := stringreplace( result[result.count-1], '_priv', '', [] );
end;
end
//result[i] := uppercase( result[i] );
end;
q.next;
end;
end;
begin
// show/hide Privileges-Controls
// v : some privileges set?
// w : a user selected?
// y : no privileges set
LabelPrivileges.Visible := v;
Label11.Visible := v;
Label12.Visible := v;
Label13.Visible := v;
LabelUser.Visible := v;
LabelDB.Visible := v;
LabelTable.Visible := v;
LabelColumn.Visible := v;
CheckListBoxPrivs.Visible := v;
ButtonSelectAll.Visible := v;
ButtonSelectNone.Visible := v;
ButtonSet.Visible := v;
if v then
ButtonSet.Enabled := false;
ButtonRevoke.Visible := v;
if v then
ButtonRevoke.Enabled := editcurrent;
LabelPleaseSelect.Visible := w;
LabelNoPrivs.Visible := y;
ButtonSelectPrivileges.Visible := y;
if TreeViewUsers.Selected <> nil then
begin
CheckListBoxPrivs.Clear;
case TreeViewUsers.Selected.Level of
0 : begin // General
CheckListBoxPrivs.Items := getPrivNames( PRIVTABLE_USERS );
ButtonRevoke.Caption := 'Delete User';
end;
1 : begin // DB
CheckListBoxPrivs.Items := getPrivNames( PRIVTABLE_DB );
ButtonRevoke.Caption := 'Revoke Privileges';
end;
2 : begin // Table
CheckListBoxPrivs.Items := getPrivNames( PRIVTABLE_TABLES );
ButtonRevoke.Caption := 'Revoke Privileges';
end;
3 : begin // Column
CheckListBoxPrivs.Items := getPrivNames( PRIVTABLE_COLUMNS );
ButtonRevoke.Caption := 'Revoke Privileges';
end;
end;
end;
end;
procedure TUserManagerForm.ButtonSelectPrivilegesClick(Sender: TObject);
begin
// Specify some privileges
editcurrent := false;
ShowPrivilegesControls(true, false, false);
end;
procedure TUserManagerForm.ShowPrivs(node: TTreeNode);
var
i,j : Integer;
ColumnName, value : String;
set_values : TStringList;
begin
// Show user-privileges (general, db, table or column)
// depending on node.level
case Node.Level of
0 : begin // General user-privileges
ZQueryUsers.First;
for i:=1 to ZQueryUsers.RecordCount do
begin
if (ZQueryUsers.Fields[0].AsString+'' = Host) and (ZQueryUsers.Fields[1].AsString+'' = User) then
begin // found the according user!
ShowPrivilegesControls(true, false, false);
for j := 0 to CheckListBoxPrivs.count -1 do
begin
CheckListBoxPrivs.Checked[j] := ZQueryUsers.FieldByName( CheckListBoxPrivs.Items[j] + '_priv' ).AsBoolean;
end;
break;
end;
ZQueryUsers.Next;
end;
end;
1 : begin // db-privileges
ZQueryDBs.First;
for i:=1 to ZQueryDBs.RecordCount do
begin
if (ZQueryDBs.Fields[0].AsString = Host)
and (ZQueryDBs.Fields[1].AsString = Node.Text)
and (ZQueryDBs.Fields[2].AsString = User) then
begin
// some privs are set:
ShowPrivilegesControls(true, false, false);
for j := 0 to CheckListBoxPrivs.count -1 do
begin
CheckListBoxPrivs.Checked[j] := ZQueryDbs.FieldByName( CheckListBoxPrivs.Items[j] + '_priv' ).AsBoolean;
end;
end;
ZQueryDBs.Next;
end;
end;
2 : begin // table-privileges
ZQueryTables.First;
for i:=1 to ZQueryTables.RecordCount do
begin
if (ZQueryTables.Fields[0].AsString = Host)
and (ZQueryTables.Fields[1].AsString = Node.Parent.Text)
and (ZQueryTables.Fields[2].AsString = User)
and (ZQueryTables.Fields[3].AsString = Node.Text) then
begin // found the according record!
// some privs are set:
ShowPrivilegesControls(true, false, false);
for j := 0 to CheckListBoxPrivs.count -1 do
begin
if pos( ':', CheckListBoxPrivs.Items[j] ) > 0 then
begin
ColumnName := copy( CheckListBoxPrivs.Items[j], 0, pos( ':', CheckListBoxPrivs.Items[j] )-1 ) + '_priv';
set_values := Explode( ',', ZQueryTables.FieldByName( ColumnName ).AsString );
value := copy(CheckListBoxPrivs.Items[j], pos( ':', CheckListBoxPrivs.Items[j] )+2, length(CheckListBoxPrivs.Items[j]));
CheckListBoxPrivs.Checked[j] := (set_values.IndexOf( value )>-1 );
end
else
CheckListBoxPrivs.Checked[j] := ZQueryTables.FieldByName( CheckListBoxPrivs.Items[j] + '_priv' ).AsBoolean;
end;
end;
ZQueryTables.Next;
end;
end;
3 : begin // column-privileges
ZQueryColumns.First;
for i:=1 to ZQueryColumns.RecordCount do
begin
if (ZQueryColumns.Fields[0].AsString = Host)
and (ZQueryColumns.Fields[1].AsString = Node.Parent.Parent.Text)
and (ZQueryColumns.Fields[2].AsString = User)
and (ZQueryColumns.Fields[3].AsString = Node.Parent.Text)
and (ZQueryColumns.Fields[4].AsString = Node.Text) then
begin
// some privs are set:
ShowPrivilegesControls(true, false, false);
for j := 0 to CheckListBoxPrivs.count -1 do
begin
if pos( ':', CheckListBoxPrivs.Items[j] ) > 0 then
begin
ColumnName := copy( CheckListBoxPrivs.Items[j], 0, pos( ':', CheckListBoxPrivs.Items[j] )-1 ) + '_priv';
set_values := Explode( ',', ZQueryColumns.FieldByName( ColumnName ).AsString );
value := copy(CheckListBoxPrivs.Items[j], pos( ':', CheckListBoxPrivs.Items[j] )+2, length(CheckListBoxPrivs.Items[j]));
CheckListBoxPrivs.Checked[j] := (set_values.IndexOf( value )>-1 );
end
else
CheckListBoxPrivs.Checked[j] := ZQueryColumns.FieldByName( CheckListBoxPrivs.Items[j] + '_priv' ).AsBoolean;
end;
end;
ZQueryColumns.Next;
end;
end;
end;
end;
// Generate column-names for INSERT
function TUserManagerForm.getColumnNamesOrValues( which: String = 'columns' ): TStringList;
var
i : Integer;
ColumnNames, Values, set_values : TStringList;
ColumnName, privobject : String;
begin
ColumnNames := TStringList.Create;
Values := TStringList.Create;
i := 0;
while i < CheckListBoxPrivs.Items.Count do
begin
if pos( ':', CheckListBoxPrivs.Items[i] ) = 0 then
begin // user- and db-privs, which are stored in enumns
ColumnNames.Add( Mainform.Mask( CheckListBoxPrivs.Items[i] + '_priv' ) );
Values.add( bool2str(CheckListBoxPrivs.Checked[i] ) );
end
else
begin // table- and columns-privs, which are stored in sets
ColumnName := copy( CheckListBoxPrivs.Items[i], 0, pos( ':', CheckListBoxPrivs.Items[i] )-1 );
ColumnNames.Add( Mainform.Mask( ColumnName + '_priv' ) );
set_values := TStringList.Create;
while i < CheckListBoxPrivs.Items.Count do
begin
if not StrCmpBegin( ColumnName+':', CheckListBoxPrivs.Items[i] ) then
begin
dec(i);
break;
end;
privobject := copy( CheckListBoxPrivs.Items[i], length(ColumnName)+3, length(CheckListBoxPrivs.Items[i] ) );
if CheckListBoxPrivs.Checked[i] then
set_values.Add( privobject );
inc(i);
end;
Values.add( ImplodeStr( ',', set_values ) );
end;
inc(i);
end;
if which = 'columns' then
result := ColumnNames
else
result := Values;
end;
// Grant specified Privileges
procedure TUserManagerForm.ButtonSetClick(Sender: TObject);
// Generate names and values for UPDATE
function getUpdateClause : String;
var
i : Byte;
columns, values : TStringList;
begin
result := '';
columns := getColumnNamesOrValues( 'columns' );
values := getColumnNamesOrValues( 'values' );
if values.Count <> columns.count then
begin
MessageDlg( 'Internal Error: ColumnNames.Count <> Values.Count .', mtError, [mbOK], 0 );
exit;
end;
for i := 0 to columns.Count - 1 do
begin
if i > 0 then
result := result + ', ';
result := result + columns[i] + ' = ''' + values[i] + '''';
end;
end;
var
sql : String;
begin
Screen.Cursor := crHourglass;
case TreeViewUsers.Selected.Level of
0 : begin // general
sql := 'UPDATE '+mainform.mask(PRIVTABLE_USERS)+' SET ';
sql := sql + getUpdateClause;
sql := sql + ' WHERE Host = ''' + Host + ''' AND User = ''' + User + '''';
Mainform.Childwin.ExecUpdateQuery(sql);
GetResUsers;
end;
1 : begin // db
if editcurrent then
begin
sql := 'UPDATE '+mainform.mask(PRIVTABLE_DB)+' SET ';
sql := sql + getUpdateClause;
sql := sql + ' WHERE Host = ''' + Host + ''' AND Db = ''' + TreeViewUsers.Selected.Text + ''' AND User = ''' + User + '''';
end
else
begin
sql := 'INSERT INTO '+mainform.mask(PRIVTABLE_DB)+' (Host, Db, User, ';
sql := sql + ImplodeStr( ', ', getColumnNamesOrValues( 'columns' ) );
sql := sql + ') VALUES (''' + Host + ''', ''' + TreeViewUsers.Selected.Text + ''', ''' + User + ''', ';
sql := sql + '''' + ImplodeStr( ''', ''', getColumnNamesOrValues( 'values' ) ) + '''';
sql := sql + ')';
editcurrent := true;
end;
Mainform.Childwin.ExecUpdateQuery(sql);
GetResDBs;
end;
2 : begin // table
if editcurrent then
begin
sql := 'UPDATE '+mainform.mask(PRIVTABLE_TABLES)+' SET ';
sql := sql + getUpdateClause;
sql := sql + ' WHERE Host = ''' + Host + ''' AND Db = ''' + TreeViewUsers.Selected.Parent.Text + ''' AND User = ''' + User + ''' AND Table_name = ''' + TreeViewUsers.Selected.Text + '''';
end
else
begin
sql := 'INSERT INTO '+mainform.mask(PRIVTABLE_TABLES)+' (Host, Db, User, Table_name, Grantor, ';
sql := sql + ImplodeStr( ', ', getColumnNamesOrValues( 'columns' ) );
sql := sql + ') VALUES ('''+Host+''','''+TreeViewUsers.Selected.Parent.Text+''','''+User+''','''+TreeViewUsers.Selected.Text+''','''+Mainform.Childwin.Conn.MysqlParams.User+''', ';
sql := sql + '''' + ImplodeStr( ''', ''', getColumnNamesOrValues( 'values' ) ) + '''';
sql := sql + ')';
editcurrent := true;
end;
Mainform.Childwin.ExecUpdateQuery(sql);
GetResTables;
end;
3 : begin // column
if editcurrent then begin
sql := 'UPDATE '+mainform.mask(PRIVTABLE_COLUMNS)+' SET ';
sql := sql + getUpdateClause;
sql := sql + ' WHERE Host = ''' + Host + ''' AND Db = ''' + TreeViewUsers.Selected.Parent.Parent.Text + ''' AND User = ''' + User + ''' AND Table_name = ''' + TreeViewUsers.Selected.Parent.Text + ''' AND Column_name = ''' + TreeViewUsers.Selected.Text + '''';
end
else begin
sql := 'INSERT INTO '+mainform.mask(PRIVTABLE_COLUMNS)+' (Host, Db, User, Table_name, Column_name, ';
sql := sql + ImplodeStr( ', ', getColumnNamesOrValues( 'columns' ) );
sql := sql + ') VALUES ('''+Host+''','''+TreeViewUsers.Selected.Parent.Parent.Text+''','''+User+''','''+TreeViewUsers.Selected.Parent.Text+''','''+TreeViewUsers.Selected.Text+''', ';
sql := sql + '''' + ImplodeStr( ''', ''', getColumnNamesOrValues( 'values' ) ) + '''';
sql := sql + ')';
editcurrent := true;
end;
Mainform.Childwin.ExecUpdateQuery(sql);
GetResColumns;
end;
end;
Mainform.Childwin.ExecUpdateQuery('FLUSH PRIVILEGES');
ButtonRevoke.Enabled := editcurrent;
Screen.Cursor := crDefault;
end;
procedure TUserManagerForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
clearCache;
end;
procedure TUserManagerForm.CheckListBoxPrivsClickCheck(Sender: TObject);
begin
ButtonSet.Enabled := true;
end;
{***
A database-node is about to be expanded:
Drop the dummy-node and add all tables
}
procedure TUserManagerForm.DBUserTreeExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
i : Integer;
TableNames : TStringList;
begin
if (Node.getFirstChild <> nil) and (Node.getFirstChild.Text = DUMMY_NODE_TEXT) then
begin
// Drop dummynode
for i := Node.Count-1 downto 0 do
Node.Item[i].delete;
// Get all tables into dbtree
TableNames := Mainform.Childwin.GetCol( 'SHOW TABLES FROM ' + MainForm.mask(Node.Text) );
for i:=0 to TableNames.Count-1 do
begin
with DBUserTree.Items.AddChild( Node, TableNames[i] ) do
begin
ImageIndex := 39;
SelectedIndex := 40;
end;
end;
end;
end;
procedure TUserManagerForm.ButtonRevokeClick(Sender: TObject);
var sql : String;
begin
// Delete some Privs
Screen.Cursor := crHourglass;
case TreeViewUsers.Selected.Level of
0 : // delete user
if MessageDLG('Delete User '''+User+''' and all its privileges?', mtConfirmation, [mbNo, mbYes], 0) = mrYes then begin
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_USERS)+' WHERE Host='''+Host+''' AND User='''+User+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_DB)+' WHERE Host='''+Host+''' AND User='''+User+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_TABLES)+' WHERE Host='''+Host+''' AND User='''+User+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_COLUMNS)+' WHERE Host='''+Host+''' AND User='''+User+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
TreeViewUsers.Selected.Delete;
FreeAndNil( ZQueryDBs );
FreeAndNil( ZQueryTables );
FreeAndNil( ZQueryColumns );
GetResUsers;
Mainform.Childwin.ExecUpdateQuery('FLUSH PRIVILEGES');
end;
1 : // delete db-privs
begin
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_DB)+' WHERE Host='''+Host+''' AND User='''+User+''' AND Db='''+TreeViewUsers.Selected.Text+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
ShowPrivilegesControls(false, false, true);
GetResDBs;
Mainform.Childwin.ExecUpdateQuery('FLUSH PRIVILEGES');
end;
2 : // delete table-privs
begin
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_TABLES)+' WHERE Host='''+Host+''' AND User='''+User+''' AND Db='''+TreeViewUsers.Selected.Parent.Text+''' AND Table_name='''+TreeViewUsers.Selected.Text+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
ShowPrivilegesControls(false, false, true);
GetResTables;
Mainform.Childwin.ExecUpdateQuery('FLUSH PRIVILEGES');
end;
3 : // delete column-privs
begin
sql := 'DELETE FROM '+mainform.mask(PRIVTABLE_COLUMNS)+' WHERE Host='''+Host+''' AND User='''+User+''' AND Db='''+TreeViewUsers.Selected.Parent.Parent.Text+''' AND Table_name='''+TreeViewUsers.Selected.Parent.Text+''' AND Column_name='''+TreeViewUsers.Selected.Text+'''';
Mainform.Childwin.ExecUpdateQuery(sql);
ShowPrivilegesControls(false, false, true);
GetResColumns;
Mainform.Childwin.ExecUpdateQuery('FLUSH PRIVILEGES');
end;
end;
Screen.Cursor := crDefault;
end;
procedure TUserManagerForm.ButtonEditUserClick(Sender: TObject);
begin
EditUserWindow(self);
end;
procedure TUserManagerForm.clearCache;
begin
// free memory
if ZQueryUsers <> nil then ZQueryUsers.Close;
FreeAndNil( ZQueryUsers );
if ZQueryDBs <> nil then ZQueryDBs.Close;
FreeAndNil( ZQueryDBs );
if ZQueryTables <> nil then ZQueryTables.Close;
FreeAndNil( ZQueryTables );
if ZQueryColumns <> nil then ZQueryColumns.Close;
FreeAndNil( ZQueryColumns );
if ColumnsUsers <> nil then ColumnsUsers.Close;
FreeAndNil(ColumnsUsers);
if ColumnsDB <> nil then ColumnsDB.Close;
FreeAndNil(ColumnsDB);
if ColumnsTables <> nil then ColumnsTables.Close;
FreeAndNil(ColumnsTables);
if ColumnsColumns <> nil then ColumnsColumns.Close;
FreeAndNil(ColumnsColumns);
end;
procedure TUserManagerForm.Button1Click(Sender: TObject);
begin
clearCache;
ShowPrivilegesControls(false, true, false);
TreeViewUsers.Items.Clear;
PageControl1.OnChange(self);
end;
procedure TUserManagerForm.GetResUsers;
begin
if (not Assigned(ZQueryUsers)) or (not ZQueryUsers.Active) then
ZQueryUsers := Mainform.Childwin.GetResults( 'SELECT * FROM '+mainform.mask(PRIVTABLE_USERS)
+ ' ORDER BY '+mainform.mask('User')+', '+mainform.mask('Host'));
end;
procedure TUserManagerForm.GetResDBs;
begin
if (not Assigned(ZQueryDBs)) or (not ZQueryDBs.Active) then
ZQueryDBs := Mainform.Childwin.GetResults( 'SELECT * FROM '+mainform.mask(PRIVTABLE_DB));
end;
procedure TUserManagerForm.GetResTables;
begin
if (not Assigned(ZQueryTables)) or (not ZQueryTables.Active) then
ZQueryTables := Mainform.Childwin.GetResults( 'SELECT * FROM '+mainform.mask(PRIVTABLE_TABLES));
end;
procedure TUserManagerForm.GetResColumns;
begin
if (not Assigned(ZQueryColumns)) or (not ZQueryColumns.Active) then
ZQueryColumns := Mainform.Childwin.GetResults( 'SELECT * FROM '+mainform.mask(PRIVTABLE_COLUMNS));
end;
{***
Return and cache column names from privtables
This caching avoids tons of SHOW COLUMNS queries
@param string Name of privileges table
}
function TUserManagerForm.getPrivColumns( privtable: String ): TDataSet;
begin
if privtable = PRIVTABLE_USERS then
begin
if not Assigned(ColumnsUsers) then
ColumnsUsers := Mainform.Childwin.GetResults( 'SHOW COLUMNS FROM '+mainform.mask(privtable));
result := ColumnsUsers;
end
else if privtable = PRIVTABLE_DB then
begin
if not Assigned(ColumnsDB) then
ColumnsDB := Mainform.Childwin.GetResults( 'SHOW COLUMNS FROM '+mainform.mask(privtable));
result := ColumnsDB;
end
else if privtable = PRIVTABLE_TABLES then
begin
if not Assigned(ColumnsTables) then
ColumnsTables := Mainform.Childwin.GetResults( 'SHOW COLUMNS FROM '+mainform.mask(privtable));
result := ColumnsTables;
end
else if privtable = PRIVTABLE_COLUMNS then
begin
if not Assigned(ColumnsColumns) then
ColumnsColumns := Mainform.Childwin.GetResults( 'SHOW COLUMNS FROM '+mainform.mask(privtable));
result := ColumnsColumns;
end
else
begin
result := nil;
end;
// Make sure cursor is set to 1st row
if Assigned(result) then
result.First;
end;
end.