Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into fix/gridview-inline…
Browse files Browse the repository at this point in the history
…-editing
  • Loading branch information
cafour committed Sep 6, 2019
2 parents f3e80da + d27bbd5 commit a5f2bf0
Show file tree
Hide file tree
Showing 58 changed files with 1,272 additions and 329 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ private static DotvvmConfiguration UseDotVVM(this IApplicationBuilder app, strin
app.UseMiddleware<DotvvmErrorPageMiddleware>();
}

app.UseMiddleware<DotvvmMiddleware>(config, new List<IMiddleware>
{
app.UseMiddleware<DotvvmMiddleware>(config, new List<IMiddleware> {
ActivatorUtilities.CreateInstance<DotvvmCsrfTokenMiddleware>(config.ServiceProvider),
ActivatorUtilities.CreateInstance<DotvvmLocalResourceMiddleware>(app.ApplicationServices),
DotvvmFileUploadMiddleware.TryCreate(app.ApplicationServices),
new DotvvmReturnedFileMiddleware(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public string GenerateToken(IDotvvmRequestContext context)
public void VerifyToken(IDotvvmRequestContext context, string token)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (string.IsNullOrWhiteSpace(token)) throw new SecurityException("CSRF protection token is missing.");
if (string.IsNullOrWhiteSpace(token)) throw new CorruptedCsrfTokenException("CSRF protection token is missing.");

// Construct protector with purposes
var protector = this.protectionProvider.CreateProtector(PURPOSE_TOKEN);
Expand All @@ -69,7 +69,7 @@ public void VerifyToken(IDotvvmRequestContext context, string token)
catch (Exception ex)
{
// Incorrect Base64 formatting of crypto protection error
throw new SecurityException("CSRF protection token is invalid.", ex);
throw new CorruptedCsrfTokenException("CSRF protection token is invalid.", ex);
}

// Get SID from cookie and compare with token one
Expand Down Expand Up @@ -104,7 +104,7 @@ private byte[] GetOrCreateSessionId(IDotvvmRequestContext context, bool canGener
// Incorrect Base64 formatting of crypto protection error
// Generate new one or thow error if can't
if (!canGenerate)
throw new SecurityException("Value of the SessionID cookie is corrupted or has been tampered with.", ex);
throw new CorruptedCsrfTokenException("Value of the SessionID cookie is corrupted or has been tampered with.", ex);
// else suppress error and generate new SID
}
}
Expand Down Expand Up @@ -136,7 +136,7 @@ private byte[] GetOrCreateSessionId(IDotvvmRequestContext context, bool canGener
}
else
{
throw new SecurityException("SessionID cookie is missing, so can't verify CSRF token.");
throw new CorruptedCsrfTokenException("SessionID cookie is missing, so can't verify CSRF token.");
}
}

Expand Down
1 change: 1 addition & 0 deletions src/DotVVM.Framework.Hosting.Owin/AppBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ private static DotvvmConfiguration UseDotVVM(this IAppBuilder app, string applic
}

app.Use<DotvvmMiddleware>(config, new List<IMiddleware> {
ActivatorUtilities.CreateInstance<DotvvmCsrfTokenMiddleware>(config.ServiceProvider),
ActivatorUtilities.CreateInstance<DotvvmLocalResourceMiddleware>(config.ServiceProvider),
DotvvmFileUploadMiddleware.TryCreate(config.ServiceProvider),
new DotvvmReturnedFileMiddleware(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public string GenerateToken(IDotvvmRequestContext context)
public void VerifyToken(IDotvvmRequestContext context, string token)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (string.IsNullOrWhiteSpace(token)) throw new SecurityException("CSRF protection token is missing.");
if (string.IsNullOrWhiteSpace(token)) throw new CorruptedCsrfTokenException("CSRF protection token is missing.");

// Construct protector with purposes
var protector = this.protectionProvider.Create(PURPOSE_TOKEN);
Expand All @@ -70,12 +70,12 @@ public void VerifyToken(IDotvvmRequestContext context, string token)
catch (Exception ex)
{
// Incorrect Base64 formatting of crypto protection error
throw new SecurityException("CSRF protection token is invalid.", ex);
throw new CorruptedCsrfTokenException("CSRF protection token is invalid.", ex);
}

// Get SID from cookie and compare with token one
var cookieSid = this.GetOrCreateSessionId(context, canGenerate: false); // should not generate new token
if (!cookieSid.SequenceEqual(tokenSid)) throw new SecurityException("CSRF protection token is invalid.");
if (!cookieSid.SequenceEqual(tokenSid)) throw new CorruptedCsrfTokenException("CSRF protection token is invalid.");
}

private byte[] GetOrCreateSessionId(IDotvvmRequestContext context, bool canGenerate = true)
Expand Down Expand Up @@ -104,7 +104,7 @@ private byte[] GetOrCreateSessionId(IDotvvmRequestContext context, bool canGener
// Incorrect Base64 formatting of crypto protection error
// Generate new one or thow error if can't
if (!canGenerate)
throw new SecurityException("Value of the SessionID cookie is corrupted or has been tampered with.", ex);
throw new CorruptedCsrfTokenException("Value of the SessionID cookie is corrupted or has been tampered with.", ex);
// else suppress error and generate new SID
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ public void BindingCompiler_Valid_MemberAssignment()
Assert.AreEqual("42", vm.TestViewModel2.SomeString);
}


[TestMethod]
public void BindingCompiler_Valid_NamespaceAlias()
{
Expand Down Expand Up @@ -410,6 +409,34 @@ public void BindingCompiler_SimpleBlockExpression()
Assert.AreEqual("akkll", result);
}

[TestMethod]
public void BindingCompiler_SimpleBlockExpression_TaskSequence_TaskNonTask()
{
var vm = new TestViewModel4();
var resultTask = (Task)ExecuteBinding("Increment(); Number = Number * 5", new[] { vm });
resultTask.Wait();
Assert.AreEqual(5, vm.Number);
}

[TestMethod]
public void BindingCompiler_SimpleBlockExpression_TaskSequence_NonTaskTask()
{
var vm = new TestViewModel4();
var resultTask = (Task)ExecuteBinding("Number = 10; Increment();", new[] { vm });
resultTask.Wait();
Assert.AreEqual(11, vm.Number);
}

[TestMethod]
public void BindingCompiler_SimpleBlockExpression_TaskSequence_VoidTaskJoining()
{
var vm = new TestViewModel4();
var resultTask = (Task)ExecuteBinding("Increment(); Multiply()", new[] { vm });
resultTask.Wait();
Assert.AreEqual(10, vm.Number);
}


[TestMethod]
public void BindingCompiler_MultiBlockExpression()
{
Expand Down Expand Up @@ -618,6 +645,23 @@ class TestViewModel3 : DotvvmViewModelBase
public string SomeString { get; set; }
}

class TestViewModel4
{
public int Number { get; set; }

public async Task Increment()
{
await Task.Delay(100);
Number += 1;
}

public Task Multiply()
{
Number *= 10;
return Task.Delay(100);
}
}

class Something
{
public bool Value { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ public string CompileBinding(string expression, Type[] contexts, Type expectedTy
public void StaticCommandCompilation_SimpleCommand()
{
var result = CompileBinding("StaticCommands.GetLength(StringProp)", typeof(TestViewModel));
Assert.AreEqual("(function(a,b){return new Promise(function(resolve){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[b.$data.StringProp()],function(r_0){resolve(r_0);});});}(this,ko.contextFor(this)))", result);
Assert.AreEqual("(function(a,b){return new Promise(function(resolve,reject){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[b.$data.StringProp()],function(r_0){resolve(r_0);},reject);});}(this,ko.contextFor(this)))", result);
}

[TestMethod]
public void StaticCommandCompilation_AssignedCommand()
{
var result = CompileBinding("StringProp = StaticCommands.GetLength(StringProp).ToString()", typeof(TestViewModel));
Assert.AreEqual("(function(a,b){return new Promise(function(resolve){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[b.$data.StringProp()],function(r_0){resolve(b.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_0)()).StringProp());});});}(this,ko.contextFor(this)))", result);
Assert.AreEqual("(function(a,b){return new Promise(function(resolve,reject){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[b.$data.StringProp()],function(r_0){resolve(b.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_0)()).StringProp());},reject);});}(this,ko.contextFor(this)))", result);
}

[TestMethod]
Expand All @@ -79,21 +79,21 @@ public void StaticCommandCompilation_JsOnlyCommand()
public void StaticCommandCompilation_ChainedCommands()
{
var result = CompileBinding("StringProp = StaticCommands.GetLength(StaticCommands.GetLength(StringProp).ToString()).ToString()", typeof(TestViewModel));
Assert.AreEqual("(function(a,b){return new Promise(function(resolve){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[b.$data.StringProp()],function(r_0){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[dotvvm.globalize.bindingNumberToString(r_0)()],function(r_1){resolve(b.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_1)()).StringProp());});});});}(this,ko.contextFor(this)))", result);
Assert.AreEqual("(function(a,b){return new Promise(function(resolve,reject){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[b.$data.StringProp()],function(r_0){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[dotvvm.globalize.bindingNumberToString(r_0)()],function(r_1){resolve(b.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_1)()).StringProp());},reject);},reject);});}(this,ko.contextFor(this)))", result);
}

[TestMethod]
public void StaticCommandCompilation_ChainedCommandsWithSemicolon()
{
var result = CompileBinding("StringProp = StaticCommands.GetLength(StringProp).ToString(); StringProp = StaticCommands.GetLength(StringProp).ToString()", typeof(TestViewModel));
Assert.AreEqual("(function(a,c,b){return new Promise(function(resolve){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[c.$data.StringProp()],function(r_0){(b=c.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_0)()).StringProp(),dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[c.$data.StringProp()],function(r_1){resolve((b,c.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_1)()).StringProp()));}));});});}(this,ko.contextFor(this)))", result);
Assert.AreEqual("(function(a,c,b){return new Promise(function(resolve,reject){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[c.$data.StringProp()],function(r_0){(b=c.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_0)()).StringProp(),dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0TGVuZ3RoIixbXSwiQUE9PSJd\",[c.$data.StringProp()],function(r_1){resolve((b,c.$data.StringProp(dotvvm.globalize.bindingNumberToString(r_1)()).StringProp()));},reject));},reject);});}(this,ko.contextFor(this)))", result);
}

[TestMethod]
public void StaticCommandCompilation_DateTimeResultAssignment()
{
var result = CompileBinding("DateFrom = StaticCommands.GetDate()", typeof(TestViewModel));
Assert.AreEqual("(function(a,b){return new Promise(function(resolve){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0RGF0ZSIsW10sIiJd\",[],function(r_0){resolve(b.$data.DateFrom(dotvvm.serialization.serializeDate(r_0,false)).DateFrom());});});}(this,ko.contextFor(this)))", result);
Assert.AreEqual("(function(a,b){return new Promise(function(resolve,reject){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuU3RhdGljQ29tbWFuZHMsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiR2V0RGF0ZSIsW10sIiJd\",[],function(r_0){resolve(b.$data.DateFrom(dotvvm.serialization.serializeDate(r_0,false)).DateFrom());},reject);});}(this,ko.contextFor(this)))", result);
}

[TestMethod]
Expand All @@ -115,7 +115,7 @@ public void StaticCommandCompilation_PossibleAmniguousMatch()
{
var result = CompileBinding("SomeString = injectedService.Load(SomeString)", new[] { typeof(TestViewModel3) }, typeof(Func<string, string>));

Assert.AreEqual("(function(a,b){return new Promise(function(resolve){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuVGVzdFNlcnZpY2UsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiTG9hZCIsW10sIkFRQT0iXQ==\",[b.$data.SomeString()],function(r_0){resolve(b.$data.SomeString(r_0).SomeString());});});}(this,ko.contextFor(this)))", result);
Assert.AreEqual("(function(a,b){return new Promise(function(resolve,reject){dotvvm.staticCommandPostback(\"root\",a,\"WARNING/NOT/ENCRYPTED+++WyJEb3RWVk0uRnJhbWV3b3JrLlRlc3RzLkJpbmRpbmcuVGVzdFNlcnZpY2UsIERvdFZWTS5GcmFtZXdvcmsuVGVzdHMuQ29tbW9uIiwiTG9hZCIsW10sIkFRQT0iXQ==\",[b.$data.SomeString()],function(r_0){resolve(b.$data.SomeString(r_0).SomeString());},reject);});}(this,ko.contextFor(this)))", result);
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class UrlHelperTests
[DataRow(@"\\www.google.com", false)] // Chrome replaces backslashes with forward slashes...
[DataRow(@"\/www.google.com", false)]
[DataRow(@"/\www.google.com", false)]
[DataRow(@"/4aef74ba-388c-4292-9d53-98387e4f797b/reservation?LocationId=e5eed4c5-dfe9-45fd-a341-7408205d76ce&BeginDate=201909011300&Duration=2", true)]
public void UrlHelper_IsLocalUrl(string url, bool exepectedResult)
{
var result = UrlHelper.IsLocalUrl(url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using DotVVM.Framework.Compilation.Parser.Binding.Tokenizer;
using DotVVM.Framework.Utils;
using System.Linq;
using System.Threading.Tasks;

namespace DotVVM.Framework.Compilation.Binding
{
Expand Down Expand Up @@ -276,13 +277,19 @@ protected override Expression VisitBlock(BlockBindingParserNode node)
var right = HandleErrors(node.SecondExpression, Visit) ?? Expression.Default(typeof(void));
ThrowOnErrors();

if (typeof(Task).IsAssignableFrom(left.Type))
{
return ExpressionHelper.RewriteTaskSequence(left, right);
}

if (right is BlockExpression rightBlock)
{
// flat the `(a; b; c; d; e; ...)` expression down
return Expression.Block(rightBlock.Variables, new Expression[] { left }.Concat(rightBlock.Expressions));
}
else return Expression.Block(left, right);
}


private Expression GetMemberOrTypeExpression(IdentifierNameBindingParserNode node, Type[] typeParameters)
{
Expand Down
Loading

0 comments on commit a5f2bf0

Please sign in to comment.