mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
dmvcframework 3.2.0-boron
This commit is contained in:
parent
887a065b86
commit
7ce87edb51
@ -167,7 +167,7 @@ end;
|
||||
- New Sample! Server in DLL
|
||||
- Improved! New constants defined in `HTTP_STATUS` to better describe the http status response.
|
||||
- Improved! Now Firebird RQL' SQLGenerator can include primary key in `CreateInsert` if not autogenerated.
|
||||
- New! Added support for `TArray<String>` and `TArray<Integer>` in default JSON serializer (Thank you [Pedro Oliveira](https://github.com/pedrooliveira01))
|
||||
- New! Added support for `TArray<String>`, `TArray<Integer>` and `TArray<Double>` in default JSON serializer (Thank you [Pedro Oliveira](https://github.com/pedrooliveira01))
|
||||
- Improved JWT Standard Compliance! Thanks to [Vinicius Sanchez](https://github.com/viniciussanchez) for his work on [issue #241](https://github.com/danieleteti/delphimvcframework/issues/241)
|
||||
- Improved! DMVCFramework now has 130+ unit tests that checks its functionalities at each build!
|
||||
- New! `StrToJSONObject` function to safely parse a string into a JSON object.
|
||||
@ -207,7 +207,7 @@ end;
|
||||
- ` procedure ResponseAccepted(const HREF: String; const ID: String; const Reason: String = 'Accepted'); virtual;`
|
||||
- `procedure ResponseNoContent(const Reason: String = 'No Content'); virtual;`
|
||||
|
||||
- Added deserializing generic lists support without `MVCListOf` attribute (Thank you to [João Antônio Duarte](https://github.com/joaoduarte19)).
|
||||
- Added de/serializing iterables (e.g. generic lists) support without `MVCListOf` attribute (Thank you to [João Antônio Duarte](https://github.com/joaoduarte19)).
|
||||
|
||||
It is now possible to deserialize a generic class like this:
|
||||
|
||||
|
@ -63,7 +63,7 @@ type
|
||||
constructor Create; virtual;
|
||||
|
||||
function GenerateJsonObject: TJSONObject; virtual; abstract;
|
||||
procedure Load(pJson: TJSONObject); virtual; abstract;
|
||||
procedure Load(pJson: TJSONObject); virtual;
|
||||
|
||||
/// <summary>
|
||||
/// A single security scheme definition, mapping a "name" to the scheme it defines.
|
||||
@ -153,6 +153,11 @@ begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
procedure TSwagSecurityDefinition.Load(pJson: TJSONObject);
|
||||
begin
|
||||
//do nothing
|
||||
end;
|
||||
|
||||
function TSwagSecurityDefinition.ReturnTypeSecurityToString: string;
|
||||
begin
|
||||
Result := c_SwagSecurityDefinitionType[GetTypeSecurity];
|
||||
|
@ -81,7 +81,7 @@ begin
|
||||
end);
|
||||
FMVC.AddController(TPrivateController);
|
||||
FMVC.AddMiddleware(
|
||||
TMVCRoleBasedAuthenticationMiddleware.Create(
|
||||
TMVCRoleBasedAuthMiddleware.Create(
|
||||
TCustomRoleAuth.Create,
|
||||
'/system/users/logged'
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{EDD78707-A0BE-4217-9B4E-919CCEDF5CF6}</ProjectGuid>
|
||||
<ProjectVersion>18.6</ProjectVersion>
|
||||
<ProjectVersion>18.7</ProjectVersion>
|
||||
<FrameworkType>VCL</FrameworkType>
|
||||
<MainSource>custom_exception_handling.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
@ -43,6 +43,11 @@
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='OSX64' and '$(Base)'=='true') or '$(Base_OSX64)'!=''">
|
||||
<Base_OSX64>true</Base_OSX64>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
|
||||
<Base_Win32>true</Base_Win32>
|
||||
<CfgParent>Base</CfgParent>
|
||||
@ -91,6 +96,11 @@
|
||||
<PropertyGroup Condition="'$(Base_Android)'!=''">
|
||||
<DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
|
||||
<EnabledSysJars>android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar</EnabledSysJars>
|
||||
<Android_NotificationIcon24>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png</Android_NotificationIcon24>
|
||||
<Android_NotificationIcon36>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png</Android_NotificationIcon36>
|
||||
<Android_NotificationIcon48>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png</Android_NotificationIcon48>
|
||||
<Android_NotificationIcon72>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png</Android_NotificationIcon72>
|
||||
<Android_NotificationIcon96>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png</Android_NotificationIcon96>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_iOSDevice32)'!=''">
|
||||
<DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;TMSFMXCloudPackPkgDXE11;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
|
||||
@ -107,6 +117,14 @@
|
||||
<PropertyGroup Condition="'$(Base_OSX32)'!=''">
|
||||
<DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXInterBaseDriver;DataSnapFireDAC;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_OSX64)'!=''">
|
||||
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts</VerInfo_Keys>
|
||||
<BT_BuildType>Debug</BT_BuildType>
|
||||
<Base_OSX32>true</Base_OSX32>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
<DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXInterBaseDriver;DataSnapFireDAC;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage);$(DCC_UsePackage)</DCC_UsePackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||
<DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;DataSnapFireDAC;svnui;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;pfmgrPkgDXE11;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;inetdb;TMSCryptoPkgDXE11;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;pfcorePkgDXE11;FixInsight_10_2;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TMSFMXCloudPackPkgDXE11;TeeDB;emshosting;TMSFMXWebGMapsPkgDXE11;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;TMSFMXCloudPackPkgDEDXE11;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;TMSFMXPackPkgDXE11;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;TMSCryptoPkgDEDXE11;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
|
||||
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
||||
@ -259,6 +277,12 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_Colors">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\values</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_DefaultAppIcon">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable</RemoteDir>
|
||||
@ -295,6 +319,36 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon24">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon36">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon48">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon72">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon96">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_SplashImage426">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-small</RemoteDir>
|
||||
@ -319,6 +373,12 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_Strings">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\values</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="DebugSymbols">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
@ -417,6 +477,17 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024x768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1536">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -428,6 +499,39 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1536x2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1668">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1668x2388">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -439,6 +543,61 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048x1536">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048x2732">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2224">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2388x1668">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2732x2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -450,6 +609,116 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768x1024">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1136x640">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1242">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1242x2688">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1334">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1792">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2208">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2436">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2688x1242">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch320">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -483,6 +752,28 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch750">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch828">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
@ -597,6 +888,7 @@
|
||||
<Platform value="iOSSimulator">False</Platform>
|
||||
<Platform value="Linux64">False</Platform>
|
||||
<Platform value="OSX32">False</Platform>
|
||||
<Platform value="OSX64">False</Platform>
|
||||
<Platform value="Win32">True</Platform>
|
||||
<Platform value="Win64">False</Platform>
|
||||
</Platforms>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{7B54055A-5749-4136-9FE2-35FDBEEA874C}</ProjectGuid>
|
||||
<ProjectVersion>18.6</ProjectVersion>
|
||||
<ProjectVersion>18.7</ProjectVersion>
|
||||
<FrameworkType>VCL</FrameworkType>
|
||||
<MainSource>JWTServer.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
@ -91,6 +91,11 @@
|
||||
<BT_BuildType>Debug</BT_BuildType>
|
||||
<AUP_CALL_PHONE>true</AUP_CALL_PHONE>
|
||||
<AUP_ACCESS_FINE_LOCATION>true</AUP_ACCESS_FINE_LOCATION>
|
||||
<Android_NotificationIcon24>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png</Android_NotificationIcon24>
|
||||
<Android_NotificationIcon36>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png</Android_NotificationIcon36>
|
||||
<Android_NotificationIcon48>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png</Android_NotificationIcon48>
|
||||
<Android_NotificationIcon72>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png</Android_NotificationIcon72>
|
||||
<Android_NotificationIcon96>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png</Android_NotificationIcon96>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
||||
@ -265,6 +270,12 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_Colors">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\values</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_DefaultAppIcon">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable</RemoteDir>
|
||||
@ -301,6 +312,36 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon24">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon36">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon48">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon72">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon96">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_SplashImage426">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-small</RemoteDir>
|
||||
@ -325,6 +366,12 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_Strings">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\values</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="DebugSymbols">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
@ -423,6 +470,17 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024x768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1536">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -434,6 +492,39 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1536x2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1668">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1668x2388">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -445,6 +536,61 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048x1536">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048x2732">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2224">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2388x1668">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2732x2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -456,6 +602,116 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768x1024">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1136x640">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1242">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1242x2688">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1334">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1792">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2208">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2436">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2688x1242">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch320">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -489,6 +745,28 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch750">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch828">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{E7317702-64D3-4A65-8734-030F3AE3DBBC}</ProjectGuid>
|
||||
<ProjectVersion>18.6</ProjectVersion>
|
||||
<ProjectVersion>18.7</ProjectVersion>
|
||||
<FrameworkType>VCL</FrameworkType>
|
||||
<MainSource>JWTClient.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
@ -211,6 +211,12 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_Colors">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\values</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_DefaultAppIcon">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable</RemoteDir>
|
||||
@ -247,6 +253,36 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon24">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon36">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon48">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon72">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_NotificationIcon96">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_SplashImage426">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-small</RemoteDir>
|
||||
@ -271,6 +307,12 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_Strings">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\values</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="DebugSymbols">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
@ -390,6 +432,17 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024x768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1536">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -401,6 +454,39 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1536x2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1668">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1668x2388">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -412,6 +498,61 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048x1536">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2048x2732">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2224">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2388x1668">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2732x2048">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -423,6 +564,116 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768x1024">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1136x640">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1242">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1242x2688">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1334">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1792">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2208">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2436">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2688x1242">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch320">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -456,6 +707,28 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch750">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch828">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSDevice64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
|
@ -62,9 +62,9 @@ object MainForm: TMainForm
|
||||
TabOrder = 2
|
||||
object Label1: TLabel
|
||||
AlignWithMargins = True
|
||||
Left = 338
|
||||
Left = 417
|
||||
Top = 4
|
||||
Width = 379
|
||||
Width = 300
|
||||
Height = 73
|
||||
Align = alClient
|
||||
Caption =
|
||||
@ -74,12 +74,13 @@ object MainForm: TMainForm
|
||||
'alidityWindowInSeconds seconds. It is useful to mimic the classi' +
|
||||
'c session cookie with the semplicity of the JWT.'
|
||||
WordWrap = True
|
||||
ExplicitLeft = 338
|
||||
ExplicitWidth = 368
|
||||
ExplicitHeight = 65
|
||||
end
|
||||
object btnGet: TButton
|
||||
AlignWithMargins = True
|
||||
Left = 171
|
||||
Left = 250
|
||||
Top = 4
|
||||
Width = 161
|
||||
Height = 73
|
||||
@ -88,17 +89,31 @@ object MainForm: TMainForm
|
||||
TabOrder = 0
|
||||
WordWrap = True
|
||||
OnClick = btnGetClick
|
||||
ExplicitLeft = 171
|
||||
end
|
||||
object btnLOGIN: TButton
|
||||
AlignWithMargins = True
|
||||
Left = 4
|
||||
Top = 4
|
||||
Width = 161
|
||||
Width = 117
|
||||
Height = 73
|
||||
Align = alLeft
|
||||
Caption = 'Login'
|
||||
Caption = 'Login (Custom headers)'
|
||||
TabOrder = 1
|
||||
WordWrap = True
|
||||
OnClick = btnLOGINClick
|
||||
end
|
||||
object btnLoginWithHeaderBasic: TButton
|
||||
AlignWithMargins = True
|
||||
Left = 127
|
||||
Top = 4
|
||||
Width = 117
|
||||
Height = 73
|
||||
Align = alLeft
|
||||
Caption = 'Login (with Basic Schema)'
|
||||
TabOrder = 2
|
||||
WordWrap = True
|
||||
OnClick = btnLoginWithHeaderBasicClick
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -16,8 +16,10 @@ type
|
||||
btnLOGIN: TButton;
|
||||
Splitter1: TSplitter;
|
||||
Label1: TLabel;
|
||||
btnLoginWithHeaderBasic: TButton;
|
||||
procedure btnGetClick(Sender: TObject);
|
||||
procedure btnLOGINClick(Sender: TObject);
|
||||
procedure btnLoginWithHeaderBasicClick(Sender: TObject);
|
||||
private
|
||||
FJWT: string;
|
||||
procedure SetJWT(const Value: string);
|
||||
@ -33,13 +35,13 @@ implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
|
||||
uses
|
||||
MVCFramework.RESTClient,
|
||||
MVCFramework.Middleware.JWT,
|
||||
MVCFramework.Serializer.JSONDataObjects,
|
||||
MVCFramework.SystemJSONUtils,
|
||||
System.JSON,
|
||||
System.NetEncoding;
|
||||
System.NetEncoding,
|
||||
JsonDataObjects;
|
||||
|
||||
procedure TMainForm.btnGetClick(Sender: TObject);
|
||||
var
|
||||
@ -53,7 +55,9 @@ begin
|
||||
try
|
||||
lClient.ReadTimeOut(0);
|
||||
if not FJWT.IsEmpty then
|
||||
begin
|
||||
lClient.RequestHeaders.Values[TMVCJWTDefaults.AUTHORIZATION_HEADER] := 'Bearer ' + FJWT;
|
||||
end;
|
||||
lQueryStringParams := TStringList.Create;
|
||||
try
|
||||
lQueryStringParams.Values['firstname'] := 'Daniele';
|
||||
@ -61,7 +65,7 @@ begin
|
||||
lResp := lClient.doGET('/admin/role1', [], lQueryStringParams);
|
||||
|
||||
if lResp.HasError then
|
||||
ShowMessage(lResp.Error.ExceptionMessage);
|
||||
ShowMessage(lResp.Error.Status + sLineBreak + lResp.Error.ExceptionMessage);
|
||||
|
||||
finally
|
||||
lQueryStringParams.Free;
|
||||
@ -90,13 +94,33 @@ begin
|
||||
lClient := TRESTClient.Create('localhost', 8080);
|
||||
try
|
||||
lClient.ReadTimeOut(0);
|
||||
lClient
|
||||
.Header(TMVCJWTDefaults.USERNAME_HEADER, 'user1')
|
||||
.Header(TMVCJWTDefaults.PASSWORD_HEADER, 'user1');
|
||||
lRest := lClient.doPOST('/login', []);
|
||||
lJSON := TSystemJSON.StringAsJSONObject(lRest.BodyAsString);
|
||||
lClient.Header(TMVCJWTDefaults.USERNAME_HEADER, 'user1').Header(TMVCJWTDefaults.PASSWORD_HEADER, 'user1');
|
||||
lRest := lClient.doGET('/login', []); { any HTTP verbs is OK }
|
||||
lJSON := StrToJSONObject(lRest.BodyAsString);
|
||||
try
|
||||
JWT := lJSON.GetValue('token').Value;
|
||||
JWT := lJSON.S['token'];
|
||||
finally
|
||||
lJSON.Free;
|
||||
end;
|
||||
finally
|
||||
lClient.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnLoginWithHeaderBasicClick(Sender: TObject);
|
||||
var
|
||||
lClient: TRESTClient;
|
||||
lRest: IRESTResponse;
|
||||
lJSON: TJSONObject;
|
||||
begin
|
||||
lClient := TRESTClient.Create('localhost', 8080);
|
||||
try
|
||||
lClient.ReadTimeOut(0);
|
||||
lClient.Authentication('user1', 'user1');
|
||||
lRest := lClient.doPOST('/login', []);
|
||||
lJSON := StrToJSONObject(lRest.BodyAsString);
|
||||
try
|
||||
JWT := lJSON.S['token'];
|
||||
finally
|
||||
lJSON.Free;
|
||||
end;
|
||||
|
@ -58,8 +58,22 @@ type
|
||||
property RecordAlias: TNullableRecordAlias read fRecordAlias write fRecordAlias;
|
||||
end;
|
||||
|
||||
TArrayTest = class
|
||||
private
|
||||
fStrings: TArray<String>;
|
||||
fIntegers: TArray<Integer>;
|
||||
fDoubles: TArray<Double>;
|
||||
public
|
||||
constructor Create;
|
||||
property Integers: TArray<Integer> read fIntegers write fIntegers;
|
||||
property Strings: TArray<String> read fStrings write fStrings;
|
||||
property Doubles: TArray<Double> read fDoubles write fDoubles;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.SysUtils, System.Math;
|
||||
|
||||
{ TSysUser }
|
||||
|
||||
@ -80,4 +94,28 @@ begin
|
||||
FUserName := Value;
|
||||
end;
|
||||
|
||||
{ TArrayTest }
|
||||
|
||||
constructor TArrayTest.Create;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
inherited;
|
||||
SetLength(fStrings, 5);
|
||||
for I := 0 to Length(fStrings) - 1 do
|
||||
begin
|
||||
fStrings[I] := 'Value ' + I.ToString;
|
||||
end;
|
||||
SetLength(fIntegers, 5);
|
||||
for I := 0 to Length(fIntegers) - 1 do
|
||||
begin
|
||||
fIntegers[I] := I;
|
||||
end;
|
||||
SetLength(fDoubles, 5);
|
||||
for I := 0 to Length(fDoubles) - 1 do
|
||||
begin
|
||||
fDoubles[I] := Power(I, I) * 1.1;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -163,6 +163,10 @@ type
|
||||
[MVCPath('/customserializationtype')]
|
||||
procedure GetCustomSerializationType;
|
||||
|
||||
[MVCHTTPMethod([httpGET])]
|
||||
[MVCPath('/simplearray')]
|
||||
procedure GetSimpleArrays;
|
||||
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -587,6 +591,11 @@ begin
|
||||
Render<TPerson>(List);
|
||||
end;
|
||||
|
||||
procedure TRenderSampleController.GetSimpleArrays;
|
||||
begin
|
||||
Render(TArrayTest.Create);
|
||||
end;
|
||||
|
||||
procedure TRenderSampleController.GetPeopleAsCSV;
|
||||
begin
|
||||
ResponseStream.AppendLine('first_name;last_name;age');
|
||||
|
@ -99,10 +99,10 @@ begin
|
||||
DMVC.SetViewEngine(TMVCMustacheViewEngine);
|
||||
|
||||
// Register a custom serializer for TUserRoles (is compatible only with the default serializer)
|
||||
DMVC
|
||||
.Serializers
|
||||
.Items[TMVCMediaType.APPLICATION_JSON]
|
||||
.RegisterTypeSerializer(TypeInfo(TUserRoles), TUserRolesSerializer.Create);
|
||||
// DMVC
|
||||
// .Serializers
|
||||
// .Items[TMVCMediaType.APPLICATION_JSON]
|
||||
// .RegisterTypeSerializer(TypeInfo(TUserRoles), TUserRolesSerializer.Create);
|
||||
|
||||
// You can check how this custom type serializer works
|
||||
// calling http://localhost:8080/customserializationtype
|
||||
|
@ -11,6 +11,7 @@ uses
|
||||
MVCFramework.Middleware.Authentication.RoleBasedAuthHandler;
|
||||
|
||||
type
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
TAddress = class
|
||||
private
|
||||
@ -33,6 +34,9 @@ type
|
||||
property Number: string read FNumber write FNumber;
|
||||
end;
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
TPhones = class(TObjectList<TPhone>)
|
||||
end;
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
TPerson = class
|
||||
@ -42,7 +46,7 @@ type
|
||||
FCountry: string;
|
||||
FCode: Integer;
|
||||
FAddress: TAddress;
|
||||
FPhones: TObjectList<TPhone>;
|
||||
FPhones: TPhones;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@ -55,27 +59,29 @@ type
|
||||
property Age: Integer read FAge write FAge;
|
||||
[MVCSwagJsonSchemaField('country', 'Nationality of the person', True, False)]
|
||||
property Country: string read FCountry write FCountry;
|
||||
// [MVCSwagJsonSchemaField(stObject, 'address', 'Address')]
|
||||
property Address: TAddress read FAddress write FAddress;
|
||||
// [MVCSwagJsonSchemaField(stArray, 'phones', 'Contact phones of the person', False, True)]
|
||||
property Phones: TObjectList<TPhone> read FPhones write FPhones;
|
||||
property Phones: TPhones read FPhones write FPhones;
|
||||
end;
|
||||
|
||||
[MVCPath('/person')]
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
TPeople = class(TObjectList<TPerson>)
|
||||
end;
|
||||
|
||||
[MVCPath('/people')]
|
||||
[MVCSwagAuthentication(atBasic)]
|
||||
TMyController2 = class(TMVCController)
|
||||
public
|
||||
[MVCPath('')]
|
||||
[MVCHTTPMethod([httpGET])]
|
||||
[MVCSwagSummary('Person', 'List all persons')]
|
||||
[MVCSwagSummary('People', 'List all persons', 'getPeople')]
|
||||
[MVCSwagParam(plQuery, 'per_page', 'Items per page', ptInteger)]
|
||||
[MVCSwagResponses(200, 'Success', TPerson, True)]
|
||||
[MVCSwagResponses(500, 'Internal Server Error')]
|
||||
procedure GetAllPerson;
|
||||
procedure GetAllPeople;
|
||||
|
||||
[MVCPath('/($Id)')]
|
||||
[MVCHTTPMethod([httpGET])]
|
||||
[MVCSwagSummary('Person', 'List Persons by Id', '66e83aa7-d170-44a7-a502-8f25ddd2a18a')]
|
||||
[MVCSwagSummary('People', 'List Persons by Id', 'getPersonById')]
|
||||
[MVCSwagParam(plPath, 'Id', 'Person id', ptInteger)]
|
||||
[MVCSwagResponses(200, 'Success', TPerson)]
|
||||
[MVCSwagResponses(500, 'Internal Server Error')]
|
||||
@ -83,7 +89,7 @@ type
|
||||
|
||||
[MVCPath('')]
|
||||
[MVCHTTPMethod([httpPOST])]
|
||||
[MVCSwagSummary('Person', 'Insert Person')]
|
||||
[MVCSwagSummary('People', 'Insert Person', 'createPerson')]
|
||||
[MVCSwagParam(plBody, 'entity', 'Person object', TPerson)]
|
||||
[MVCSwagResponses(201, 'Created')]
|
||||
[MVCSwagResponses(401, 'Requires Authentication')]
|
||||
@ -94,12 +100,11 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
MVCFramework.Controllers.Register;
|
||||
uses MVCFramework.Controllers.Register;
|
||||
|
||||
{ TMyController2 }
|
||||
|
||||
procedure TMyController2.GetAllPerson;
|
||||
procedure TMyController2.GetAllPeople;
|
||||
var
|
||||
LPerson: TPerson;
|
||||
LPersons: TObjectList<TPerson>;
|
||||
@ -142,7 +147,7 @@ constructor TPerson.Create;
|
||||
begin
|
||||
inherited;
|
||||
FAddress := TAddress.Create;
|
||||
FPhones := TObjectList<TPhone>.Create;
|
||||
FPhones := TPhones.Create;
|
||||
end;
|
||||
|
||||
destructor TPerson.Destroy;
|
||||
|
@ -47,75 +47,54 @@ type
|
||||
FListSep: Char;
|
||||
public
|
||||
constructor Create(const aRole: string); overload;
|
||||
constructor Create(const aRole: string;
|
||||
const aRoleEval: MVCRoleEval); overload;
|
||||
constructor Create(const aRole: string; const aRoleEval: MVCRoleEval;
|
||||
const aListSep: Char); overload;
|
||||
constructor Create(const aRole: string; const aRoleEval: MVCRoleEval); overload;
|
||||
constructor Create(const aRole: string; const aRoleEval: MVCRoleEval; const aListSep: Char); overload;
|
||||
function GetRoles: TArray<string>;
|
||||
property RoleEval: MVCRoleEval read FRoleEval;
|
||||
end;
|
||||
|
||||
IMVCRoleBasedAuthenticationHandler = interface(IMVCAuthenticationHandler)
|
||||
['{07ABEF93-DBCC-4C55-BD39-BD1F48490A73}']
|
||||
// procedure OnAuthorization(const AContext: TWebContext;
|
||||
// const AUserRoles: TList<string>;
|
||||
// const AControllerQualifiedClassName: string; const AActionName: string;
|
||||
// var AIsAuthorized: Boolean);
|
||||
// procedure OnAuthorization(const AContext: TWebContext;
|
||||
// const AUserRoles: TList<string>;
|
||||
// const AControllerQualifiedClassName: string; const AActionName: string;
|
||||
// var AIsAuthorized: Boolean);
|
||||
end;
|
||||
|
||||
TRoleBasedAuthHandler = class(TInterfacedObject, IMVCAuthenticationHandler,
|
||||
IMVCRoleBasedAuthenticationHandler)
|
||||
TRoleBasedAuthHandler = class(TInterfacedObject, IMVCAuthenticationHandler, IMVCRoleBasedAuthenticationHandler)
|
||||
private
|
||||
FRttiContext: TRttiContext;
|
||||
|
||||
function TryGetAttributes<TTypeOfAttribute: TCustomAttribute>
|
||||
(const aAttributes: TArray<TCustomAttribute>;
|
||||
function TryGetAttributes<TTypeOfAttribute: TCustomAttribute>(const aAttributes: TArray<TCustomAttribute>;
|
||||
out aListOfAttributes: TArray<TTypeOfAttribute>): Boolean;
|
||||
function CheckUserRoles(const AContext: TWebContext;
|
||||
const AUserRoles: TList<string>;
|
||||
function CheckUserRoles(const AContext: TWebContext; const AUserRoles: TList<string>;
|
||||
const aRoleAttributes: TArray<MVCRequiresRoleAttribute>): Boolean;
|
||||
|
||||
function ResolveRole(const AContext: TWebContext;
|
||||
const aRole: string): string;
|
||||
function ResolveRole(const AContext: TWebContext; const aRole: string): string;
|
||||
function CreateParameterNameList(const aTemplate: string): TList<string>;
|
||||
public
|
||||
procedure OnRequest(const AContext: TWebContext; const ControllerQualifiedClassName: string;
|
||||
const ActionName: string; var AuthenticationRequired: Boolean);
|
||||
|
||||
procedure OnAuthentication(const AContext: TWebContext; const UserName: string; const Password: string;
|
||||
UserRoles: TList<string>; var IsValid: Boolean;
|
||||
const SessionData: TDictionary<string, string>); virtual; abstract;
|
||||
|
||||
procedure OnAuthorization(
|
||||
const AContext: TWebContext;
|
||||
UserRoles: TList<string>;
|
||||
const ControllerQualifiedClassName: string;
|
||||
const ActionName: string;
|
||||
var IsAuthorized: Boolean); overload;
|
||||
|
||||
// procedure OnAuthorization(const AContext: TWebContext;
|
||||
// const AUserRoles: TList<string>;
|
||||
// const AControllerQualifiedClassName: string; const AActionName: string;
|
||||
// var AIsAuthorized: Boolean); overload;
|
||||
UserRoles: TList<string>; var IsValid: Boolean; const SessionData: TDictionary<string, string>); virtual;
|
||||
abstract;
|
||||
|
||||
procedure OnAuthorization(const AContext: TWebContext; UserRoles: TList<string>;
|
||||
const ControllerQualifiedClassName: string; const ActionName: string; var IsAuthorized: Boolean); overload;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
TMVCRoleBasedAuthenticationMiddleware = class
|
||||
(TMVCCustomAuthenticationMiddleware, IMVCMiddleware)
|
||||
TMVCRoleBasedAuthMiddleware = class(TMVCCustomAuthenticationMiddleware, IMVCMiddleware)
|
||||
private
|
||||
FAuthenticationHandler: IMVCRoleBasedAuthenticationHandler;
|
||||
|
||||
procedure DoRoleBasedBeforeControllerAction(
|
||||
const AContext: TWebContext;
|
||||
const aHandler: IMVCRoleBasedAuthenticationHandler;
|
||||
const AControllerQualifiedClassName: string; const AActionName: string;
|
||||
var AHandled: Boolean);
|
||||
fAuthenticationHandler: IMVCRoleBasedAuthenticationHandler;
|
||||
procedure DoRoleBasedBeforeControllerAction(const AContext: TWebContext;
|
||||
const aHandler: IMVCRoleBasedAuthenticationHandler; const AControllerQualifiedClassName: string;
|
||||
const AActionName: string; var AHandled: Boolean);
|
||||
protected
|
||||
procedure OnBeforeControllerAction(AContext: TWebContext;
|
||||
const AControllerQualifiedClassName: string; const AActionName: string;
|
||||
var AHandled: Boolean);
|
||||
procedure OnBeforeControllerAction(AContext: TWebContext; const AControllerQualifiedClassName: string;
|
||||
const AActionName: string; var AHandled: Boolean);
|
||||
public
|
||||
constructor Create(const AAuthenticationHandler: IMVCAuthenticationHandler;
|
||||
const ALoginUrl: string = '/system/users/logged'); override;
|
||||
@ -134,14 +113,12 @@ begin
|
||||
Self.Create(aRole, MVCRoleEval.reAND, DefaultListSeparator);
|
||||
end;
|
||||
|
||||
constructor MVCRequiresRoleAttribute.Create(const aRole: string;
|
||||
const aRoleEval: MVCRoleEval);
|
||||
constructor MVCRequiresRoleAttribute.Create(const aRole: string; const aRoleEval: MVCRoleEval);
|
||||
begin
|
||||
Self.Create(aRole, aRoleEval, DefaultListSeparator);
|
||||
end;
|
||||
|
||||
constructor MVCRequiresRoleAttribute.Create(const aRole: string;
|
||||
const aRoleEval: MVCRoleEval; const aListSep: Char);
|
||||
constructor MVCRequiresRoleAttribute.Create(const aRole: string; const aRoleEval: MVCRoleEval; const aListSep: Char);
|
||||
begin
|
||||
inherited Create;
|
||||
FRole := aRole;
|
||||
@ -156,8 +133,7 @@ end;
|
||||
|
||||
{ TRoleBasedAuthHandler }
|
||||
|
||||
function TRoleBasedAuthHandler.CheckUserRoles(const AContext: TWebContext;
|
||||
const AUserRoles: TList<System.string>;
|
||||
function TRoleBasedAuthHandler.CheckUserRoles(const AContext: TWebContext; const AUserRoles: TList<System.string>;
|
||||
const aRoleAttributes: TArray<MVCRequiresRoleAttribute>): Boolean;
|
||||
var
|
||||
vAttribute: MVCRequiresRoleAttribute;
|
||||
@ -199,8 +175,7 @@ begin
|
||||
FRttiContext := TRttiContext.Create;
|
||||
end;
|
||||
|
||||
function TRoleBasedAuthHandler.CreateParameterNameList(const aTemplate: string)
|
||||
: TList<string>;
|
||||
function TRoleBasedAuthHandler.CreateParameterNameList(const aTemplate: string): TList<string>;
|
||||
const
|
||||
MatchPattern = '\(\$([A-Za-z0-9\_]+)\)'; // Matches ($<name>) placeholders
|
||||
var
|
||||
@ -211,8 +186,7 @@ var
|
||||
begin
|
||||
Result := TList<string>.Create;
|
||||
try
|
||||
Matches := TRegEx.Matches(aTemplate, MatchPattern,
|
||||
[roIgnoreCase, roCompiled, roSingleLine]);
|
||||
Matches := TRegEx.Matches(aTemplate, MatchPattern, [roIgnoreCase, roCompiled, roSingleLine]);
|
||||
for M in Matches do
|
||||
for I := 0 to M.Groups.Count - 1 do
|
||||
begin
|
||||
@ -235,12 +209,8 @@ begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TRoleBasedAuthHandler.OnAuthorization(
|
||||
const AContext: TWebContext;
|
||||
UserRoles: TList<string>;
|
||||
const ControllerQualifiedClassName: string;
|
||||
const ActionName: string;
|
||||
var IsAuthorized: Boolean);
|
||||
procedure TRoleBasedAuthHandler.OnAuthorization(const AContext: TWebContext; UserRoles: TList<string>;
|
||||
const ControllerQualifiedClassName: string; const ActionName: string; var IsAuthorized: Boolean);
|
||||
var
|
||||
vRttiType: TRttiType;
|
||||
vAttributes: TArray<MVCRequiresRoleAttribute>;
|
||||
@ -251,8 +221,7 @@ begin
|
||||
|
||||
// Check all Role requirements on the controller level
|
||||
vRttiType := FRttiContext.FindType(ControllerQualifiedClassName);
|
||||
if TryGetAttributes<MVCRequiresRoleAttribute>(vRttiType.GetAttributes,
|
||||
vAttributes) then
|
||||
if TryGetAttributes<MVCRequiresRoleAttribute>(vRttiType.GetAttributes, vAttributes) then
|
||||
if not CheckUserRoles(AContext, UserRoles, vAttributes) then
|
||||
begin
|
||||
IsAuthorized := False;
|
||||
@ -263,8 +232,7 @@ begin
|
||||
// we have successfully cleared these.
|
||||
// Verify all roles on the Action.
|
||||
vRttiMethod := vRttiType.GetMethod(ActionName);
|
||||
if TryGetAttributes<MVCRequiresRoleAttribute>(vRttiMethod.GetAttributes,
|
||||
vAttributes) then
|
||||
if TryGetAttributes<MVCRequiresRoleAttribute>(vRttiMethod.GetAttributes, vAttributes) then
|
||||
if not CheckUserRoles(AContext, UserRoles, vAttributes) then
|
||||
begin
|
||||
IsAuthorized := False;
|
||||
@ -273,7 +241,7 @@ begin
|
||||
end;
|
||||
|
||||
procedure TRoleBasedAuthHandler.OnRequest(const AContext: TWebContext; const ControllerQualifiedClassName: string;
|
||||
const ActionName: string; var AuthenticationRequired: Boolean);
|
||||
const ActionName: string; var AuthenticationRequired: Boolean);
|
||||
var
|
||||
vRttiType: TRttiType;
|
||||
vAttributes: TArray<MVCRequiresAuthenticationAttribute>;
|
||||
@ -282,19 +250,16 @@ begin
|
||||
vRttiType := FRttiContext.FindType(ControllerQualifiedClassName);
|
||||
|
||||
// Check class and Actions if they have role definitions.
|
||||
AuthenticationRequired := TryGetAttributes<MVCRequiresAuthenticationAttribute>
|
||||
(vRttiType.GetAttributes, vAttributes);
|
||||
AuthenticationRequired := TryGetAttributes<MVCRequiresAuthenticationAttribute>(vRttiType.GetAttributes, vAttributes);
|
||||
if not AuthenticationRequired then
|
||||
begin
|
||||
vRttiMethod := vRttiType.GetMethod(ActionName);
|
||||
AuthenticationRequired :=
|
||||
TryGetAttributes<MVCRequiresAuthenticationAttribute>
|
||||
(vRttiMethod.GetAttributes, vAttributes);
|
||||
AuthenticationRequired := TryGetAttributes<MVCRequiresAuthenticationAttribute>(vRttiMethod.GetAttributes,
|
||||
vAttributes);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TRoleBasedAuthHandler.ResolveRole(const AContext: TWebContext;
|
||||
const aRole: string): string;
|
||||
function TRoleBasedAuthHandler.ResolveRole(const AContext: TWebContext; const aRole: string): string;
|
||||
var
|
||||
vPlaceholders: TList<string>;
|
||||
vPlaceholder: string;
|
||||
@ -310,15 +275,14 @@ begin
|
||||
Exit;
|
||||
|
||||
for vPlaceholder in vPlaceholders do
|
||||
Result := Result.Replace(Format('($%s)', [vPlaceholder]),
|
||||
AContext.ParamsTable.Items[vPlaceholder], [rfReplaceAll]);
|
||||
Result := Result.Replace(Format('($%s)', [vPlaceholder]), AContext.ParamsTable.Items[vPlaceholder],
|
||||
[rfReplaceAll]);
|
||||
finally
|
||||
vPlaceholders.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TRoleBasedAuthHandler.TryGetAttributes<TTypeOfAttribute>
|
||||
(const aAttributes: TArray<TCustomAttribute>;
|
||||
function TRoleBasedAuthHandler.TryGetAttributes<TTypeOfAttribute>(const aAttributes: TArray<TCustomAttribute>;
|
||||
out aListOfAttributes: TArray<TTypeOfAttribute>): Boolean;
|
||||
var
|
||||
vAttribute: TCustomAttribute;
|
||||
@ -342,23 +306,18 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TMVCRoleBasedAuthenticationMiddleware }
|
||||
{ TMVCRoleBasedAuthMiddleware }
|
||||
|
||||
constructor TMVCRoleBasedAuthenticationMiddleware.Create
|
||||
(const AAuthenticationHandler: IMVCAuthenticationHandler;
|
||||
constructor TMVCRoleBasedAuthMiddleware.Create(const AAuthenticationHandler: IMVCAuthenticationHandler;
|
||||
const ALoginUrl: string);
|
||||
begin
|
||||
inherited Create(AAuthenticationHandler, ALoginUrl);
|
||||
Supports(AAuthenticationHandler, IMVCRoleBasedAuthenticationHandler,
|
||||
FAuthenticationHandler);
|
||||
Supports(AAuthenticationHandler, IMVCRoleBasedAuthenticationHandler, fAuthenticationHandler);
|
||||
end;
|
||||
|
||||
procedure TMVCRoleBasedAuthenticationMiddleware.
|
||||
DoRoleBasedBeforeControllerAction(
|
||||
const AContext: TWebContext;
|
||||
const aHandler: IMVCRoleBasedAuthenticationHandler;
|
||||
const AControllerQualifiedClassName: string; const AActionName: string;
|
||||
var AHandled: Boolean);
|
||||
procedure TMVCRoleBasedAuthMiddleware.DoRoleBasedBeforeControllerAction(const AContext: TWebContext;
|
||||
const aHandler: IMVCRoleBasedAuthenticationHandler; const AControllerQualifiedClassName: string;
|
||||
const AActionName: string; var AHandled: Boolean);
|
||||
var
|
||||
IsValid: Boolean;
|
||||
IsAuthorized: Boolean;
|
||||
@ -366,7 +325,6 @@ var
|
||||
begin
|
||||
// This procedure is a basic copy of the inherited OnBeforeControllerAction procedure.
|
||||
// Extention is by enabling the Authorization based on the context the call is being performed.
|
||||
|
||||
aHandler.OnRequest(nil, AControllerQualifiedClassName, AActionName, AuthRequired);
|
||||
if not AuthRequired then
|
||||
begin
|
||||
@ -388,31 +346,40 @@ begin
|
||||
// Modification here from:
|
||||
// FAuthenticationHandler.OnAuthorization(AContext.LoggedUser.Roles, AControllerQualifiedClassName, AActionName, IsAuthorized);
|
||||
// to:
|
||||
aHandler.OnAuthorization(AContext, AContext.LoggedUser.Roles,
|
||||
AControllerQualifiedClassName, AActionName, IsAuthorized);
|
||||
aHandler.OnAuthorization(AContext, AContext.LoggedUser.Roles, AControllerQualifiedClassName, AActionName,
|
||||
IsAuthorized);
|
||||
// Modification end
|
||||
|
||||
if IsAuthorized then
|
||||
AHandled := False
|
||||
begin
|
||||
AHandled := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if IsValid then
|
||||
begin
|
||||
SendResponse(AContext, AHandled, HTTP_STATUS.Forbidden)
|
||||
end
|
||||
else
|
||||
begin
|
||||
SendResponse(AContext, AHandled, HTTP_STATUS.Unauthorized);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMVCRoleBasedAuthenticationMiddleware.OnBeforeControllerAction
|
||||
(AContext: TWebContext; const AControllerQualifiedClassName,
|
||||
AActionName: string; var AHandled: Boolean);
|
||||
procedure TMVCRoleBasedAuthMiddleware.OnBeforeControllerAction(AContext: TWebContext;
|
||||
const AControllerQualifiedClassName, AActionName: string; var AHandled: Boolean);
|
||||
begin
|
||||
if Assigned(FAuthenticationHandler) then
|
||||
DoRoleBasedBeforeControllerAction(AContext, FAuthenticationHandler,
|
||||
AControllerQualifiedClassName, AActionName, AHandled)
|
||||
if Assigned(fAuthenticationHandler) then
|
||||
begin
|
||||
DoRoleBasedBeforeControllerAction(AContext, fAuthenticationHandler, AControllerQualifiedClassName,
|
||||
AActionName, AHandled)
|
||||
end
|
||||
else
|
||||
inherited OnBeforeControllerAction(AContext, AControllerQualifiedClassName,
|
||||
AActionName, AHandled);
|
||||
begin
|
||||
inherited OnBeforeControllerAction(AContext, AControllerQualifiedClassName, AActionName, AHandled);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
@ -52,8 +52,7 @@ type
|
||||
procedure InternalRender(AContent: string; AContext: TWebContext);
|
||||
public
|
||||
constructor Create(const AEngine: TMVCEngine; const ASwaggerInfo: TMVCSwaggerInfo;
|
||||
const ASwaggerDocumentationURL: string = '/swagger.json';
|
||||
const AJWTDescription: string = JWT_DEFAULT_DESCRIPTION;
|
||||
const ASwaggerDocumentationURL: string = '/swagger.json'; const AJWTDescription: string = JWT_DEFAULT_DESCRIPTION;
|
||||
const AEnableBasicAuthentication: Boolean = False);
|
||||
destructor Destroy; override;
|
||||
procedure OnBeforeRouting(AContext: TWebContext; var AHandled: Boolean);
|
||||
@ -76,7 +75,7 @@ uses
|
||||
MVCFramework.Middleware.JWT,
|
||||
Swag.Doc.Path.Operation.RequestParameter,
|
||||
Swag.Doc.SecurityDefinitionApiKey,
|
||||
Swag.Doc.SecurityDefinitionBasic;
|
||||
Swag.Doc.SecurityDefinitionBasic, Swag.Doc.Definition;
|
||||
|
||||
{ TMVCSwaggerMiddleware }
|
||||
|
||||
@ -176,10 +175,10 @@ begin
|
||||
begin
|
||||
LSwagPathOp := TSwagPathOperation.Create;
|
||||
TMVCSwagger.FillOperationSummary(LSwagPathOp, LMethod);
|
||||
|
||||
if TMVCSwagger.MethodRequiresAuthentication(LMethod, LObjType, LAuthTypeName) then
|
||||
begin
|
||||
LSwagPathOp.Security.Add(LAuthTypeName);
|
||||
|
||||
end;
|
||||
LSwagPathOp.Parameters.AddRange(TMVCSwagger.GetParamsFromMethod(LSwagPath.Uri, LMethod));
|
||||
LSwagPathOp.Operation := TMVCSwagger.MVCHttpMethodToSwagPathOperation(I);
|
||||
LSwagPath.Operations.Add(LSwagPathOp);
|
||||
|
@ -392,6 +392,8 @@ begin
|
||||
AJsonObject.A[AName].Add(AValue.GetArrayElement(I).AsInteger);
|
||||
tkInt64:
|
||||
AJsonObject.A[AName].Add(AValue.GetArrayElement(I).AsInt64);
|
||||
tkFloat:
|
||||
AJsonObject.A[AName].Add(AValue.GetArrayElement(I).AsExtended);
|
||||
else
|
||||
raise EMVCSerializationException.CreateFmt
|
||||
('Cannot serialize property or field "%s" of TypeKind tkArray or tkDynArray.', [AName]);
|
||||
|
@ -33,19 +33,20 @@ uses
|
||||
Json.Schema,
|
||||
System.Rtti,
|
||||
Swag.Common.Types,
|
||||
System.SysUtils,
|
||||
MVCFramework.Commons,
|
||||
Swag.Doc.Path.Operation.RequestParameter,
|
||||
Swag.Doc.Path.Operation,
|
||||
Swag.Doc.Path,
|
||||
System.JSON,
|
||||
System.Json,
|
||||
Json.Schema.Field,
|
||||
Json.Schema.Field.Objects;
|
||||
Json.Schema.Field.Objects, Swag.Doc.Definition;
|
||||
|
||||
type
|
||||
TMVCSwagParamLocation = (plNotDefined, plQuery, plHeader, plPath, plFormData, plBody);
|
||||
TMVCSwagParamType = (ptNotDefined, ptString, ptNumber, ptInteger, ptBoolean, ptArray, ptFile);
|
||||
TMVCSwagSchemaType = (stUnknown, stInteger, stInt64, stNumber, stDateTime, stDate, stTime,
|
||||
stEnumeration, stBoolean, stObject, stArray, stString, stChar, stGuid);
|
||||
TMVCSwagSchemaType = (stUnknown, stInteger, stInt64, stNumber, stDateTime, stDate, stTime, stEnumeration, stBoolean,
|
||||
stObject, stArray, stString, stChar, stGuid);
|
||||
TMVCSwagAuthenticationType = (atBasic, atJsonWebToken);
|
||||
|
||||
/// <summary>
|
||||
@ -69,20 +70,21 @@ type
|
||||
/// </summary>
|
||||
MVCSwagSummaryAttribute = class(TCustomAttribute)
|
||||
private
|
||||
FTags: string;
|
||||
FDeprecated: Boolean;
|
||||
FDescription: string;
|
||||
FOperationID: string;
|
||||
fTags: string;
|
||||
fDeprecated: Boolean;
|
||||
fDescription: string;
|
||||
fOperationID: string;
|
||||
public
|
||||
constructor Create(const ATags, ADescription: string; const APathId: string = ''; ADeprecated: Boolean = False);
|
||||
constructor Create(const ATags, ADescription: string; const AOperationId: string = '';
|
||||
ADeprecated: Boolean = False);
|
||||
function GetTags: TArray<string>;
|
||||
property Tags: string read FTags;
|
||||
property Description: string read FDescription;
|
||||
property OperationID: string read FOperationID;
|
||||
property Deprecated: Boolean read FDeprecated;
|
||||
property Tags: string read fTags;
|
||||
property Description: string read fDescription;
|
||||
property OperationID: string read fOperationID;
|
||||
property Deprecated: Boolean read fDeprecated;
|
||||
end;
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Specifies your controller authentication type
|
||||
/// </summary>
|
||||
MVCSwagAuthenticationAttribute = class(TCustomAttribute)
|
||||
@ -98,30 +100,23 @@ type
|
||||
/// </summary>
|
||||
MVCSwagResponsesAttribute = class(TCustomAttribute)
|
||||
private
|
||||
FStatusCode: Integer;
|
||||
FDescription: string;
|
||||
FJsonSchema: string;
|
||||
FJsonSchemaClass: TClass;
|
||||
FIsArray: Boolean;
|
||||
fStatusCode: Integer;
|
||||
fDescription: string;
|
||||
fJsonSchema: string;
|
||||
fJsonSchemaClass: TClass;
|
||||
fIsArray: Boolean;
|
||||
public
|
||||
constructor Create(
|
||||
const AStatusCode: Integer;
|
||||
const ADescription: string;
|
||||
const AJsonSchema: string = ''
|
||||
); overload;
|
||||
constructor Create(const AStatusCode: Integer; const ADescription: string; const AJsonSchema: string = '');
|
||||
overload;
|
||||
|
||||
constructor Create(
|
||||
const AStatusCode: Integer;
|
||||
const ADescription: string;
|
||||
const AJsonSchemaClass: TClass;
|
||||
const AIsArray: Boolean = False
|
||||
); overload;
|
||||
constructor Create(const AStatusCode: Integer; const ADescription: string; const AJsonSchemaClass: TClass;
|
||||
const AIsArray: Boolean = False); overload;
|
||||
|
||||
property StatusCode: Integer read FStatusCode;
|
||||
property Description: string read FDescription;
|
||||
property JsonSchema: string read FJsonSchema;
|
||||
property JsonSchemaClass: TClass read FJsonSchemaClass;
|
||||
property IsArray: Boolean read FIsArray;
|
||||
property StatusCode: Integer read fStatusCode;
|
||||
property Description: string read fDescription;
|
||||
property JsonSchema: string read fJsonSchema;
|
||||
property JsonSchemaClass: TClass read fJsonSchemaClass;
|
||||
property IsArray: Boolean read fIsArray;
|
||||
end;
|
||||
|
||||
/// <summary>
|
||||
@ -129,68 +124,51 @@ type
|
||||
/// </summary>
|
||||
MVCSwagParamAttribute = class(TCustomAttribute)
|
||||
private
|
||||
FParamLocation: TMVCSwagParamLocation;
|
||||
FParamName: string;
|
||||
FParamDescription: string;
|
||||
FParamType: TMVCSwagParamType;
|
||||
FRequired: Boolean;
|
||||
FJsonSchema: string;
|
||||
FJsonSchemaClass: TClass;
|
||||
fParamLocation: TMVCSwagParamLocation;
|
||||
fParamName: string;
|
||||
fParamDescription: string;
|
||||
fParamType: TMVCSwagParamType;
|
||||
fRequired: Boolean;
|
||||
fJsonSchema: string;
|
||||
fJsonSchemaClass: TClass;
|
||||
public
|
||||
constructor Create(
|
||||
const AParamLocation: TMVCSwagParamLocation;
|
||||
const AParamName: string;
|
||||
const AParamDescription: string;
|
||||
const AParamType: TMVCSwagParamType;
|
||||
const ARequired: Boolean = True;
|
||||
constructor Create(const AParamLocation: TMVCSwagParamLocation; const AParamName: string;
|
||||
const AParamDescription: string; const AParamType: TMVCSwagParamType; const ARequired: Boolean = True;
|
||||
const AJsonSchema: string = ''); overload;
|
||||
constructor Create(
|
||||
const AParamLocation: TMVCSwagParamLocation;
|
||||
const AParamName: string;
|
||||
const AParamDescription: string;
|
||||
const AJsonSchemaClass: TClass;
|
||||
const AParamType: TMVCSwagParamType = ptNotDefined;
|
||||
const ARequired: Boolean = True); overload;
|
||||
constructor Create(const AParamLocation: TMVCSwagParamLocation; const AParamName: string;
|
||||
const AParamDescription: string; const AJsonSchemaClass: TClass;
|
||||
const AParamType: TMVCSwagParamType = ptNotDefined; const ARequired: Boolean = True); overload;
|
||||
|
||||
property ParamLocation: TMVCSwagParamLocation read FParamLocation;
|
||||
property ParamName: string read FParamName;
|
||||
property ParamDescription: string read FParamDescription;
|
||||
property ParamType: TMVCSwagParamType read FParamType;
|
||||
property Required: Boolean read FRequired;
|
||||
property JsonSchema: string read FJsonSchema;
|
||||
property JsonSchemaClass: TClass read FJsonSchemaClass;
|
||||
property ParamLocation: TMVCSwagParamLocation read fParamLocation;
|
||||
property ParamName: string read fParamName;
|
||||
property ParamDescription: string read fParamDescription;
|
||||
property ParamType: TMVCSwagParamType read fParamType;
|
||||
property Required: Boolean read fRequired;
|
||||
property JsonSchema: string read fJsonSchema;
|
||||
property JsonSchemaClass: TClass read fJsonSchemaClass;
|
||||
end;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the field definition in the json schema.
|
||||
/// Use this attribute on a class property that will be mapped to a json schema
|
||||
/// </summary>
|
||||
MVCSwagJsonSchemaFieldAttribute = class(TCustomAttribute)
|
||||
MVCSwagJSONSchemaFieldAttribute = class(TCustomAttribute)
|
||||
private
|
||||
FSchemaFieldType: TMVCSwagSchemaType;
|
||||
FFieldName: string;
|
||||
FDescription: string;
|
||||
FRequired: Boolean;
|
||||
fDescription: string;
|
||||
fRequired: Boolean;
|
||||
FNullable: Boolean;
|
||||
public
|
||||
constructor Create(
|
||||
const ASchemaFieldType: TMVCSwagSchemaType;
|
||||
const AFieldName: string;
|
||||
const ADescription: string;
|
||||
const ARequired: Boolean = True;
|
||||
const ANullable: Boolean = False
|
||||
); overload;
|
||||
constructor Create(
|
||||
const AFieldName: string;
|
||||
const ADescription: string;
|
||||
const ARequired: Boolean = True;
|
||||
const ANullable: Boolean = False
|
||||
); overload;
|
||||
constructor Create(const ASchemaFieldType: TMVCSwagSchemaType; const AFieldName: string; const ADescription: string;
|
||||
const ARequired: Boolean = True; const ANullable: Boolean = False); overload;
|
||||
constructor Create(const AFieldName: string; const ADescription: string; const ARequired: Boolean = True;
|
||||
const ANullable: Boolean = False); overload;
|
||||
|
||||
property SchemaFieldType: TMVCSwagSchemaType read FSchemaFieldType;
|
||||
property FieldName: string read FFieldName;
|
||||
property Description: string read FDescription;
|
||||
property Required: Boolean read FRequired;
|
||||
property Description: string read fDescription;
|
||||
property Required: Boolean read fRequired;
|
||||
property Nullable: Boolean read FNullable;
|
||||
end;
|
||||
|
||||
@ -201,22 +179,22 @@ type
|
||||
private
|
||||
class var FRttiContext: TRttiContext;
|
||||
class function GetMVCSwagParamsFromMethod(const AMethod: TRttiMethod): TArray<MVCSwagParamAttribute>;
|
||||
class function MVCParamLocationToSwagRequestParamInLocation(const AMVCSwagParamLocation: TMVCSwagParamLocation):
|
||||
TSwagRequestParameterInLocation;
|
||||
class function MVCParamLocationToSwagRequestParamInLocation(const AMVCSwagParamLocation: TMVCSwagParamLocation)
|
||||
: TSwagRequestParameterInLocation;
|
||||
class function MVCParamTypeToSwagTypeParameter(const AMVSwagParamType: TMVCSwagParamType): TSwagTypeParameter;
|
||||
class procedure ExtractJsonSchemaFromClass(const AJsonFieldRoot: TJsonFieldObject; const AClass: TClass); overload;
|
||||
class function ExtractJsonSchemaFromClass(const AClass: TClass; const AIsArray: Boolean = False)
|
||||
: TJSONObject; overload;
|
||||
class function GetJsonFieldClass(const ASchemaFieldType: TMVCSwagSchemaType): TJsonFieldClass;
|
||||
class function TypeKindToMVCSwagSchemaType(APropType: TRttiType): TMVCSwagSchemaType; static;
|
||||
class function RttiTypeIsObjectList(const ARttiType: TRttiType): Boolean; static;
|
||||
class function TypeIsEnumerable(const ARttiType: TRttiType): Boolean; static;
|
||||
public
|
||||
class constructor Create;
|
||||
class destructor Destroy;
|
||||
class function MVCHttpMethodToSwagPathOperation(const AMVCHTTPMethod: TMVCHTTPMethodType): TSwagPathTypeOperation;
|
||||
class function MVCPathToSwagPath(const AResourcePath: string): string;
|
||||
class function GetParamsFromMethod(const AResourcePath: string; const AMethod: TRttiMethod):
|
||||
TArray<TSwagRequestParameter>;
|
||||
class function GetParamsFromMethod(const AResourcePath: string; const AMethod: TRttiMethod)
|
||||
: TArray<TSwagRequestParameter>;
|
||||
class function RttiTypeToSwagType(const ARttiType: TRttiType): TSwagTypeParameter;
|
||||
class procedure FillOperationSummary(const ASwagPathOperation: TSwagPathOperation; const AMethod: TRttiMethod);
|
||||
class function MethodRequiresAuthentication(const AMethod: TRttiMethod; const AType: TRttiType;
|
||||
@ -227,16 +205,9 @@ type
|
||||
const
|
||||
SECURITY_BEARER_NAME = 'bearer';
|
||||
SECURITY_BASIC_NAME = 'basic';
|
||||
JWT_JSON_SCHEMA =
|
||||
'{' + sLineBreak +
|
||||
' "type": "object",' + sLineBreak +
|
||||
' "properties": {' + sLineBreak +
|
||||
' "token": {' + sLineBreak +
|
||||
' "type": "string",' + sLineBreak +
|
||||
' "description": "JWT Token"' + sLineBreak +
|
||||
' }' + sLineBreak +
|
||||
' }' + sLineBreak +
|
||||
'}';
|
||||
JWT_JSON_SCHEMA = '{' + sLineBreak + ' "type": "object",' + sLineBreak + ' "properties": {' + sLineBreak +
|
||||
' "token": {' + sLineBreak + ' "type": "string",' + sLineBreak + ' "description": "JWT Token"' +
|
||||
sLineBreak + ' }' + sLineBreak + ' }' + sLineBreak + '}';
|
||||
JWT_DEFAULT_DESCRIPTION = 'For accessing the API a valid JWT token must be passed in all the queries ' +
|
||||
'in the ''Authorization'' header.' + sLineBreak + sLineBreak +
|
||||
'A valid JWT token is generated by the API and retourned as answer of a call ' + 'to the route defined ' +
|
||||
@ -249,11 +220,9 @@ implementation
|
||||
uses
|
||||
System.Classes,
|
||||
System.RegularExpressions,
|
||||
System.SysUtils,
|
||||
MVCFramework,
|
||||
MVCFramework.Serializer.Abstract,
|
||||
MVCFramework.Serializer.Commons,
|
||||
MVCFramework.Middleware.Authentication.RoleBasedAuthHandler,
|
||||
Swag.Doc.Path.Operation.Response,
|
||||
Json.Schema.Field.Numbers,
|
||||
Json.Schema.Field.Strings,
|
||||
@ -277,8 +246,7 @@ begin
|
||||
tkChar, tkString, tkWChar, tkLString, tkWString, tkUString:
|
||||
Result := stpString;
|
||||
tkFloat:
|
||||
if (ARttiType.Handle = TypeInfo(TDateTime)) or
|
||||
(ARttiType.Handle = TypeInfo(TDate)) or
|
||||
if (ARttiType.Handle = TypeInfo(TDateTime)) or (ARttiType.Handle = TypeInfo(TDate)) or
|
||||
(ARttiType.Handle = TypeInfo(TTime)) then
|
||||
Result := stpString
|
||||
else
|
||||
@ -298,8 +266,7 @@ begin
|
||||
FRttiContext.Free;
|
||||
end;
|
||||
|
||||
|
||||
class function TMVCSwagger.RttiTypeIsObjectList(const ARttiType: TRttiType): Boolean;
|
||||
class function TMVCSwagger.TypeIsEnumerable(const ARttiType: TRttiType): Boolean;
|
||||
begin
|
||||
Result := ARttiType.GetMethod('GetEnumerator') <> nil;
|
||||
end;
|
||||
@ -318,154 +285,169 @@ type
|
||||
|
||||
class procedure TMVCSwagger.ExtractJsonSchemaFromClass(const AJsonFieldRoot: TJsonFieldObject; const AClass: TClass);
|
||||
var
|
||||
LFieldSchemaDef: TFieldSchemaDefinition;
|
||||
LObjType: TRttiType;
|
||||
LProp: TRttiProperty;
|
||||
LSkipProp: Boolean;
|
||||
LAttr: TCustomAttribute;
|
||||
LJSFieldAttr: MVCSwagJsonSchemaFieldAttribute;
|
||||
LJsonFieldClass: TJsonFieldClass;
|
||||
LJsonField: TJsonField;
|
||||
LJsonFieldObject: TJsonFieldObject;
|
||||
LAbstractSer: THackMVCAbstractSerializer;
|
||||
LClass: TClass;
|
||||
lFieldSchemaDef: TFieldSchemaDefinition;
|
||||
lObjType: TRttiType;
|
||||
lProp: TRttiProperty;
|
||||
lSkipProp: Boolean;
|
||||
lAttr: TCustomAttribute;
|
||||
lJSFieldAttr: MVCSwagJSONSchemaFieldAttribute;
|
||||
lJsonFieldClass: TJsonFieldClass;
|
||||
lJsonField: TJsonField;
|
||||
lJsonFieldObject: TJsonFieldObject;
|
||||
lAbstractSer: THackMVCAbstractSerializer;
|
||||
lClass: TClass;
|
||||
begin
|
||||
LObjType := FRttiContext.GetType(AClass);
|
||||
for LProp in LObjType.GetProperties do
|
||||
lObjType := FRttiContext.GetType(AClass);
|
||||
for lProp in lObjType.GetProperties do
|
||||
begin
|
||||
LSkipProp := False;
|
||||
LFieldSchemaDef := TFieldSchemaDefinition.Create;
|
||||
lSkipProp := False;
|
||||
lFieldSchemaDef := TFieldSchemaDefinition.Create;
|
||||
|
||||
for LAttr in LProp.GetAttributes do
|
||||
for lAttr in lProp.GetAttributes do
|
||||
begin
|
||||
if LAttr is MVCDoNotSerializeAttribute then
|
||||
if lAttr is MVCDoNotSerializeAttribute then
|
||||
begin
|
||||
LSkipProp := True;
|
||||
lSkipProp := True;
|
||||
Break;
|
||||
end;
|
||||
|
||||
if LAttr is MVCSwagJsonSchemaFieldAttribute then
|
||||
if lAttr is MVCSwagJSONSchemaFieldAttribute then
|
||||
begin
|
||||
LJSFieldAttr := MVCSwagJsonSchemaFieldAttribute(LAttr);
|
||||
LFieldSchemaDef.SchemaFieldType := LJSFieldAttr.SchemaFieldType;
|
||||
LFieldSchemaDef.FieldName := LJSFieldAttr.FieldName;
|
||||
LFieldSchemaDef.Description := LJSFieldAttr.Description;
|
||||
LFieldSchemaDef.Required := LJSFieldAttr.Required;
|
||||
LFieldSchemaDef.Nullable := LJSFieldAttr.Nullable;
|
||||
lJSFieldAttr := MVCSwagJSONSchemaFieldAttribute(lAttr);
|
||||
lFieldSchemaDef.SchemaFieldType := lJSFieldAttr.SchemaFieldType;
|
||||
lFieldSchemaDef.FieldName := lJSFieldAttr.FieldName;
|
||||
lFieldSchemaDef.Description := lJSFieldAttr.Description;
|
||||
lFieldSchemaDef.Required := lJSFieldAttr.Required;
|
||||
lFieldSchemaDef.Nullable := lJSFieldAttr.Nullable;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
if LSkipProp then
|
||||
if lSkipProp then
|
||||
Continue;
|
||||
|
||||
if LFieldSchemaDef.SchemaFieldType = stUnknown then
|
||||
if lFieldSchemaDef.SchemaFieldType = stUnknown then
|
||||
begin
|
||||
LFieldSchemaDef.SchemaFieldType := TypeKindToMVCSwagSchemaType(LProp.PropertyType);
|
||||
LFieldSchemaDef.FieldName := TMVCSerializerHelper.GetKeyName(LProp, LObjType);
|
||||
lFieldSchemaDef.SchemaFieldType := TypeKindToMVCSwagSchemaType(lProp.PropertyType);
|
||||
lFieldSchemaDef.FieldName := TMVCSerializerHelper.GetKeyName(lProp, lObjType);
|
||||
end;
|
||||
|
||||
LJsonFieldClass := GetJsonFieldClass(LFieldSchemaDef.SchemaFieldType);
|
||||
if not Assigned(LJsonFieldClass) then
|
||||
lJsonFieldClass := GetJsonFieldClass(lFieldSchemaDef.SchemaFieldType);
|
||||
if not Assigned(lJsonFieldClass) then
|
||||
Continue;
|
||||
|
||||
LJsonField := LJsonFieldClass.Create;
|
||||
lJsonField := lJsonFieldClass.Create;
|
||||
|
||||
if (LJsonField is TJsonFieldObject) and (not RttiTypeIsObjectList(LProp.PropertyType)) then
|
||||
if (lJsonField is TJsonFieldObject) and (not TypeIsEnumerable(lProp.PropertyType)) then
|
||||
begin
|
||||
ExtractJsonSchemaFromClass((LJsonField as TJsonFieldObject), LProp.PropertyType.AsInstance.MetaClassType);
|
||||
ExtractJsonSchemaFromClass((lJsonField as TJsonFieldObject), lProp.PropertyType.AsInstance.MetaClassType);
|
||||
end;
|
||||
|
||||
if (LJsonField is TJsonFieldArray) and RttiTypeIsObjectList(LProp.PropertyType) then
|
||||
if (lJsonField is TJsonFieldArray) and TypeIsEnumerable(lProp.PropertyType) then
|
||||
begin
|
||||
LJsonFieldObject := TJsonFieldObject.Create;
|
||||
lJsonFieldObject := TJsonFieldObject.Create;
|
||||
|
||||
LAbstractSer := THackMVCAbstractSerializer.Create;
|
||||
lAbstractSer := THackMVCAbstractSerializer.Create;
|
||||
try
|
||||
LClass := LAbstractSer.GetObjectTypeOfGenericList(LProp.PropertyType.Handle);
|
||||
ExtractJsonSchemaFromClass(LJsonFieldObject, LClass);
|
||||
(LJsonField as TJsonFieldArray).ItemFieldType := LJsonFieldObject;
|
||||
lClass := lAbstractSer.GetObjectTypeOfGenericList(lProp.PropertyType.Handle);
|
||||
ExtractJsonSchemaFromClass(lJsonFieldObject, lClass);
|
||||
(lJsonField as TJsonFieldArray).ItemFieldType := lJsonFieldObject;
|
||||
finally
|
||||
LAbstractSer.Free;
|
||||
lAbstractSer.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
LJsonField.Name := LFieldSchemaDef.FieldName;
|
||||
LJsonField.Required := LFieldSchemaDef.Required;
|
||||
LJsonField.Nullable := LFieldSchemaDef.Nullable;
|
||||
if not LFieldSchemaDef.Description.IsEmpty then
|
||||
TJsonFieldInteger(LJsonField).Description := LFieldSchemaDef.Description;
|
||||
lJsonField.Name := lFieldSchemaDef.FieldName;
|
||||
lJsonField.Required := lFieldSchemaDef.Required;
|
||||
lJsonField.Nullable := lFieldSchemaDef.Nullable;
|
||||
if not lFieldSchemaDef.Description.IsEmpty then
|
||||
TJsonFieldInteger(lJsonField).Description := lFieldSchemaDef.Description;
|
||||
|
||||
AJsonFieldRoot.AddField(LJsonField);
|
||||
AJsonFieldRoot.AddField(lJsonField);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TMVCSwagger.ExtractJsonSchemaFromClass(const AClass: TClass; const AIsArray: Boolean): TJSONObject;
|
||||
var
|
||||
LJsonSchema: TJsonField;
|
||||
LJsonRoot: TJsonFieldObject;
|
||||
lJsonSchema: TJsonField;
|
||||
lJsonRoot: TJsonFieldObject;
|
||||
begin
|
||||
var
|
||||
lClassName := AClass.ClassName;
|
||||
if AIsArray then
|
||||
LJsonSchema := TJsonFieldArray.Create
|
||||
begin
|
||||
lJsonSchema := TJsonFieldArray.Create
|
||||
end
|
||||
else
|
||||
LJsonSchema := TJsonFieldObject.Create;
|
||||
begin
|
||||
lJsonSchema := TJsonFieldObject.Create;
|
||||
end;
|
||||
try
|
||||
if AIsArray then
|
||||
begin
|
||||
LJsonRoot := TJsonFieldObject.Create;
|
||||
TJsonFieldArray(LJsonSchema).ItemFieldType := LJsonRoot;
|
||||
TJsonFieldArray(LJsonSchema).Name := 'items';
|
||||
lJsonRoot := TJsonFieldObject.Create;
|
||||
TJsonFieldArray(lJsonSchema).ItemFieldType := lJsonRoot;
|
||||
TJsonFieldArray(lJsonSchema).Name := 'items';
|
||||
end
|
||||
else
|
||||
begin
|
||||
LJsonRoot := LJsonSchema as TJsonFieldObject;
|
||||
lJsonRoot := lJsonSchema as TJsonFieldObject;
|
||||
end;
|
||||
|
||||
ExtractJsonSchemaFromClass(LJsonRoot, AClass);
|
||||
Result := LJsonSchema.ToJsonSchema;
|
||||
ExtractJsonSchemaFromClass(lJsonRoot, AClass);
|
||||
Result := lJsonSchema.ToJsonSchema;
|
||||
finally
|
||||
LJsonSchema.Free;
|
||||
lJsonSchema.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TMVCSwagger.FillOperationSummary(const ASwagPathOperation: TSwagPathOperation;
|
||||
const AMethod: TRttiMethod);
|
||||
var
|
||||
LAttr: TCustomAttribute;
|
||||
LSwagResponse: TSwagResponse;
|
||||
LSwagResponsesAttr: MVCSwagResponsesAttribute;
|
||||
lAttr: TCustomAttribute;
|
||||
lSwagResponse: TSwagResponse;
|
||||
lSwagResponsesAttr: MVCSwagResponsesAttribute;
|
||||
begin
|
||||
for LAttr in AMethod.GetAttributes do
|
||||
for lAttr in AMethod.GetAttributes do
|
||||
begin
|
||||
if LAttr is MVCSwagSummaryAttribute then
|
||||
if lAttr is MVCSwagSummaryAttribute then
|
||||
begin
|
||||
ASwagPathOperation.Tags.AddRange(MVCSwagSummaryAttribute(LAttr).GetTags);
|
||||
ASwagPathOperation.Description := MVCSwagSummaryAttribute(LAttr).Description;
|
||||
ASwagPathOperation.OperationId := MVCSwagSummaryAttribute(LAttr).OperationID;
|
||||
ASwagPathOperation.Deprecated := MVCSwagSummaryAttribute(LAttr).Deprecated;
|
||||
ASwagPathOperation.Tags.AddRange(MVCSwagSummaryAttribute(lAttr).GetTags);
|
||||
ASwagPathOperation.Description := MVCSwagSummaryAttribute(lAttr).Description;
|
||||
ASwagPathOperation.OperationID := MVCSwagSummaryAttribute(lAttr).OperationID;
|
||||
// dt [2019-10-31] Ensure OperationID is always defined
|
||||
if ASwagPathOperation.OperationID.IsEmpty then
|
||||
begin
|
||||
ASwagPathOperation.OperationID := AMethod.Name;
|
||||
end;
|
||||
// dt [2019-10-31]
|
||||
ASwagPathOperation.Deprecated := MVCSwagSummaryAttribute(lAttr).Deprecated;
|
||||
end;
|
||||
if LAttr is MVCConsumesAttribute then
|
||||
if lAttr is MVCConsumesAttribute then
|
||||
begin
|
||||
ASwagPathOperation.Consumes.Add(MVCConsumesAttribute(LAttr).Value)
|
||||
ASwagPathOperation.Consumes.Add(MVCConsumesAttribute(lAttr).Value)
|
||||
end;
|
||||
if LAttr is MVCProducesAttribute then
|
||||
if lAttr is MVCProducesAttribute then
|
||||
begin
|
||||
ASwagPathOperation.Produces.Add(MVCProducesAttribute(LAttr).Value)
|
||||
ASwagPathOperation.Produces.Add(MVCProducesAttribute(lAttr).Value)
|
||||
end;
|
||||
if LAttr is MVCSwagResponsesAttribute then
|
||||
if lAttr is MVCSwagResponsesAttribute then
|
||||
begin
|
||||
LSwagResponsesAttr := MVCSwagResponsesAttribute(LAttr);
|
||||
lSwagResponsesAttr := MVCSwagResponsesAttribute(lAttr);
|
||||
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := LSwagResponsesAttr.StatusCode.ToString;
|
||||
LSwagResponse.Description := LSwagResponsesAttr.Description;
|
||||
if not LSwagResponsesAttr.JsonSchema.IsEmpty then
|
||||
LSwagResponse.Schema.JsonSchema := TJSONObject.ParseJSONValue(LSwagResponsesAttr.JsonSchema) as TJSONObject
|
||||
else if Assigned(LSwagResponsesAttr.JsonSchemaClass) then
|
||||
LSwagResponse.Schema.JsonSchema := ExtractJsonSchemaFromClass(LSwagResponsesAttr.JsonSchemaClass,
|
||||
LSwagResponsesAttr.IsArray);
|
||||
|
||||
ASwagPathOperation.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := lSwagResponsesAttr.StatusCode.ToString;
|
||||
lSwagResponse.Description := lSwagResponsesAttr.Description;
|
||||
if not lSwagResponsesAttr.JsonSchema.IsEmpty then
|
||||
begin
|
||||
lSwagResponse.Schema.JsonSchema := TJSONObject.ParseJSONValue(lSwagResponsesAttr.JsonSchema) as TJSONObject
|
||||
end
|
||||
else if Assigned(lSwagResponsesAttr.JsonSchemaClass) then
|
||||
begin
|
||||
lSwagResponse.Schema.JsonSchema := ExtractJsonSchemaFromClass(lSwagResponsesAttr.JsonSchemaClass,
|
||||
lSwagResponsesAttr.IsArray);
|
||||
end;
|
||||
ASwagPathOperation.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -477,15 +459,15 @@ begin
|
||||
|
||||
if ASwagPathOperation.Responses.Count <= 0 then
|
||||
begin
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := HTTP_STATUS.OK.ToString;
|
||||
LSwagResponse.Description := 'Ok';
|
||||
ASwagPathOperation.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := HTTP_STATUS.OK.ToString;
|
||||
lSwagResponse.Description := 'Ok';
|
||||
ASwagPathOperation.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := HTTP_STATUS.InternalServerError.ToString;
|
||||
LSwagResponse.Description := 'Internal server error';
|
||||
ASwagPathOperation.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := HTTP_STATUS.InternalServerError.ToString;
|
||||
lSwagResponse.Description := 'Internal server error';
|
||||
ASwagPathOperation.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
end;
|
||||
|
||||
end;
|
||||
@ -532,11 +514,10 @@ begin
|
||||
case APropType.TypeKind of
|
||||
tkClass:
|
||||
begin
|
||||
if (APropType.Handle = TypeInfo(TStream)) or
|
||||
(APropType.Handle = TypeInfo(TMemoryStream)) or
|
||||
if (APropType.Handle = TypeInfo(TStream)) or (APropType.Handle = TypeInfo(TMemoryStream)) or
|
||||
(APropType.Handle = TypeInfo(TStringStream)) then
|
||||
Result := stString
|
||||
else if RttiTypeIsObjectList(APropType) then
|
||||
else if TypeIsEnumerable(APropType) then
|
||||
Result := stArray
|
||||
else
|
||||
Result := stObject;
|
||||
@ -577,71 +558,67 @@ end;
|
||||
|
||||
class function TMVCSwagger.GetJWTAuthenticationPath(const AJWTUrlSegment: string): TSwagPath;
|
||||
var
|
||||
LSwagPathOp: TSwagPathOperation;
|
||||
LSwagResponse: TSwagResponse;
|
||||
lSwagPathOp: TSwagPathOperation;
|
||||
lSwagResponse: TSwagResponse;
|
||||
begin
|
||||
LSwagPathOp := TSwagPathOperation.Create;
|
||||
LSwagPathOp.Tags.Add('JWT Authentication');
|
||||
LSwagPathOp.Operation := ohvPost;
|
||||
LSwagPathOp.Security.Add(SECURITY_BASIC_NAME);
|
||||
LSwagPathOp.Description := 'Create JSON Web Token';
|
||||
LSwagPathOp.Produces.Add(TMVCMediaType.APPLICATION_JSON);
|
||||
lSwagPathOp := TSwagPathOperation.Create;
|
||||
lSwagPathOp.Tags.Add('JWT Authentication');
|
||||
lSwagPathOp.Operation := ohvPost;
|
||||
lSwagPathOp.Security.Add(SECURITY_BASIC_NAME);
|
||||
lSwagPathOp.Description := 'Create JSON Web Token';
|
||||
lSwagPathOp.Produces.Add(TMVCMediaType.APPLICATION_JSON);
|
||||
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := HTTP_STATUS.Unauthorized.ToString;
|
||||
LSwagResponse.Description := 'Invalid authorization type';
|
||||
LSwagPathOp.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := HTTP_STATUS.Unauthorized.ToString;
|
||||
lSwagResponse.Description := 'Invalid authorization type';
|
||||
lSwagPathOp.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := HTTP_STATUS.Forbidden.ToString;
|
||||
LSwagResponse.Description := 'Forbidden';
|
||||
LSwagPathOp.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := HTTP_STATUS.Forbidden.ToString;
|
||||
lSwagResponse.Description := 'Forbidden';
|
||||
lSwagPathOp.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := HTTP_STATUS.InternalServerError.ToString;
|
||||
LSwagResponse.Description := 'Internal server error';
|
||||
LSwagPathOp.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := HTTP_STATUS.InternalServerError.ToString;
|
||||
lSwagResponse.Description := 'Internal server error';
|
||||
lSwagPathOp.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
|
||||
LSwagResponse := TSwagResponse.Create;
|
||||
LSwagResponse.StatusCode := HTTP_STATUS.OK.ToString;
|
||||
LSwagResponse.Description := 'OK';
|
||||
LSwagResponse.Schema.JsonSchema := TJSONObject.ParseJSONValue(JWT_JSON_SCHEMA) as TJSONObject;
|
||||
LSwagPathOp.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := HTTP_STATUS.OK.ToString;
|
||||
lSwagResponse.Description := 'OK';
|
||||
lSwagResponse.Schema.JsonSchema := TJSONObject.ParseJSONValue(JWT_JSON_SCHEMA) as TJSONObject;
|
||||
lSwagPathOp.Responses.Add(lSwagResponse.StatusCode, lSwagResponse);
|
||||
|
||||
Result := TSwagPath.Create;
|
||||
Result.Uri := AJwtUrlSegment;
|
||||
Result.Operations.Add(LSwagPathOp);
|
||||
Result.Uri := AJWTUrlSegment;
|
||||
Result.Operations.Add(lSwagPathOp);
|
||||
end;
|
||||
|
||||
class function TMVCSwagger.GetMVCSwagParamsFromMethod(const AMethod: TRttiMethod): TArray<MVCSwagParamAttribute>;
|
||||
var
|
||||
LAttr: TCustomAttribute;
|
||||
lAttr: TCustomAttribute;
|
||||
begin
|
||||
SetLength(Result, 0);
|
||||
for LAttr in AMethod.GetAttributes do
|
||||
for lAttr in AMethod.GetAttributes do
|
||||
begin
|
||||
if LAttr is MVCSwagParamAttribute then
|
||||
if lAttr is MVCSwagParamAttribute then
|
||||
begin
|
||||
Insert([MVCSwagParamAttribute(LAttr)], Result, High(Result));
|
||||
Insert([MVCSwagParamAttribute(lAttr)], Result, High(Result));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TMVCSwagger.GetParamsFromMethod(const AResourcePath: string; const AMethod: TRttiMethod):
|
||||
TArray<TSwagRequestParameter>;
|
||||
class function TMVCSwagger.GetParamsFromMethod(const AResourcePath: string; const AMethod: TRttiMethod)
|
||||
: TArray<TSwagRequestParameter>;
|
||||
|
||||
function TryGetMVCPathParamByName(const AParams: TArray<MVCSwagParamAttribute>;
|
||||
const
|
||||
AParamName:
|
||||
string;
|
||||
out AMVCParam: MVCSwagParamAttribute;
|
||||
out AIndex: Integer): Boolean;
|
||||
function TryGetMVCPathParamByName(const AParams: TArray<MVCSwagParamAttribute>; const AParamName: string;
|
||||
out AMVCParam: MVCSwagParamAttribute; out AIndex: Integer): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
AMVCParam := nil;
|
||||
AIndex := - 1;
|
||||
AIndex := -1;
|
||||
for I := Low(AParams) to High(AParams) do
|
||||
if SameText(AParams[I].ParamName, AParamName) and (AParams[I].ParamLocation = plPath) then
|
||||
begin
|
||||
@ -652,73 +629,81 @@ class function TMVCSwagger.GetParamsFromMethod(const AResourcePath: string; cons
|
||||
end;
|
||||
|
||||
var
|
||||
LMatches: TMatchCollection;
|
||||
LMatch: TMatch;
|
||||
LParamName: string;
|
||||
LMethodParam: TRttiParameter;
|
||||
LSwagParam: TSwagRequestParameter;
|
||||
LMVCSwagParams: TArray<MVCSwagParamAttribute>;
|
||||
LMVCParam: MVCSwagParamAttribute;
|
||||
LIndex: Integer;
|
||||
lMatches: TMatchCollection;
|
||||
lMatch: TMatch;
|
||||
lParamName: string;
|
||||
lMethodParam: TRttiParameter;
|
||||
lSwagParam: TSwagRequestParameter;
|
||||
lMVCSwagParams: TArray<MVCSwagParamAttribute>;
|
||||
lMVCParam: MVCSwagParamAttribute;
|
||||
lIndex: Integer;
|
||||
I: Integer;
|
||||
begin
|
||||
LMVCSwagParams := GetMVCSwagParamsFromMethod(AMethod);
|
||||
lMVCSwagParams := GetMVCSwagParamsFromMethod(AMethod);
|
||||
|
||||
SetLength(Result, 0);
|
||||
|
||||
// Path parameters
|
||||
LMatches := TRegEx.Matches(AResourcePath, '({)([\w_]+)(})', [roIgnoreCase, roMultiLine]);
|
||||
for LMatch in LMatches do
|
||||
lMatches := TRegEx.Matches(AResourcePath, '({)([\w_]+)(})', [roIgnoreCase, roMultiLine]);
|
||||
for lMatch in lMatches do
|
||||
begin
|
||||
LParamName := LMatch.Groups[2].Value;
|
||||
for LMethodParam in AMethod.GetParameters do
|
||||
lParamName := lMatch.Groups[2].Value;
|
||||
for lMethodParam in AMethod.GetParameters do
|
||||
begin
|
||||
if SameText(LMethodParam.Name, LParamName) then
|
||||
if SameText(lMethodParam.Name, lParamName) then
|
||||
begin
|
||||
LSwagParam := TSwagRequestParameter.Create;
|
||||
lSwagParam := TSwagRequestParameter.Create;
|
||||
|
||||
if TryGetMVCPathParamByName(LMVCSwagParams, LParamName, LMVCParam, LIndex) then
|
||||
if TryGetMVCPathParamByName(lMVCSwagParams, lParamName, lMVCParam, lIndex) then
|
||||
begin
|
||||
LSwagParam.Name := LParamName;
|
||||
LSwagParam.InLocation := MVCParamLocationToSwagRequestParamInLocation(LMVCParam.ParamLocation);
|
||||
LSwagParam.Required := LMVCParam.Required;
|
||||
LSwagParam.TypeParameter := MVCParamTypeToSwagTypeParameter(LMVCParam.ParamType);
|
||||
LSwagParam.Description := LMVCParam.ParamDescription;
|
||||
if not LMVCParam.JsonSchema.IsEmpty then
|
||||
LSwagParam.Schema.JsonSchema := TJSONObject.ParseJSONValue(LMVCParam.JsonSchema) as TJSONObject
|
||||
else if Assigned(LMVCParam.JsonSchemaClass) then
|
||||
LSwagParam.Schema.JsonSchema := ExtractJsonSchemaFromClass(LMVCParam.JsonSchemaClass,
|
||||
LMVCParam.ParamType = ptArray);
|
||||
Delete(LMVCSwagParams, LIndex, 1);
|
||||
lSwagParam.Name := lParamName;
|
||||
lSwagParam.InLocation := MVCParamLocationToSwagRequestParamInLocation(lMVCParam.ParamLocation);
|
||||
lSwagParam.Required := lMVCParam.Required;
|
||||
lSwagParam.TypeParameter := MVCParamTypeToSwagTypeParameter(lMVCParam.ParamType);
|
||||
lSwagParam.Description := lMVCParam.ParamDescription;
|
||||
if not lMVCParam.JsonSchema.IsEmpty then
|
||||
begin
|
||||
lSwagParam.Schema.JsonSchema := TJSONObject.ParseJSONValue(lMVCParam.JsonSchema) as TJSONObject
|
||||
end
|
||||
else if Assigned(lMVCParam.JsonSchemaClass) then
|
||||
begin
|
||||
lSwagParam.Schema.JsonSchema := ExtractJsonSchemaFromClass(lMVCParam.JsonSchemaClass,
|
||||
lMVCParam.ParamType = ptArray);
|
||||
end;
|
||||
Delete(lMVCSwagParams, lIndex, 1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
LSwagParam.Name := LParamName;
|
||||
LSwagParam.InLocation := rpiPath;
|
||||
LSwagParam.Required := True;
|
||||
LSwagParam.TypeParameter := RttiTypeToSwagType(LMethodParam.ParamType);
|
||||
lSwagParam.Name := lParamName;
|
||||
lSwagParam.InLocation := rpiPath;
|
||||
lSwagParam.Required := True;
|
||||
lSwagParam.TypeParameter := RttiTypeToSwagType(lMethodParam.ParamType);
|
||||
end;
|
||||
Insert([LSwagParam], Result, High(Result));
|
||||
Insert([lSwagParam], Result, High(Result));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Other parameters
|
||||
for I := Low(LMVCSwagParams) to High(LMVCSwagParams) do
|
||||
for I := Low(lMVCSwagParams) to High(lMVCSwagParams) do
|
||||
begin
|
||||
LSwagParam := TSwagRequestParameter.Create;
|
||||
LSwagParam.Name := LMVCSwagParams[I].ParamName;
|
||||
LSwagParam.InLocation := MVCParamLocationToSwagRequestParamInLocation(LMVCSwagParams[I].ParamLocation);
|
||||
LSwagParam.Required := LMVCSwagParams[I].Required;
|
||||
LSwagParam.TypeParameter := MVCParamTypeToSwagTypeParameter(LMVCSwagParams[I].ParamType);
|
||||
LSwagParam.Description := LMVCSwagParams[I].ParamDescription;
|
||||
if not LMVCSwagParams[I].JsonSchema.IsEmpty then
|
||||
LSwagParam.Schema.JsonSchema := TJSONObject.ParseJSONValue(LMVCSwagParams[I].JsonSchema) as TJSONObject
|
||||
else if Assigned(LMVCSwagParams[I].JsonSchemaClass) then
|
||||
LSwagParam.Schema.JsonSchema := ExtractJsonSchemaFromClass(LMVCSwagParams[I].JsonSchemaClass,
|
||||
LMVCSwagParams[I].ParamType = ptArray);
|
||||
lSwagParam := TSwagRequestParameter.Create;
|
||||
lSwagParam.Name := lMVCSwagParams[I].ParamName;
|
||||
lSwagParam.InLocation := MVCParamLocationToSwagRequestParamInLocation(lMVCSwagParams[I].ParamLocation);
|
||||
lSwagParam.Required := lMVCSwagParams[I].Required;
|
||||
lSwagParam.TypeParameter := MVCParamTypeToSwagTypeParameter(lMVCSwagParams[I].ParamType);
|
||||
lSwagParam.Description := lMVCSwagParams[I].ParamDescription;
|
||||
if not lMVCSwagParams[I].JsonSchema.IsEmpty then
|
||||
begin
|
||||
lSwagParam.Schema.JsonSchema := TJSONObject.ParseJSONValue(lMVCSwagParams[I].JsonSchema) as TJSONObject
|
||||
end
|
||||
else if Assigned(lMVCSwagParams[I].JsonSchemaClass) then
|
||||
begin
|
||||
lSwagParam.Schema.JsonSchema := ExtractJsonSchemaFromClass(lMVCSwagParams[I].JsonSchemaClass,
|
||||
lMVCSwagParams[I].ParamType = ptArray);
|
||||
end;
|
||||
|
||||
Insert([LSwagParam], Result, High(Result));
|
||||
Insert([lSwagParam], Result, High(Result));
|
||||
end;
|
||||
|
||||
end;
|
||||
@ -726,20 +711,20 @@ end;
|
||||
class function TMVCSwagger.MethodRequiresAuthentication(const AMethod: TRttiMethod; const AType: TRttiType;
|
||||
out AAuthenticationTypeName: string): Boolean;
|
||||
var
|
||||
LAttr: TCustomAttribute;
|
||||
lAttr: TCustomAttribute;
|
||||
begin
|
||||
Result := False;
|
||||
AAuthenticationTypeName := '';
|
||||
|
||||
for LAttr in AMethod.GetAttributes do
|
||||
if LAttr is MVCRequiresAuthenticationAttribute then
|
||||
for lAttr in AMethod.GetAttributes do
|
||||
if lAttr is MVCRequiresAuthenticationAttribute then
|
||||
begin
|
||||
AAuthenticationTypeName := SECURITY_BEARER_NAME;
|
||||
Exit(True);
|
||||
end
|
||||
else if LAttr is MVCSwagAuthenticationAttribute then
|
||||
else if lAttr is MVCSwagAuthenticationAttribute then
|
||||
begin
|
||||
case MVCSwagAuthenticationAttribute(LAttr).AuthenticationType of
|
||||
case MVCSwagAuthenticationAttribute(lAttr).AuthenticationType of
|
||||
atBasic:
|
||||
AAuthenticationTypeName := SECURITY_BASIC_NAME;
|
||||
atJsonWebToken:
|
||||
@ -748,15 +733,15 @@ begin
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
for LAttr in AType.GetAttributes do
|
||||
if LAttr is MVCRequiresAuthenticationAttribute then
|
||||
for lAttr in AType.GetAttributes do
|
||||
if lAttr is MVCRequiresAuthenticationAttribute then
|
||||
begin
|
||||
AAuthenticationTypeName := SECURITY_BEARER_NAME;
|
||||
Exit(True);
|
||||
end
|
||||
else if LAttr is MVCSwagAuthenticationAttribute then
|
||||
else if lAttr is MVCSwagAuthenticationAttribute then
|
||||
begin
|
||||
case MVCSwagAuthenticationAttribute(LAttr).AuthenticationType of
|
||||
case MVCSwagAuthenticationAttribute(lAttr).AuthenticationType of
|
||||
atBasic:
|
||||
AAuthenticationTypeName := SECURITY_BASIC_NAME;
|
||||
atJsonWebToken:
|
||||
@ -766,8 +751,8 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TMVCSwagger.MVCHttpMethodToSwagPathOperation(const AMVCHTTPMethod: TMVCHTTPMethodType):
|
||||
TSwagPathTypeOperation;
|
||||
class function TMVCSwagger.MVCHttpMethodToSwagPathOperation(const AMVCHTTPMethod: TMVCHTTPMethodType)
|
||||
: TSwagPathTypeOperation;
|
||||
begin
|
||||
case AMVCHTTPMethod of
|
||||
httpGET:
|
||||
@ -790,8 +775,7 @@ begin
|
||||
end;
|
||||
|
||||
class function TMVCSwagger.MVCParamLocationToSwagRequestParamInLocation(const AMVCSwagParamLocation
|
||||
: TMVCSwagParamLocation)
|
||||
: TSwagRequestParameterInLocation;
|
||||
: TMVCSwagParamLocation): TSwagRequestParameterInLocation;
|
||||
begin
|
||||
case AMVCSwagParamLocation of
|
||||
plQuery:
|
||||
@ -837,18 +821,18 @@ end;
|
||||
|
||||
{ MVCSwagSummary }
|
||||
|
||||
constructor MVCSwagSummaryAttribute.Create(const ATags, ADescription: string; const APathId: string;
|
||||
constructor MVCSwagSummaryAttribute.Create(const ATags, ADescription: string; const AOperationId: string;
|
||||
ADeprecated: Boolean);
|
||||
begin
|
||||
FTags := ATags;
|
||||
FDescription := ADescription;
|
||||
FOperationID := APathId;
|
||||
FDeprecated := ADeprecated;
|
||||
fTags := ATags;
|
||||
fDescription := ADescription;
|
||||
fOperationID := AOperationId;
|
||||
fDeprecated := ADeprecated;
|
||||
end;
|
||||
|
||||
function MVCSwagSummaryAttribute.GetTags: TArray<string>;
|
||||
begin
|
||||
Result := FTags.Split([',']);
|
||||
Result := fTags.Split([',']);
|
||||
end;
|
||||
|
||||
{ MVCSwagResponsesAttribute }
|
||||
@ -856,57 +840,58 @@ end;
|
||||
constructor MVCSwagResponsesAttribute.Create(const AStatusCode: Integer; const ADescription: string;
|
||||
const AJsonSchema: string);
|
||||
begin
|
||||
FStatusCode := AStatusCode;
|
||||
FDescription := ADescription;
|
||||
FJsonSchema := AJsonSchema;
|
||||
FJsonSchemaClass := nil;
|
||||
fStatusCode := AStatusCode;
|
||||
fDescription := ADescription;
|
||||
fJsonSchema := AJsonSchema;
|
||||
fJsonSchemaClass := nil;
|
||||
end;
|
||||
|
||||
constructor MVCSwagResponsesAttribute.Create(const AStatusCode: Integer; const ADescription: string;
|
||||
const AJsonSchemaClass: TClass; const AIsArray: Boolean);
|
||||
begin
|
||||
Create(AStatusCode, ADescription, '');
|
||||
FJsonSchemaClass := AJsonSchemaClass;
|
||||
FIsArray := AIsArray;
|
||||
fJsonSchemaClass := AJsonSchemaClass;
|
||||
fIsArray := AIsArray;
|
||||
end;
|
||||
|
||||
{ MVCSwagParamAttribute }
|
||||
|
||||
constructor MVCSwagParamAttribute.Create(const AParamLocation: TMVCSwagParamLocation; const AParamName,
|
||||
AParamDescription: string; const AParamType: TMVCSwagParamType; const ARequired: Boolean; const AJsonSchema: string);
|
||||
constructor MVCSwagParamAttribute.Create(const AParamLocation: TMVCSwagParamLocation;
|
||||
const AParamName, AParamDescription: string; const AParamType: TMVCSwagParamType; const ARequired: Boolean;
|
||||
const AJsonSchema: string);
|
||||
begin
|
||||
FParamLocation := AParamLocation;
|
||||
FParamName := AParamName;
|
||||
FParamDescription := AParamDescription;
|
||||
FParamType := AParamType;
|
||||
FRequired := ARequired;
|
||||
FJsonSchema := AJsonSchema;
|
||||
FJsonSchemaClass := nil;
|
||||
fParamLocation := AParamLocation;
|
||||
fParamName := AParamName;
|
||||
fParamDescription := AParamDescription;
|
||||
fParamType := AParamType;
|
||||
fRequired := ARequired;
|
||||
fJsonSchema := AJsonSchema;
|
||||
fJsonSchemaClass := nil;
|
||||
end;
|
||||
|
||||
constructor MVCSwagParamAttribute.Create(const AParamLocation: TMVCSwagParamLocation; const AParamName,
|
||||
AParamDescription: string; const AJsonSchemaClass: TClass; const AParamType: TMVCSwagParamType;
|
||||
constructor MVCSwagParamAttribute.Create(const AParamLocation: TMVCSwagParamLocation;
|
||||
const AParamName, AParamDescription: string; const AJsonSchemaClass: TClass; const AParamType: TMVCSwagParamType;
|
||||
const ARequired: Boolean);
|
||||
begin
|
||||
Create(AParamLocation, AParamName, AParamDescription, AParamType, ARequired, '');
|
||||
FJsonSchemaClass := AJsonSchemaClass;
|
||||
fJsonSchemaClass := AJsonSchemaClass;
|
||||
end;
|
||||
|
||||
{ MVCSwagJsonSchemaFieldAttribute }
|
||||
{ MVCSwagJSONSchemaFieldAttribute }
|
||||
|
||||
constructor MVCSwagJsonSchemaFieldAttribute.Create(const AFieldName, ADescription: string; const ARequired,
|
||||
ANullable: Boolean);
|
||||
constructor MVCSwagJSONSchemaFieldAttribute.Create(const AFieldName, ADescription: string;
|
||||
const ARequired, ANullable: Boolean);
|
||||
begin
|
||||
Create(stUnknown, AFieldName, ADescription, ARequired, ANullable);
|
||||
end;
|
||||
|
||||
constructor MVCSwagJsonSchemaFieldAttribute.Create(const ASchemaFieldType: TMVCSwagSchemaType; const AFieldName,
|
||||
ADescription: string; const ARequired, ANullable: Boolean);
|
||||
constructor MVCSwagJSONSchemaFieldAttribute.Create(const ASchemaFieldType: TMVCSwagSchemaType;
|
||||
const AFieldName, ADescription: string; const ARequired, ANullable: Boolean);
|
||||
begin
|
||||
FSchemaFieldType := ASchemaFieldType;
|
||||
FFieldName := AFieldName;
|
||||
FDescription := ADescription;
|
||||
FRequired := ARequired;
|
||||
fDescription := ADescription;
|
||||
fRequired := ARequired;
|
||||
FNullable := ANullable;
|
||||
end;
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
const
|
||||
DMVCFRAMEWORK_VERSION = '3.2.0 (boron) RC1';
|
||||
DMVCFRAMEWORK_VERSION = '3.2.0 (boron) RC2';
|
@ -53,7 +53,7 @@ type
|
||||
FName: string;
|
||||
|
||||
// The MVCListOfAttribute attribute can be placed in Field or Property
|
||||
[MVCListOf(TNote)]
|
||||
//[MVCListOf(TNote)]
|
||||
FNotes: TObjectList<TNote>;
|
||||
public
|
||||
constructor Create;
|
||||
@ -63,7 +63,7 @@ type
|
||||
[MVCNameAs('Name')]
|
||||
property name: string read FName write FName;
|
||||
|
||||
[MVCListOf(TNote)]
|
||||
// [MVCListOf(TNote)]
|
||||
property Notes: TObjectList<TNote> read FNotes write FNotes;
|
||||
end;
|
||||
|
||||
@ -82,10 +82,10 @@ type
|
||||
FDepartment: TDepartment;
|
||||
FDepartmentNull: TDepartment;
|
||||
|
||||
[MVCListOf(TNote)]
|
||||
// [MVCListOf(TNote)]
|
||||
FNotes: TObjectList<TNote>;
|
||||
|
||||
[MVCListOf(TNote)]
|
||||
// [MVCListOf(TNote)]
|
||||
FNotesEmpty: TObjectList<TNote>;
|
||||
|
||||
// The MVCValueAsTypeAttribute attribute can be placed in Field or Property
|
||||
@ -117,10 +117,10 @@ type
|
||||
property Department: TDepartment read FDepartment write FDepartment;
|
||||
property DepartmentNull: TDepartment read FDepartmentNull write FDepartmentNull;
|
||||
|
||||
[MVCListOf(TNote)]
|
||||
//[MVCListOf(TNote)]
|
||||
property Notes: TObjectList<TNote> read FNotes;
|
||||
|
||||
[MVCListOf(TNote)]
|
||||
//[MVCListOf(TNote)]
|
||||
property NotesEmpty: TObjectList<TNote> read FNotesEmpty;
|
||||
|
||||
[MVCValueAsType(System.TypeInfo(string))]
|
||||
|
Loading…
Reference in New Issue
Block a user