From 04d38189fd1e9a14c2169179e076697e66ebf699 Mon Sep 17 00:00:00 2001 From: Thulio Bittencourt Date: Wed, 7 Apr 2021 22:03:05 -0300 Subject: [PATCH] refactor --- boss-lock.json | 5 + boss.json | 9 + samples/Safety4DSample.dpr | 15 + samples/Safety4DSample.dproj | 922 ++++++++++++++++++ samples/Safety4DSample.res | Bin 0 -> 112148 bytes samples/Unit1.dfm | 192 +++- samples/Unit1.pas | 172 ++-- samples/Win32/Debug/RbacSample.s4d | 63 ++ src/Safety4D.Configuration.pas | 61 ++ src/Safety4D.Groups.pas | 3 +- src/Safety4D.Interfaces.pas | 9 + ...ety4D.Resources.Group.Provider.Actions.pas | 1 - src/Safety4D.Resources.Group.Provider.pas | 7 - src/Safety4D.Resources.Register.pas | 2 +- src/Safety4D.Resources.pas | 30 +- src/Safety4D.UserKey.pas | 9 +- src/Safety4D.Validation.pas | 8 +- src/Safety4D.pas | 52 +- 18 files changed, 1384 insertions(+), 176 deletions(-) create mode 100644 boss-lock.json create mode 100644 boss.json create mode 100644 samples/Safety4DSample.dpr create mode 100644 samples/Safety4DSample.dproj create mode 100644 samples/Safety4DSample.res create mode 100644 samples/Win32/Debug/RbacSample.s4d create mode 100644 src/Safety4D.Configuration.pas diff --git a/boss-lock.json b/boss-lock.json new file mode 100644 index 0000000..c952514 --- /dev/null +++ b/boss-lock.json @@ -0,0 +1,5 @@ +{ + "hash": "d41d8cd98f00b204e9800998ecf8427e", + "updated": "2021-04-07T22:02:42.8886995-03:00", + "installedModules": {} +} \ No newline at end of file diff --git a/boss.json b/boss.json new file mode 100644 index 0000000..8609a38 --- /dev/null +++ b/boss.json @@ -0,0 +1,9 @@ +{ + "name": "safety4d", + "description": "", + "version": "1.0.0", + "homepage": "", + "mainsrc": "./", + "projects": [], + "dependencies": {} +} \ No newline at end of file diff --git a/samples/Safety4DSample.dpr b/samples/Safety4DSample.dpr new file mode 100644 index 0000000..78d95a7 --- /dev/null +++ b/samples/Safety4DSample.dpr @@ -0,0 +1,15 @@ +program Safety4DSample; + +uses + Vcl.Forms, + Unit1 in 'Unit1.pas' {Form1}; + +{$R *.res} + +begin + Application.Initialize; + ReportMemoryLeaksOnShutdown := True; + Application.MainFormOnTaskbar := True; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. diff --git a/samples/Safety4DSample.dproj b/samples/Safety4DSample.dproj new file mode 100644 index 0000000..b8e8342 --- /dev/null +++ b/samples/Safety4DSample.dproj @@ -0,0 +1,922 @@ + + + {94E1E924-4B2D-49BF-9361-D6402259FADC} + 19.2 + VCL + True + Debug + Win32 + 1 + Application + Safety4DSample.dpr + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + Safety4DSample + + + DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;bindcompvclsmp;emsclientfiredac;tethering;svnui;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;DBXOracleDriver;inetdb;CEF4Delphi;emsedge;fmx;FireDACIBDriver;fmxdae;vcledge;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;TBGWebCharts;IndySystem;FireDACDb2Driver;bindcompvclwinx;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + $(BDS)\bin\default_app.manifest + + + DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;bindcompvclsmp;emsclientfiredac;tethering;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;inetdb;CEF4Delphi;emsedge;fmx;FireDACIBDriver;fmxdae;vcledge;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;bindcompvclwinx;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + PerMonitorV2 + D:\Projetos\Componentes\RBAC4D\src;$(DCC_UnitSearchPath) + true + 1033 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + PerMonitorV2 + + + + MainSource + + +
Form1
+ dfm +
+ + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Application + + + + Safety4DSample.dpr + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + CEF4Delphi + + + + + + Safety4DSample.exe + true + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen + 64 + + + ..\$(PROJECTNAME).launchscreen + 64 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + Contents + 1 + + + Contents + 1 + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + False + + + 12 + + + + +
diff --git a/samples/Safety4DSample.res b/samples/Safety4DSample.res new file mode 100644 index 0000000000000000000000000000000000000000..32a65141fb3246b099f5ecbcfec662e578e4a684 GIT binary patch literal 112148 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
  • Ez2vSvr*0QyMMgY1?BhA+hC2yMnx7~NC!ZzH>vAO^ z)pjD1yKbY-m~A(#VP?wQNaNUM?_O$q9%zQkxGYhW7kf0*kxUeV9;@jovVXzx&wF8& z18M--TcUYqF647f;j)wqe|TWXX3&%KeizMbVi)hA@t1eM)Bh6waB$Wlxgddl{ihvi zH!%G2zseczlT-Ew#NYeuxprr8ceP}#(%IQw7lgFh-Oo_!ZQ*xu`PgpaemhdncQ*4a zw@BSEA;frg$-B;PhTU-g9Qx$++x7wxx!TV&Z!1uurCyqT=`wtl@$-b-!P-@#V@t;_ zFP&m7DYEIh@{6F(lNP3A8}Lh9xV-lD>4%j`$Gf{;@EDeO^~{;UOI(DtO0|NdcS(5{ zTc(Y55xu+ZbIHi30y`wdR(f+2pwRsnJ}zkAS6VDMao3U9E%{IRx>=U@yjUoQ>nP9` z3Lkn;F_7FnL`+uiN!hHJ2`M`~B#s&oQqtT}#A+jf7@6J2gJBk9d2+5u)%<=JvwV1; z&Ey>)A)IuWXU&q&TN1|k@BjRH4~N-qjZPnTUtEbZhd*-`s9ie zhgKXpxIVu+BQ5B>_Yjy7X!mTkF4R~T*OgLA1q=D)O+w7uhptU47@oZ~h|*K`&g{Wr z2FZ^`>VH`{x3BAnBQ6$Rrh~1Vk13ew==4!ES#+3p^2{qls{9$NLZ5#f1U1jbba+|{ zO?OwA!JKt`m1{=tX=fvj+}ijo?fCT6(Oo;nyzw2-%jCRD$T*)_Bg}3D-kGth@|cIj z$SVbMFEekCqnxMQgf+#E{VjLT85H!;cv{6o(a~K-i+15Ze|xjF)iwv^gQ}A%9x4|P z5Pwuj2?Ui56*F)-T74i~gYPq!_LOk3x0)oSX!)Tq3(7@!+h5GU(x!UqaH+tvflv3^ zPMRnBOh9Pu`zxJQWZEgtf+9FDQM&Ae$1tOCC-q6kb&`7OT-M?u!XAv$?BcD5>!5FE z#|Wi7dRkc8qmq|+KedmBXjv3Q?_|?2fBUK8lG6Rdg$Z4!#8*=Tbque?nCtA~tGQ7y zYof-cJ?lKBt^8q8fG>Yco?6(u=gv7%i+VjDVeWa4`|b6DEb*=fM{I&s;UPJ~Hp=Ic z`+7d+e)}f#cF%zM0fM-MJcPIn2D2Dfi)Tv{FcrFw=OK?0un_y7QO?=WD_SyphP!Yr z0ha+w@NtNO#oXAdeREzGFZ(iv=LE3?8dT++p1Mz`t~EdE**$;74B4zn3p<4qxJ;q! z$|rB3(IdmuH^<|KyWCcxy`jB_a}i}p$9uUdGauv4rIr*iwB)|gm_Y%~usp|G z)$s`A?fJelrL)w$l82+mP-$}La+2SptFXm}a?16HT-Bod!ZZHu+OqPQ5e`(G@oe4zD59A|2xfSfq^3IZQb`?2c#LinV=A2%h|f*9Ofv zo*(trF?ERuv6#CjRFYvH@{8iA?ii0F-X`TlIeyuE>IQc*PtS*AEao^x68}M7b}^aD zV*?gKUgG)vP45L+=q`O73`ZrMnRq zO{@BNcRAI;`$<8TXF8XPj0vG)E@NFYB(K8@<*d19T0o5l?+-rtpdtD`Fa^G81A+(QYCeN0@FX>;3V>?VUGN1U_ zGsdBMJ|#+{aQH4|uKSyl*4{I=5{Z#KqMr6dU}o2o-3D=s5AjpxG3oxyPq(PbPxeUf zX`__)FH^`LmseO$Id*jXoX?xIr_OU!=2G5t==g1Mo)Dg^L?2 zC$;1X_o_%2Zj$X+;0|f00jLA?0^s?>#rE5>2l^5PFaZbxNCLQAs5kb4IJLx9Zy=>VM6HLEs*HjxRi1HcTR>rW6xo5>R7i#neS@DD&f z0IPcXQSnNECainr0Q|KD4p}D1QWYQ);3L3~(j~k36auaL07e0P?VNK+9&G^)$V>oW zI>2=Rc6ITy)87Lg<^ptR3%X;6N03o_fcXGV0e-gLIGsQCAAJBivm>KFF)hf1AHW{q zIRK~S{;T182RwQL;9k8pe}NqI0kDqz)%4Wb^kf6iQvurK7!vpv12_cG+H(HY@#CDr zkhW400I%Et*v9{gW4NDXE2SV0UjW>#{l{LwUtfST06$C4zk0qmKsLB^^T%Dl*8~9U z`~2!U_}TOofQ)Sa6axTWcmY-c)ByZ!+5S%Xi-Tl0CZ{seEO?i1x4gHG3@SjjGk!%I0J_whqkFZXMdVVqGSb)m=L6E=?NUm*IhK-6 zb4tirlZwfSql-!K6(dy#7n1S=z5@7={R(!CHts)v z%3oUj42eU#eV$!S9z9S=ddw>&b(M-p`Tm8Z@}TC)pt&+@5FguFrJrd7kbh@@j0SYE zWCy>q{u>%bSs6)QO|63Vtd!J}EBcZ30+zdVl zn-jWk%lfC;!THmbHwglJHY!E(9E&W z_0pEq0gxBA`*&KHXOpyZQvb`m%BX8CxE|k9P=Y!aeLb{cOl~r&m~^r%A-4pVlNZld zQhfk^v^6}-swUNBIMNQh1syhf?>VFy*IK$qyqwg3AhemSK`YMF;=29_(1Xp?67o=d z1&L+zM_rg7hkQ&Nn_CBfJd;~PrZk+tgZ^o>((b4WoU;pFQBJ~9-9N+(7TT6@!ms2$ z@WAppBoJ2$fUWgCn#>s8e@Fe(c)@x>O{R$4ytbUg_5Rkp-oB|JHHL9yo_I8?bpY^* z`?Xr7PNm`fo%K)S0mo_R3wZ4kblO|-+O@TU6YE9$SkXW5hGV`Q8jr1Y{}c32lMUKI zSV(!R`LmXllBA&)+jRi04>x%(8N|`0@zt95KS}>6C+r)bFDUu~w#Ichv62)1BbH6o z0l-T{YwDeb`%lw9@`e2ZC(G8cfeM(H;6NR4l9~R22dw*F&~((A_dikpC@-{uMRQAA zr7eiv3H<=}=7#Z%$}Ws-0N$yzrq1bc|Ec;%9?`dF(;CiCB%<$-hAi9t05c}~UrMi| z*8Ke^>mTKY{ejdAoF5n9emOSxnM5+tKb}R^s^dNy{y$y+$S3-G7JT9C`~dotn3memwme)&cNr1RFS; zO;20UKgtu=lwQ5y>_*pRo~7)z0h1fiKc30gY(2I#O zThQshReZde*;HH8KaK-d!X6J!U0IK-**afhm{@@;P5qjU1AAOg(?8%@!7OfTylad4$MfXSzn>FVB@8EY6k9$Is5QJWhNgdA zrNV8kp<`w^+oJwa9v@+^0;etm&6ewbv`W!2n*IULUS_&#jdyKP|9Jk((@f6I1)Gg+ z`5XZFEncMQ-$b_vzp2^cwxlI#+oJyEBnrv2+Z<{Dpc0v8+;aWnH?L{>pD?Hko3bjOLfZB_rb;4CmsU7XUtu};wePUy5bINGHC z!EfW<9nR?=&zNkE%<1FO*ZRF368wH$UQcThu?E6V9pmAKYhxXHB8g zGJOi{TZ*Tp>Dr?HalFQ<3w=OvO`)aoSC%TQ^8tdjpouNT)6#TpQUCsMP6el~jC5H4 zVZ#rYe*FjZuhddKwlrN^(?9M9I0Ae4ICY&l2|j>qoF@%Bult4!{O$pIC1j?`M3S6|JG^$9A2{!b#x)J@$v4OAI zw6vA-kA3uiFLQ3rAKMTYd$!ts)YZgB^v@5^@x0Jx>#`+j+KT>dr*XFI<9YGy%=>|^ z@Ladv4fS8!2Aph(E?bhOE$AQnefaHAPG0A5?;jiEe$Z7$W4f=^ziUf$*^)GWy8f}x z*BWPl;P+=+B5%4hTbSs7C|x{u^I@9)Pu4%q%g>xxLgJZCoV;@3jA{<($B2pk@yusD zAA%G4FvamF>mSc&XpQq>L)Wo4=LdTI0??6>{%hNS;J^BBx&5PEbJE9`R(}-2IkSkH zP2K#%O!u|={~>39{b}VN>wNUbz;oMMyZYv0Cd2UQx!@ zT3@X$w=*j94WC2&J^=U~!6wUbOXK{`%X%{HM|D zmX+V2d-Mso+*&rkN&Vxw3iv$^)Kg0V=hVR`nl#oeCM_oylS|!7$=DqgB%Zff@TC#u zwDO}nH#k=BKLs7O=$qh>Zv5|{|8j7vEG`0owUL%U38X`RYV@o46|Q$s$Ba>Bd#q0@ z`%bKs_r~IY?zsT|YYiLVWcmLUbjB$f&=zM*;K(cs%K{L0MBVo+rZ!QU*8r`_wMlh80>R$NY?3qhnJaNS$zk1h5=M? zh%PFBfA#-O|5)c^x#ytnQO09g)h{dY0N?t*`v0agPW{4tTsX#O$Ctkmy&Pagr_G52 zc?bbue}W_R)8Fz>lDLNp*NkZM$Q+VwKH%xw9Nn@S7w~dyJlK}?kNZIO!nd5*IlqsI ztu*^vzpUyX<3YYVnB>iJ-OyI`|LR2zId@hGyZ+mZa*Kqk93 z(AM-{3g7VD5nc}SlZBkF?`gL14s_CoRXws35Asn2C}qb6+KT@1dp*YwR#Ly+$l?Ay zP49Tev)hf?(P?wjLViwv_0M<|fZyyrl2}3gP6M9%!;Y+2NE_5#{c$2b&=ti3ZH@B& zr95BYZkc+5=KjlKJw^^f0lybkNa5gW>>e*VZGoBJ`D>6p>G zH;`}t=IE-m;sPBK054DutOA~0{;RCFHr9&c-VHpf?eW8EGUaR~83VomOWn#ybAw`P zA0E%%`GMuUpuRRxOd`@0teq#kyb}K&$RE2K=q9J9hBny8Rx2x^J=nuKH{#-M~AZ zIh6#!jvRl-w74f%v!!zT)6#(~#sFMv19p%BJWc^5nRtg&v<0sQVg zz#;sN&$Jb&^>+Zqg*0XWBLI2>{4LwRn*sc#mn8`_=KBh#ArXW){hI*5MHhzG^&(I( z%=0Y*1_{ES_JA6lE}A0$ft!ne+}o*!nFt~v~Vp& zv|ud@HQ&Pih@cKVLFiz(mRgJ@j^VoO2!fhn&bRc`3@P8j)C>c@g{d5U3sMQ7%bv<1 zUG`K08iwh}p%O$#4waxBdi+38!!U*ZJrGzg3z8jR&jIuTfbveE4>znIAe=-09_p8R3^oiy z1zC?ls6gv6q(hSR2yPhmC+k-@5TqxVTA$JpOs#L}2&C4>bOciCYdV6&5g#2vIvA!S z$RERW8B&AaBt*@QP9oIo=r|Vt8ow?Bov-0KmDC1l2&vrQvsw;n(bZ8XPK#fQpf30o zK`k}-l**#`xA(|G9d>*SBWguBQEYE@Bbr(0Qp$}eEJ1=r^yrdS6Q~U3?L6afK9&;-!%Sdcbw-GXbm|4-i`p+ zCeiZxRqq#pMqy6M0PuAI_?>)Qus-g=2^jz$)H}}0f2VI>_cHSQ=}NZY%*jgf=z$9A zx$XGP6leH82Yx4=&3)P^1Gek{((?k~I@Nc)Veg8CCnz$FjdzSl15O;qQ z_^5LEnf#+1@cRkA@VyHb&mqOOyGb*EIJ&Ixj&XiA|0n~jCpWGsXH^E1m26(OZFJoF(Yk7JEcZTCecxS{a?--92{Xc>4V66=-V+#1aV_BYUR!kmBsA%?gi18ao_${0! z^0@==znepWXXww*w7qMHw>9{u&jY{dgYs+6g=hD%P#=DG9s}gNmOgJ*ez!LNNCWb+ zepMOEXD;E{OjC`Eo3erJ^ko3@!FmtBH`G+RdhdS(|1=o{`jk=YdRA=V^oh!*YyjsI z>*_)HJ*>IBWBeb*KjwvYfORA*7k+=v0M0^cf+tOy4M04XCgL`V>qqjB^kJWu)$cZL zfHKnrPs`}|k8dJwqqu%F|45?;d~1Z2>-K+Dq%xdo$b_$CI{u$9iN_Gf&)^^FeEqWN zJ_3H1MRPdQGLT!lCe;pbR{T!<@7fB7+_7-s`Dje|ssa8*00uIN!z}#|t^eq0bevtn z0{0~8?^Vi_epqi*fb$=5eT`{6M(=-?{f|;EVyP|MwyB&cUr?VK!#eClM*KDP{Aclx zZ6VHsGP&pzh-o#Z$E>z_RrV7>Glu!=La6kneoZ!-Ou8G+h*4KKQm34j)SrP zLtP&N{vI&mk=gT~!9SLLocnI-!ta*gH%pk%{|5M{4gny}UMBGv;`kZ-vugX-F2VQ* zWW|K9lXT;sc}(Il#POr~M}BVKfQe2PE*9p4m(uYs{X6i#$`2MiSh#RqgoW=gkD%k9 z0REf3H}yyAAML)JwQ7&LmfnQz=K{a=&ZvX%isstDkKiBqSTwhkEM=|9Bk{XErf?Q` z6TEDp>7I6n_)-AP+IQI6{Nr4H;@%3D`Z}~?K^^ljulGaL3bLq>g-#xgak%5Wkaq3)?@ahWKOTCv>wd#?Jtpbu_@>2Sh5ziVYI5tw za&jw-#TmiQh;pi)vCaDQv3Wex*vIc4Si)KOG}@TlC)Y9D;0L6^dXVKaTv*|sMqg{* zaV*eOU$<5s=o7^BJP&w};~|#T!F~n)alL27lCq}yIyAdr>3mAyKN^6RhT;8Z^Iud{ zL%KRJALG#Raj=28GYmo+5r8KB*MBDe>36DFY3FFV`w0B>X2@_OFCe}?0MqvHXYh~T zU0$)YthxSh=8dq}PJsT6Y0pRojmhN~c!s=pVUazSq5(d% z1BPYc7vPyzKcT-eNA%uMFn|~9g8%@g?E<`~(efkj*k@Z0z*c#0$a7<1$YUG;?&tfF z{4vW5eRY}oHa5lwJI^3LVSrr#Kid}2cSDpNUf4+sd8+}SpFK1Ew8p#tAkR_k(9Wr} zKnIQ+#{i&@ackNGmhlvT@c`fXFmj3?cJKgQIFE#LY3OUqDZM`hTrCj2gLAR_0Tu!b1^6X(-CTLXdW!(S0Qmt08ZbXS0oUFU@Halg zcL430i6}ANMhG;x)6NO0y9W@|i*_Chqx;ub9Q+?p zi>vm|C|@qh*LZdG=G2C3?*g=Y?P(XC8^}YPCZ~q-qsg^S&J+SJkUJG2=z)qz{F|Pr z2|&A;fO@6`1jfDr@XQI`8A2R!fL8D8vBD&W0of;-a#Jt4T?1Y#Q^Nm-7tMA;M@Sf@$Yv5 zPHYo#UJY%eVZNLWzl1y{0B}O&NH>$YiwD$9p zkawq+D592joX4u8(QsrD=`^RLS>OoqZKsuxQ^yyR;PY9Biym(izbWv(Sv){|oGLZrl%yd(VTwCjib5VwE498)36(8XyqEi?LYEgshz8Uw_u zC09sVnU_${s$j(jJ?CjPH4Our*3;_%;s^ksZ8b_a?Riu5)8aLCNB@$;u>R1LFKzU8 zhJLiz=d0_t!f%77^2GO?qMw%6I@n)~>)?#8l9Cz{eBBwzw9X#_@NK2xWOnB?{g_we z7Us@fQDF>q5Q8=ZIIyi{Y0jxN=!Y}?$j1*DE8*qyY7*l#BG>2ej2EB>K%?zd!!)fy zKjzWY-nuE!cWOurgmE0#59*7Njl63tKF95!mM@Hz$&c?D`wuOLeitn+{T;^B2Cxrm zHvKbZzgtWGnCICf#{0cvb~L`90p$&Du8rtYmNe`fZRbhL5$(SD%( z&TNWq+WXd|ANSrfx^^?@M_~Dd`cs2OUsLziq96B{=e=cIe=^!niuEVZ+zo)GeZ;Lr z|9mUPPSV)NGaJ`v`-S5%F#zm8WB@eUM$kWRE&6X>XS}x|8~V|zgBztS2WX@Evcr7~ zJ)Mkxw+8(<55eqWvKK9yHUWPye0lX}kbmIN!{0EY{leKhLfvrx-DmJIX#AK!`?fV|RG3 z4bbR%eQVK=^Sbdd6-}M-h+{-n{n(d4T&m5}-#JY`?zKc8P$srcPeTyU(wNAr&Vw51?TH6 z&5N4_b0!y)GbR+16UP)&_xRxa90M8|J;ybadUbt6S{a3FdH7Bb&CH(>U93FEHIx?7 zPU8vEqb>OWG+L(NIV*HDHx8CnTtjJ=&CqCW><+kap5-Axb7^UA{HKry_Qx6{gRN(P z6WfQS08HCyc;8%_F+R@Sqs;5(W!WN@Nn*$YeL#^9?1Q(2R{AtJ?;Qxhk#nn=kp0~& z$P@dmsB0WQ;24ONaU9w<+F=9$j{gL{L;MpS03A4v>kjp!7R(9Ef_V*hnBNFMz~A@` z-(eh#%PA7Sx{-Z#{PG9iBlJfS$9oQXiNQSp-H_mp8NxrRf0I8!Q2m{B2;!^z5FB5NN97mzr14FY z15GY8IiY_YRc?TYDo02_l`BM~%9-lEM-cH{=>53(FxT(C2P6T{bOGx8xF8KX7uXN_ z;h-7raLmwKaN8x0pUH`rNeSLRxWO z7lZjLs0F{jAYXZadhJk4^QX~#<60Ft4!)~E&lCJcd#GoV5GDXp0qVtNH-Dr9=M~U@ zsR8c)AY4~A;rHkU@2T+{%OCg5p^j;QHsa=3O5*$qqq*FBcdHsZKYu(;3y}ABK1)bX zWBD&x#CZR)ChXPR9ohK0ZX@TDp1}MepAG<}m|sI^ZvM3NIQQ7_!gaz1^GaxIT>!?> z(lxxdG=H>vERzi{JlCT^9wrd3SLW#7w={pmu@uh9Z+PLJOM3h&g9?{HyS266Gdex6 zlRu7m8(vo~R@KiR+D*_2)=3SYQ^V}!4}6g&;1fiDp-$-YqPE||3ghXY(f|Gt`2(HU zpRPw2EzC~-==0d{x=g9hKj=Ri^75qR*YM6x{)?Tzx4+o$*Rz*Fo?{y3OAE7;e`9Ma z&UW9mjmD4{j!kiH_B$Q4H2+nNtSP^PbvCv7=aXSy4tm7YIXa_ z^uOj#%^zvF(2$14@~7cs^^WUkjr0MoKwfq2Z>JLe%;4euYU&wn$>8g;d2Jav z9p)@)=^MFY-?pCI>GQ|m@SX>tj)q2XFvHL69p>E}Uue`tJ$q;&E!fY%Hl8Wp4dqZP z3$)4a%0)Biz&@>fW4Kv;2I*<_1J+TE){_nBDSG#|6~Ma%0QGQS7$6kp-bie3=mF1X#IuWZ>#x0F-=_`-{B{JO zu6Z!3-|<{LY-`lNtr0Ik1dy&P0Cj#D*Gy>F`BRnTVfePpiNlrTi=1!%n&=x@xt~N zpVjL34(&aw>0iI9u1gPT53!p5?yax%Urwp>&pHNa(Po&-55`4Xg1?Q;yj|+rD6~@? zi+x5M^z@^ijvcHdv3Q)SZNj&_Q+PM@^iZ+M6DK$#u_ zKJOslZveE@@AhKkLr; z(|vCpYoo8V71l~0VOK2|5fJdTjvCyKi{K`7b!$VTae`PLkYh~Tf6GfqNYsX)YU6`> z+pi(43lV1rm_LRHK#M2<7yLrnzJ2RmOUHZR0tqjBH+Lr&=aB;xhRY9-uy?j~v2${s zJ92=9`8Zj%0TS*W*3Nd;3tXJ-M-K3@cORgm-Ko8nwY$6hLYoCX5`e(jedGX7H)joZ zTSxna*6y+koowA)++7?zWNlp*YFN839PXtsKw_b_vy+3pyT_Dzxlxm2951CNkthv- zoFyb6Z-}j7?drO~$=2EfDA$Ikbgi6rq;(cK-o1*wFCq!J!s@zu@G{UP^?JIimP^D&P?`rRC2io@adGx= zb6Md2EkT{VsScONzi)3`J#9dzJq(>4Txfc1 z!o0yUznY-Cy{)GkNUTnjZuW~j!RYPnOx>KkoEF&6wXd^Cu*tf&W4$3EnzFIIm;Hh| z(Mm`x!0^Zc*6xPRULX^2g7md9?CmB_mN2v%Ibf;1qP&8F zvdRcq1r=pgS!E?#6I|va*7# zjkUV1tevX5owBvEwW__68ap`;S74mCf`jS^RofA&vTE}73bM+IO6syuL~Uf%lW{PGGRpr-K3>>; - - - - - //Buscar grupo de permissões - TRbac4D - .New - .getFunctionDefinitions; //TArray - - - //Busar Resources - TRbac4D - .New - .getResourcesGroup('GroupName'); //TArray - - - //Como validar o acesso a um recurso - TRbac4D - .New - .validateAccess - .roleName('operador') - .group('housex') - .provider('user') - .resource('Actions.getSaldo') - .Execute; //Boolean - - - //Atribuir as Roles na instancia global - TRbac4D - .New - .roleName('operador|marketing|gerente'); - - - TRbac4D - .New - .loadConfiguration(aJsonString); - - TRbac4D - .New - .saveConfiguration; //Retorna JsonString; - - *} end; procedure TForm1.Button1Click(Sender: TObject); @@ -228,7 +213,7 @@ begin TSafety4D.New.getConfig(aJsonSafety4D); Memo1.Lines.Clear; - Memo1.Lines.Add(TJson.Format(aJsonSafety4D)); + Memo1.Lines.Add(aJsonSafety4D.Format); finally aJsonSafety4D.Free; end; @@ -237,7 +222,35 @@ end; procedure TForm1.Button4Click(Sender: TObject); begin - RegisterResources; + TSafety4D + .New + .resources + .registerResources + .resourcesGroupName + .add('newapplication') + .providerName + .add('users') + .actions + .add('read') + .description('read-only') + .errormsg('not permit') + .&end + .add('write') + .description('read-write') + .errormsg('not write data') + .&end + .add('delete') + .description('delete-data') + .errormsg('not delete data') + .&end + .add('view') + .description('view data') + .errormsg('not view data') + .&end + .&end + .&end; + + __ReWriteMemoConfig; end; procedure TForm1.Button5Click(Sender: TObject); @@ -266,13 +279,17 @@ end; procedure TForm1.Button8Click(Sender: TObject); begin + __ReloadConfig; try TSafety4D.New + .configurations + .exceptions(True) + .&end .Validation - .userKey('{34C940ED-50E7-4CE3-B701-03CF1E15F28B}') - .application('delphitohero') - .resource('users') - .action(edit1.Text) + .userKey(edtUserKey.Text) + .application(edtApplication.Text) + .resource(edtResource.Text) + .action(edtAction.Text) .validate; ShowMessage('Usuario Autorizado'); except on e : Exception do @@ -282,36 +299,7 @@ end; procedure TForm1.RegisterResources; begin - TSafety4D - .New - .resources - .registerResources - .resourcesGroupName - .add('delphitohero') - .providerName - .add('users') - .actions - .add('read') - .description('read-only') - .errormsg('not permit') - .&end - .add('write') - .description('read-write') - .errormsg('not write data') - .&end - .add('delete') - .description('delete-data') - .errormsg('not delete data') - .&end - .add('view') - .description('view data') - .errormsg('not view data') - .&end - .&end - .&end - .&end - .&end - .&end; + end; end. diff --git a/samples/Win32/Debug/RbacSample.s4d b/samples/Win32/Debug/RbacSample.s4d new file mode 100644 index 0000000..3a44e20 --- /dev/null +++ b/samples/Win32/Debug/RbacSample.s4d @@ -0,0 +1,63 @@ +{ + "resources": { + "delphitohero": { + "users": { + "actions": { + "read": { + "description": "read-only", + "errormsg": "not permit" + }, + "write": { + "description": "read-write", + "errormsg": "not write data" + }, + "delete": { + "description": "delete-data", + "errormsg": "not delete data" + }, + "view": { + "description": "view data", + "errormsg": "not view data" + } + } + } + } + }, + "groupPermission": { + "{4D62E4C3-C73D-488A-8518-03A9545B5611}": { + "key": "Gerente", + "description": "Permiss�es completa de gest�o do Sistema", + "Actions": [ + "users.write" + ], + "NotActions": [ + "*" + ] + }, + "{C188D1AB-EC28-4380-96E0-D1B13A29A8B3}": { + "key": "Comercial", + "description": "Permiss�es de Recursos Comerciais", + "Actions": [ + "*" + ], + "NotActions": [ + "users.delete", + "users.write" + ] + } + }, + "userKeys": { + "{34C940ED-50E7-4CE3-B701-03CF1E15F28B}": { + "description": "Fulano de Tal", + "permissionGroups": [ + "{4D62E4C3-C73D-488A-8518-03A9545B5611}" + ] + }, + "{96B4C46F-0EBB-443B-B309-09C81844406E}": { + "description": "Beltrano", + "permissionGroups": [ + "{C188D1AB-EC28-4380-96E0-D1B13A29A8B3}" + ] + } + } +} diff --git a/src/Safety4D.Configuration.pas b/src/Safety4D.Configuration.pas new file mode 100644 index 0000000..d55eb67 --- /dev/null +++ b/src/Safety4D.Configuration.pas @@ -0,0 +1,61 @@ +unit Safety4D.Configuration; + +interface + +uses + Safety4D.Interfaces; + +type + TSafety4DConfiguration = class(TInterfacedObject, iSafety4DConfiguration) + private + [weak] + FParent : iSafety4D; + FException : Boolean; + public + constructor Create(aParent : iSafety4D); + destructor Destroy; override; + class function New(aParent : iSafety4D) : iSafety4DConfiguration; + function exceptions( aValue : Boolean ) : iSafety4DConfiguration; overload; + function exceptions : boolean; overload; + function &End : iSafety4D; + end; + +implementation + +{ TSafety4DConfiguration } + +function TSafety4DConfiguration.&end : iSafety4D; +begin + Result := FParent; +end; + +function TSafety4DConfiguration.exceptions: boolean; +begin + Result := FException; +end; + +function TSafety4DConfiguration.exceptions( + aValue: Boolean): iSafety4DConfiguration; +begin + Result := Self; + FException := aValue; +end; + +constructor TSafety4DConfiguration.Create(aParent : iSafety4D); +begin + FParent := aParent; + FException := False; +end; + +destructor TSafety4DConfiguration.Destroy; +begin + + inherited; +end; + +class function TSafety4DConfiguration.New(aParent : iSafety4D): iSafety4DConfiguration; +begin + Result := Self.Create(aParent); +end; + +end. diff --git a/src/Safety4D.Groups.pas b/src/Safety4D.Groups.pas index 03d39fc..26ba3de 100644 --- a/src/Safety4D.Groups.pas +++ b/src/Safety4D.Groups.pas @@ -43,11 +43,10 @@ function TSafety4DGroups.getGroups( var aJson: TJsonObject): iSafety4DGroup; var aJsonActions : TJsonArray; - aJsonGroups : TJsonObject; aJsonGroup : TJsonObject; begin Result := Self; - for var group in FgroupRegister.getGroupsRegisters do + for var group in groupRegister.getGroupsRegisters do begin aJson.AddPair(group.Key, TJsonObject.Create); aJsonGroup := aJson.GetValue(group.Key); diff --git a/src/Safety4D.Interfaces.pas b/src/Safety4D.Interfaces.pas index 03ee417..4420f67 100644 --- a/src/Safety4D.Interfaces.pas +++ b/src/Safety4D.Interfaces.pas @@ -16,6 +16,7 @@ type iSafety4DGroup = interface; iSafety4DUserKey = interface; iSafety4DValidation = interface; + iSafety4DConfiguration = interface; iSafety4D = interface @@ -23,12 +24,20 @@ type function Validation : iSafety4DValidation; function resources : iSafety4DResources; function groupPermission : iSafety4DGroup; + function configurations : iSafety4DConfiguration; function userKey : iSafety4DUserKey; function getConfig (var aJson : TJsonObject ) : iSafety4D; function SaveToStorage ( aPath : String = '' ) : iSafety4D; function LoadConfig ( aJson : TJsonObject ) : iSafety4D; end; + iSafety4DConfiguration = interface + ['{E5561A2B-42D5-4A53-9EE6-57C1882C610D}'] + function exceptions( aValue : Boolean ) : iSafety4DConfiguration; overload; + function exceptions : boolean; overload; + function &end : iSafety4D; + end; + iSafety4DValidation = interface ['{3EB75190-778C-4E0B-ABE7-A17A78103C5B}'] function userKey( aValue : String ) : iSafety4DValidation; overload; diff --git a/src/Safety4D.Resources.Group.Provider.Actions.pas b/src/Safety4D.Resources.Group.Provider.Actions.pas index e509505..d9cbf3e 100644 --- a/src/Safety4D.Resources.Group.Provider.Actions.pas +++ b/src/Safety4D.Resources.Group.Provider.Actions.pas @@ -12,7 +12,6 @@ type [weak] FParent : iSafety4DResourcesGroupProvider; FActionList : TDictionary; - FActionsMsg : iSafety4DResourcesGroupProviderActionsMsg; public constructor Create(aParent : iSafety4DResourcesGroupProvider); destructor Destroy; override; diff --git a/src/Safety4D.Resources.Group.Provider.pas b/src/Safety4D.Resources.Group.Provider.pas index 06617fb..cf2783f 100644 --- a/src/Safety4D.Resources.Group.Provider.pas +++ b/src/Safety4D.Resources.Group.Provider.pas @@ -50,13 +50,6 @@ begin Result := Self; FProviderName := aValue; FProviderNameList.Add(aValue, TSafety4DResourcesGroupProviderActions.New(Self)); -// FProviderNameList -// .Items[aValue] -// .add('*') -// .add('read') -// .add('write') -// .add('delete') -// .add('view'); end; constructor TSafety4DResourcesGroupProvider.Create(aParent : iSafety4DResourcesGroup); diff --git a/src/Safety4D.Resources.Register.pas b/src/Safety4D.Resources.Register.pas index 343e5df..7372090 100644 --- a/src/Safety4D.Resources.Register.pas +++ b/src/Safety4D.Resources.Register.pas @@ -35,7 +35,7 @@ end; function TSafety4DResourcesRegister.getResourceGroups: TDictionary; begin - Result := FResourceGroupName.getResourcesGroupList; + Result := resourcesGroupName.getResourcesGroupList; end; constructor TSafety4DResourcesRegister.Create(aParent : iSafety4DResources); diff --git a/src/Safety4D.Resources.pas b/src/Safety4D.Resources.pas index 5fd3f56..a2b1505 100644 --- a/src/Safety4D.Resources.pas +++ b/src/Safety4D.Resources.pas @@ -40,31 +40,43 @@ var iResourceActions : iSafety4DResourcesGroupProviderActions; iActionMessage : iSafety4DResourcesGroupProviderActionsMsg; begin - Result := False; + Result := True; - if not FRegisterResources.getResourceGroups.TryGetValue(aApplication, iResource) then - raise Exception.Create('Unregistered Application'); + if not registerResources.getResourceGroups.TryGetValue(aApplication, iResource) then + begin + Result := False; + if FParent.configurations.exceptions then + raise Exception.Create('Unregistered Application'); + exit; + end; if not iResource.getProviderNames.TryGetValue(aResource, iResourceActions) then - raise Exception.Create('Unregistered resource'); + begin + Result := False; + if FParent.configurations.exceptions then + raise Exception.Create('Unregistered resource'); + exit; + end; if not iResourceActions.getActions.TryGetValue(aAction, iActionMessage) then - raise Exception.Create('unregistered action'); + begin + Result := False; + if FParent.configurations.exceptions then + raise Exception.Create('unregistered action'); + exit; + end; end; function TSafety4DResources.getResource( var aJson: TJsonObject): iSafety4DResources; var - aJsonResources : TJsonObject; aJsonGroup : TJsonObject; aJsonProvider : TJsonObject; aJsonActions : TJsonObject; begin Result := Self; - //aJson.AddPair('resources', TJSONArray.Create.Add(TJSONObject.Create)); - for var Resource in FRegisterResources.getResourceGroups do + for var Resource in registerResources.getResourceGroups do begin - //aJsonResources := (aJson.GetValue('resources').Items[0] as TJsonObject); aJson.AddPair(Resource.Key, TJSONObject.Create); for var Provider in Resource.Value.getProviderNames do begin diff --git a/src/Safety4D.UserKey.pas b/src/Safety4D.UserKey.pas index c125d0f..1100f18 100644 --- a/src/Safety4D.UserKey.pas +++ b/src/Safety4D.UserKey.pas @@ -38,8 +38,13 @@ function TSafety4DUserKey.exists(aUserKey: String): Boolean; var iUser : iSafety4DUserKeyRegisterGroupPermission; begin + Result := True; if not FRegisterUserKey.GetUserKeyRegister.TryGetValue(aUserKey, iUser) then - raise Exception.Create('User key not registered'); + begin + Result := False; + if FParent.configurations.exceptions then + raise Exception.Create('User key not registered'); + end; end; function TSafety4DUserKey.getUserKey(var aJson: TJsonObject): iSafety4DUserKey; @@ -47,7 +52,7 @@ var aJsonRegister : TJsonObject; aJsonPermission : TJsonArray; begin - for var userRegister in FRegisterUserKey.GetUserKeyRegister do + for var userRegister in registerUserKey.GetUserKeyRegister do begin aJson.AddPair(userRegister.Key, TJsonObject.Create); aJsonRegister := aJson.GetValue(userRegister.Key); diff --git a/src/Safety4D.Validation.pas b/src/Safety4D.Validation.pas index f690cdb..3395bac 100644 --- a/src/Safety4D.Validation.pas +++ b/src/Safety4D.Validation.pas @@ -104,7 +104,6 @@ end; function TSafety4DValidation.validate: boolean; var - aTeste : String; FAllAcess : Boolean; FAllBlock : Boolean; iGroupPermission : iSafety4DGroupListActions; @@ -118,7 +117,6 @@ begin for var UserPermission in FParent.userKey.getUserKeyPermissions(FuserKey) do begin - aTeste := UserPermission; iGroupPermission := FParent.groupPermission.getGroupPermission(UserPermission); for var aAction in iGroupPermission.actions.getActions do @@ -136,7 +134,8 @@ begin for var aNotAction in iGroupPermission.notActions.getNotActions do begin if UpperCase(aNotAction) = UpperCase(FResource+'.'+FAction) then - raise Exception.Create('Access not allowed to these resources'); + if FParent.configurations.exceptions then + raise Exception.Create('Access not allowed to these resources'); if aNotAction = '*' then FAllBlock := True; @@ -144,7 +143,8 @@ begin if not Result and FAllAcess then Result := FAllAcess; if not Result and FAllBlock then - raise Exception.Create('Access not allowed to these resources'); + if FParent.configurations.exceptions then + raise Exception.Create('Access not allowed to these resources'); end; except on e : Exception do raise Exception.Create(e.Message); diff --git a/src/Safety4D.pas b/src/Safety4D.pas index 02a6353..0fbb129 100644 --- a/src/Safety4D.pas +++ b/src/Safety4D.pas @@ -3,7 +3,9 @@ unit Safety4D; interface uses - Safety4D.Interfaces, System.JSON; + Safety4D.Interfaces, + System.JSON, + System.Generics.Collections; type TSafety4D = class(TInterfacedObject, iSafety4D) @@ -12,6 +14,7 @@ type FGroupPermission : iSafety4DGroup; FuserKey : iSafety4DUserKey; FValidation : iSafety4DValidation; + FConfigurations : iSafety4DConfiguration; procedure __loadResourcesJson(var aJson : TJsonObject); procedure __loadGroupPermissionJson(var aJson : TJsonObject); procedure __loadUserKeysJson(var aJson : TJsonObject); @@ -22,6 +25,7 @@ type function Validation : iSafety4DValidation; function resources : iSafety4DResources; function groupPermission : iSafety4DGroup; + function configurations : iSafety4DConfiguration; function userKey : iSafety4DUserKey; function getConfig (var aJson : TJsonObject ) : iSafety4D; function SaveToStorage ( aPath : String = '' ) : iSafety4D; @@ -40,10 +44,18 @@ uses Safety4D.UserKey, System.SysUtils, System.Classes, - Rest.Json, Safety4D.Validation; + Rest.Json, Safety4D.Validation, Safety4D.Configuration; { TSafety4D } +function TSafety4D.configurations: iSafety4DConfiguration; +begin + if not Assigned(FConfigurations) then + FConfigurations := TSafety4DConfiguration.New(Self); + + Result := FConfigurations; +end; + constructor TSafety4D.Create; begin @@ -67,9 +79,9 @@ begin aResource := aJson.GetValue('resources'); aGroup := aJson.GetValue('groupPermission'); aUser := aJson.GetValue('userKeys'); - FResources.getResource(aResource); - FGroupPermission.getGroups(aGroup); - FuserKey.getUserKey(aUser); + resources.getResource(aResource); + groupPermission.getGroups(aGroup); + userKey.getUserKey(aUser); end; function TSafety4D.groupPermission: iSafety4DGroup; @@ -125,7 +137,7 @@ begin StrList := TStringList.Create; try Self.getConfig(aJsonResult); - StrList.Add(TJson.Format(aJsonResult)); + StrList.Add(aJsonResult.Format); StrList.SaveToFile(aPath); finally StrList.DisposeOf; @@ -162,8 +174,8 @@ var begin for I := 0 to Pred(aJson.Count) do begin - FGroupName := aJson.Get(I).JsonString.Value; - aJsonGroup := aJson.Get(I).JsonValue as TJsonObject; + FGroupName := aJson.Pairs[I].JsonString.Value; + aJsonGroup := aJson.Pairs[I].JsonValue as TJsonObject; aJsonActions := aJsonGroup.GetValue('Actions'); aJsonNotActions := aJsonGroup.GetValue('NotActions'); @@ -177,14 +189,14 @@ begin for X := 0 to Pred(aJsonActions.Count) do begin - iAction.add(aJsonActions.Get(X).Value); + iAction.add(aJsonActions.Items[X].Value); end; iNotAction := iAction.&end.notActions; for X := 0 to Pred(aJsonNotActions.Count) do begin - iNotAction.add(aJsonNotActions.Get(X).Value); + iNotAction.add(aJsonNotActions.Items[X].Value); end; end; end; @@ -203,12 +215,12 @@ var begin for I := 0 to Pred(aJson.Count) do begin - FGroupName := aJson.Get(I).JsonString.Value; - aJsonGroup := aJson.Get(I).JsonValue as TJSONObject; + FGroupName := aJson.Pairs[I].JsonString.Value; + aJsonGroup := aJson.Pairs[I].JsonValue as TJSONObject; for J := 0 to Pred(aJsonGroup.Count) do begin - FProviderName := aJsonGroup.Get(J).JsonString.Value; - aJsonProvider := aJsonGroup.Get(I).JsonValue as TJSONObject; + FProviderName := aJsonGroup.Pairs[J].JsonString.Value; + aJsonProvider := aJsonGroup.Pairs[I].JsonValue as TJSONObject; aJsonActions := aJsonProvider.GetValue('actions'); iProviderAction := @@ -223,9 +235,9 @@ begin for K := 0 to Pred(aJsonActions.Count) do begin iProviderAction - .add(aJsonActions.Get(K).JsonString.Value) - .description(aJsonActions.Get(K).JsonValue.GetValue('description')) - .errormsg(aJsonActions.Get(K).JsonValue.GetValue('errormsg')) + .add(aJsonActions.Pairs[K].JsonString.Value) + .description(aJsonActions.Pairs[K].JsonValue.GetValue('description')) + .errormsg(aJsonActions.Pairs[K].JsonValue.GetValue('errormsg')) end; end; end; @@ -242,8 +254,8 @@ var begin for I := 0 to Pred(aJson.Count) do begin - FGroupName := aJson.Get(I).JsonString.Value; - aJsonGroup := aJson.Get(I).JsonValue as TJsonObject; + FGroupName := aJson.Pairs[I].JsonString.Value; + aJsonGroup := aJson.Pairs[I].JsonValue as TJsonObject; aJsonPermission := aJsonGroup.GetValue('permissionGroups'); iPermissionGroup := @@ -254,7 +266,7 @@ begin for X := 0 to Pred(aJsonPermission.Count) do begin - iPermissionGroup.addPermission(aJsonPermission.Get(X).Value); + iPermissionGroup.addPermission(aJsonPermission.Items[X].Value); end; end; end;