mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-14 10:02:10 +08:00
Initial check in the new files
This commit is contained in:
53
source/VirtualCheckTree.pas
Normal file
53
source/VirtualCheckTree.pas
Normal file
@ -0,0 +1,53 @@
|
||||
unit VirtualCheckTree;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
VirtualTrees, Vcl.Graphics, Vcl.ImgList;
|
||||
|
||||
type
|
||||
|
||||
TVirtualCheckTree = class(TVirtualStringTree)
|
||||
public
|
||||
class function GetCheckImageListFor(Kind: TCheckImageKind): TCustomImageList; override;
|
||||
function GetCheckImage(Node: PVirtualNode; ImgCheckType: TCheckType = ctNone; ImgCheckState: TCheckState = csUncheckedNormal; ImgEnabled: Boolean = True): Integer; override;
|
||||
procedure GetHitTestInfoAt(X, Y: Integer; Relative: Boolean; var HitInfo: THitInfo); override;
|
||||
procedure PaintCheckImage(Canvas: TCanvas; const ImageInfo: TVTImageInfo; Selected: Boolean); override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
userprivileges;
|
||||
|
||||
{ TVirtualCheckTree }
|
||||
|
||||
function TVirtualCheckTree.GetCheckImage(Node: PVirtualNode;
|
||||
ImgCheckType: TCheckType; ImgCheckState: TCheckState;
|
||||
ImgEnabled: Boolean): Integer;
|
||||
begin
|
||||
Result:= inherited GetCheckImage(Node, ImgCheckType, ImgCheckState, ImgEnabled);
|
||||
end;
|
||||
|
||||
class function TVirtualCheckTree.GetCheckImageListFor(
|
||||
Kind: TCheckImageKind): TCustomImageList;
|
||||
begin
|
||||
Result:= inherited GetCheckImageListFor(Kind);
|
||||
end;
|
||||
|
||||
procedure TVirtualCheckTree.GetHitTestInfoAt(X, Y: Integer; Relative: Boolean;
|
||||
var HitInfo: THitInfo);
|
||||
begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TVirtualCheckTree.PaintCheckImage(Canvas: TCanvas;
|
||||
const ImageInfo: TVTImageInfo; Selected: Boolean);
|
||||
begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
504
source/types_helpers.pas
Normal file
504
source/types_helpers.pas
Normal file
@ -0,0 +1,504 @@
|
||||
unit types_helpers;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Vcl.Graphics;
|
||||
|
||||
type
|
||||
|
||||
// === Database ===
|
||||
|
||||
TNetType = (ntMySQL_TCPIP, ntMySQL_NamedPipe, ntMySQL_SSHtunnel,
|
||||
ntMSSQL_NamedPipe, ntMSSQL_TCPIP, ntMSSQL_SPX, ntMSSQL_VINES, ntMSSQL_RPC,
|
||||
ntPgSQL_TCPIP,
|
||||
ntMariaDB_TCPIP, ntMariaDB_NamedPipe, ntMariaDB_SSHtunnel);
|
||||
TNetTypeGroup = (ngMySQL, ngMSSQL, ngPgSQL, ngMariaDB);
|
||||
|
||||
// === Users and Privileges ===
|
||||
|
||||
TNodeObjectKind = (
|
||||
okGlobal, okSchema, okGroupTables, okGroupViews, okGroupProcedures,
|
||||
okGroupFunctions, okGroupTriggers, okGroupEvents, okTable, okView,
|
||||
okProcedure, okFunction, {okTrigger, okEvent, }okColumn
|
||||
);
|
||||
TNodeObjectKinds = set of TNodeObjectKind;
|
||||
|
||||
TPrivilege = (prNone, prExecute, prProcess, prSelect, prShowDatabases,
|
||||
prShowView, prAlter, prAlterRoutine, prCreate, prCreateRoutine,
|
||||
prCreateTableSpace, prCreateTemporaryTables, prCreateView, prDelete, prDrop,
|
||||
prEvent, prIndex, prInsert, prReferences, prTrigger, prUpdate, prCreateRole,
|
||||
prCreateUser, prDropRole, prFile, prGrant, prLockTables, prReload,
|
||||
prReplicationClient, prReplicationSlave, prShutdown, prSuper);
|
||||
|
||||
TPrivileges = set of TPrivilege;
|
||||
|
||||
TPrivilegeHelper = record helper for TPrivilege
|
||||
public
|
||||
function AvailableForObjectKind(const AObjectKind: TNodeObjectKind): Boolean;
|
||||
function AvailableForServer(
|
||||
const ANetTypeGroup: TNetTypeGroup;
|
||||
const AVersion: Integer): Boolean;
|
||||
function ColorBG: TColor;
|
||||
function ColorFG: TColor;
|
||||
function ToString: string;
|
||||
function FromString(const AString: string): Boolean;
|
||||
|
||||
const
|
||||
CL_VIOLET_FG = clPurple;
|
||||
CL_GREEN_FG = clGreen;
|
||||
CL_RED_FG = clMaroon;
|
||||
CL_BLUE_FG = clNavy;
|
||||
CL_VIOLET_BG = $00FFE1FF;
|
||||
CL_GREEN_BG = $00E1FFE1;
|
||||
CL_RED_BG = $00E1E1FF;
|
||||
CL_BLUE_BG = $00FFE1E1;
|
||||
end;
|
||||
|
||||
TPrivilegesHelper = record helper for TPrivileges
|
||||
public
|
||||
function ToString: string;
|
||||
function FromGrant(const AGrant: string): Boolean;
|
||||
function FromString(const AString: string): Boolean;
|
||||
end;
|
||||
|
||||
TUserKind = (ukGroupUsers, ukGroupRoles, ukUser, ukRole, ukHost);
|
||||
TUserChangedPart = (ucpCaption, ucpProperties, ucpPrivileges);
|
||||
TUserChangedParts = set of TUserChangedPart;
|
||||
TUserProblem = (upNone, upEmptyPassword, upInvalidPasswordLen, upSkipNameResolve, upUnknown);
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
helpers, SynRegExpr, System.Classes, System.SysUtils;
|
||||
|
||||
const
|
||||
S_REGEX_GRANTS = '^GRANT\s+(.+)\s+ON\s+((TABLE|FUNCTION|PROCEDURE)\s+)?(\*|[`"]([^`"]+)[`"])\.(\*|[`"]([^`"]+)[`"])\s+TO\s+\S+(\s+IDENTIFIED\s+BY\s+(PASSWORD)?\s+''?([^'']+)''?)?(\s+.+)?$';
|
||||
|
||||
{ TPrivilegeHelper }
|
||||
|
||||
function TPrivilegeHelper.AvailableForObjectKind(
|
||||
const AObjectKind: TNodeObjectKind): Boolean;
|
||||
begin
|
||||
Result:= FALSE;
|
||||
case Self of
|
||||
prAlter:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable];
|
||||
prAlterRoutine:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okProcedure, okFunction];
|
||||
prCreate:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable];
|
||||
prCreateRole:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prCreateRoutine:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okProcedure, okFunction];
|
||||
prCreateTableSpace:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prCreateTemporaryTables:
|
||||
Result := AObjectKind in [okGlobal, okSchema];
|
||||
prCreateUser:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prCreateView:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okView];
|
||||
prDelete:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable];
|
||||
prDrop:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable, okView];
|
||||
prDropRole:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prEvent:
|
||||
Result := AObjectKind in [okGlobal, okSchema];
|
||||
prExecute:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okProcedure, okFunction];
|
||||
prFile:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prGrant:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable, okProcedure,
|
||||
okFunction, okColumn];
|
||||
prIndex:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable];
|
||||
prInsert:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable, okColumn];
|
||||
prLockTables:
|
||||
Result := AObjectKind in [okGlobal, okSchema];
|
||||
prProcess:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prReferences:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable];
|
||||
prReload:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prReplicationClient:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prReplicationSlave:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prSelect:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable, okColumn];
|
||||
prShowDatabases:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prShowView:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okView];
|
||||
prShutdown:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prSuper:
|
||||
Result := AObjectKind in [okGlobal];
|
||||
prTrigger:
|
||||
Result := AObjectKind in [okGlobal, okSchema];
|
||||
prUpdate:
|
||||
Result := AObjectKind in [okGlobal, okSchema, okTable, okColumn];
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPrivilegeHelper.AvailableForServer(const ANetTypeGroup: TNetTypeGroup;
|
||||
const AVersion: Integer): Boolean;
|
||||
var
|
||||
NTG: TNetTypeGroup;
|
||||
V: Integer;
|
||||
begin
|
||||
Result:= FALSE;
|
||||
NTG:= ANetTypeGroup;
|
||||
V:= AVersion;
|
||||
case Self of
|
||||
// TODO: Add other supported servers and their min versions!
|
||||
|
||||
prAlter:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prAlterRoutine:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50003)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prCreate:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prCreateRole:
|
||||
Result := ((NTG = ngMySQL) and (V >= 80000)) or
|
||||
((NTG = ngMariaDB) and (FALSE)); // Not supported in MariaDB! Here we have to have CREATE USER privilege.
|
||||
prCreateRoutine:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50003)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prCreateTableSpace:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50404)) or
|
||||
((NTG = ngMariaDB) and (FALSE));
|
||||
prCreateTemporaryTables:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prCreateUser:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50003)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prCreateView:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50001)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prDelete:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prDrop:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prDropRole:
|
||||
Result := ((NTG = ngMySQL) and (V >= 80000)) or
|
||||
((NTG = ngMariaDB) and (FALSE)); // Not supported in MariaDB! Here we have to have CREATE USER privilege.
|
||||
prEvent:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50106)) or
|
||||
((NTG = ngMariaDB) and (V >= 50106));
|
||||
prExecute:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prFile:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prGrant:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prIndex:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prInsert:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prLockTables:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prProcess:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prReferences:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prReload:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prReplicationClient:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prReplicationSlave:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prSelect:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prShowDatabases:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prShowView:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50001)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prShutdown:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prSuper:
|
||||
Result := ((NTG = ngMySQL) and (V >= 40002)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
prTrigger:
|
||||
Result := ((NTG = ngMySQL) and (V >= 50106)) or
|
||||
((NTG = ngMariaDB) and (V >= 50106));
|
||||
prUpdate:
|
||||
Result := ((NTG = ngMySQL) and (V >= 0)) or
|
||||
((NTG = ngMariaDB) and (V >= 50100));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPrivilegeHelper.ColorBG: TColor;
|
||||
begin
|
||||
Result:= clNone;
|
||||
case Self of
|
||||
prExecute: Result:= CL_GREEN_BG;
|
||||
prProcess: Result:= CL_GREEN_BG;
|
||||
prSelect: Result:= CL_GREEN_BG;
|
||||
prShowDatabases: Result:= CL_GREEN_BG;
|
||||
prShowView: Result:= CL_GREEN_BG;
|
||||
prAlter: Result:= CL_RED_BG;
|
||||
prAlterRoutine: Result:= CL_RED_BG;
|
||||
prCreate: Result:= CL_RED_BG;
|
||||
prCreateRoutine: Result:= CL_RED_BG;
|
||||
prCreateTableSpace: Result:= CL_RED_BG;
|
||||
prCreateTemporaryTables: Result:= CL_RED_BG;
|
||||
prCreateView: Result:= CL_RED_BG;
|
||||
prDelete: Result:= CL_RED_BG;
|
||||
prDrop: Result:= CL_RED_BG;
|
||||
prEvent: Result:= CL_RED_BG;
|
||||
prIndex: Result:= CL_RED_BG;
|
||||
prInsert: Result:= CL_RED_BG;
|
||||
prReferences: Result:= CL_RED_BG;
|
||||
prTrigger: Result:= CL_RED_BG;
|
||||
prUpdate: Result:= CL_RED_BG;
|
||||
prCreateRole: Result:= CL_BLUE_BG;
|
||||
prCreateUser: Result:= CL_BLUE_BG;
|
||||
prDropRole: Result:= CL_BLUE_BG;
|
||||
prFile: Result:= CL_BLUE_BG;
|
||||
prGrant: Result:= CL_BLUE_BG;
|
||||
prLockTables: Result:= CL_BLUE_BG;
|
||||
prReload: Result:= CL_BLUE_BG;
|
||||
prReplicationClient: Result:= CL_BLUE_BG;
|
||||
prReplicationSlave: Result:= CL_BLUE_BG;
|
||||
prShutdown: Result:= CL_BLUE_BG;
|
||||
prSuper: Result:= CL_BLUE_BG;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPrivilegeHelper.ColorFG: TColor;
|
||||
begin
|
||||
Result:= clNone;
|
||||
case Self of
|
||||
prExecute: Result:= CL_GREEN_FG;
|
||||
prProcess: Result:= CL_GREEN_FG;
|
||||
prSelect: Result:= CL_GREEN_FG;
|
||||
prShowDatabases: Result:= CL_GREEN_FG;
|
||||
prShowView: Result:= CL_GREEN_FG;
|
||||
prAlter: Result:= CL_RED_FG;
|
||||
prAlterRoutine: Result:= CL_RED_FG;
|
||||
prCreate: Result:= CL_RED_FG;
|
||||
prCreateRoutine: Result:= CL_RED_FG;
|
||||
prCreateTableSpace: Result:= CL_RED_FG;
|
||||
prCreateTemporaryTables: Result:= CL_RED_FG;
|
||||
prCreateView: Result:= CL_RED_FG;
|
||||
prDelete: Result:= CL_RED_FG;
|
||||
prDrop: Result:= CL_RED_FG;
|
||||
prEvent: Result:= CL_RED_FG;
|
||||
prIndex: Result:= CL_RED_FG;
|
||||
prInsert: Result:= CL_RED_FG;
|
||||
prReferences: Result:= CL_RED_FG;
|
||||
prTrigger: Result:= CL_RED_FG;
|
||||
prUpdate: Result:= CL_RED_FG;
|
||||
prCreateRole: Result:= CL_BLUE_FG;
|
||||
prCreateUser: Result:= CL_BLUE_FG;
|
||||
prDropRole: Result:= CL_BLUE_FG;
|
||||
prFile: Result:= CL_BLUE_FG;
|
||||
prGrant: Result:= CL_BLUE_FG;
|
||||
prLockTables: Result:= CL_BLUE_FG;
|
||||
prReload: Result:= CL_BLUE_FG;
|
||||
prReplicationClient: Result:= CL_BLUE_FG;
|
||||
prReplicationSlave: Result:= CL_BLUE_FG;
|
||||
prShutdown: Result:= CL_BLUE_FG;
|
||||
prSuper: Result:= CL_BLUE_FG;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPrivilegeHelper.FromString(const AString: string): Boolean;
|
||||
begin
|
||||
Self:= prNone;
|
||||
if CompareText(AString, 'ALTER') = 0 then
|
||||
Self:= prAlter
|
||||
else if CompareText(AString, 'ALTER ROUTINE') = 0 then
|
||||
Self:= prAlterRoutine
|
||||
else if CompareText(AString, 'CREATE') = 0 then
|
||||
Self:= prCreate
|
||||
else if CompareText(AString, 'CREATE ROLE') = 0 then
|
||||
Self:= prCreateRole
|
||||
else if CompareText(AString, 'CREATE ROUTINE') = 0 then
|
||||
Self:= prCreateRoutine
|
||||
else if CompareText(AString, 'CREATE TABLESPACE') = 0 then
|
||||
Self:= prCreateTableSpace
|
||||
else if CompareText(AString, 'CREATE TEMPORARY TABLES') = 0 then
|
||||
Self:= prCreateTemporaryTables
|
||||
else if CompareText(AString, 'CREATE USER') = 0 then
|
||||
Self:= prCreateUser
|
||||
else if CompareText(AString, 'CREATE VIEW') = 0 then
|
||||
Self:= prCreateView
|
||||
else if CompareText(AString, 'DELETE') = 0 then
|
||||
Self:= prDelete
|
||||
else if CompareText(AString, 'DROP') = 0 then
|
||||
Self:= prDrop
|
||||
else if CompareText(AString, 'DROP ROLE') = 0 then
|
||||
Self:= prDropRole
|
||||
else if CompareText(AString, 'EVENT') = 0 then
|
||||
Self:= prEvent
|
||||
else if CompareText(AString, 'EXECUTE') = 0 then
|
||||
Self:= prExecute
|
||||
else if CompareText(AString, 'FILE') = 0 then
|
||||
Self:= prFile
|
||||
else if CompareText(AString, 'GRANT') = 0 then
|
||||
Self:= prGrant
|
||||
else if CompareText(AString, 'INDEX') = 0 then
|
||||
Self:= prIndex
|
||||
else if CompareText(AString, 'INSERT') = 0 then
|
||||
Self:= prInsert
|
||||
else if CompareText(AString, 'LOCK TABLES') = 0 then
|
||||
Self:= prLockTables
|
||||
else if CompareText(AString, 'PROCESS') = 0 then
|
||||
Self:= prProcess
|
||||
else if CompareText(AString, 'REFERENCES') = 0 then
|
||||
Self:= prReferences
|
||||
else if CompareText(AString, 'RELOAD') = 0 then
|
||||
Self:= prReload
|
||||
else if CompareText(AString, 'REPLICATION CLIENT') = 0 then
|
||||
Self:= prReplicationClient
|
||||
else if CompareText(AString, 'REPLICATION SLAVE') = 0 then
|
||||
Self:= prReplicationSlave
|
||||
else if CompareText(AString, 'SELECT') = 0 then
|
||||
Self:= prSelect
|
||||
else if CompareText(AString, 'SHOW DATABASES') = 0 then
|
||||
Self:= prShowDatabases
|
||||
else if CompareText(AString, 'SHOW VIEW') = 0 then
|
||||
Self:= prShowView
|
||||
else if CompareText(AString, 'SHUTDOWN') = 0 then
|
||||
Self:= prShutdown
|
||||
else if CompareText(AString, 'SUPER') = 0 then
|
||||
Self:= prSuper
|
||||
else if CompareText(AString, 'TRIGGER') = 0 then
|
||||
Self:= prTrigger
|
||||
else if CompareText(AString, 'UPDATE') = 0 then
|
||||
Self:= prUpdate;
|
||||
Result:= (Self <> prNone);
|
||||
end;
|
||||
|
||||
function TPrivilegeHelper.ToString: string;
|
||||
begin
|
||||
case Self of
|
||||
prAlter: Result:= 'ALTER';
|
||||
prAlterRoutine: Result:= 'ALTER ROUTINE';
|
||||
prCreate: Result:= 'CREATE';
|
||||
prCreateRole: Result:= 'CREATE ROLE';
|
||||
prCreateRoutine: Result:= 'CREATE ROUTINE';
|
||||
prCreateTableSpace: Result:= 'CREATE TABLE SPACE';
|
||||
prCreateTemporaryTables: Result:= 'CREATE TEMPORARY TABLES';
|
||||
prCreateUser: Result:= 'CREATE USER';
|
||||
prCreateView: Result:= 'CREATE VIEW';
|
||||
prDelete: Result:= 'DELETE';
|
||||
prDrop: Result:= 'DROP';
|
||||
prDropRole: Result:= 'DROP ROLE';
|
||||
prEvent: Result:= 'EVENT';
|
||||
prExecute: Result:= 'EXECUTE';
|
||||
prFile: Result:= 'FILE';
|
||||
prGrant: Result:= 'GRANT';
|
||||
prIndex: Result:= 'INDEX';
|
||||
prInsert: Result:= 'INSERT';
|
||||
prLockTables: Result:= 'LOCK TABLES';
|
||||
prProcess: Result:= 'PROCESS';
|
||||
prReferences: Result:= 'REFERENCES';
|
||||
prReload: Result:= 'RELOAD';
|
||||
prReplicationClient: Result:= 'REPLICATION CLIENT';
|
||||
prReplicationSlave: Result:= 'REPLICATION SLAVE';
|
||||
prSelect: Result:= 'SELECT';
|
||||
prShowDatabases: Result:= 'SHOW DATABASES';
|
||||
prShowView: Result:= 'SHOW VIEW';
|
||||
prShutdown: Result:= 'SHUTDOWN';
|
||||
prSuper: Result:= 'SUPER';
|
||||
prTrigger: Result:= 'TRIGGER';
|
||||
prUpdate: Result:= 'UPDATE';
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TPrivilegesHelper }
|
||||
|
||||
function TPrivilegesHelper.FromGrant(const AGrant: string): Boolean;
|
||||
var
|
||||
R: TRegExpr;
|
||||
S: string;
|
||||
begin
|
||||
Result:= FALSE;
|
||||
R := TRegExpr.Create;
|
||||
try
|
||||
R.ModifierI:= True;
|
||||
R.Expression:= S_REGEX_GRANTS;
|
||||
if R.Exec(AGrant) then begin
|
||||
S:= R.Match[1];
|
||||
if S.Length > 0 then begin
|
||||
Result:= Self.FromString(S);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
FreeAndNil(R);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPrivilegesHelper.FromString(const AString: string): Boolean;
|
||||
var
|
||||
P: TPrivilege;
|
||||
S: string;
|
||||
SL: TStringList;
|
||||
begin
|
||||
Result:= FALSE;
|
||||
if CompareText(AString.Trim, 'ALL PRIVILEGES') = 0 then begin
|
||||
for P:= Low(TPrivilege) to High(TPrivilege) do begin
|
||||
Self:= Self + [P] - [prNone];
|
||||
end;
|
||||
Result:= TRUE;
|
||||
end else begin
|
||||
SL:= Explode(',', AString);
|
||||
try
|
||||
for S in SL do begin
|
||||
if P.FromString(S.Trim) then begin
|
||||
Self:= Self + [P] - [prNone];
|
||||
end;
|
||||
end;
|
||||
Result:= (SL.Count > 0);
|
||||
finally
|
||||
FreeAndNil(SL);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPrivilegesHelper.ToString: string;
|
||||
var
|
||||
P: TPrivilege;
|
||||
S: string;
|
||||
begin
|
||||
Result:= '';
|
||||
S:= '';
|
||||
for P in Self do begin
|
||||
S:= S + ',' + P.ToString;
|
||||
end;
|
||||
Result:= Copy(S, 2, Length(S));
|
||||
end;
|
||||
|
||||
end.
|
15751
source/usermanager2.dfm
Normal file
15751
source/usermanager2.dfm
Normal file
File diff suppressed because it is too large
Load Diff
1505
source/usermanager2.pas
Normal file
1505
source/usermanager2.pas
Normal file
File diff suppressed because it is too large
Load Diff
535
source/userprivileges.pas
Normal file
535
source/userprivileges.pas
Normal file
@ -0,0 +1,535 @@
|
||||
unit userprivileges;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.Classes, System.Generics.Collections, System.Generics.Defaults,
|
||||
Vcl.Graphics, types_helpers;
|
||||
|
||||
type
|
||||
TPrivilegeColumnComparer = class(TComparer<TPrivilege>)
|
||||
function Compare(const Left, Right: TPrivilege): Integer; override;
|
||||
end;
|
||||
|
||||
TPrivilegesTreeColumns = class(TList<TPrivilege>)
|
||||
private
|
||||
FComparer: TPrivilegeColumnComparer;
|
||||
public
|
||||
constructor Create(const ANetTypeGroup: TNetTypeGroup; const AServerVersion: Integer); virtual;
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Sort;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
PObjectData = ^TObjectData;
|
||||
TObjectData = class
|
||||
Kind: TNodeObjectKind;
|
||||
Caption: string;
|
||||
Privileges: TPrivileges;
|
||||
Inherites: Boolean;
|
||||
InternalSchema: Boolean;
|
||||
Changed: Boolean;
|
||||
|
||||
function Granted(APrivilege: TPrivilege): Boolean; virtual;
|
||||
function GroupNode: Boolean; virtual;
|
||||
function ToggleInherites: Boolean; virtual;
|
||||
function TogglePrivilege(APrivilege: TPrivilege): Boolean; virtual;
|
||||
|
||||
procedure SaveToDB(const ASchemeName, AGranteeName: string;
|
||||
const ANetTypeGroup: TNetTypeGroup;
|
||||
const AServerVersion: Integer); virtual;
|
||||
end;
|
||||
TObjectDataList = TObjectList<TObjectData>;
|
||||
|
||||
PUserData = ^TUserData;
|
||||
TUserDataList = TList<PUserData>;
|
||||
TUserData = class
|
||||
Kind: TUserKind;
|
||||
Caption: string;
|
||||
Changed: Boolean;
|
||||
ChangedParts: TUserChangedParts;
|
||||
InternalName: string;
|
||||
New: Boolean;
|
||||
ParentData: PUserData;
|
||||
ChildData: TUserDataList;
|
||||
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
|
||||
function AddChild(AChild: PUserData): Integer;
|
||||
procedure SetCaption(const ACaption: string; const ASetChanged: Boolean = TRUE);
|
||||
procedure SetChanged(const APart: TUserChangedPart);
|
||||
end;
|
||||
|
||||
TUser = class(TObject)
|
||||
Username: string;
|
||||
Host: string;
|
||||
Password: string;
|
||||
Cipher: string;
|
||||
Issuer: string;
|
||||
Subject: String;
|
||||
MaxQueries: Integer;
|
||||
MaxUpdates: Integer;
|
||||
MaxConnections: Integer;
|
||||
MaxUserConnections: Integer;
|
||||
SSL: Integer;
|
||||
Problem: TUserProblem;
|
||||
function HostRequiresNameResolve: Boolean;
|
||||
end;
|
||||
PUser = ^TUser;
|
||||
|
||||
TUsersList = class(TObjectList<TUser>)
|
||||
private
|
||||
FUserNames: TStringList;
|
||||
FHostNames: TStringList;
|
||||
protected
|
||||
function GetHostNames(const AUserName: string): TStringList; virtual;
|
||||
function GetUserNames: TStringList; virtual;
|
||||
public
|
||||
constructor Create(AOwnsObjects: Boolean = True); overload;
|
||||
destructor Destroy; override;
|
||||
|
||||
function Add(const Value: TUser): Integer; virtual;
|
||||
procedure Clear; virtual;
|
||||
|
||||
property HostNames[const UserName: string]: TStringList read GetHostNames;
|
||||
property UserNames: TStringList read GetUserNames;
|
||||
end;
|
||||
|
||||
TObjectPrivilegeDataList = class;
|
||||
|
||||
TObjectPrivilegeData = class(TObject)
|
||||
private
|
||||
FParent: TObjectPrivilegeDataList;
|
||||
public
|
||||
Kind: TNodeObjectKind;
|
||||
Grantee: string;
|
||||
Privilege: TPrivilege;
|
||||
SchemaName: string;
|
||||
ObjectName: string;
|
||||
ColumnName: string;
|
||||
Index: Integer;
|
||||
|
||||
constructor Create(AParent: TObjectPrivilegeDataList); virtual;
|
||||
end;
|
||||
|
||||
TObjectPrivilegeDataList = class(TObjectList<TObjectPrivilegeData>)
|
||||
private
|
||||
FFilterable: Boolean;
|
||||
FFilteredList: TObjectPrivilegeDataList;
|
||||
public
|
||||
constructor Create(AOwnsObjects: Boolean = TRUE;
|
||||
AFilterable: Boolean = TRUE); overload;
|
||||
destructor Destroy; override;
|
||||
|
||||
function Append: TObjectPrivilegeData;
|
||||
function Filter(const AGrantee: string;
|
||||
const AKind: TNodeObjectKind;
|
||||
const ASchemaName: string = '';
|
||||
const AObjectName: string = '';
|
||||
const AColumnName: string = ''): TObjectPrivilegeDataList;
|
||||
|
||||
function FilteredPrivileges: TPrivileges;
|
||||
function Privileges: TPrivileges;
|
||||
|
||||
property FilteredList: TObjectPrivilegeDataList read FFilteredList;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SynRegExpr, System.SysUtils, VirtualTrees, dbconnection;
|
||||
|
||||
{ TObjectData }
|
||||
|
||||
function TObjectData.Granted(APrivilege: TPrivilege): Boolean;
|
||||
begin
|
||||
Result:= APrivilege in Self.Privileges;
|
||||
end;
|
||||
|
||||
function TObjectData.GroupNode: Boolean;
|
||||
begin
|
||||
Result := (Self.Kind = okGroupTables) or
|
||||
(Self.Kind = okGroupViews) or
|
||||
(Self.Kind = okGroupProcedures) or
|
||||
(Self.Kind = okGroupFunctions) or
|
||||
(Self.Kind = okGroupTriggers) or
|
||||
(Self.Kind = okGroupEvents);
|
||||
end;
|
||||
|
||||
procedure TObjectData.SaveToDB(const ASchemeName, AGranteeName: string;
|
||||
const ANetTypeGroup: TNetTypeGroup; const AServerVersion: Integer);
|
||||
begin
|
||||
case ANetTypeGroup of
|
||||
ngMySQL:
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
ngMariaDB:
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TObjectData.ToggleInherites: Boolean;
|
||||
begin
|
||||
Self.Inherites:= not Self.Inherites;
|
||||
Self.Changed:= TRUE;
|
||||
Result:= Self.Inherites;
|
||||
end;
|
||||
|
||||
function TObjectData.TogglePrivilege(APrivilege: TPrivilege): Boolean;
|
||||
begin
|
||||
if not Self.Inherites then begin
|
||||
Changed:= TRUE;
|
||||
end;
|
||||
if Self.Granted(APrivilege) then begin
|
||||
Self.Privileges:= Self.Privileges - [APrivilege];
|
||||
Result:= FALSE;
|
||||
end else begin
|
||||
Self.Privileges:= Self.Privileges + [APrivilege];
|
||||
Result:= TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ TPrivilegesInfo }
|
||||
|
||||
constructor TPrivilegesTreeColumns.Create(const ANetTypeGroup: TNetTypeGroup;
|
||||
const AServerVersion: Integer);
|
||||
var
|
||||
I: Integer;
|
||||
P: TPrivilege;
|
||||
begin
|
||||
FComparer:= TPrivilegeColumnComparer.Create;
|
||||
inherited Create;
|
||||
for P:= Low(TPrivilege) to High(TPrivilege) do begin
|
||||
if P.AvailableForServer(ANetTypeGroup, AServerVersion) then begin
|
||||
Self.Add(P);
|
||||
end;
|
||||
end;
|
||||
Sort;
|
||||
end;
|
||||
|
||||
destructor TPrivilegesTreeColumns.Destroy;
|
||||
begin
|
||||
FreeAndNil(FComparer);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
procedure TPrivilegesTreeColumns.Sort;
|
||||
begin
|
||||
inherited Sort(FComparer);
|
||||
end;
|
||||
|
||||
{ TPrivilegeInfoComparer }
|
||||
|
||||
function TPrivilegeColumnComparer.Compare(const Left,
|
||||
Right: TPrivilege): Integer;
|
||||
begin
|
||||
Result:= 0;
|
||||
if Left.ColorFg = Right.ColorFg then begin
|
||||
Result:= CompareStr(Left.ToString, Right.ToString);
|
||||
end else begin
|
||||
if (Left.ColorFg = TPrivilege.CL_GREEN_FG) and (Right.ColorFg <> TPrivilege.CL_GREEN_FG) then begin
|
||||
Result:= -1;
|
||||
end else begin
|
||||
if (Left.ColorFg = TPrivilege.CL_RED_FG) and (Right.ColorFg = TPrivilege.CL_BLUE_FG) then begin
|
||||
Result:= -1;
|
||||
end else begin
|
||||
Result:= 1;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TUserData }
|
||||
|
||||
constructor TUserData.Create;
|
||||
begin
|
||||
ChildData:= TUserDataList.Create;
|
||||
end;
|
||||
|
||||
destructor TUserData.Destroy;
|
||||
begin
|
||||
FreeAndNil(ChildData);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TUserData.AddChild(AChild: PUserData): Integer;
|
||||
begin
|
||||
Result:= -1;
|
||||
if not ChildData.Contains(AChild) then begin
|
||||
Result:= ChildData.Add(AChild);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TUserData.SetCaption(const ACaption: string;
|
||||
const ASetChanged: Boolean = TRUE);
|
||||
var
|
||||
D, PD: PUserData;
|
||||
iPos: Integer;
|
||||
begin
|
||||
if Caption <> ACaption then begin
|
||||
Caption:= ACaption;
|
||||
if ASetChanged then begin
|
||||
SetChanged(ucpCaption);
|
||||
end;
|
||||
case Kind of
|
||||
ukUser:
|
||||
begin
|
||||
InternalName:= ACaption;
|
||||
for D in ChildData do begin
|
||||
D^.InternalName:= '''' + ACaption + '''@''' + D^.Caption + '''';
|
||||
if ASetChanged then begin
|
||||
D^.SetChanged(ucpCaption);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
ukHost:
|
||||
begin
|
||||
PD:= ParentData;
|
||||
if PD <> NIL then begin
|
||||
InternalName:= '''' + PD^.Caption + '''@''' + ACaption + '''';
|
||||
end;
|
||||
end
|
||||
|
||||
else begin
|
||||
InternalName:= ACaption;
|
||||
end;
|
||||
|
||||
if ASetChanged then begin
|
||||
SetChanged(ucpCaption);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TUserData.SetChanged(const APart: TUserChangedPart);
|
||||
var
|
||||
N: PVirtualNode;
|
||||
D: PUserData;
|
||||
begin
|
||||
if not (APart in Self.ChangedParts) then begin
|
||||
Self.Changed:= TRUE;
|
||||
Self.ChangedParts:= Self.ChangedParts + [APart];
|
||||
case Self.Kind of
|
||||
ukGroupUsers: ;
|
||||
ukGroupRoles: ;
|
||||
ukUser:
|
||||
begin
|
||||
// N:= tvUsers
|
||||
end;
|
||||
ukRole: ;
|
||||
ukHost: ;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ TUser }
|
||||
|
||||
function TUser.HostRequiresNameResolve: Boolean;
|
||||
var
|
||||
rx: TRegExpr;
|
||||
begin
|
||||
rx := TRegExpr.Create;
|
||||
rx.Expression := '^(localhost|[\d\.\/\:]+|.*%.*|[\w\d]{4}\:.*)$';
|
||||
Result := not rx.Exec(Host);
|
||||
rx.Free;
|
||||
end;
|
||||
|
||||
{ TUsersList }
|
||||
|
||||
constructor TUsersList.Create(AOwnsObjects: Boolean);
|
||||
begin
|
||||
inherited Create(AOwnsObjects);
|
||||
FHostNames:= TStringList.Create;
|
||||
FUserNames:= TStringList.Create;
|
||||
end;
|
||||
|
||||
destructor TUsersList.Destroy;
|
||||
begin
|
||||
FreeAndNil(FHostNames);
|
||||
FreeAndNil(FUserNames);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TUsersList.GetHostNames(const AUserName: string): TStringList;
|
||||
var
|
||||
User: TUser;
|
||||
UserName: string;
|
||||
begin
|
||||
if not Assigned(FHostNames) then
|
||||
FHostNames:= TStringList.Create
|
||||
else
|
||||
FHostNames.Clear;
|
||||
for User in Self do begin
|
||||
if CompareText(User.Username, AUserName) = 0 then begin
|
||||
FHostNames.Add(User.Host);
|
||||
end;
|
||||
end;
|
||||
Result:= FHostNames;
|
||||
end;
|
||||
|
||||
function TUsersList.GetUserNames: TStringList;
|
||||
begin
|
||||
if Assigned(FUserNames) then
|
||||
Result:= FUserNames
|
||||
else begin
|
||||
FUserNames:= TStringList.Create;
|
||||
Result:= FUserNames;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TUsersList.Add(const Value: TUser): Integer;
|
||||
begin
|
||||
Result:= inherited Add(Value);
|
||||
if FUserNames.IndexOf(Value.Username) = -1 then begin
|
||||
FUserNames.Add(Value.UserName);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TUsersList.Clear;
|
||||
begin
|
||||
inherited Clear;
|
||||
FHostNames.Clear;
|
||||
FUserNames.Clear;
|
||||
end;
|
||||
|
||||
{ TObjectPrivilegeData }
|
||||
|
||||
constructor TObjectPrivilegeData.Create(AParent: TObjectPrivilegeDataList);
|
||||
begin
|
||||
inherited Create;
|
||||
FParent:= AParent;
|
||||
end;
|
||||
|
||||
{ TObjectPrivilegeDataList }
|
||||
|
||||
constructor TObjectPrivilegeDataList.Create(AOwnsObjects: Boolean = TRUE;
|
||||
AFilterable: Boolean = TRUE);
|
||||
begin
|
||||
inherited Create(AOwnsObjects);
|
||||
FFilterable:= AFilterable;
|
||||
if FFilterable then begin
|
||||
FFilteredList:= TObjectPrivilegeDataList.Create(FALSE, FALSE);
|
||||
end else begin
|
||||
FFilteredList:= NIL;
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TObjectPrivilegeDataList.Destroy;
|
||||
begin
|
||||
FreeAndNil(FFilteredList);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TObjectPrivilegeDataList.Append: TObjectPrivilegeData;
|
||||
var
|
||||
OPD: TObjectPrivilegeData;
|
||||
I: Integer;
|
||||
begin
|
||||
OPD:= TObjectPrivilegeData.Create(Self);
|
||||
I:= Add(OPD);
|
||||
OPD.Index:= I;
|
||||
Result:= OPD;
|
||||
end;
|
||||
|
||||
|
||||
function TObjectPrivilegeDataList.Filter(const AGrantee: string;
|
||||
const AKind: TNodeObjectKind; const ASchemaName, AObjectName,
|
||||
AColumnName: string): TObjectPrivilegeDataList;
|
||||
var
|
||||
OPD: TObjectPrivilegeData;
|
||||
begin
|
||||
Result:= NIL;
|
||||
if not FFilterable then begin
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
FFilteredList.Clear;
|
||||
case AKind of
|
||||
okGlobal:
|
||||
begin
|
||||
for OPD in Self do begin
|
||||
if (OPD.Kind = AKind) and
|
||||
(CompareText(OPD.Grantee, AGrantee) = 0) then
|
||||
begin
|
||||
FFilteredList.Add(OPD);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
okSchema:
|
||||
begin
|
||||
for OPD in Self do begin
|
||||
if (OPD.Kind = AKind) and
|
||||
(CompareText(OPD.Grantee, AGrantee) = 0) and
|
||||
(CompareText(OPD.SchemaName, ASchemaName) = 0) then
|
||||
begin
|
||||
FFilteredList.Add(OPD);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
okTable, okView, okProcedure, okFunction:
|
||||
begin
|
||||
for OPD in Self do begin
|
||||
if (OPD.Kind = AKind) and
|
||||
(CompareText(OPD.Grantee, AGrantee) = 0) and
|
||||
(CompareText(OPD.SchemaName, ASchemaName) = 0) and
|
||||
(CompareText(OPD.ObjectName, AObjectName) = 0) then
|
||||
begin
|
||||
FFilteredList.Add(OPD);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
okColumn:
|
||||
begin
|
||||
for OPD in Self do begin
|
||||
if (OPD.Kind = AKind) and
|
||||
(CompareText(OPD.Grantee, AGrantee) = 0) and
|
||||
(CompareText(OPD.SchemaName, ASchemaName) = 0) and
|
||||
(CompareText(OPD.ObjectName, AObjectName) = 0) and
|
||||
(CompareText(OPD.ColumnName, AColumnName) = 0) then
|
||||
begin
|
||||
FFilteredList.Add(OPD);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Result:= FFilteredList;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TObjectPrivilegeDataList.FilteredPrivileges: TPrivileges;
|
||||
var
|
||||
OPD: TObjectPrivilegeData;
|
||||
begin
|
||||
Result:= [];
|
||||
for OPD in FFilteredList do begin
|
||||
Result:= Result + [OPD.Privilege];
|
||||
end;
|
||||
end;
|
||||
|
||||
function TObjectPrivilegeDataList.Privileges: TPrivileges;
|
||||
var
|
||||
OPD: TObjectPrivilegeData;
|
||||
begin
|
||||
Result:= [];
|
||||
for OPD in Self do begin
|
||||
Result:= Result + [OPD.Privilege];
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
Reference in New Issue
Block a user