Initial check in the new files

This commit is contained in:
CodehunterWorks
2018-02-23 10:39:15 +01:00
parent e09b58d21e
commit dfd74add6f
5 changed files with 18348 additions and 0 deletions

View 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
View 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

File diff suppressed because it is too large Load Diff

1505
source/usermanager2.pas Normal file

File diff suppressed because it is too large Load Diff

535
source/userprivileges.pas Normal file
View 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.