Small FIXES for ActiveRecordController

This commit is contained in:
Daniele Teti 2020-06-18 14:49:06 +02:00
parent ad23c85469
commit e76ece994e
7 changed files with 129 additions and 35 deletions

View File

@ -652,6 +652,7 @@ end;
- Fixed! [issue38](https://github.com/danieleteti/delphimvcframework/issues/38)
- Fixed! [issue140](https://github.com/danieleteti/delphimvcframework/issues/140)
- Fixed! [issue161](https://github.com/danieleteti/delphimvcframework/issues/161)
- Fixed! [issue184](https://github.com/danieleteti/delphimvcframework/issues/184)
- Fixed! [issue278](https://github.com/danieleteti/delphimvcframework/issues/278)
- Fixed! [issue164](https://github.com/danieleteti/delphimvcframework/issues/164)

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{848C41EB-8EF5-472E-8C10-A70151A657B3}</ProjectGuid>
<ProjectVersion>18.8</ProjectVersion>
<ProjectVersion>19.0</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>isapiapp.dpr</MainSource>
<Base>True</Base>
@ -686,6 +686,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -708,6 +718,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -807,6 +827,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -818,6 +848,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -862,6 +902,26 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
@ -883,6 +943,7 @@
<DeployClass Name="ProjectiOSDeviceResourceRules"/>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSLaunchScreen"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>

View File

@ -51,7 +51,8 @@ type
function GetMaxRecordCount: Integer;
function CheckAuthorization(aClass: TMVCActiveRecordClass; aAction: TMVCActiveRecordAction): Boolean; virtual;
public
constructor Create(const aConnectionFactory: TFunc<TFDConnection>; const aAuthorization: TMVCActiveRecordAuthFunc = nil); reintroduce;
constructor Create(const aConnectionFactory: TFunc<TFDConnection>;
const aAuthorization: TMVCActiveRecordAuthFunc = nil); reintroduce;
destructor Destroy; override;
[MVCPath('/($entityname)')]
@ -90,6 +91,7 @@ type
constructor Create(AList: TMVCActiveRecordList; AOwns: Boolean = True); virtual;
destructor Destroy; override;
[MVCListOf(TMVCActiveRecord)]
[MVCNameAs('data')]
property Items: TMVCActiveRecordList read FList;
[MVCNameAs('meta')]
property Metadata: TMVCStringDictionary read FMetadata;
@ -151,7 +153,8 @@ begin
lInstance.Free;
end;
lResp := TMVCActiveRecordListResponse.Create(TMVCActiveRecord.SelectRQL(lARClassRef, lRQL, GetMaxRecordCount), True);
lResp := TMVCActiveRecordListResponse.Create(TMVCActiveRecord.SelectRQL(lARClassRef, lRQL,
GetMaxRecordCount), True);
try
lResp.Metadata.Add('count', lResp.Items.Count.ToString);
Render(lResp);
@ -179,7 +182,14 @@ begin
begin
lJSON := TJsonObject.Parse(Context.Request.Body) as TJsonObject;
try
lRQL := lJSON.s['rql'];
if Assigned(lJSON) then
begin
lRQL := lJSON.s['rql'];
end
else
begin
lRQL := '';
end;
finally
lJSON.Free;
end;
@ -208,7 +218,7 @@ begin
if not ActiveRecordMappingRegistry.FindEntityClassByURLSegment(entityname, lARClass) then
begin
raise EMVCException.Create('Cannot find class for entity');
raise EMVCException.CreateFmt(http_status.NotFound, 'Cannot find entity %s', [entityname]);
end;
lAR := lARClass.Create;
try
@ -236,7 +246,8 @@ begin
Result := StrToIntDef(Config[TMVCConfigKey.MaxEntitiesRecordCount], 20);
end;
function TMVCActiveRecordController.CheckAuthorization(aClass: TMVCActiveRecordClass; aAction: TMVCActiveRecordAction): Boolean;
function TMVCActiveRecordController.CheckAuthorization(aClass: TMVCActiveRecordClass;
aAction: TMVCActiveRecordAction): Boolean;
begin
if Assigned(fAuthorization) then
begin
@ -287,7 +298,7 @@ begin
if not ActiveRecordMappingRegistry.FindEntityClassByURLSegment(entityname, lARClass) then
begin
raise EMVCException.Create('Cannot find class for entity');
raise EMVCException.CreateFmt(http_status.NotFound, 'Cannot find entity %s', [entityname]);
end;
lAR := lARClass.Create;
try
@ -299,10 +310,8 @@ begin
Context.Request.BodyFor<TMVCActiveRecord>(lAR);
lAR.Insert;
StatusCode := http_status.Created;
//Context.Response.CustomHeaders.AddPair('X-REF', Context.Request.PathInfo + '/' + lAR.GetPK.AsInt64.ToString);
Context.Response.CustomHeaders.Add('X-REF:' + Context.Request.PathInfo + '/' + lAR.GetPK.AsInt64.ToString);
// StatusCode := http_status.Created;
Context.Response.CustomHeaders.Values['X-REF'] := Context.Request.PathInfo + '/' + lAR.GetPK.AsInt64.ToString;
if Context.Request.QueryStringParam('refresh').ToLower = 'true' then
begin
Render(http_status.Created, entityname.ToLower + ' created', '', lAR);
@ -327,16 +336,16 @@ begin
if ActiveRecordMappingRegistry.FindProcessorByURLSegment(entityname, lProcessor) then
begin
lHandled := False;
lProcessor.UpdateEntity(Context, self, entityname,id ,lHandled);
lProcessor.UpdateEntity(Context, self, entityname, id, lHandled);
if lHandled then
begin
Exit;
end;
end;
// lAR := ActiveRecordMappingRegistry.GetEntityByURLSegment(entityname).Create;
if not ActiveRecordMappingRegistry.FindEntityClassByURLSegment(entityname, lARClass) then
begin
raise EMVCException.Create('Cannot find class for entity');
raise EMVCException.CreateFmt(http_status.NotFound, 'Cannot find class for entity %s', [entityname]);
end;
lAR := lARClass.Create;
try
@ -347,13 +356,11 @@ begin
end;
lAR.CheckAction(TMVCEntityAction.eaUpdate);
if not lAR.LoadByPK(id) then
raise EMVCException.Create('Cannot find entity');
raise EMVCException.CreateFmt(http_status.NotFound, 'Cannot find entity %s', [entityname]);
Context.Request.BodyFor<TMVCActiveRecord>(lAR);
lAR.SetPK(id);
lAR.Update;
//Context.Response.CustomHeaders.AddPair('X-REF', Context.Request.PathInfo);
Context.Response.CustomHeaders.Add('X-REF:' + Context.Request.PathInfo);
Context.Response.CustomHeaders.Values['X-REF'] := Context.Request.PathInfo;
if Context.Request.QueryStringParam('refresh').ToLower = 'true' then
begin
Render(http_status.OK, entityname.ToLower + ' updated', '', lAR);
@ -372,22 +379,27 @@ var
lAR: TMVCActiveRecord;
lARClass: TMVCActiveRecordClass;
begin
// lAR := ActiveRecordMappingRegistry.GetEntityByURLSegment(entityname).Create;
if not ActiveRecordMappingRegistry.FindEntityClassByURLSegment(entityname, lARClass) then
begin
raise EMVCException.Create('Cannot find class for entity');
raise EMVCException.CreateFmt(http_status.NotFound, 'Cannot find class for entity %s', [entityname]);
end;
lAR := lARClass.Create;
try
if not CheckAuthorization(TMVCActiveRecordClass(lAR), TMVCActiveRecordAction.Delete) then
if not CheckAuthorization(TMVCActiveRecordClass(lAR.ClassType) { TMVCActiveRecordClass(lAR) } ,
TMVCActiveRecordAction.Delete) then
begin
Render(TMVCErrorResponse.Create(http_status.Forbidden, 'Cannot delete ' + entityname, ''));
Exit;
end;
if not lAR.LoadByPK(id) then
raise EMVCException.Create('Cannot find entity');
lAR.SetPK(id);
lAR.Delete;
{
HTTP DELETE is an idempotent operation. Invoking it multiple times consecutively must result in
the same behavior as the first. Meaning: you shouldn't return HTTP 404.
}
if lAR.LoadByPK(id) then
begin
lAR.SetPK(id);
lAR.Delete;
end;
Render(http_status.OK, entityname.ToLower + ' deleted');
finally
lAR.Free;

View File

@ -643,6 +643,7 @@ implementation
uses
IdCoder3to4,
System.NetEncoding,
System.Character,
MVCFramework.Serializer.JsonDataObjects, MVCFramework.Serializer.Commons;
var

View File

@ -74,6 +74,8 @@ function GetConsoleBufferSize: TMVCConsoleSize;
procedure ClrScr;
function GetCh: Char;
procedure WaitForReturn;
procedure SaveColors;
procedure RestoreSavedColors;
function ColorName(const color: TConsoleColor): String;
@ -86,8 +88,8 @@ const
ESC = Chr(27);
var
GForeGround: Integer;
GBackGround: Integer;
GForeGround, GSavedForeGround: Integer;
GBackGround, GSavedBackGround: Integer;
GOutHandle: THandle = INVALID_HANDLE_VALUE;
GInputHandle: THandle = INVALID_HANDLE_VALUE;
@ -96,6 +98,7 @@ begin
Result := GetEnumName(TypeInfo(TConsoleColor), Ord(color));
end;
{$IFDEF LINUX}
procedure WaitForReturn;
begin
@ -282,6 +285,20 @@ begin
UpdateMode;
end;
procedure SaveColors;
begin
GSavedForeGround := GForeGround;
GSavedBackGround := GBackGround;
end;
procedure RestoreSavedColors;
begin
GForeGround := GSavedForeGround;
GBackGround := GSavedBackGround;
UpdateMode;
end;
initialization
Init;

View File

@ -1279,7 +1279,7 @@ begin
begin
{$IFDEF AUTOREFCOUNT}
if TMVCSerializerHelper.IsAPropertyToSkip(Prop.Name) then
if TMVCSerializerHelper.IsAPropertyToSkip(lProp.Name) then
continue;
{$ENDIF}
@ -1291,8 +1291,10 @@ begin
lKeyName := TMVCSerializerHelper.GetKeyName(lProp, lObjType);
JsonDataValueToAttribute(AJsonObject, lKeyName, lAttributeValue, AType, AIgnoredAttributes,
lProp.GetAttributes);
if (not lAttributeValue.IsEmpty) and lProp.IsWritable then
if (not lAttributeValue.IsEmpty) and (not lAttributeValue.IsObject) and lProp.IsWritable then
begin
lProp.SetValue(AObject, lAttributeValue);
end;
end;
end;
except

View File

@ -146,12 +146,6 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="TestServer" Configuration="CI" Class="ProjectOutput">
<Platform Name="Linux64">
<RemoteName>TestServer</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\www\index.html" Configuration="CI" Class="File">
<Platform Name="Linux64">
<RemoteDir>.\www</RemoteDir>
@ -159,6 +153,12 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="TestServer" Configuration="CI" Class="ProjectOutput">
<Platform Name="Linux64">
<RemoteName>TestServer</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\customers.json" Configuration="CI" Class="File">
<Platform Name="Linux64">
<RemoteName>customers.json</RemoteName>