Changed the behavior of the JWT LiveValidityWindows

Added milligram.css to some samples
This commit is contained in:
Daniele Teti 2018-05-17 21:55:32 +02:00
parent 34bc5e0638
commit a4381ec719
24 changed files with 831 additions and 236 deletions

View File

@ -0,0 +1,602 @@
/*!
* Milligram v1.3.0
* https://milligram.github.io
*
* Copyright (c) 2017 CJ Patoilo
* Licensed under the MIT license
*/
*,
*:after,
*:before {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-size: 62.5%;
}
body {
color: #606c76;
font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
font-size: 1.6em;
font-weight: 300;
letter-spacing: .01em;
line-height: 1.6;
}
blockquote {
border-left: 0.3rem solid #d1d1d1;
margin-left: 0;
margin-right: 0;
padding: 1rem 1.5rem;
}
blockquote *:last-child {
margin-bottom: 0;
}
.button,
button,
input[type='button'],
input[type='reset'],
input[type='submit'] {
background-color: #9b4dca;
border: 0.1rem solid #9b4dca;
border-radius: .4rem;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 1.1rem;
font-weight: 700;
height: 3.8rem;
letter-spacing: .1rem;
line-height: 3.8rem;
padding: 0 3.0rem;
text-align: center;
text-decoration: none;
text-transform: uppercase;
white-space: nowrap;
}
.button:focus, .button:hover,
button:focus,
button:hover,
input[type='button']:focus,
input[type='button']:hover,
input[type='reset']:focus,
input[type='reset']:hover,
input[type='submit']:focus,
input[type='submit']:hover {
background-color: #606c76;
border-color: #606c76;
color: #fff;
outline: 0;
}
.button[disabled],
button[disabled],
input[type='button'][disabled],
input[type='reset'][disabled],
input[type='submit'][disabled] {
cursor: default;
opacity: .5;
}
.button[disabled]:focus, .button[disabled]:hover,
button[disabled]:focus,
button[disabled]:hover,
input[type='button'][disabled]:focus,
input[type='button'][disabled]:hover,
input[type='reset'][disabled]:focus,
input[type='reset'][disabled]:hover,
input[type='submit'][disabled]:focus,
input[type='submit'][disabled]:hover {
background-color: #9b4dca;
border-color: #9b4dca;
}
.button.button-outline,
button.button-outline,
input[type='button'].button-outline,
input[type='reset'].button-outline,
input[type='submit'].button-outline {
background-color: transparent;
color: #9b4dca;
}
.button.button-outline:focus, .button.button-outline:hover,
button.button-outline:focus,
button.button-outline:hover,
input[type='button'].button-outline:focus,
input[type='button'].button-outline:hover,
input[type='reset'].button-outline:focus,
input[type='reset'].button-outline:hover,
input[type='submit'].button-outline:focus,
input[type='submit'].button-outline:hover {
background-color: transparent;
border-color: #606c76;
color: #606c76;
}
.button.button-outline[disabled]:focus, .button.button-outline[disabled]:hover,
button.button-outline[disabled]:focus,
button.button-outline[disabled]:hover,
input[type='button'].button-outline[disabled]:focus,
input[type='button'].button-outline[disabled]:hover,
input[type='reset'].button-outline[disabled]:focus,
input[type='reset'].button-outline[disabled]:hover,
input[type='submit'].button-outline[disabled]:focus,
input[type='submit'].button-outline[disabled]:hover {
border-color: inherit;
color: #9b4dca;
}
.button.button-clear,
button.button-clear,
input[type='button'].button-clear,
input[type='reset'].button-clear,
input[type='submit'].button-clear {
background-color: transparent;
border-color: transparent;
color: #9b4dca;
}
.button.button-clear:focus, .button.button-clear:hover,
button.button-clear:focus,
button.button-clear:hover,
input[type='button'].button-clear:focus,
input[type='button'].button-clear:hover,
input[type='reset'].button-clear:focus,
input[type='reset'].button-clear:hover,
input[type='submit'].button-clear:focus,
input[type='submit'].button-clear:hover {
background-color: transparent;
border-color: transparent;
color: #606c76;
}
.button.button-clear[disabled]:focus, .button.button-clear[disabled]:hover,
button.button-clear[disabled]:focus,
button.button-clear[disabled]:hover,
input[type='button'].button-clear[disabled]:focus,
input[type='button'].button-clear[disabled]:hover,
input[type='reset'].button-clear[disabled]:focus,
input[type='reset'].button-clear[disabled]:hover,
input[type='submit'].button-clear[disabled]:focus,
input[type='submit'].button-clear[disabled]:hover {
color: #9b4dca;
}
code {
background: #f4f5f6;
border-radius: .4rem;
font-size: 86%;
margin: 0 .2rem;
padding: .2rem .5rem;
white-space: nowrap;
}
pre {
background: #f4f5f6;
border-left: 0.3rem solid #9b4dca;
overflow-y: hidden;
}
pre > code {
border-radius: 0;
display: block;
padding: 1rem 1.5rem;
white-space: pre;
}
hr {
border: 0;
border-top: 0.1rem solid #f4f5f6;
margin: 3.0rem 0;
}
input[type='email'],
input[type='number'],
input[type='password'],
input[type='search'],
input[type='tel'],
input[type='text'],
input[type='url'],
textarea,
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: transparent;
border: 0.1rem solid #d1d1d1;
border-radius: .4rem;
box-shadow: none;
box-sizing: inherit;
height: 3.8rem;
padding: .6rem 1.0rem;
width: 100%;
}
input[type='email']:focus,
input[type='number']:focus,
input[type='password']:focus,
input[type='search']:focus,
input[type='tel']:focus,
input[type='text']:focus,
input[type='url']:focus,
textarea:focus,
select:focus {
border-color: #9b4dca;
outline: 0;
}
select {
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="#d1d1d1" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>') center right no-repeat;
padding-right: 3.0rem;
}
select:focus {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="#9b4dca" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>');
}
textarea {
min-height: 6.5rem;
}
label,
legend {
display: block;
font-size: 1.6rem;
font-weight: 700;
margin-bottom: .5rem;
}
fieldset {
border-width: 0;
padding: 0;
}
input[type='checkbox'],
input[type='radio'] {
display: inline;
}
.label-inline {
display: inline-block;
font-weight: normal;
margin-left: .5rem;
}
.container {
margin: 0 auto;
max-width: 112.0rem;
padding: 0 2.0rem;
position: relative;
width: 100%;
}
.row {
display: flex;
flex-direction: column;
padding: 0;
width: 100%;
}
.row.row-no-padding {
padding: 0;
}
.row.row-no-padding > .column {
padding: 0;
}
.row.row-wrap {
flex-wrap: wrap;
}
.row.row-top {
align-items: flex-start;
}
.row.row-bottom {
align-items: flex-end;
}
.row.row-center {
align-items: center;
}
.row.row-stretch {
align-items: stretch;
}
.row.row-baseline {
align-items: baseline;
}
.row .column {
display: block;
flex: 1 1 auto;
margin-left: 0;
max-width: 100%;
width: 100%;
}
.row .column.column-offset-10 {
margin-left: 10%;
}
.row .column.column-offset-20 {
margin-left: 20%;
}
.row .column.column-offset-25 {
margin-left: 25%;
}
.row .column.column-offset-33, .row .column.column-offset-34 {
margin-left: 33.3333%;
}
.row .column.column-offset-50 {
margin-left: 50%;
}
.row .column.column-offset-66, .row .column.column-offset-67 {
margin-left: 66.6666%;
}
.row .column.column-offset-75 {
margin-left: 75%;
}
.row .column.column-offset-80 {
margin-left: 80%;
}
.row .column.column-offset-90 {
margin-left: 90%;
}
.row .column.column-10 {
flex: 0 0 10%;
max-width: 10%;
}
.row .column.column-20 {
flex: 0 0 20%;
max-width: 20%;
}
.row .column.column-25 {
flex: 0 0 25%;
max-width: 25%;
}
.row .column.column-33, .row .column.column-34 {
flex: 0 0 33.3333%;
max-width: 33.3333%;
}
.row .column.column-40 {
flex: 0 0 40%;
max-width: 40%;
}
.row .column.column-50 {
flex: 0 0 50%;
max-width: 50%;
}
.row .column.column-60 {
flex: 0 0 60%;
max-width: 60%;
}
.row .column.column-66, .row .column.column-67 {
flex: 0 0 66.6666%;
max-width: 66.6666%;
}
.row .column.column-75 {
flex: 0 0 75%;
max-width: 75%;
}
.row .column.column-80 {
flex: 0 0 80%;
max-width: 80%;
}
.row .column.column-90 {
flex: 0 0 90%;
max-width: 90%;
}
.row .column .column-top {
align-self: flex-start;
}
.row .column .column-bottom {
align-self: flex-end;
}
.row .column .column-center {
-ms-grid-row-align: center;
align-self: center;
}
@media (min-width: 40rem) {
.row {
flex-direction: row;
margin-left: -1.0rem;
width: calc(100% + 2.0rem);
}
.row .column {
margin-bottom: inherit;
padding: 0 1.0rem;
}
}
a {
color: #9b4dca;
text-decoration: none;
}
a:focus, a:hover {
color: #606c76;
}
dl,
ol,
ul {
list-style: none;
margin-top: 0;
padding-left: 0;
}
dl dl,
dl ol,
dl ul,
ol dl,
ol ol,
ol ul,
ul dl,
ul ol,
ul ul {
font-size: 90%;
margin: 1.5rem 0 1.5rem 3.0rem;
}
ol {
list-style: decimal inside;
}
ul {
list-style: circle inside;
}
.button,
button,
dd,
dt,
li {
margin-bottom: 1.0rem;
}
fieldset,
input,
select,
textarea {
margin-bottom: 1.5rem;
}
blockquote,
dl,
figure,
form,
ol,
p,
pre,
table,
ul {
margin-bottom: 2.5rem;
}
table {
border-spacing: 0;
width: 100%;
}
td,
th {
border-bottom: 0.1rem solid #e1e1e1;
padding: 1.2rem 1.5rem;
text-align: left;
}
td:first-child,
th:first-child {
padding-left: 0;
}
td:last-child,
th:last-child {
padding-right: 0;
}
b,
strong {
font-weight: bold;
}
p {
margin-top: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 300;
letter-spacing: -.1rem;
margin-bottom: 2.0rem;
margin-top: 0;
}
h1 {
font-size: 4.6rem;
line-height: 1.2;
}
h2 {
font-size: 3.6rem;
line-height: 1.25;
}
h3 {
font-size: 2.8rem;
line-height: 1.3;
}
h4 {
font-size: 2.2rem;
letter-spacing: -.08rem;
line-height: 1.35;
}
h5 {
font-size: 1.8rem;
letter-spacing: -.05rem;
line-height: 1.5;
}
h6 {
font-size: 1.6rem;
letter-spacing: 0;
line-height: 1.4;
}
img {
max-width: 100%;
}
.clearfix:after {
clear: both;
content: ' ';
display: table;
}
.float-left {
float: left;
}
.float-right {
float: right;
}
/*# sourceMappingURL=milligram.css.map */

View File

@ -1,12 +1,13 @@
* {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
}
.header {
padding-top: 5px;
}
#wineList {
overflow-y: scroll;
height: 80%;
}
.leftArea {
position: absolute;
left: 10px;

View File

@ -1,7 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Cellar</title>
<link rel="stylesheet" href="css/milligram.css" />
<link rel="stylesheet" href="css/styles.css" />
</head>
@ -9,8 +11,8 @@
<div class="header">
<input type="text" id="searchKey" />
<button id="btnSearch">Search</button>
<button id="btnAdd">New Wine</button>
<button class="button" id="btnSearch">Search</button>
<button class="button" id="btnAdd">New Wine</button>
</div>
@ -38,10 +40,12 @@
<input type="text" id="region" name="region" />
<label>Year:</label>
<select id="year" name="year"><option value=""></option></select>
<select id="year" name="year">
<option value=""></option>
</select>
<div class="padding02">
<button id="btnSave">Save</button>
<button id="btnDelete">Delete</button>
<button class="button" id="btnSave">Save</button>
<button class="button" id="btnDelete">Delete</button>
</div>
</div>
@ -58,6 +62,9 @@
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/main.js"></script>
<div class="footer textcenter padding02">The client code of this demo is slightly based on <a target="_blank" href="http://coenraets.org/blog/2011/12/restful-services-with-jquery-php-and-the-slim-framework/">"RESTful services with jQuery, PHP and the Slim Framework"</a></div>
<div class="footer textcenter padding02">The client code of this demo is slightly based on
<a target="_blank" href="http://coenraets.org/blog/2011/12/restful-services-with-jquery-php-and-the-slim-framework/">"RESTful services with jQuery, PHP and the Slim Framework"</a>
</div>
</body>
</html>

View File

@ -55,10 +55,11 @@ implementation
uses
System.SysUtils, System.Classes, System.IOUtils,
WinesBO, MVCFramework.Serializer.Commons;
WinesBO, MVCFramework.Serializer.Commons, MVCFramework.Logger;
procedure TWineCellarApp.FindWines(ctx: TWebContext);
begin
Log.Debug('','MYTAG');
Render(dm.FindWines(ctx.Request.Params['value']));
end;

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{61ADE231-72F2-4E11-8EDD-62C5AFEF0463}</ProjectGuid>
<ProjectVersion>18.3</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>mod_dmvc.dpr</MainSource>
<Base>True</Base>

View File

@ -3,11 +3,27 @@ unit MainDM;
interface
uses
System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.FB, Data.DB,
FireDAC.Comp.Client, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
FireDAC.DApt, FireDAC.Comp.DataSet, FireDAC.Phys.FBDef, FireDAC.VCLUI.Wait;
System.SysUtils,
System.Classes,
FireDAC.Stan.Intf,
FireDAC.Stan.Option,
FireDAC.Stan.Error,
FireDAC.UI.Intf,
FireDAC.Phys.Intf,
FireDAC.Stan.Def,
FireDAC.Stan.Pool,
FireDAC.Stan.Async,
FireDAC.Phys,
FireDAC.Phys.FB,
Data.DB,
FireDAC.Comp.Client,
FireDAC.Stan.Param,
FireDAC.DatS,
FireDAC.DApt.Intf,
FireDAC.DApt,
FireDAC.Comp.DataSet,
FireDAC.Phys.FBDef,
FireDAC.VCLUI.Wait;
type
TdmMain = class(TDataModule)
@ -28,10 +44,13 @@ implementation
procedure TdmMain.ConnectionBeforeConnect(Sender: TObject);
begin
// currently, this demo uses firebird 2.5
{$IFNDEF WINDOWSSERVICE}
// if you want to use firebird 2.5, you can use the file ORDERSMANAGER_FB25.FDB
Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB30.FDB';
// Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB25.FDB';
{$ELSE}
Connection.Params.Values['Database'] := 'C:\DEV\dmvcframework\samples\data\ORDERSMANAGER_FB30.FDB';
{$ENDIF}
end;
end.

View File

@ -6,7 +6,6 @@ object WebModule1: TWebModule1
Default = True
Name = 'DefaultHandler'
PathInfo = '/'
OnAction = WebModule1DefaultHandlerAction
end>
Height = 230
Width = 415

View File

@ -6,8 +6,6 @@ uses System.SysUtils, System.Classes, Web.HTTPApp, mvcframework;
type
TWebModule1 = class(TWebModule)
procedure WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
procedure WebModuleCreate(Sender: TObject);
private
FEngine: TMVCEngine;
@ -26,22 +24,12 @@ uses Controllers.Articles, MVCFramework.Middleware.CORS, MVCFramework.Middleware
{$R *.dfm}
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
Response.Content :=
'<html>' +
'<head><title>Web Server Application</title></head>' +
'<body>Web Server Application</body>' +
'</html>';
end;
procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
FEngine := TMVCEngine.Create(self);
FEngine.AddController(TArticlesController);
FEngine.AddMiddleware(TCORSMiddleware.Create);
FEngine.AddMiddleware(TCompressionMiddleware.Create);
FEngine.AddMiddleware(TCompressionMiddleware.Create(256));
end;

View File

@ -82,7 +82,6 @@ object Form5: TForm5
Caption = 'Get a protected resource'
TabOrder = 0
OnClick = btnGetClick
ExplicitTop = 2
end
object btnLOGIN: TButton
AlignWithMargins = True

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{7B54055A-5749-4136-9FE2-35FDBEEA874C}</ProjectGuid>
<ProjectVersion>18.2</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>JWTServer.dpr</MainSource>
<Base>True</Base>

View File

@ -27,7 +27,6 @@ implementation
{$R *.dfm}
uses
AppControllerU,
System.Generics.Collections,
@ -45,11 +44,12 @@ begin
JWT.Claims.Issuer := 'Delphi MVC Framework JWT Middleware Sample';
JWT.Claims.NotBefore := Now - OneMinute * 5; // valid since 5 minutes ago
JWT.Claims.IssuedAt := Now;
JWT.Claims.ExpirationTime := Now + OneSecond * 30;
JWT.CustomClaims['mycustomvalue'] := 'hello there';
// Here we dont use a fixed ExpirationTime but a LiveValidityWindowInSeconds
// to make the ExpirationTime dynamic, incrementing the
// ExpirationTime by LiveValidityWindowInSeconds seconds at each request
JWT.LiveValidityWindowInSeconds := 5; // 60 * 60; // 1 hour
JWT.LiveValidityWindowInSeconds := 10; // 60 * 60; // 1 hour
end;
MVC := TMVCEngine.Create(Self);
@ -57,17 +57,9 @@ begin
MVC.Config[TMVCConfigKey.SessionTimeout] := '30';
MVC.Config[TMVCConfigKey.DefaultContentType] := 'text/html';
MVC.AddController(TApp1MainController).AddController(TAdminController)
.AddMiddleware(TMVCJWTAuthenticationMiddleware.Create(
TAuthenticationSample.Create,
lClaimsSetup,
'mys3cr37',
'/login',
[
TJWTCheckableClaim.ExpirationTime,
TJWTCheckableClaim.NotBefore,
TJWTCheckableClaim.IssuedAt
],
0 // just for test, Leeway seconds is zero.
.AddMiddleware(TMVCJWTAuthenticationMiddleware.Create(TAuthenticationSample.Create, lClaimsSetup, 'mys3cr37',
'/login', [TJWTCheckableClaim.ExpirationTime, TJWTCheckableClaim.NotBefore, TJWTCheckableClaim.IssuedAt], 0
// just for test, Leeway seconds is zero.
));
end;

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{E7317702-64D3-4A65-8734-030F3AE3DBBC}</ProjectGuid>
<ProjectVersion>18.2</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>JWTClient.dpr</MainSource>
<Base>True</Base>

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{0388D146-2B8B-427B-AEDD-EFD5F51D3139}</ProjectGuid>
<ProjectVersion>18.2</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>MiddlewareSamples.dpr</MainSource>
<Base>True</Base>

View File

@ -4,7 +4,6 @@ program OutputCacheWithRedis;
uses
System.SysUtils,
Winapi.Windows,
IdHTTPWebBrokerBridge,
Web.WebReq,
Web.WebBroker,
@ -20,9 +19,6 @@ uses
procedure RunServer(APort: Integer);
var
LInputRecord: TInputRecord;
LEvent: DWord;
LHandle: THandle;
LServer: TIdHTTPWebBrokerBridge;
begin
Writeln(Format('Starting "OutputCacheWithRedis" HTTP Server or port %d', [APort]));
@ -32,16 +28,8 @@ begin
LServer.ListenQueue := 200;
LServer.MaxConnections := 5000;
LServer.Active := True;
Writeln('Press ESC to stop the server');
LHandle := GetStdHandle(STD_INPUT_HANDLE);
while True do
begin
Win32Check(ReadConsoleInput(LHandle, LInputRecord, 1, LEvent));
if (LInputRecord.EventType = KEY_EVENT) and
LInputRecord.Event.KeyEvent.bKeyDown and
(LInputRecord.Event.KeyEvent.wVirtualKeyCode = VK_ESCAPE) then
break;
end;
Writeln('Press RETURN to stop the server');
ReadLn;
finally
LServer.Free;
end;

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{BE3A3D14-17E0-45C1-BD21-4710DE4CBCC2}</ProjectGuid>
<ProjectVersion>18.2</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>OutputCacheWithRedis.dpr</MainSource>
<Base>True</Base>

View File

@ -64,8 +64,6 @@ type
{ Public declarations }
end;
var
MyDataModule: TMyDataModule;
implementation

View File

@ -229,7 +229,7 @@ begin
lDM := TMyDataModule.Create(nil);
try
lDM.qryCustomers.Open;
Render(lDM.qryCustomers);
Render(lDM.qryCustomers, False);
finally
lDM.Free;
end;

View File

@ -404,37 +404,37 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\renders\default.txaPackage" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\renders\default.txvpck" Configuration="Debug" Class="ProjectFile">
<Platform Name="Linux64">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\RenderSampleControllerU\default.txaPackage" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\renders1\default.txvpck" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\renders\default.txvpck" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\renders.exe" Configuration="Release" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>renders.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\renders\default.txvpck" Configuration="Debug" Class="ProjectFile">
<Platform Name="Linux64">
<DeployFile LocalName="ModelSupport_renders\renders1\default.txvpck" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="ModelSupport_renders\renders\default.txaPackage" Configuration="Debug" Class="ProjectFile">
<DeployFile LocalName="ModelSupport_renders\renders\default.txvpck" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>

View File

@ -11,7 +11,7 @@ type
TRoutingSampleController = class(TMVCController)
public
[MVCPath('/')]
procedure Index(CTX: TWebContext);
procedure Index;
{ This action requires that the ACCEPT header is text/plain to be invocated }
[MVCHTTPMethod([httpGet])]
@ -57,7 +57,7 @@ begin
lPerson := Context.Request.BodyAs<TPerson>;
lPerson.Validate;
// SavePerson(lPerson);
Render(201, 'Person created');
Render(HTTP_STATUS.Created, 'Person created');
end;
procedure TRoutingSampleController.DeletePerson(const id: Integer);
@ -83,7 +83,7 @@ begin
Render(P);
end;
procedure TRoutingSampleController.Index(CTX: TWebContext);
procedure TRoutingSampleController.Index;
begin
Render('This is the root path');
end;

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{F9CBCE21-869A-478F-992C-88FCAC97BC8B}</ProjectGuid>
<ProjectVersion>18.2</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>SessionSample.dpr</MainSource>
<Base>True</Base>

View File

@ -1,12 +1,13 @@
* {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
}
.header {
padding-top: 5px;
}
#wineList {
overflow-y: scroll;
height: 80%;
}
.leftArea {
position: absolute;
left: 10px;

View File

@ -1,7 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Cellar</title>
<link rel="stylesheet" href="css/milligram.css" />
<link rel="stylesheet" href="css/styles.css" />
</head>
@ -9,8 +11,8 @@
<div class="header">
<input type="text" id="searchKey" />
<button id="btnSearch">Search</button>
<button id="btnAdd">New Wine</button>
<button class="button" id="btnSearch">Search</button>
<button class="button" id="btnAdd">New Wine</button>
</div>
@ -38,10 +40,12 @@
<input type="text" id="region" name="region" />
<label>Year:</label>
<select id="year" name="year"><option value=""></option></select>
<select id="year" name="year">
<option value=""></option>
</select>
<div class="padding02">
<button id="btnSave">Save</button>
<button id="btnDelete">Delete</button>
<button class="button" id="btnSave">Save</button>
<button class="button" id="btnDelete">Delete</button>
</div>
</div>
@ -58,6 +62,9 @@
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/main.js"></script>
<div class="footer textcenter padding02">The client code of this demo is slightly based on <a target="_blank" href="http://coenraets.org/blog/2011/12/restful-services-with-jquery-php-and-the-slim-framework/">"RESTful services with jQuery, PHP and the Slim Framework"</a></div>
<div class="footer textcenter padding02">The client code of this demo is slightly based on
<a target="_blank" href="http://coenraets.org/blog/2011/12/restful-services-with-jquery-php-and-the-slim-framework/">"RESTful services with jQuery, PHP and the Slim Framework"</a>
</div>
</body>
</html>

View File

@ -208,8 +208,9 @@ type
property LeewaySeconds: Cardinal read FLeewaySeconds;
property RegClaimsToChecks: TJWTCheckableClaims read FRegClaimsToChecks write SetChecks;
/// <summary>
/// Use LiveValidityWindowInSeconds to make the ExpirationTime dynamic at each request,
/// incrementing the ExpirationTime by LiveValidityWindowInSeconds seconds at each request
/// Use LiveValidityWindowInSeconds to make the ExpirationTime dynamic at each request.
/// ExpirationTime will be incremented by LiveValidityWindowInSeconds seconds automatically
/// if the remaining seconds are less than the LiveValidityWindowInSeconds.
/// </summary>
property LiveValidityWindowInSeconds: Cardinal read GetLiveValidityWindowInSeconds write SetLiveValidityWindowInSeconds;
end;

View File

@ -50,67 +50,40 @@ type
FLeewaySeconds: Cardinal;
FLoginURLSegment: string;
protected
procedure InternalRender(
AJSONValue: TJSONValue;
AContentType: string;
AContentEncoding: string;
AContext: TWebContext;
AInstanceOwner: Boolean = True
);
function NeedsToBeExtended(const JWTValue: TJWT): Boolean;
procedure ExtendExpirationTime(const JWTValue: TJWT);
procedure InternalRender(AJSONValue: TJSONValue; AContentType: string; AContentEncoding: string;
AContext: TWebContext; AInstanceOwner: Boolean = True);
procedure RenderError(
const AErrorCode: UInt16;
const AErrorMessage: string;
const AContext: TWebContext;
const AErrorClassName: string = ''
);
procedure RenderError(const AErrorCode: UInt16; const AErrorMessage: string; const AContext: TWebContext;
const AErrorClassName: string = '');
procedure OnBeforeRouting(
AContext: TWebContext;
var AHandled: Boolean
);
procedure OnBeforeRouting(AContext: TWebContext; var AHandled: Boolean);
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);
procedure OnAfterControllerAction(
AContext: TWebContext;
const AActionName: string;
const AHandled: Boolean
);
procedure OnAfterControllerAction(AContext: TWebContext; const AActionName: string; const AHandled: Boolean);
public
constructor Create(AAuthenticationHandler: IMVCAuthenticationHandler;
AConfigClaims: TJWTClaimsSetup;
ASecret: string = 'D3lph1MVCFram3w0rk';
ALoginURLSegment: string = '/login';
AClaimsToCheck: TJWTCheckableClaims = [
TJWTCheckableClaim.ExpirationTime,
TJWTCheckableClaim.NotBefore,
TJWTCheckableClaim.IssuedAt
];
ALeewaySeconds: Cardinal = 300); virtual;
constructor Create(AAuthenticationHandler: IMVCAuthenticationHandler; AConfigClaims: TJWTClaimsSetup;
ASecret: string = 'D3lph1MVCFram3w0rk'; ALoginURLSegment: string = '/login';
AClaimsToCheck: TJWTCheckableClaims = [TJWTCheckableClaim.ExpirationTime, TJWTCheckableClaim.NotBefore,
TJWTCheckableClaim.IssuedAt]; ALeewaySeconds: Cardinal = 300); virtual;
end;
implementation
uses System.NetEncoding, System.DateUtils;
uses
System.NetEncoding,
System.DateUtils,
System.Math;
{ TMVCJWTAuthenticationMiddleware }
constructor TMVCJWTAuthenticationMiddleware.Create(AAuthenticationHandler: IMVCAuthenticationHandler;
AConfigClaims: TJWTClaimsSetup;
ASecret: string = 'D3lph1MVCFram3w0rk';
ALoginURLSegment: string = '/login';
AClaimsToCheck: TJWTCheckableClaims = [
TJWTCheckableClaim.ExpirationTime,
TJWTCheckableClaim.NotBefore,
TJWTCheckableClaim.IssuedAt
];
ALeewaySeconds: Cardinal = 300);
AConfigClaims: TJWTClaimsSetup; ASecret: string = 'D3lph1MVCFram3w0rk'; ALoginURLSegment: string = '/login';
AClaimsToCheck: TJWTCheckableClaims = [TJWTCheckableClaim.ExpirationTime, TJWTCheckableClaim.NotBefore,
TJWTCheckableClaim.IssuedAt]; ALeewaySeconds: Cardinal = 300);
begin
inherited Create;
FAuthenticationHandler := AAuthenticationHandler;
@ -121,8 +94,13 @@ begin
FLeewaySeconds := ALeewaySeconds;
end;
procedure TMVCJWTAuthenticationMiddleware.InternalRender(
AJSONValue: TJSONValue; AContentType, AContentEncoding: string;
procedure TMVCJWTAuthenticationMiddleware.ExtendExpirationTime(const JWTValue: TJWT);
begin
JWTValue.Claims.ExpirationTime := Max(JWTValue.Claims.ExpirationTime, Now) +
(JWTValue.LeewaySeconds + JWTValue.LiveValidityWindowInSeconds) * OneSecond;
end;
procedure TMVCJWTAuthenticationMiddleware.InternalRender(AJSONValue: TJSONValue; AContentType, AContentEncoding: string;
AContext: TWebContext; AInstanceOwner: Boolean);
var
Encoding: TEncoding;
@ -135,9 +113,8 @@ begin
Encoding := TEncoding.GetEncoding(AContentEncoding);
try
AContext.Response.SetContentStream(
TBytesStream.Create(TEncoding.Convert(TEncoding.Default, Encoding, TEncoding.Default.GetBytes(JValue))),
ContentType);
AContext.Response.SetContentStream(TBytesStream.Create(TEncoding.Convert(TEncoding.Default, Encoding,
TEncoding.Default.GetBytes(JValue))), ContentType);
finally
Encoding.Free;
end;
@ -146,16 +123,28 @@ begin
FreeAndNil(AJSONValue)
end;
procedure TMVCJWTAuthenticationMiddleware.OnAfterControllerAction(
AContext: TWebContext; const AActionName: string;
function TMVCJWTAuthenticationMiddleware.NeedsToBeExtended(const JWTValue: TJWT): Boolean;
var
lWillExpireIn: Int64;
begin
lWillExpireIn := SecondsBetween(Now, JWTValue.Claims.ExpirationTime);
Result := lWillExpireIn <= JWTValue.LiveValidityWindowInSeconds;
// Log.Debug('--------------------------', 'EXPIRE');
// Log.DebugFmt('Now : %s', [TimeToStr(Now)], 'EXPIRE');
// Log.DebugFmt('ExpirationTime : %s', [TimeToStr(JWTValue.Claims.ExpirationTime)], 'EXPIRE');
// Log.DebugFmt('WillExpireIn : %d', [lWillExpireIn], 'EXPIRE');
// Log.DebugFmt('LVW : %d', [JWTValue.LiveValidityWindowInSeconds], 'EXPIRE');
// Log.DebugFmt('NeedsToBeExtened: %s', [BoolToStr(Result, True)], 'EXPIRE');
end;
procedure TMVCJWTAuthenticationMiddleware.OnAfterControllerAction(AContext: TWebContext; const AActionName: string;
const AHandled: Boolean);
begin
// Implement as needed
end;
procedure TMVCJWTAuthenticationMiddleware.OnBeforeControllerAction(
AContext: TWebContext; const AControllerQualifiedClassName,
AActionName: string; var AHandled: Boolean);
procedure TMVCJWTAuthenticationMiddleware.OnBeforeControllerAction(AContext: TWebContext;
const AControllerQualifiedClassName, AActionName: string; var AHandled: Boolean);
var
AuthRequired: Boolean;
IsAuthorized: Boolean;
@ -223,15 +212,20 @@ begin
AContext.LoggedUser.LoggedSince := JWTValue.Claims.IssuedAt;
AContext.LoggedUser.CustomData := JWTValue.CustomClaims.AsCustomData;
FAuthenticationHandler.OnAuthorization(AContext.LoggedUser.Roles, AControllerQualifiedClassName, AActionName, IsAuthorized);
FAuthenticationHandler.OnAuthorization(AContext.LoggedUser.Roles, AControllerQualifiedClassName, AActionName,
IsAuthorized);
if IsAuthorized then
begin
if JWTValue.LiveValidityWindowInSeconds > 0 then
begin
JWTValue.Claims.ExpirationTime := Now + JWTValue.LiveValidityWindowInSeconds * OneSecond;
if NeedsToBeExtended(JWTValue) then
begin
ExtendExpirationTime(JWTValue);
// .Claims.ExpirationTime := Now + JWTValue.LiveValidityWindowInSeconds * OneSecond;
AContext.Response.SetCustomHeader('Authentication', 'bearer ' + JWTValue.GetToken);
end;
end;
AHandled := False
end
else
@ -245,8 +239,7 @@ begin
end;
end;
procedure TMVCJWTAuthenticationMiddleware.OnBeforeRouting(
AContext: TWebContext; var AHandled: Boolean);
procedure TMVCJWTAuthenticationMiddleware.OnBeforeRouting(AContext: TWebContext; var AHandled: Boolean);
var
UserName: string;
Password: string;
@ -284,7 +277,8 @@ begin
// these claims are mandatory and managed by the middleware
if not JWTValue.CustomClaims['username'].IsEmpty then
raise EMVCJWTException.Create('Custom claim "username" is reserved and cannot be modified in the JWT setup');
raise EMVCJWTException.Create
('Custom claim "username" is reserved and cannot be modified in the JWT setup');
if not JWTValue.CustomClaims['roles'].IsEmpty then
raise EMVCJWTException.Create('Custom claim "roles" is reserved and cannot be modified in the JWT setup');
@ -294,7 +288,10 @@ begin
if JWTValue.LiveValidityWindowInSeconds > 0 then
begin
JWTValue.Claims.ExpirationTime := Now + (JWTValue.LeewaySeconds + JWTValue.LiveValidityWindowInSeconds) * OneSecond;
if NeedsToBeExtended(JWTValue) then
begin
ExtendExpirationTime(JWTValue);
end;
end;
// setup the current logged user from the JWT
@ -315,12 +312,8 @@ begin
end;
end;
InternalRender(
TJSONObject.Create(TJSONPair.Create('token', JWTValue.GetToken)),
TMVCMediaType.APPLICATION_JSON,
TMVCConstants.DEFAULT_CONTENT_CHARSET,
AContext
);
InternalRender(TJSONObject.Create(TJSONPair.Create('token', JWTValue.GetToken)),
TMVCMediaType.APPLICATION_JSON, TMVCConstants.DEFAULT_CONTENT_CHARSET, AContext);
AHandled := True;
finally
JWTValue.Free;
@ -340,9 +333,8 @@ begin
end;
end;
procedure TMVCJWTAuthenticationMiddleware.RenderError(const AErrorCode: UInt16;
const AErrorMessage: string; const AContext: TWebContext;
const AErrorClassName: string);
procedure TMVCJWTAuthenticationMiddleware.RenderError(const AErrorCode: UInt16; const AErrorMessage: string;
const AContext: TWebContext; const AErrorClassName: string);
var
Jo: TJSONObject;
Status: string;