Merge remote-tracking branch 'origin/v8/dev' into v8/feature/10613-distributed-locks

This commit is contained in:
Mole
2021-03-02 08:13:42 +01:00
26 changed files with 252 additions and 63 deletions

View File

@@ -42,6 +42,7 @@
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.1,4.999999)" />
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.1,4.999999)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.9.0,4.999999)" />
<dependency id="HtmlSanitizer" version="[5.0.376,5.999999)" />
</group>

View File

@@ -18,5 +18,5 @@ using System.Resources;
[assembly: AssemblyVersion("8.0.0")]
// these are FYI and changed automatically
[assembly: AssemblyFileVersion("8.11.1")]
[assembly: AssemblyInformationalVersion("8.11.1")]
[assembly: AssemblyFileVersion("8.12.0")]
[assembly: AssemblyInformationalVersion("8.12.0-rc")]

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the alias identifiers for Umbraco's core application sections.
/// </summary>
public static class SvgSanitizer
{
/// <summary>
/// Allowlist for SVG attributes.
/// </summary>
public static readonly IList<string> Attributes = new [] { "accent-height", "accumulate", "additive", "alignment-baseline", "allowReorder", "alphabetic", "amplitude", "arabic-form", "ascent", "attributeName", "attributeType", "autoReverse", "azimuth", "baseFrequency", "baseline-shift", "baseProfile", "bbox", "begin", "bias", "by", "calcMode", "cap-height", "class", "clip", "clipPathUnits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "contentScriptType", "contentStyleType", "cursor", "cx", "cy", "d", "decelerate", "descent", "diffuseConstant", "direction", "display", "divisor", "dominant-baseline", "dur", "dx", "dy", "edgeMode", "elevation", "enable-background", "end", "exponent", "externalResourcesRequired", "Section", "fill", "fill-opacity", "fill-rule", "filter", "filterRes", "filterUnits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "format", "from", "fr", "fx", "fy", "g1", "g2", "glyph-name", "glyph-orientation-horizontal", "glyph-orientation-vertical", "glyphRef", "gradientTransform", "gradientUnits", "hanging", "height", "href", "hreflang", "horiz-adv-x", "horiz-origin-x", "ISection", "id", "ideographic", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kernelMatrix", "kernelUnitLength", "kerning", "keyPoints", "keySplines", "keyTimes", "lang", "lengthAdjust", "letter-spacing", "lighting-color", "limitingConeAngle", "local", "MSection", "marker-end", "marker-mid", "marker-start", "markerHeight", "markerUnits", "markerWidth", "mask", "maskContentUnits", "maskUnits", "mathematical", "max", "media", "method", "min", "mode", "NSection", "name", "numOctaves", "offset", "opacity", "operator", "order", "orient", "orientation", "origin", "overflow", "overline-position", "overline-thickness", "panose-1", "paint-order", "path", "pathLength", "patternContentUnits", "patternTransform", "patternUnits", "ping", "pointer-events", "points", "pointsAtX", "pointsAtY", "pointsAtZ", "preserveAlpha", "preserveAspectRatio", "primitiveUnits", "r", "radius", "referrerPolicy", "refX", "refY", "rel", "rendering-intent", "repeatCount", "repeatDur", "requiredExtensions", "requiredFeatures", "restart", "result", "rotate", "rx", "ry", "scale", "seed", "shape-rendering", "slope", "spacing", "specularConstant", "specularExponent", "speed", "spreadMethod", "startOffset", "stdDeviation", "stemh", "stemv", "stitchTiles", "stop-color", "stop-opacity", "strikethrough-position", "strikethrough-thickness", "string", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "surfaceScale", "systemLanguage", "tabindex", "tableValues", "target", "targetX", "targetY", "text-anchor", "text-decoration", "text-rendering", "textLength", "to", "transform", "type", "u1", "u2", "underline-position", "underline-thickness", "unicode", "unicode-bidi", "unicode-range", "units-per-em", "v-alphabetic", "v-hanging", "v-ideographic", "v-mathematical", "values", "vector-effect", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "viewBox", "viewTarget", "visibility", "width", "widths", "word-spacing", "writing-mode", "x", "x-height", "x1", "x2", "xChannelSelector", "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "y", "y1", "y2", "yChannelSelector", "z", "zoomAndPan" };
/// <summary>
/// Allowlist for SVG tabs.
/// </summary>
public static readonly IList<string> Tags = new [] { "a", "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hatch", "hatchpath", "hkern", "image", "line", "linearGradient", "marker", "mask", "mesh", "meshgradient", "meshpatch", "meshrow", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "set", "solidcolor", "stop", "svg", "switch", "symbol", "text", "textPath", "title", "tref", "tspan", "unknown", "use", "view", "vkern" };
}
}
}

View File

@@ -281,7 +281,7 @@ where tbl.[name]=@0 and col.[name]=@1;", tableName, columnName)
private static void ObtainWriteLock(IDatabase db, TimeSpan timeout, int lockId)
{
db.Execute("SET LOCK_TIMEOUT" + timeout.TotalMilliseconds + ";");
db.Execute("SET LOCK_TIMEOUT " + timeout.TotalMilliseconds + ";");
var i = db.Execute(
@"UPDATE umbracoLock WITH (REPEATABLEREAD) SET value = (CASE WHEN (value=1) THEN -1 ELSE 1 END) WHERE id=@id",
new {id = lockId});

View File

@@ -25,6 +25,12 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
private static readonly JsonSerializerSettings ImageCropperValueJsonSerializerSettings = new JsonSerializerSettings
{
Culture = CultureInfo.InvariantCulture,
FloatParseHandling = FloatParseHandling.Decimal
};
/// <inheritdoc />
public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
{
@@ -34,11 +40,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
ImageCropperValue value;
try
{
value = JsonConvert.DeserializeObject<ImageCropperValue>(sourceString, new JsonSerializerSettings
{
Culture = CultureInfo.InvariantCulture,
FloatParseHandling = FloatParseHandling.Decimal
});
value = JsonConvert.DeserializeObject<ImageCropperValue>(sourceString, ImageCropperValueJsonSerializerSettings);
}
catch (Exception ex)
{

View File

@@ -19,6 +19,7 @@ namespace Umbraco.Core.Serialization
internal class NoTypeConverterJsonConverter<T> : JsonConverter
{
static readonly IContractResolver resolver = new NoTypeConverterContractResolver();
private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { ContractResolver = resolver };
private class NoTypeConverterContractResolver : DefaultContractResolver
{
@@ -41,12 +42,12 @@ namespace Umbraco.Core.Serialization
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = resolver }).Deserialize(reader, objectType);
return JsonSerializer.CreateDefault(JsonSerializerSettings).Deserialize(reader, objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = resolver }).Serialize(writer, value);
JsonSerializer.CreateDefault(JsonSerializerSettings).Serialize(writer, value);
}
}
}

View File

@@ -256,6 +256,7 @@
<Compile Include="CompositionExtensions_Essentials.cs" />
<Compile Include="CompositionExtensions_FileSystems.cs" />
<Compile Include="CompositionExtensions_Uniques.cs" />
<Compile Include="Constants-SvgSanitizer.cs" />
<Compile Include="Exceptions\PanicException.cs" />
<Compile Include="FactoryExtensions.cs" />
<Compile Include="Composing\RegisterFactory.cs" />

View File

@@ -574,7 +574,7 @@ context('Content', () => {
// Create content with content picker
cy.get('.umb-tree-root-link').rightclick();
cy.get('.-opens-dialog > .umb-action-link').click();
cy.get('[data-element="action-create"]').click();
cy.get('[data-element="action-create-' + pickerDocTypeAlias + '"] > .umb-action-link').click();
// Fill out content
cy.umbracoEditorHeaderName('ContentPickerContent');

View File

@@ -0,0 +1,69 @@
using BenchmarkDotNet.Attributes;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Tests.Benchmarks.Config;
namespace Umbraco.Tests.Benchmarks
{
[QuickRunConfig]
[MemoryDiagnoser]
public class JsonSerializerSettingsBenchmarks
{
[Benchmark]
public void SerializerSettingsInstantiation()
{
int instances = 1000;
for (int i = 0; i < instances; i++)
{
new JsonSerializerSettings();
}
}
[Benchmark(Baseline =true)]
public void SerializerSettingsSingleInstantiation()
{
new JsonSerializerSettings();
}
// // * Summary *
// BenchmarkDotNet=v0.11.3, OS=Windows 10.0.18362
//Intel Core i5-8265U CPU 1.60GHz(Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
// [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.8.4250.0
// Job-JIATTD : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.8.4250.0
//IterationCount=3 IterationTime=100.0000 ms LaunchCount = 1
//WarmupCount=3
// Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
//-------------------------------------- |-------------:|-------------:|------------:|-------:|--------:|------------:|------------:|------------:|--------------------:|
// SerializerSettingsInstantiation | 29,120.48 ns | 5,532.424 ns | 303.2508 ns | 997.84 | 23.66 | 73.8122 | - | - | 232346 B |
// SerializerSettingsSingleInstantiation | 29.19 ns | 8.089 ns | 0.4434 ns | 1.00 | 0.00 | 0.0738 | - | - | 232 B |
//// * Warnings *
//MinIterationTime
// JsonSerializerSettingsBenchmarks.SerializerSettingsSingleInstantiation: IterationCount= 3, IterationTime= 100.0000 ms, LaunchCount= 1, WarmupCount= 3->MinIterationTime = 96.2493 ms which is very small. It's recommended to increase it.
//// * Legends *
// Mean : Arithmetic mean of all measurements
// Error : Half of 99.9% confidence interval
// StdDev : Standard deviation of all measurements
// Ratio : Mean of the ratio distribution ([Current]/[Baseline])
// RatioSD : Standard deviation of the ratio distribution([Current]/[Baseline])
// Gen 0/1k Op : GC Generation 0 collects per 1k Operations
// Gen 1/1k Op : GC Generation 1 collects per 1k Operations
// Gen 2/1k Op : GC Generation 2 collects per 1k Operations
// Allocated Memory/Op : Allocated memory per single operation(managed only, inclusive, 1KB = 1024B)
// 1 ns : 1 Nanosecond(0.000000001 sec)
//// * Diagnostic Output - MemoryDiagnoser *
// // ***** BenchmarkRunner: End *****
// Run time: 00:00:04 (4.88 sec), executed benchmarks: 2
}
}

View File

@@ -53,6 +53,7 @@
<Compile Include="CtorInvokeBenchmarks.cs" />
<Compile Include="HexStringBenchmarks.cs" />
<Compile Include="EnumeratorBenchmarks.cs" />
<Compile Include="JsonSerializerSettingsBenchmarks.cs" />
<Compile Include="LinqCastBenchmarks.cs" />
<Compile Include="ModelToSqlExpressionHelperBenchmarks.cs" />
<Compile Include="Program.cs" />

View File

@@ -23,7 +23,7 @@
</button>
</li>
<li data-element="action-documentTypeWithIsElementTypeChecked" class="umb-action">
<button type="button" ng-click="createElement()" class="umb-action-link umb-outline btn-reset" umb-auto-focus>
<button type="button" ng-click="createElement()" class="umb-action-link umb-outline btn-reset">
<i class="large icon icon-science" aria-hidden="true"></i>
<span class="menu-label">
<localize key="create_elementType">Element Type</localize>

View File

@@ -347,9 +347,9 @@
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>8111</DevelopmentServerPort>
<DevelopmentServerPort>8120</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:8111</IISUrl>
<IISUrl>http://localhost:8120</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>

View File

@@ -135,7 +135,10 @@ namespace Umbraco.Web.Cache
public static void RemoveMemberCache(this DistributedCache dc, params IMember[] members)
{
if (members.Length == 0) return;
dc.RefreshByPayload(MemberCacheRefresher.UniqueId, members.Select(x => new MemberCacheRefresher.JsonPayload(x.Id, x.Username)));
dc.RefreshByPayload(MemberCacheRefresher.UniqueId, members.Select(x => new MemberCacheRefresher.JsonPayload(x.Id, x.Username)
{
Removed = true
}));
}
#endregion

View File

@@ -33,6 +33,10 @@ namespace Umbraco.Web.Cache
public int Id { get; }
public string Username { get; }
// TODO: In netcore change this to be get only and adjust the ctor. We cannot do that now since that
// is a breaking change due to only having a single jsonconstructor allowed.
public bool Removed { get; set; }
}
#region Define

View File

@@ -226,7 +226,7 @@ namespace Umbraco.Web.Editors
.ToDictionary(pv => pv.Key, pv =>
pv.ToDictionary(pve => pve.valueAlias, pve => pve.value));
return new JsonNetResult { Data = nestedDictionary, Formatting = Formatting.None };
return new JsonNetResult(JsonNetResult.DefaultJsonSerializerSettings) { Data = nestedDictionary, Formatting = Formatting.None };
}
/// <summary>
@@ -273,7 +273,7 @@ namespace Umbraco.Web.Editors
GetAssetList,
new TimeSpan(0, 2, 0));
return new JsonNetResult { Data = result, Formatting = Formatting.None };
return new JsonNetResult(JsonNetResult.DefaultJsonSerializerSettings) { Data = result, Formatting = Formatting.None };
}
[UmbracoAuthorize(Order = 0)]
@@ -281,7 +281,7 @@ namespace Umbraco.Web.Editors
public JsonNetResult GetGridConfig()
{
var gridConfig = Current.Configs.Grids();
return new JsonNetResult { Data = gridConfig.EditorsConfig.Editors, Formatting = Formatting.None };
return new JsonNetResult(JsonNetResult.DefaultJsonSerializerSettings) { Data = gridConfig.EditorsConfig.Editors, Formatting = Formatting.None };
}

View File

@@ -253,19 +253,20 @@ namespace Umbraco.Web
ImageCropRatioMode? ratioMode = null,
bool upScale = true) => ImageCropperTemplateCoreExtensions.GetCropUrl(imageUrl, Current.ImageUrlGenerator, cropDataSet, width, height, cropAlias, quality, imageCropMode, imageCropAnchor, preferFocalPoint, useCropDimensions, cacheBusterValue, furtherOptions, ratioMode, upScale);
private static readonly JsonSerializerSettings ImageCropperValueJsonSerializerSettings = new JsonSerializerSettings
{
Culture = CultureInfo.InvariantCulture,
FloatParseHandling = FloatParseHandling.Decimal
};
internal static ImageCropperValue DeserializeImageCropperValue(this string json)
{
var imageCrops = new ImageCropperValue();
ImageCropperValue imageCrops = null;
if (json.DetectIsJson())
{
try
{
imageCrops = JsonConvert.DeserializeObject<ImageCropperValue>(json, new JsonSerializerSettings
{
Culture = CultureInfo.InvariantCulture,
FloatParseHandling = FloatParseHandling.Decimal
});
imageCrops = JsonConvert.DeserializeObject<ImageCropperValue>(json, ImageCropperValueJsonSerializerSettings);
}
catch (Exception ex)
{
@@ -273,6 +274,7 @@ namespace Umbraco.Web
}
}
imageCrops = imageCrops ?? new ImageCropperValue();
return imageCrops;
}
}

View File

@@ -22,10 +22,19 @@ namespace Umbraco.Web.Mvc
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
/// <summary>
/// Default, unchanged JsonSerializerSettings
/// </summary>
public static readonly JsonSerializerSettings DefaultJsonSerializerSettings = new JsonSerializerSettings();
public JsonNetResult()
{
SerializerSettings = new JsonSerializerSettings();
}
public JsonNetResult(JsonSerializerSettings jsonSerializerSettings)
{
SerializerSettings = jsonSerializerSettings;
}
public override void ExecuteResult(ControllerContext context)
{

View File

@@ -121,6 +121,10 @@ namespace Umbraco.Web.PropertyEditors
return base.ToEditor(property, dataTypeService, culture, segment);
}
private static readonly JsonSerializerSettings LinkDisplayJsonSerializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
public override object FromEditor(ContentPropertyData editorValue, object currentValue)
{
@@ -142,11 +146,8 @@ namespace Umbraco.Web.PropertyEditors
Target = link.Target,
Udi = link.Udi,
Url = link.Udi == null ? link.Url : null, // only save the URL for external links
},
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
}, LinkDisplayJsonSerializerSettings
);
}
catch (Exception ex)
{

View File

@@ -303,17 +303,18 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
return s;
}
private static readonly JsonSerializerSettings NestedContentDataJsonSerializerSettings = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new ForceInt32Converter() }
};
private static ContentNestedData DeserializeNestedData(string data)
{
// by default JsonConvert will deserialize our numeric values as Int64
// which is bad, because they were Int32 in the database - take care
var settings = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new ForceInt32Converter() }
};
return JsonConvert.DeserializeObject<ContentNestedData>(data, settings);
return JsonConvert.DeserializeObject<ContentNestedData>(data, NestedContentDataJsonSerializerSettings);
}
}
}

View File

@@ -40,6 +40,7 @@ using Current = Umbraco.Web.Composing.Current;
using Umbraco.Web.PropertyEditors;
using Umbraco.Core.Models;
using Umbraco.Web.Models;
using Ganss.XSS;
namespace Umbraco.Web.Runtime
{
@@ -139,6 +140,14 @@ namespace Umbraco.Web.Runtime
composition.RegisterUnique<ISectionService, SectionService>();
composition.RegisterUnique<IDashboardService, DashboardService>();
composition.RegisterUnique<IIconService, IconService>();
composition.Register<IHtmlSanitizer>(_ =>
{
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedAttributes.UnionWith(Umbraco.Core.Constants.SvgSanitizer.Attributes);
sanitizer.AllowedCssProperties.UnionWith(Umbraco.Core.Constants.SvgSanitizer.Attributes);
sanitizer.AllowedTags.UnionWith(Umbraco.Core.Constants.SvgSanitizer.Tags);
return sanitizer;
},Lifetime.Singleton);
composition.RegisterUnique<IExamineManager>(factory => ExamineManager.Instance);

View File

@@ -271,10 +271,20 @@ namespace Umbraco.Web.Search
break;
case MessageType.RefreshByPayload:
var payload = (MemberCacheRefresher.JsonPayload[])args.MessageObject;
var members = payload.Select(x => _services.MemberService.GetById(x.Id));
foreach(var m in members)
foreach(var p in payload)
{
ReIndexForMember(m);
if (p.Removed)
{
DeleteIndexForEntity(p.Id, false);
}
else
{
var m = _services.MemberService.GetById(p.Id);
if (m != null)
{
ReIndexForMember(m);
}
}
}
break;
case MessageType.RefreshAll:

View File

@@ -169,11 +169,31 @@ namespace Umbraco.Web.Security
// Enables the application to validate the security stamp when the user
// logs in. This is a security feature which is used when you
// change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator
.OnValidateIdentity<BackOfficeUserManager, BackOfficeIdentityUser, int>(
OnValidateIdentity = context =>
{
// capture the current ticket for the request
var identity = context.Identity;
return SecurityStampValidator
.OnValidateIdentity<BackOfficeUserManager, BackOfficeIdentityUser, int>(
// This will re-verify the security stamp at a throttled 30 mins
// (the standard/default set in aspnet identity).
// This ensures that if the security stamp has changed - i.e. passwords,
// external logins, or other security profile data changed behind the
// scenes while being logged in, that they are logged out and have
// to re-verify their identity.
TimeSpan.FromMinutes(30),
(manager, user) => manager.GenerateUserIdentityAsync(user),
identity => identity.GetUserId<int>()),
async (manager, user) =>
{
var regenerated = await manager.GenerateUserIdentityAsync(user);
// Keep any custom claims from the original identity
regenerated.MergeClaimsFromBackOfficeIdentity(identity);
return regenerated;
},
identity => identity.GetUserId<int>())(context);
}
};

View File

@@ -27,12 +27,6 @@ namespace Umbraco.Web.Security
{
var baseIdentity = await base.CreateAsync(manager, user, authenticationType);
// now we can flow any custom claims that the actual user has currently assigned which could be done in the OnExternalLogin callback
foreach (var claim in user.Claims)
{
baseIdentity.AddClaim(new Claim(claim.ClaimType, claim.ClaimValue));
}
var umbracoIdentity = new UmbracoBackOfficeIdentity(baseIdentity,
user.Id,
user.UserName,
@@ -40,12 +34,16 @@ namespace Umbraco.Web.Security
user.CalculatedContentStartNodeIds,
user.CalculatedMediaStartNodeIds,
user.Culture,
//NOTE - there is no session id assigned here, this is just creating the identity, a session id will be generated when the cookie is written
// NOTE - there is no session id assigned here, this is just creating the identity, a session id will be generated when the cookie is written
Guid.NewGuid().ToString(),
user.SecurityStamp,
user.AllowedSections,
user.Roles.Select(x => x.RoleId).ToArray());
// now we can flow any custom claims that the actual user has currently
// assigned which could be done in the OnExternalLogin callback
umbracoIdentity.MergeClaimsFromBackOfficeIdentity(user);
return umbracoIdentity;
}
}

View File

@@ -0,0 +1,34 @@
using System.Linq;
using System.Security.Claims;
using Umbraco.Core.Models.Identity;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Security
{
internal static class ClaimsIdentityExtensions
{
// Ignore these Claims when merging, these claims are dynamically added whenever the ticket
// is re-issued and we don't want to merge old values of these.
private static readonly string[] IgnoredClaims = new[] { ClaimTypes.CookiePath, Constants.Security.SessionIdClaimType };
internal static void MergeClaimsFromBackOfficeIdentity(this ClaimsIdentity destination, ClaimsIdentity source)
{
foreach (var claim in source.Claims
.Where(claim => !IgnoredClaims.Contains(claim.Type))
.Where(claim => !destination.HasClaim(claim.Type, claim.Value)))
{
destination.AddClaim(new Claim(claim.Type, claim.Value));
}
}
internal static void MergeClaimsFromBackOfficeIdentity(this ClaimsIdentity destination, BackOfficeIdentityUser source)
{
foreach (var claim in source.Claims
.Where(claim => !IgnoredClaims.Contains(claim.ClaimType))
.Where(claim => !destination.HasClaim(claim.ClaimType, claim.ClaimValue)))
{
destination.AddClaim(new Claim(claim.ClaimType, claim.ClaimValue));
}
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Ganss.XSS;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
@@ -12,31 +13,24 @@ namespace Umbraco.Web.Services
public class IconService : IIconService
{
private readonly IGlobalSettings _globalSettings;
private readonly IHtmlSanitizer _htmlSanitizer;
public IconService(IGlobalSettings globalSettings)
public IconService(IGlobalSettings globalSettings, IHtmlSanitizer htmlSanitizer)
{
_globalSettings = globalSettings;
_htmlSanitizer = htmlSanitizer;
}
/// <inheritdoc />
public IList<IconModel> GetAllIcons()
{
var icons = new List<IconModel>();
var directory = new DirectoryInfo(IOHelper.MapPath($"{_globalSettings.IconsPath}/"));
var iconNames = directory.GetFiles("*.svg");
iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo =>
{
var icon = GetIcon(iconInfo);
return iconNames.OrderBy(f => f.Name)
.Select(iconInfo => GetIcon(iconInfo)).WhereNotNull().ToList();
if (icon != null)
{
icons.Add(icon);
}
});
return icons;
}
/// <inheritdoc />
@@ -70,10 +64,12 @@ namespace Umbraco.Web.Services
try
{
var svgContent = System.IO.File.ReadAllText(iconPath);
var sanitizedString = _htmlSanitizer.Sanitize(svgContent);
var svg = new IconModel
{
Name = iconName,
SvgString = svgContent
SvgString = sanitizedString
};
return svg;

View File

@@ -65,6 +65,9 @@
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
<PackageReference Include="Examine" Version="1.1.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.8.14" />
<PackageReference Include="HtmlSanitizer">
<Version>5.0.376</Version>
</PackageReference>
<PackageReference Include="ImageProcessor">
<Version>2.7.0.100</Version>
</PackageReference>
@@ -285,6 +288,7 @@
<Compile Include="Security\BackOfficeExternalLoginProviderErrorMiddlware.cs" />
<Compile Include="Security\BackOfficeExternalLoginProviderErrors.cs" />
<Compile Include="Security\BackOfficeExternalLoginProviderOptions.cs" />
<Compile Include="Security\ClaimsIdentityExtensions.cs" />
<Compile Include="Security\SignOutAuditEventArgs.cs" />
<Compile Include="Security\UserInviteEventArgs.cs" />
<Compile Include="Services\DashboardService.cs" />
@@ -1293,7 +1297,7 @@
</PropertyGroup>
<ItemGroup>
<!-- we want to exclude all facade references ?! -->
<FixedReferencePath Include="@(ReferencePath)" Condition="'%(ReferencePath.FileName)' != 'System.ValueTuple' and '%(ReferencePath.FileName)' != 'System.Net.Http'" />
<FixedReferencePath Include="@(ReferencePath)" Condition="'%(ReferencePath.FileName)' != 'System.ValueTuple' and '%(ReferencePath.FileName)' != 'System.Net.Http' and '%(ReferencePath.FileName)' != 'System.Text.Encoding.CodePages'" />
</ItemGroup>
<Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
<!--
@@ -1303,4 +1307,4 @@
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>
</Target>
</Project>
</Project>