Swagger PathID renamed to OperationID

Moved MVCRequiresAuthenticationAttribute into MVCFramework.pas
This commit is contained in:
Daniele Teti 2019-10-30 00:21:13 +01:00
parent 3ccd6b6122
commit 51b0efdba4
15 changed files with 467 additions and 40 deletions

View File

@ -53,7 +53,9 @@ begin
MVC.Config[TMVCConfigKey.DocumentRoot] := '..\..\www';
MVC.Config[TMVCConfigKey.SessionTimeout] := '30';
MVC.Config[TMVCConfigKey.DefaultContentType] := 'text/html';
MVC.AddController(TApp1MainController).AddController(TAdminController)
MVC
.AddController(TApp1MainController)
.AddController(TAdminController)
.AddMiddleware(TMVCJWTAuthenticationMiddleware.Create(TAuthenticationSample.Create, 'mys3cr37', '/login', LClaimsSetup,
[TJWTCheckableClaim.ExpirationTime, TJWTCheckableClaim.NotBefore, TJWTCheckableClaim.IssuedAt], 300));
end;

View File

@ -30,8 +30,10 @@ uses
MainControllerU,
System.IOUtils,
MVCFramework.Commons,
MVCFramework.Serializer.Commons,
LoggerPro.FileAppender,
LoggerPro,
System.DateUtils,
MVCFramework.Middleware.Analytics;
var
@ -51,8 +53,11 @@ begin
lLog := TLoggerProFileAppender.Create(5, 2000, AppPath + 'analytics', [], '%s.%2.2d.%s.csv');
TLoggerProFileAppender(lLog).OnLogRow := procedure(const LogItem: TLogItem; out LogRow: string)
begin
LogRow := Format('%s;%s;%s;%s', [datetimetostr(LogItem.TimeStamp),
LogItem.LogTypeAsString, LogItem.LogMessage, LogItem.LogTag]);
LogRow := Format('%s;%s;%s;%s', [
FormatDateTime('yyyy-mm-dd hh:nn:ss', LogItem.TimeStamp),
LogItem.LogTypeAsString,
LogItem.LogMessage,
LogItem.LogTag]);
end;
GLogWriter := BuildLogWriter([lLog]);
end;

View File

@ -54,6 +54,11 @@ type
[MVCPath('/customers')]
procedure GetCustomersAsDataSetWithRefLinks;
[MVCHTTPMethod([httpGET])]
[MVCPath('/customers/withcallback')]
[MVCProduces('application/json')]
procedure GetCustomersWithCallback;
[MVCHTTPMethod([httpGET])]
[MVCPath('/customers/($ID)/asdataset')]
procedure GetCustomer_AsDataSetRecord(const ID: Integer);
@ -371,16 +376,96 @@ begin
Render(lDM.qryCustomers, False,
procedure(const DS: TDataset; const Links: IMVCLinks)
begin
Links.AddRefLink.Add(HATEOAS.HREF, '/customers/' + DS.FieldByName('cust_no').AsString).Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json');
Links.AddRefLink.Add(HATEOAS.HREF, '/customers/' + DS.FieldByName('cust_no').AsString + '/orders')
.Add(HATEOAS.REL, 'orders').Add(HATEOAS._TYPE, 'application/json');
Links
.AddRefLink
.Add(HATEOAS.HREF, '/customers/' + DS.FieldByName('cust_no').AsString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json');
Links
.AddRefLink
.Add(HATEOAS.HREF, '/customers/' + DS.FieldByName('cust_no').AsString + '/orders')
.Add(HATEOAS.REL, 'orders')
.Add(HATEOAS._TYPE, 'application/json');
end);
finally
lDM.Free;
end;
end;
procedure TRenderSampleController.GetCustomersWithCallback;
var
lDM: TMyDataModule;
lSer: TMVCJsonDataObjectsSerializer;
lJArray: TJsonArray;
lJobj: TJsonObject;
begin
lDM := TMyDataModule.Create(nil);
try
lDM.qryCustomers.Open('SELECT * FROM CUSTOMER ORDER BY CUST_NO');
lSer := TMVCJsonDataObjectsSerializer.Create;
try
lJobj := TJsonObject.Create;
lJArray := lJObj.A['customers'];
lSer.DataSetToJsonArray(lDM.qryCustomers, lJArray, TMVCNameCase.ncLowerCase, [],
procedure(const aField: TField; const aJsonObject: TJSONObject;
var Handled: Boolean)
var
lTmp: String;
lPieces: TArray<String>;
begin
//ignore one attribute
if SameText(aField.FieldName, 'contact_last') then
begin
Handled := True;
end;
//change the attribute value
if SameText(aField.FieldName, 'on_hold') then
begin
aJsonObject.B['on_hold'] := not aField.IsNull;
Handled := True;
end;
//change the attribute type!
if SameText(aField.FieldName, 'phone_no') then
begin
lTmp := aField.AsString.Replace('(','').Replace(')','').Replace('-',' ').Replace(' ',' ', [rfReplaceAll]).Trim;
if lTmp.IsEmpty then
begin
Handled := True;
Exit;
end;
lPieces := lTmp.Split([' ']);
aJsonObject.O['phone'].S['intl_prefix'] := lPieces[0];
Delete(lPieces,0,1);
aJsonObject.O['phone'].S['number'] := String.Join('-', lPieces);
Handled := True;
end;
//add an attribute
if SameText(aField.FieldName, 'country') then
begin
aJsonObject.B['is_usa_customer'] := SameText(aField.AsString,'usa');
end;
//merge 2 or more attributes
if SameText(aField.FieldName, 'contact_first') then
begin
aJsonObject.S['contact_full_name'] :=
aField.DataSet.FieldByName('contact_first').AsString + ', ' +
aField.DataSet.FieldByName('contact_last').AsString;
Handled := True;
end;
end);
finally
lSer.Free;
end;
Render(lJobj);
finally
lDM.Free;
end;
end;
procedure TRenderSampleController.GetCustomer_AsDataSetRecord(const ID: Integer);
var
lDM: TMyDataModule;
@ -620,9 +705,17 @@ begin
Render<TPerson>(People, True,
procedure(const APerson: TPerson; const Links: IMVCLinks)
begin
Links.AddRefLink.Add(HATEOAS.HREF, '/people/' + APerson.ID.ToString).Add(HATEOAS.REL, 'self').Add(HATEOAS._TYPE,
'application/json').Add('title', 'Details for ' + APerson.FullName);
Links.AddRefLink.Add(HATEOAS.HREF, '/people').Add(HATEOAS.REL, 'people').Add(HATEOAS._TYPE, 'application/json');
Links
.AddRefLink
.Add(HATEOAS.HREF, '/people/' + APerson.ID.ToString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json')
.Add('title', 'Details for ' + APerson.FullName);
Links
.AddRefLink
.Add(HATEOAS.HREF, '/people')
.Add(HATEOAS.REL, 'people')
.Add(HATEOAS._TYPE, 'application/json');
end);
end;

View File

@ -11,6 +11,7 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnClose = FormClose
OnCreate = FormCreate
PixelsPerInch = 96
@ -27,7 +28,7 @@ object MainForm: TMainForm
Top = 8
Width = 105
Height = 65
Caption = 'Parse'
Caption = 'RQL to SQL'
TabOrder = 0
OnClick = btnParseClick
end
@ -132,7 +133,7 @@ object MainForm: TMainForm
Width = 764
Height = 81
Align = alTop
Caption = 'RQL Backend'
Caption = 'Available RQL Backends'
Columns = 2
TabOrder = 3
end

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{FD44EB2E-3630-4DA7-A18A-D8F572433F4E}</ProjectGuid>
<ProjectVersion>18.6</ProjectVersion>
<ProjectVersion>18.7</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>RQL2SQL.dpr</MainSource>
<Base>True</Base>
@ -87,6 +87,7 @@
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@ -134,10 +135,10 @@
<Source Name="MainSource">RQL2SQL.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k250.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp250.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k250.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp250.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k260.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp260.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k260.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp260.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
@ -213,6 +214,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>
@ -249,6 +256,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>
@ -273,6 +310,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>
@ -392,6 +435,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>
@ -403,6 +457,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>
@ -414,6 +501,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>
@ -425,6 +567,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>
@ -458,6 +710,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>

View File

@ -0,0 +1,40 @@
ne(value,null)
eq(value,null)
eq(value,false)
eq(value,true)
in ( value , [ 1 , 2 , 3 ] )
in ( value , [ 1 , 2 , 3 ] )
in(value,[])
in(value,[1,2,3])
in(name,["daniele","scott"])
and(eq(owneruserid, "%s"),in(status,["ERROR","TO_SEND","NOT_COMPLETED"]))
and(eq(owneruserid, 1),in(status,["ERROR","TO_SEND","NOT_COMPLETED"]))
and(eq(name,"João"),in(codperson,[1,2,3]))
in(codperson,[1,2,3])
eq(name,-1)
contains(nome,"João")
sort(+last_name);limit(0,1)
limit(1,5)
sort(+nome, -cognome)
ge(nome,"pi\ppo");
and ( eq ( nome , "Daniele" ) , eq ( cognome , "Teti" ) );sort(-nome);limit(10,20)
ge(nome,"pi\ppo");limit(0,10)
eq(last_name,"TE\"%20/*TI")*/
ge ( nome, "hello world")
and ( eq ( nome , "Daniele" ) , eq ( cognome , "Teti" ) )
and ( eq ( nome , "Daniele" ) , eq ( cognome , "Teti" ) )
and ( eq ( nome , "Daniele" ) , eq ( cognome , "Teti" ) )
and ( eq ( nome , "Daniele" ) , eq ( cognome , "Teti" ) )
ge(nome,"")
ge(nome,"pi\ppo")
and(eq(nome,"Daniele"),eq(cognome,"Teti"),or(eq(field1,"Ciao"),eq(field2,"Mondo")));sort(+nome,-cognome)
sort(+nome)
and(eq(nome,"Daniele"),eq(cognome,"Teti"),or(eq(field1,"Ciao"),eq(field2,"Mondo")))
and(eq(nome,"Daniele"),eq(cognome,"Teti"), or(eq(field1,"Ciao"),eq(field2,"Mondo")))
and(eq(nome,"Daniele"),eq(cognome,"Teti"))
le(valore,4)
ge(nome,"pippo")
ne(nome,4)
eq(valore,4)
lt(valore,3)
eq(nome,"Daniele")

View File

@ -5,7 +5,8 @@ interface
uses
MVCFramework,
MVCFramework.Commons,
MVCFramework.Swagger.Commons;
MVCFramework.Swagger.Commons,
MVCFramework.Middleware.Authentication.RoleBasedAuthHandler;
const
INDEX_JSON_SCHEMA =
@ -34,7 +35,7 @@ type
public
[MVCPath('')]
[MVCSwagSummary('Status', 'API Status')]
[MVCSwagResponses(200, 'Sucess', INDEX_JSON_SCHEMA)]
[MVCSwagResponses(200, 'Success', INDEX_JSON_SCHEMA)]
[MVCSwagResponses(500, 'Internal Server Error')]
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
[MVCHTTPMethod([httpGET])]
@ -51,6 +52,7 @@ uses
{ TMyController1 }
procedure TMyController1.Index;
var
LObj: TJDOJsonObject;

View File

@ -29,14 +29,15 @@ type
end;
[MVCPath('/person')]
[MVCRequiresAuthentication]
TMyController2 = class(TMVCController)
public
[MVCPath('/($Id)')]
[MVCHTTPMethod([httpGET])]
[MVCSwagSummary('Person', 'List Persons', '66e83aa7-d170-44a7-a502-8f25ddd2a18a')]
[MVCSwagParam(plPath, 'Id', 'Person id', ptInteger)]
[MVCSwagParam(plQuery, 'filter', 'Search filter', ptString)]
[MVCSwagParam(plQuery, 'per_page', 'Items per page', ptInteger)]
[MVCSwagParam(plPath, 'Id', 'Person id', ptInteger, True)]
[MVCSwagParam(plQuery, 'filter', 'Search filter', ptString, False)]
[MVCSwagParam(plQuery, 'per_page', 'Items per page', ptInteger, False)]
[MVCSwagResponses(200, 'Success', TPerson)]
[MVCSwagResponses(500, 'Internal Server Error')]
procedure GetPerson(const Id: Integer);
@ -49,7 +50,6 @@ type
[MVCSwagResponses(401, 'Requires Authentication')]
[MVCSwagResponses(500, 'Internal Server Error')]
[MVCConsumes(TMVCMediaType.APPLICATION_JSON)]
[MVCRequiresAuthentication]
procedure InsertPerson;
end;
@ -78,7 +78,7 @@ var
begin
LPerson := Context.Request.BodyAs<TPerson>;
Render(LPerson);
ResponseStatus(201, 'Created');
ResponseCreated();
end;
initialization

View File

@ -51,7 +51,7 @@ type
implementation
uses
System.SysUtils;
System.SysUtils, System.DateUtils;
{ TMVCAnalyticsMiddleware }
@ -69,12 +69,7 @@ end;
procedure TMVCAnalyticsMiddleware.OnBeforeControllerAction(Context: TWebContext; const AControllerQualifiedClassName, AActionNAme: string;
var Handled: Boolean);
begin
// WriteLn(CSVFile, 'DateTime, IpAddress, ControllerName, ActionName, DomainName, Host');
// WriteLn(CSVFile, DateTimeToStr(Now), ',', Context.Request.ClientIp, ',', AControllerQualifiedClassName, ',', AActionNAme, ',',
// Context.Request.RawWebRequest.Referer, ',', Context.Request.RawWebRequest.Host);
// CloseFile(CSVFile);
FLogWriter.Info(DateTimeToStr(Now) + ';' + Context.Request.ClientIp + ';' + AControllerQualifiedClassName + ';' + AActionNAme + ';' +
FLogWriter.Info(Context.Request.ClientIp + ';' + AControllerQualifiedClassName + ';' + AActionNAme + ';' +
Context.Request.RawWebRequest.Method + ';' + Context.Request.RawWebRequest.PathTranslated + ';' + Context.Request.RawWebRequest.PathInfo
+ ';' + Context.Request.RawWebRequest.Referer + ';' + Context.Request.RawWebRequest.Host, 'analytics');
end;

View File

@ -36,8 +36,6 @@ uses
System.Rtti;
type
MVCRequiresAuthenticationAttribute = class(MVCBaseAttribute);
MVCRoleEval = (reOR, reAND);
MVCRequiresRoleAttribute = class(MVCRequiresAuthenticationAttribute)

View File

@ -78,8 +78,9 @@ type
procedure OnAfterControllerAction(AContext: TWebContext; const AActionName: string; const AHandled: Boolean);
public
/// <remarks>
/// The AAuthorizationHeaderName, AUserNameHeaderName, and APasswordHeaderName parameters do not follow
/// WARNING! The AAuthorizationHeaderName, AUserNameHeaderName, and APasswordHeaderName parameters do not follow
/// the IETF national convention - RFC 6750;
/// Please use the other constructor!
/// </remarks>
constructor Create(AAuthenticationHandler: IMVCAuthenticationHandler; AConfigClaims: TJWTClaimsSetup;
ASecret: string = 'D3lph1MVCFram3w0rk'; ALoginURLSegment: string = '/login';

View File

@ -70,13 +70,13 @@ type
FTags: string;
FDeprecated: Boolean;
FDescription: string;
FPathId: 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 PathId: string read FPathId;
property OperationID: string read FOperationId;
property Deprecated: Boolean read FDeprecated;
end;
@ -372,7 +372,7 @@ begin
begin
ASwagPathOperation.Tags.AddRange(MVCSwagSummaryAttribute(LAttr).GetTags);
ASwagPathOperation.Description := MVCSwagSummaryAttribute(LAttr).Description;
ASwagPathOperation.OperationId := MVCSwagSummaryAttribute(LAttr).PathId;
ASwagPathOperation.OperationId := MVCSwagSummaryAttribute(LAttr).OperationID;
ASwagPathOperation.Deprecated := MVCSwagSummaryAttribute(LAttr).Deprecated;
end;
if LAttr is MVCConsumesAttribute then
@ -391,9 +391,13 @@ begin
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);
end;
ASwagPathOperation.Responses.Add(LSwagResponse.StatusCode, LSwagResponse);
end;
@ -654,12 +658,20 @@ begin
Result := False;
for LAttr in AMethod.GetAttributes do
begin
if LAttr is MVCRequiresAuthenticationAttribute then
begin
Exit(True);
end;
end;
for LAttr in AType.GetAttributes do
begin
if LAttr is MVCRequiresAuthenticationAttribute then
begin
Exit(True);
end;
end;
end;
class function TMVCSwagger.MVCHttpMethodToSwagPathOperation(const AMVCHTTPMethod: TMVCHTTPMethodType):
@ -731,12 +743,12 @@ 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;
FPathId := APathId;
FOperationId := AOperationID;
FDeprecated := ADeprecated;
end;

View File

@ -103,6 +103,10 @@ type
{ public declarations }
end;
MVCRequiresAuthenticationAttribute = class(MVCBaseAttribute)
end;
MVCHTTPMethodsAttribute = class(MVCBaseAttribute)
private
FMVCHTTPMethods: TMVCHTTPMethods;