Skip to content

Commit ef714ac

Browse files
committed
Merge remote-tracking branch 'origin/v8/dev' into v8/feature/5170-IPublishedContent
# Conflicts: # src/Umbraco.Web/UmbracoHelper.cs
2 parents 347c2e8 + 8831860 commit ef714ac

78 files changed

Lines changed: 3153 additions & 310 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Umbraco.Core/Services/Implement/ContentService.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,12 +1695,11 @@ void DoDelete(IContent c)
16951695
}
16961696

16971697
const int pageSize = 500;
1698-
var page = 0;
16991698
var total = long.MaxValue;
1700-
while (page * pageSize < total)
1699+
while (total > 0)
17011700
{
17021701
//get descendants - ordered from deepest to shallowest
1703-
var descendants = GetPagedDescendants(content.Id, page, pageSize, out total, ordering: Ordering.By("Path", Direction.Descending));
1702+
var descendants = GetPagedDescendants(content.Id, 0, pageSize, out total, ordering: Ordering.By("Path", Direction.Descending));
17041703
foreach (var c in descendants)
17051704
DoDelete(c);
17061705
}
@@ -1926,11 +1925,10 @@ private void PerformMoveLocked(IContent content, int parentId, IContent parent,
19261925
paths[content.Id] = (parent == null ? (parentId == Constants.System.RecycleBinContent ? "-1,-20" : Constants.System.RootString) : parent.Path) + "," + content.Id;
19271926

19281927
const int pageSize = 500;
1929-
var page = 0;
19301928
var total = long.MaxValue;
1931-
while (page * pageSize < total)
1929+
while (total > 0)
19321930
{
1933-
var descendants = GetPagedDescendantsLocked(originalPath, page++, pageSize, out total, null, Ordering.By("Path", Direction.Ascending));
1931+
var descendants = GetPagedDescendantsLocked(originalPath, 0, pageSize, out total, null, Ordering.By("Path", Direction.Ascending));
19341932
foreach (var descendant in descendants)
19351933
{
19361934
moves.Add(Tuple.Create(descendant, descendant.Path)); // capture original path

src/Umbraco.Core/Services/Implement/MediaService.cs

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int
201201

202202
var mediaType = GetMediaType(mediaTypeAlias);
203203
if (mediaType == null)
204-
throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback // causes rollback
204+
throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback
205205

206206
var media = new Models.Media(name, parent, mediaType);
207207
CreateMedia(scope, media, parent, userId, false);
@@ -227,13 +227,13 @@ public IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTyp
227227
// locking the media tree secures media types too
228228
scope.WriteLock(Constants.Locks.MediaTree);
229229

230-
var mediaType = GetMediaType(mediaTypeAlias); // + locks // + locks
230+
var mediaType = GetMediaType(mediaTypeAlias); // + locks
231231
if (mediaType == null)
232-
throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback // causes rollback
232+
throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback
233233

234-
var parent = parentId > 0 ? GetById(parentId) : null; // + locks // + locks
234+
var parent = parentId > 0 ? GetById(parentId) : null; // + locks
235235
if (parentId > 0 && parent == null)
236-
throw new ArgumentException("No media with that id.", nameof(parentId)); // causes rollback // causes rollback
236+
throw new ArgumentException("No media with that id.", nameof(parentId)); // causes rollback
237237

238238
var media = parentId > 0 ? new Models.Media(name, parent, mediaType) : new Models.Media(name, parentId, mediaType);
239239
CreateMedia(scope, media, parent, userId, true);
@@ -261,9 +261,9 @@ public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTy
261261
// locking the media tree secures media types too
262262
scope.WriteLock(Constants.Locks.MediaTree);
263263

264-
var mediaType = GetMediaType(mediaTypeAlias); // + locks // + locks
264+
var mediaType = GetMediaType(mediaTypeAlias); // + locks
265265
if (mediaType == null)
266-
throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback // causes rollback
266+
throw new ArgumentException("No media type with that alias.", nameof(mediaTypeAlias)); // causes rollback
267267

268268
var media = new Models.Media(name, parent, mediaType);
269269
CreateMedia(scope, media, parent, userId, true);
@@ -645,8 +645,6 @@ public Attempt<OperationResult> Save(IMedia media, int userId = Constants.Securi
645645
}
646646

647647
// poor man's validation?
648-
// poor man's validation?
649-
650648
if (string.IsNullOrWhiteSpace(media.Name))
651649
throw new ArgumentException("Media has no name.", nameof(media));
652650

@@ -934,7 +932,7 @@ public Attempt<OperationResult> Move(IMedia media, int parentId, int userId = Co
934932

935933
var parent = parentId == Constants.System.Root ? null : GetById(parentId);
936934
if (parentId != Constants.System.Root && (parent == null || parent.Trashed))
937-
throw new InvalidOperationException("Parent does not exist or is trashed."); // causes rollback // causes rollback
935+
throw new InvalidOperationException("Parent does not exist or is trashed."); // causes rollback
938936

939937
var moveEventInfo = new MoveEventInfo<IMedia>(media, media.Path, parentId);
940938
var moveEventArgs = new MoveEventArgs<IMedia>(true, evtMsgs, moveEventInfo);
@@ -947,12 +945,6 @@ public Attempt<OperationResult> Move(IMedia media, int parentId, int userId = Co
947945
// if media was trashed, and since we're not moving to the recycle bin,
948946
// indicate that the trashed status should be changed to false, else just
949947
// leave it unchanged
950-
// if media was trashed, and since we're not moving to the recycle bin,
951-
952-
// indicate that the trashed status should be changed to false, else just
953-
954-
// leave it unchanged
955-
956948
var trashed = media.Trashed ? false : (bool?) null;
957949

958950
PerformMoveLocked(media, parentId, parent, userId, moves, trashed);
@@ -1042,17 +1034,11 @@ public OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUser
10421034
{
10431035
scope.WriteLock(Constants.Locks.MediaTree);
10441036

1045-
// v7 EmptyingRecycleBin and EmptiedRecycleBin events are greatly simplified since
1046-
// each deleted items will have its own deleting/deleted events. so, files and such
1047-
// are managed by Delete, and not here.
1048-
10491037
// no idea what those events are for, keep a simplified version
1038+
10501039
// v7 EmptyingRecycleBin and EmptiedRecycleBin events are greatly simplified since
10511040
// each deleted items will have its own deleting/deleted events. so, files and such
1052-
1053-
// emptying the recycle bin means deleting whatever is in there - do it properly!
10541041
// are managed by Delete, and not here.
1055-
// no idea what those events are for, keep a simplified version
10561042
var args = new RecycleBinEventArgs(nodeObjectType, evtMsgs);
10571043

10581044
if (scope.Events.DispatchCancelable(EmptyingRecycleBin, this, args))
@@ -1113,11 +1099,6 @@ public bool Sort(IEnumerable<IMedia> items, int userId = Constants.Security.Supe
11131099
{
11141100
// if the current sort order equals that of the media we don't
11151101
// need to update it, so just increment the sort order and continue.
1116-
// if the current sort order equals that of the media we don't
1117-
1118-
// else update
1119-
// need to update it, so just increment the sort order and continue.
1120-
// save
11211102
if (media.SortOrder == sortOrder)
11221103
{
11231104
sortOrder++;

src/Umbraco.Tests/Mapping/MappingTests.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,31 @@ void ThreadLoop()
172172
}
173173
}
174174

175+
[Test]
176+
public void EnumMap()
177+
{
178+
var definitions = new MapDefinitionCollection(new IMapDefinition[]
179+
{
180+
new MapperDefinition4(),
181+
});
182+
var mapper = new UmbracoMapper(definitions);
183+
184+
var thing5 = new Thing5()
185+
{
186+
Fruit1 = Thing5Enum.Apple,
187+
Fruit2 = Thing5Enum.Banana,
188+
Fruit3= Thing5Enum.Cherry
189+
};
190+
191+
var thing6 = mapper.Map<Thing5, Thing6>(thing5);
192+
193+
Assert.IsNotNull(thing6);
194+
Assert.AreEqual(Thing6Enum.Apple, thing6.Fruit1);
195+
Assert.AreEqual(Thing6Enum.Banana, thing6.Fruit2);
196+
Assert.AreEqual(Thing6Enum.Cherry, thing6.Fruit3);
197+
}
198+
199+
175200
private class Thing1
176201
{
177202
public string Value { get; set; }
@@ -188,6 +213,34 @@ private class Thing2
188213
private class Thing4
189214
{ }
190215

216+
private class Thing5
217+
{
218+
public Thing5Enum Fruit1 { get; set; }
219+
public Thing5Enum Fruit2 { get; set; }
220+
public Thing5Enum Fruit3 { get; set; }
221+
}
222+
223+
private enum Thing5Enum
224+
{
225+
Apple = 0,
226+
Banana = 1,
227+
Cherry = 2
228+
}
229+
230+
private class Thing6
231+
{
232+
public Thing6Enum Fruit1 { get; set; }
233+
public Thing6Enum Fruit2 { get; set; }
234+
public Thing6Enum Fruit3 { get; set; }
235+
}
236+
237+
private enum Thing6Enum
238+
{
239+
Apple = 0,
240+
Banana = 1,
241+
Cherry = 2
242+
}
243+
191244
private class MapperDefinition1 : IMapDefinition
192245
{
193246
public void DefineMaps(UmbracoMapper mapper)
@@ -224,5 +277,22 @@ public void DefineMaps(UmbracoMapper mapper)
224277
mapper.Define<Property, object>();
225278
}
226279
}
280+
281+
private class MapperDefinition4 : IMapDefinition
282+
{
283+
public void DefineMaps(UmbracoMapper mapper)
284+
{
285+
mapper.Define<Thing5, Thing6>((source, context) => new Thing6(), Map);
286+
mapper.Define<Thing5Enum, Thing6Enum>(
287+
(source, context) => (Thing6Enum)source);
288+
}
289+
290+
private void Map(Thing5 source, Thing6 target, MapperContext context)
291+
{
292+
target.Fruit1 = context.Map<Thing6Enum>(source.Fruit1);
293+
target.Fruit2 = context.Map<Thing6Enum>(source.Fruit2);
294+
target.Fruit3 = context.Map<Thing6Enum>(source.Fruit3);
295+
}
296+
}
227297
}
228298
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
using System.Collections.Specialized;
2+
using System.Web;
3+
using System.Web.Helpers;
4+
using Moq;
5+
using Newtonsoft.Json;
6+
using NUnit.Framework;
7+
using Umbraco.Core;
8+
using Umbraco.Tests.TestHelpers;
9+
using Umbraco.Web.Mvc;
10+
using Umbraco.Web.Security;
11+
12+
namespace Umbraco.Tests.Security
13+
{
14+
[TestFixture]
15+
public class UmbracoAntiForgeryAdditionalDataProviderTests
16+
{
17+
[Test]
18+
public void Test_Wrapped_Non_BeginUmbracoForm()
19+
{
20+
var wrapped = Mock.Of<IAntiForgeryAdditionalDataProvider>(x => x.GetAdditionalData(It.IsAny<HttpContextBase>()) == "custom");
21+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(wrapped);
22+
23+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
24+
var data = provider.GetAdditionalData(httpContextFactory.HttpContext);
25+
26+
Assert.IsTrue(data.DetectIsJson());
27+
var json = JsonConvert.DeserializeObject<UmbracoAntiForgeryAdditionalDataProvider.AdditionalData>(data);
28+
Assert.AreEqual(null, json.Ufprt);
29+
Assert.IsTrue(json.Stamp != default);
30+
Assert.AreEqual("custom", json.WrappedValue);
31+
}
32+
33+
[Test]
34+
public void Null_Wrapped_Non_BeginUmbracoForm()
35+
{
36+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
37+
38+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
39+
var data = provider.GetAdditionalData(httpContextFactory.HttpContext);
40+
41+
Assert.IsTrue(data.DetectIsJson());
42+
var json = JsonConvert.DeserializeObject<UmbracoAntiForgeryAdditionalDataProvider.AdditionalData>(data);
43+
Assert.AreEqual(null, json.Ufprt);
44+
Assert.IsTrue(json.Stamp != default);
45+
Assert.AreEqual("default", json.WrappedValue);
46+
}
47+
48+
[Test]
49+
public void Validate_Non_Json()
50+
{
51+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
52+
53+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
54+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "hello");
55+
56+
Assert.IsFalse(isValid);
57+
}
58+
59+
[Test]
60+
public void Validate_Invalid_Json()
61+
{
62+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
63+
64+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
65+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '0'}");
66+
Assert.IsFalse(isValid);
67+
68+
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': ''}");
69+
Assert.IsFalse(isValid);
70+
71+
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'hello': 'world'}");
72+
Assert.IsFalse(isValid);
73+
74+
}
75+
76+
[Test]
77+
public void Validate_No_Request_Ufprt()
78+
{
79+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
80+
81+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
82+
//there is a ufprt in the additional data, but not in the request
83+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': 'ASBVDFDFDFDF'}");
84+
Assert.IsFalse(isValid);
85+
}
86+
87+
[Test]
88+
public void Validate_No_AdditionalData_Ufprt()
89+
{
90+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
91+
92+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
93+
var requestMock = Mock.Get(httpContextFactory.HttpContext.Request);
94+
requestMock.SetupGet(x => x["ufprt"]).Returns("ABCDEFG");
95+
96+
//there is a ufprt in the additional data, but not in the request
97+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': ''}");
98+
Assert.IsFalse(isValid);
99+
}
100+
101+
[Test]
102+
public void Validate_No_AdditionalData_Or_Request_Ufprt()
103+
{
104+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
105+
106+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
107+
108+
//there is a ufprt in the additional data, but not in the request
109+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': ''}");
110+
Assert.IsTrue(isValid);
111+
}
112+
113+
[Test]
114+
public void Validate_Request_And_AdditionalData_Ufprt()
115+
{
116+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
117+
118+
var routeParams1 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
119+
var routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
120+
121+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
122+
var requestMock = Mock.Get(httpContextFactory.HttpContext.Request);
123+
requestMock.SetupGet(x => x["ufprt"]).Returns(routeParams1.EncryptWithMachineKey());
124+
125+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
126+
Assert.IsTrue(isValid);
127+
128+
routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Invalid")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
129+
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
130+
Assert.IsFalse(isValid);
131+
}
132+
133+
[Test]
134+
public void Validate_Wrapped_Request_And_AdditionalData_Ufprt()
135+
{
136+
var wrapped = Mock.Of<IAntiForgeryAdditionalDataProvider>(x => x.ValidateAdditionalData(It.IsAny<HttpContextBase>(), "custom") == true);
137+
var provider = new UmbracoAntiForgeryAdditionalDataProvider(wrapped);
138+
139+
var routeParams1 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
140+
var routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
141+
142+
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
143+
var requestMock = Mock.Get(httpContextFactory.HttpContext.Request);
144+
requestMock.SetupGet(x => x["ufprt"]).Returns(routeParams1.EncryptWithMachineKey());
145+
146+
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
147+
Assert.IsFalse(isValid);
148+
149+
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'custom', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
150+
Assert.IsTrue(isValid);
151+
152+
routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Invalid")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
153+
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
154+
Assert.IsFalse(isValid);
155+
}
156+
}
157+
}

0 commit comments

Comments
 (0)