Merge pull request #10841 from isaac2004/10346-work
Remove Cookie Consent UI from all templates and move into docs #10346
This commit is contained in:
commit
9ed49994ab
|
|
@ -9,16 +9,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RazorComponentsWeb-CSharp</title>
|
||||
<base href="~/" />
|
||||
<environment include="Development">
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||
asp-fallback-href="css/bootstrap/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"/>
|
||||
</environment>
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
<link href="css/site.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
@using Microsoft.AspNetCore.Http.Features
|
||||
|
||||
@{
|
||||
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
|
||||
var showBanner = !consentFeature?.CanTrack ?? false;
|
||||
var cookieString = consentFeature?.CreateConsentCookie();
|
||||
}
|
||||
|
||||
@if (showBanner)
|
||||
{
|
||||
<div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
|
||||
Use this space to summarize your privacy and cookie use policy. <a class="alert-link" asp-page="/Privacy">Learn More</a>.
|
||||
<button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
|
||||
<span aria-hidden="true">Accept</span>
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var button = document.querySelector("#cookieConsent button[data-cookie-string]");
|
||||
button.addEventListener("click", function (event) {
|
||||
document.cookie = button.dataset.cookieString;
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
}
|
||||
|
|
@ -4,17 +4,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - Company.WebApplication1</title>
|
||||
|
||||
<environment include="Development">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"/>
|
||||
</environment>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -44,37 +34,17 @@
|
|||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container">
|
||||
<partial name="_CookieConsentPartial" />
|
||||
<main role="main" class="pb-3">
|
||||
<main role="main" class="pb-3">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
© copyrightYear - Company.WebApplication1 - <a asp-area="" asp-page="/Privacy">Privacy</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<environment include="Development">
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
|
||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
|
||||
</script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"
|
||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-xrRywqdh3PHs8keKZN+8zzc5TX0GRTLCcmivcbNJWm2rs5C8PRhcEn3czEjhAO9o">
|
||||
</script>
|
||||
</environment>
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
||||
@RenderSection("Scripts", required: false)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,5 @@
|
|||
<environment include="Development">
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
|
||||
</script>
|
||||
</environment>
|
||||
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,11 +52,6 @@ namespace Company.WebApplication1
|
|||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||
options.CheckConsentNeeded = context => true;
|
||||
});
|
||||
|
||||
#if (IndividualLocalAuth)
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
|
|
@ -152,8 +147,6 @@ namespace Company.WebApplication1
|
|||
#endif
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseCookiePolicy();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
#if (OrganizationalAuth || IndividualAuth)
|
||||
|
|
|
|||
|
|
@ -52,11 +52,6 @@ namespace Company.WebApplication1
|
|||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||
options.CheckConsentNeeded = context => true;
|
||||
});
|
||||
|
||||
#if (IndividualLocalAuth)
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
|
|
@ -153,8 +148,6 @@ namespace Company.WebApplication1
|
|||
#endif
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseCookiePolicy();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
#if (OrganizationalAuth || IndividualAuth)
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
@using Microsoft.AspNetCore.Http.Features
|
||||
|
||||
@{
|
||||
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
|
||||
var showBanner = !consentFeature?.CanTrack ?? false;
|
||||
var cookieString = consentFeature?.CreateConsentCookie();
|
||||
}
|
||||
|
||||
@if (showBanner)
|
||||
{
|
||||
<div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
|
||||
Use this space to summarize your privacy and cookie use policy. <a class="alert-link" asp-area="" asp-controller="Home" asp-action="Privacy">Learn More</a>.
|
||||
<button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
|
||||
<span aria-hidden="true">Accept</span>
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var button = document.querySelector("#cookieConsent button[data-cookie-string]");
|
||||
button.addEventListener("click", function (event) {
|
||||
document.cookie = button.dataset.cookieString;
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
}
|
||||
|
|
@ -4,17 +4,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - Company.WebApplication1</title>
|
||||
|
||||
<environment include="Development">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"/>
|
||||
</environment>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -44,39 +34,17 @@
|
|||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container">
|
||||
<partial name="_CookieConsentPartial" />
|
||||
<main role="main" class="pb-3">
|
||||
<main role="main" class="pb-3">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
© copyrightYear - Company.WebApplication1 - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<environment include="Development">
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
|
||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
|
||||
</script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"
|
||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-xrRywqdh3PHs8keKZN+8zzc5TX0GRTLCcmivcbNJWm2rs5C8PRhcEn3czEjhAO9o">
|
||||
</script>
|
||||
</environment>
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
||||
@RenderSection("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,2 @@
|
|||
<environment include="Development">
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
|
||||
</script>
|
||||
</environment>
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
@using Microsoft.AspNetCore.Http.Features
|
||||
|
||||
@{
|
||||
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
|
||||
var showBanner = !consentFeature?.CanTrack ?? false;
|
||||
var cookieString = consentFeature?.CreateConsentCookie();
|
||||
}
|
||||
|
||||
@if (showBanner)
|
||||
{
|
||||
<div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
|
||||
Use this space to summarize your privacy and cookie use policy. <a class="alert-link" asp-page="/Privacy">Learn More</a>.
|
||||
<button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
|
||||
<span aria-hidden="true">Accept</span>
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var button = document.querySelector("#cookieConsent button[data-cookie-string]");
|
||||
button.addEventListener("click", function (event) {
|
||||
document.cookie = button.dataset.cookieString;
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
}
|
||||
|
|
@ -5,16 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - Company.WebApplication1</title>
|
||||
|
||||
<environment include="Development">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" />
|
||||
</environment>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -39,37 +30,18 @@
|
|||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container">
|
||||
<partial name="_CookieConsentPartial" />
|
||||
<main role="main" class="pb-3">
|
||||
<main role="main" class="pb-3">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
© copyrightYear - Company.WebApplication1 - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<environment include="Development">
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
|
||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
|
||||
</script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"
|
||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-xrRywqdh3PHs8keKZN+8zzc5TX0GRTLCcmivcbNJWm2rs5C8PRhcEn3czEjhAO9o">
|
||||
</script>
|
||||
</environment>
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
|
||||
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
||||
@RenderSection("Scripts", required: false)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<environment include="Development">
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
|
||||
</script>
|
||||
</environment>
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,293 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using AngleSharp;
|
||||
using AngleSharp.Dom;
|
||||
using AngleSharp.Dom.Html;
|
||||
using AngleSharp.Parser.Html;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using Templates.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class CdnScriptTagTests : IDisposable
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
private readonly HttpClient _httpClient;
|
||||
private static List<ScriptTag> _scriptTags;
|
||||
private static List<LinkTag> _linkTags;
|
||||
private static readonly string[] _packages;
|
||||
|
||||
static CdnScriptTagTests()
|
||||
{
|
||||
var searchPattern = "*.nupkg";
|
||||
_packages = Directory.EnumerateFiles(
|
||||
ResolveFolder("ArtifactsShippingPackagesDir"),
|
||||
searchPattern)
|
||||
.Concat(Directory.EnumerateFiles(
|
||||
ResolveFolder("ArtifactsNonShippingPackagesDir"),
|
||||
searchPattern))
|
||||
.ToArray();
|
||||
|
||||
_scriptTags = new List<ScriptTag>();
|
||||
_linkTags = new List<LinkTag>();
|
||||
foreach (var packagePath in _packages)
|
||||
{
|
||||
var tags = GetTags(packagePath);
|
||||
_scriptTags.AddRange(tags.scripts);
|
||||
_linkTags.AddRange(tags.links);
|
||||
}
|
||||
}
|
||||
|
||||
private static string ResolveFolder(string folder) =>
|
||||
typeof(CdnScriptTagTests).Assembly
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.Single(a => a.Key == folder).Value;
|
||||
|
||||
public CdnScriptTagTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SubresourceIntegrityCheckScriptData
|
||||
{
|
||||
get
|
||||
{
|
||||
var scriptTags = _scriptTags
|
||||
.Where(st => st.FallbackSrc != null)
|
||||
.Select(st => new object[] { st });
|
||||
Assert.NotEmpty(scriptTags);
|
||||
return scriptTags;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SubresourceIntegrityCheckLinkData
|
||||
{
|
||||
get
|
||||
{
|
||||
var linkTags = _linkTags
|
||||
.Where(st => st.FallbackHRef != null)
|
||||
.Select(st => new object[] { st });
|
||||
Assert.NotEmpty(linkTags);
|
||||
return linkTags;
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SubresourceIntegrityCheckScriptData))]
|
||||
public async Task CheckScriptSubresourceIntegrity(ScriptTag scriptTag)
|
||||
{
|
||||
var expectedIntegrity = await GetShaIntegrity(scriptTag);
|
||||
if (!string.Equals(expectedIntegrity, scriptTag.Integrity, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Assert.False(true, $"Expected {scriptTag.Src} to have Integrity '{expectedIntegrity}' but it had '{scriptTag.Integrity}'.");
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SubresourceIntegrityCheckLinkData))]
|
||||
public async Task CheckLinkSubresourceIntegrity(LinkTag linkTag)
|
||||
{
|
||||
string expectedIntegrity = await GetShaIntegrity(linkTag);
|
||||
if (!expectedIntegrity.Equals(linkTag.Integrity, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Assert.False(true, $"Expected {linkTag.HRef} to have Integrity '{expectedIntegrity}' but it had '{linkTag.Integrity}'.");
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> FallbackSrcCheckData
|
||||
{
|
||||
get
|
||||
{
|
||||
var scriptTags = _scriptTags
|
||||
.Where(st => st.FallbackSrc != null)
|
||||
.Select(st => new object[] { st });
|
||||
Assert.NotEmpty(scriptTags);
|
||||
return scriptTags;
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(FallbackSrcCheckData))]
|
||||
public async Task FallbackSrcContent_Matches_CDNContent(ScriptTag scriptTag)
|
||||
{
|
||||
var fallbackSrc = scriptTag.FallbackSrc
|
||||
.TrimStart('~')
|
||||
.TrimStart('/');
|
||||
|
||||
var cdnContent = await GetStringFromCDN(scriptTag.Src);
|
||||
var fallbackSrcContent = GetFileContentFromArchive(scriptTag, fallbackSrc);
|
||||
|
||||
Assert.Equal(RemoveLineEndings(cdnContent), RemoveLineEndings(fallbackSrcContent));
|
||||
}
|
||||
|
||||
public struct LinkTag
|
||||
{
|
||||
public string Rel;
|
||||
public string HRef;
|
||||
public string FallbackHRef;
|
||||
public string Integrity;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{HRef}, {Integrity}";
|
||||
}
|
||||
}
|
||||
|
||||
public struct ScriptTag
|
||||
{
|
||||
public string Src;
|
||||
public string Integrity;
|
||||
public string FallbackSrc;
|
||||
public string FileName;
|
||||
public string Entry;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Src}, {Entry}";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetStringFromCDN(string src)
|
||||
{
|
||||
var response = await GetFromCDN(src);
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
private async Task<byte[]> GetByteArrayFromCDN(string src)
|
||||
{
|
||||
var response = await GetFromCDN(src);
|
||||
return await response.Content.ReadAsByteArrayAsync();
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> GetFromCDN(string src)
|
||||
{
|
||||
var logger = NullLogger.Instance;
|
||||
return await RetryHelper.RetryRequest(async () =>
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, new Uri(src));
|
||||
return await _httpClient.SendAsync(request);
|
||||
}, logger);
|
||||
}
|
||||
|
||||
private Task<string> GetShaIntegrity(ScriptTag scriptTag)
|
||||
{
|
||||
return GetShaIntegrity(scriptTag.Integrity, scriptTag.Src);
|
||||
}
|
||||
|
||||
private Task<string> GetShaIntegrity(LinkTag linkTag)
|
||||
{
|
||||
return GetShaIntegrity(linkTag.Integrity, linkTag.HRef);
|
||||
}
|
||||
|
||||
private async Task<string> GetShaIntegrity(string integrity, string src)
|
||||
{
|
||||
var prefix = integrity.Substring(0, 6);
|
||||
var respStream = await GetByteArrayFromCDN(src);
|
||||
using (HashAlgorithm alg = string.Equals(prefix, "sha256") ? (HashAlgorithm)SHA256.Create() : (HashAlgorithm)SHA384.Create())
|
||||
{
|
||||
var hash = alg.ComputeHash(respStream);
|
||||
return $"{prefix}-" + Convert.ToBase64String(hash);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetFileContentFromArchive(ScriptTag scriptTag, string relativeFilePath)
|
||||
{
|
||||
var file = _packages.Single(f => f.EndsWith(scriptTag.FileName));
|
||||
using (var zip = new ZipArchive(File.OpenRead(file), ZipArchiveMode.Read, leaveOpen: false))
|
||||
{
|
||||
var entry = zip.Entries
|
||||
.Where(e => e.FullName.EndsWith(relativeFilePath, StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
using (var reader = new StreamReader(entry.Open()))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static (List<ScriptTag> scripts, List<LinkTag> links) GetTags(string zipFile)
|
||||
{
|
||||
var scriptTags = new List<ScriptTag>();
|
||||
var linkTags = new List<LinkTag>();
|
||||
using (var zip = new ZipArchive(File.OpenRead(zipFile), ZipArchiveMode.Read, leaveOpen: false))
|
||||
{
|
||||
foreach (var entry in zip.Entries)
|
||||
{
|
||||
if (!string.Equals(".cshtml", Path.GetExtension(entry.Name), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IHtmlDocument htmlDocument;
|
||||
var options = new HtmlParserOptions
|
||||
{
|
||||
IsStrictMode = false,
|
||||
IsEmbedded = false,
|
||||
};
|
||||
var config = Configuration.Default;
|
||||
var htmlParser = new HtmlParser(options, config);
|
||||
using (var reader = new StreamReader(entry.Open()))
|
||||
{
|
||||
htmlDocument = htmlParser.Parse(entry.Open());
|
||||
}
|
||||
|
||||
foreach (IElement link in htmlDocument.Body.GetElementsByTagName("link"))
|
||||
{
|
||||
linkTags.Add(new LinkTag
|
||||
{
|
||||
HRef = link.GetAttribute("href"),
|
||||
Integrity = link.GetAttribute("integrity"),
|
||||
FallbackHRef = link.GetAttribute("asp-fallback-href"),
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var scriptElement in htmlDocument.Scripts)
|
||||
{
|
||||
var fallbackSrcAttribute = scriptElement.Attributes
|
||||
.FirstOrDefault(attr => string.Equals("asp-fallback-src", attr.Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
scriptTags.Add(new ScriptTag
|
||||
{
|
||||
Src = scriptElement.Source,
|
||||
Integrity = scriptElement.Integrity,
|
||||
FallbackSrc = fallbackSrcAttribute?.Value,
|
||||
FileName = Path.GetFileName(zipFile),
|
||||
Entry = entry.FullName
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return (scriptTags, linkTags);
|
||||
}
|
||||
|
||||
private static string RemoveLineEndings(string originalString)
|
||||
{
|
||||
return originalString.Replace("\r\n", "").Replace("\n", "");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_httpClient.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
"Pages/Privacy.cshtml.cs",
|
||||
"Pages/_ViewImports.cshtml",
|
||||
"Pages/_ViewStart.cshtml",
|
||||
"Pages/Shared/_CookieConsentPartial.cshtml",
|
||||
"Pages/Shared/_Layout.cshtml",
|
||||
"Pages/Shared/_LoginPartial.cshtml",
|
||||
"Pages/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -82,7 +81,6 @@
|
|||
"Pages/Privacy.cshtml.cs",
|
||||
"Pages/_ViewImports.cshtml",
|
||||
"Pages/_ViewStart.cshtml",
|
||||
"Pages/Shared/_CookieConsentPartial.cshtml",
|
||||
"Pages/Shared/_Layout.cshtml",
|
||||
"Pages/Shared/_ValidationScriptsPartial.cshtml",
|
||||
"Properties/launchSettings.json",
|
||||
|
|
@ -141,7 +139,6 @@
|
|||
"Pages/Privacy.cshtml.cs",
|
||||
"Pages/_ViewImports.cshtml",
|
||||
"Pages/_ViewStart.cshtml",
|
||||
"Pages/Shared/_CookieConsentPartial.cshtml",
|
||||
"Pages/Shared/_Layout.cshtml",
|
||||
"Pages/Shared/_LoginPartial.cshtml",
|
||||
"Pages/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -201,7 +198,6 @@
|
|||
"Pages/Privacy.cshtml.cs",
|
||||
"Pages/_ViewImports.cshtml",
|
||||
"Pages/_ViewStart.cshtml",
|
||||
"Pages/Shared/_CookieConsentPartial.cshtml",
|
||||
"Pages/Shared/_Layout.cshtml",
|
||||
"Pages/Shared/_LoginPartial.cshtml",
|
||||
"Pages/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -261,7 +257,6 @@
|
|||
"Pages/Privacy.cshtml.cs",
|
||||
"Pages/_ViewImports.cshtml",
|
||||
"Pages/_ViewStart.cshtml",
|
||||
"Pages/Shared/_CookieConsentPartial.cshtml",
|
||||
"Pages/Shared/_Layout.cshtml",
|
||||
"Pages/Shared/_ValidationScriptsPartial.cshtml",
|
||||
"Properties/launchSettings.json",
|
||||
|
|
@ -320,7 +315,6 @@
|
|||
"Pages/Privacy.cshtml.cs",
|
||||
"Pages/_ViewImports.cshtml",
|
||||
"Pages/_ViewStart.cshtml",
|
||||
"Pages/Shared/_CookieConsentPartial.cshtml",
|
||||
"Pages/Shared/_Layout.cshtml",
|
||||
"Pages/Shared/_LoginPartial.cshtml",
|
||||
"Pages/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -484,7 +478,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_LoginPartial.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -543,7 +536,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
"wwwroot/favicon.ico",
|
||||
|
|
@ -601,7 +593,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_LoginPartial.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -660,7 +651,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_LoginPartial.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -719,7 +709,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
"wwwroot/favicon.ico",
|
||||
|
|
@ -777,7 +766,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_LoginPartial.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
|
|
@ -836,7 +824,6 @@
|
|||
"Views/Home/Index.cshtml",
|
||||
"Views/Home/Privacy.cshtml",
|
||||
"Views/Shared/Error.cshtml",
|
||||
"Views/Shared/_CookieConsentPartial.cshtml",
|
||||
"Views/Shared/_Layout.cshtml",
|
||||
"Views/Shared/_ValidationScriptsPartial.cshtml",
|
||||
"wwwroot/favicon.ico",
|
||||
|
|
|
|||
Loading…
Reference in New Issue