[Identity] Move to use static web assets support. (#11029)
* Moves Identity UI to use Static Web Assets * Removes the static files as embedded content. * Stops plugging the static assets through the embedded file provider. * Selects the UI framework at build time instead of runtime.
This commit is contained in:
parent
7a496ec162
commit
143c101693
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"solution": {
|
||||||
|
"path": "Identity.sln",
|
||||||
|
"projects": [
|
||||||
|
"ApiAuthorization.IdentityServer\\samples\\ApiAuthSample\\ApiAuthSample.csproj",
|
||||||
|
"ApiAuthorization.IdentityServer\\src\\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.csproj",
|
||||||
|
"ApiAuthorization.IdentityServer\\test\\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Tests.csproj",
|
||||||
|
"Core\\src\\Microsoft.AspNetCore.Identity.csproj",
|
||||||
|
"EntityFrameworkCore\\src\\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj",
|
||||||
|
"EntityFrameworkCore\\test\\EF.InMemory.Test\\Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test.csproj",
|
||||||
|
"EntityFrameworkCore\\test\\EF.Test\\Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj",
|
||||||
|
"Extensions.Core\\src\\Microsoft.Extensions.Identity.Core.csproj",
|
||||||
|
"Extensions.Stores\\src\\Microsoft.Extensions.Identity.Stores.csproj",
|
||||||
|
"Specification.Tests\\src\\Microsoft.AspNetCore.Identity.Specification.Tests.csproj",
|
||||||
|
"UI\\src\\Microsoft.AspNetCore.Identity.UI.csproj",
|
||||||
|
"samples\\IdentitySample.DefaultUI\\IdentitySample.DefaultUI.csproj",
|
||||||
|
"samples\\IdentitySample.Mvc\\IdentitySample.Mvc.csproj",
|
||||||
|
"test\\Identity.FunctionalTests\\Microsoft.AspNetCore.Identity.FunctionalTests.csproj",
|
||||||
|
"test\\Identity.Test\\Microsoft.AspNetCore.Identity.Test.csproj",
|
||||||
|
"test\\InMemory.Test\\Microsoft.AspNetCore.Identity.InMemory.Test.csproj",
|
||||||
|
"testassets\\Identity.DefaultUI.WebSite\\Identity.DefaultUI.WebSite.csproj"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,20 +6,15 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
public static partial class IdentityBuilderUIExtensions
|
public static partial class IdentityBuilderUIExtensions
|
||||||
{
|
{
|
||||||
public static Microsoft.AspNetCore.Identity.IdentityBuilder AddDefaultUI(this Microsoft.AspNetCore.Identity.IdentityBuilder builder) { throw null; }
|
public static Microsoft.AspNetCore.Identity.IdentityBuilder AddDefaultUI(this Microsoft.AspNetCore.Identity.IdentityBuilder builder) { throw null; }
|
||||||
public static Microsoft.AspNetCore.Identity.IdentityBuilder AddDefaultUI(this Microsoft.AspNetCore.Identity.IdentityBuilder builder, Microsoft.AspNetCore.Identity.UI.UIFramework framework) { throw null; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace Microsoft.AspNetCore.Identity.UI
|
namespace Microsoft.AspNetCore.Identity.UI
|
||||||
{
|
{
|
||||||
public partial class DefaultUIOptions
|
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly, Inherited=false, AllowMultiple=false)]
|
||||||
|
public sealed partial class UIFrameworkAttribute : System.Attribute
|
||||||
{
|
{
|
||||||
public DefaultUIOptions() { }
|
public UIFrameworkAttribute(string uiFramework) { }
|
||||||
public Microsoft.AspNetCore.Identity.UI.UIFramework UIFramework { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
public string UIFramework { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||||
}
|
|
||||||
public enum UIFramework
|
|
||||||
{
|
|
||||||
Bootstrap3 = 0,
|
|
||||||
Bootstrap4 = 1,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace Microsoft.AspNetCore.Identity.UI.Services
|
namespace Microsoft.AspNetCore.Identity.UI.Services
|
||||||
|
|
|
||||||
|
|
@ -1,16 +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.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.UI
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Options for the default Identity UI
|
|
||||||
/// </summary>
|
|
||||||
public class DefaultUIOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the <see cref="UIFramework"/> to use with the default UI.
|
|
||||||
/// </summary>
|
|
||||||
public UIFramework UIFramework { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity.UI;
|
using Microsoft.AspNetCore.Identity.UI;
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
|
|
@ -30,35 +31,16 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="builder">The <see cref="IdentityBuilder"/>.</param>
|
/// <param name="builder">The <see cref="IdentityBuilder"/>.</param>
|
||||||
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
|
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
|
||||||
public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder) => builder.AddDefaultUI(UIFramework.Bootstrap4);
|
public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder)
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a default, self-contained UI for Identity to the application using
|
|
||||||
/// Razor Pages in an area named Identity.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// In order to use the default UI, the application must be using <see cref="Microsoft.AspNetCore.Mvc"/>,
|
|
||||||
/// <see cref="Microsoft.AspNetCore.StaticFiles"/> and contain a <c>_LoginPartial</c> partial view that
|
|
||||||
/// can be found by the application.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="builder">The <see cref="IdentityBuilder"/>.</param>
|
|
||||||
/// <param name="framework">The <see cref="UIFramework"/>.</param>
|
|
||||||
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
|
|
||||||
public static IdentityBuilder AddDefaultUI(
|
|
||||||
this IdentityBuilder builder,
|
|
||||||
UIFramework framework)
|
|
||||||
{
|
{
|
||||||
builder.AddSignInManager();
|
builder.AddSignInManager();
|
||||||
AddRelatedParts(builder, framework);
|
AddRelatedParts(builder);
|
||||||
|
|
||||||
builder.Services.ConfigureOptions(
|
builder.Services.ConfigureOptions(
|
||||||
typeof(IdentityDefaultUIConfigureOptions<>)
|
typeof(IdentityDefaultUIConfigureOptions<>)
|
||||||
.MakeGenericType(builder.UserType));
|
.MakeGenericType(builder.UserType));
|
||||||
builder.Services.TryAddTransient<IEmailSender, EmailSender>();
|
builder.Services.TryAddTransient<IEmailSender, EmailSender>();
|
||||||
|
|
||||||
builder.Services.Configure<DefaultUIOptions>(o => o.UIFramework = framework);
|
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,8 +51,20 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
[UIFramework.Bootstrap4] = "Microsoft.AspNetCore.Identity.UI.Views.V4",
|
[UIFramework.Bootstrap4] = "Microsoft.AspNetCore.Identity.UI.Views.V4",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void AddRelatedParts(IdentityBuilder builder, UIFramework framework)
|
private static void AddRelatedParts(IdentityBuilder builder)
|
||||||
{
|
{
|
||||||
|
// We try to resolve the UI framework that was used by looking at the entry assembly.
|
||||||
|
// When an app runs, the entry assembly will point to the built app. In some rare cases
|
||||||
|
// (functional testing) the app assembly will be different, and we'll try to locate it through
|
||||||
|
// the same mechanism that MVC uses today.
|
||||||
|
// Finally, if for some reason we aren't able to find the assembly, we'll use our default value
|
||||||
|
// (Bootstrap4)
|
||||||
|
if (!TryResolveUIFramework(Assembly.GetEntryAssembly(), out var framework) ||
|
||||||
|
!TryResolveUIFramework(GetApplicationAssembly(builder), out framework))
|
||||||
|
{
|
||||||
|
framework = default;
|
||||||
|
}
|
||||||
|
|
||||||
var mvcBuilder = builder.Services
|
var mvcBuilder = builder.Services
|
||||||
.AddMvc()
|
.AddMvc()
|
||||||
.ConfigureApplicationPartManager(partManager =>
|
.ConfigureApplicationPartManager(partManager =>
|
||||||
|
|
@ -131,5 +125,38 @@ namespace Microsoft.AspNetCore.Identity
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Assembly GetApplicationAssembly(IdentityBuilder builder)
|
||||||
|
{
|
||||||
|
// Whis is the same logic that MVC follows to find the application assembly.
|
||||||
|
var environment = builder.Services.Where(d => d.ServiceType == typeof(IWebHostEnvironment)).ToArray();
|
||||||
|
var applicationName = ((IWebHostEnvironment)environment.LastOrDefault()?.ImplementationInstance)
|
||||||
|
.ApplicationName;
|
||||||
|
|
||||||
|
var appAssembly = Assembly.Load(applicationName);
|
||||||
|
return appAssembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryResolveUIFramework(Assembly assembly, out UIFramework uiFramework)
|
||||||
|
{
|
||||||
|
uiFramework = default;
|
||||||
|
|
||||||
|
var metadata = assembly.GetCustomAttributes<UIFrameworkAttribute>()
|
||||||
|
.SingleOrDefault()?.UIFramework; // Bootstrap4 is the default
|
||||||
|
if (metadata == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we find the metadata there must be a valid framework here.
|
||||||
|
if (!Enum.TryParse<UIFramework>(metadata, ignoreCase: true, out var uIFramework))
|
||||||
|
{
|
||||||
|
var enumValues = string.Join(", ", Enum.GetNames(typeof(UIFramework)).Select(v => $"'{v}'"));
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Found an invalid value for the 'IdentityUIFrameworkVersion'. Valid values are {enumValues}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,34 +3,26 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity.UI.Areas.Identity.Filters;
|
using Microsoft.AspNetCore.Identity.UI.Areas.Identity.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.FileProviders;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.UI
|
namespace Microsoft.AspNetCore.Identity.UI
|
||||||
{
|
{
|
||||||
internal class IdentityDefaultUIConfigureOptions<TUser> :
|
internal class IdentityDefaultUIConfigureOptions<TUser> :
|
||||||
IPostConfigureOptions<RazorPagesOptions>,
|
IPostConfigureOptions<RazorPagesOptions>,
|
||||||
IPostConfigureOptions<StaticFileOptions>,
|
|
||||||
IConfigureNamedOptions<CookieAuthenticationOptions> where TUser : class
|
IConfigureNamedOptions<CookieAuthenticationOptions> where TUser : class
|
||||||
{
|
{
|
||||||
private const string IdentityUIDefaultAreaName = "Identity";
|
private const string IdentityUIDefaultAreaName = "Identity";
|
||||||
|
|
||||||
public IdentityDefaultUIConfigureOptions(
|
public IdentityDefaultUIConfigureOptions(
|
||||||
IWebHostEnvironment environment,
|
IWebHostEnvironment environment) {
|
||||||
IOptions<DefaultUIOptions> uiOptions)
|
|
||||||
{
|
|
||||||
Environment = environment;
|
Environment = environment;
|
||||||
UiOptions = uiOptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IWebHostEnvironment Environment { get; }
|
public IWebHostEnvironment Environment { get; }
|
||||||
public IOptions<DefaultUIOptions> UiOptions { get; }
|
|
||||||
|
|
||||||
public void PostConfigure(string name, RazorPagesOptions options)
|
public void PostConfigure(string name, RazorPagesOptions options)
|
||||||
{
|
{
|
||||||
|
|
@ -50,30 +42,10 @@ namespace Microsoft.AspNetCore.Identity.UI
|
||||||
pam => pam.Filters.Add(new ExternalLoginsPageFilter<TUser>()));
|
pam => pam.Filters.Add(new ExternalLoginsPageFilter<TUser>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostConfigure(string name, StaticFileOptions options)
|
public void Configure(CookieAuthenticationOptions options) {
|
||||||
{
|
// Nothing to do here as Configure(string name, CookieAuthenticationOptions options) is hte one setting things up.
|
||||||
name = name ?? throw new ArgumentNullException(nameof(name));
|
|
||||||
options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
// Basic initialization in case the options weren't initialized by any other component
|
|
||||||
options.ContentTypeProvider = options.ContentTypeProvider ?? new FileExtensionContentTypeProvider();
|
|
||||||
if (options.FileProvider == null && Environment.WebRootFileProvider == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Missing FileProvider.");
|
|
||||||
}
|
|
||||||
|
|
||||||
options.FileProvider = options.FileProvider ?? Environment.WebRootFileProvider;
|
|
||||||
|
|
||||||
var basePath = UiOptions.Value.UIFramework == UIFramework.Bootstrap3 ? "wwwroot/V3" :
|
|
||||||
"wwwroot/V4";
|
|
||||||
|
|
||||||
// Add our provider
|
|
||||||
var filesProvider = new ManifestEmbeddedFileProvider(GetType().Assembly, basePath);
|
|
||||||
options.FileProvider = new CompositeFileProvider(options.FileProvider, filesProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(CookieAuthenticationOptions options) { }
|
|
||||||
|
|
||||||
public void Configure(string name, CookieAuthenticationOptions options)
|
public void Configure(string name, CookieAuthenticationOptions options)
|
||||||
{
|
{
|
||||||
name = name ?? throw new ArgumentNullException(nameof(name));
|
name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>ASP.NET Core Identity UI is the default Razor Pages built-in UI for the ASP.NET Core Identity framework.</Description>
|
<Description>ASP.NET Core Identity UI is the default Razor Pages built-in UI for the ASP.NET Core Identity framework.</Description>
|
||||||
|
|
@ -7,23 +7,30 @@
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>aspnetcore;identity;membership;razorpages</PackageTags>
|
<PackageTags>aspnetcore;identity;membership;razorpages</PackageTags>
|
||||||
<IsShippingPackage>true</IsShippingPackage>
|
<IsShippingPackage>true</IsShippingPackage>
|
||||||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
|
|
||||||
<ProvideApplicationPartFactoryAttributeTypeName>Microsoft.AspNetCore.Mvc.ApplicationParts.NullApplicationPartFactory, Microsoft.AspNetCore.Mvc.Core</ProvideApplicationPartFactoryAttributeTypeName>
|
<ProvideApplicationPartFactoryAttributeTypeName>Microsoft.AspNetCore.Mvc.ApplicationParts.NullApplicationPartFactory, Microsoft.AspNetCore.Mvc.Core</ProvideApplicationPartFactoryAttributeTypeName>
|
||||||
<RazorCompileOnBuild>false</RazorCompileOnBuild>
|
<RazorCompileOnBuild>false</RazorCompileOnBuild>
|
||||||
<RazorCompileOnPublish>false</RazorCompileOnPublish>
|
<RazorCompileOnPublish>false</RazorCompileOnPublish>
|
||||||
<EnableDefaultRazorGenerateItems>false</EnableDefaultRazorGenerateItems>
|
<EnableDefaultRazorGenerateItems>false</EnableDefaultRazorGenerateItems>
|
||||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||||
|
|
||||||
|
<DisableStaticWebAssetsBuildPropsFileGeneration>true</DisableStaticWebAssetsBuildPropsFileGeneration>
|
||||||
|
<StaticWebAssetsDisableProjectBuildPropsFileGeneration>true</StaticWebAssetsDisableProjectBuildPropsFileGeneration>
|
||||||
|
|
||||||
|
<GetCurrentProjectStaticWebAssetsDependsOn>
|
||||||
|
$(GetCurrentProjectStaticWebAssetsDependsOn);
|
||||||
|
_UpdatedIdentityUIStaticWebAssets
|
||||||
|
</GetCurrentProjectStaticWebAssetsDependsOn>
|
||||||
|
|
||||||
|
<IdentityUIFrameworkVersion Condition="'$(IdentityUIFrameworkVersion)' == ''">Bootstrap4</IdentityUIFrameworkVersion>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="wwwroot/**/*" />
|
<Content Remove="@(Content)" />
|
||||||
<EmbeddedResource Remove="wwwroot/**/LICENSE*" />
|
<Content Include="wwwroot\**\*" Pack="true" />
|
||||||
<None Remove="wwwroot/**/LICENSE*" />
|
<None Include="build\*" Pack="true" PackagePath="build\" />
|
||||||
<None Include="THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="/THIRD-PARTY-NOTICES.txt" />
|
<None Include="THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="/THIRD-PARTY-NOTICES.txt" />
|
||||||
|
|
||||||
<Content Update="wwwroot/**/*" Pack="false" />
|
|
||||||
<Content Update="**\*.cshtml" Pack="false" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -40,6 +47,10 @@
|
||||||
<UIFrameworkVersionMoniker Include="V4" />
|
<UIFrameworkVersionMoniker Include="V4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="build\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Source build doesn't build this package -->
|
<!-- Source build doesn't build this package -->
|
||||||
<Target Name="BuildRazorViews" DependsOnTargets="Compile" BeforeTargets="Build" Condition="'$(DotNetBuildFromSource)' != 'true'">
|
<Target Name="BuildRazorViews" DependsOnTargets="Compile" BeforeTargets="Build" Condition="'$(DotNetBuildFromSource)' != 'true'">
|
||||||
<Message Text="Building razor views assemblies" Importance="High" />
|
<Message Text="Building razor views assemblies" Importance="High" />
|
||||||
|
|
@ -63,6 +74,7 @@
|
||||||
|
|
||||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||||
<Output TaskParameter="DestinationFiles" ItemName="_RazorAssembly"/>
|
<Output TaskParameter="DestinationFiles" ItemName="_RazorAssembly"/>
|
||||||
|
|
||||||
</Copy>
|
</Copy>
|
||||||
|
|
||||||
<Copy
|
<Copy
|
||||||
|
|
@ -75,12 +87,10 @@
|
||||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)">
|
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)">
|
||||||
|
|
||||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
|
||||||
</Copy>
|
</Copy>
|
||||||
|
|
||||||
<Message
|
<Message Importance="High" Text="$(MSBuildProjectName) -> %(_RazorAssembly.FullPath)" />
|
||||||
Importance="High"
|
|
||||||
Text="$(MSBuildProjectName) -> %(_RazorAssembly.FullPath)" />
|
|
||||||
|
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
|
@ -90,19 +100,15 @@
|
||||||
|
|
||||||
<Target Name="SetupRazorInputs">
|
<Target Name="SetupRazorInputs">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<_RazorGenerate
|
<_RazorGenerate Include="Areas\Identity\Pages\$(UIFrameworkVersion)\**\*.cshtml" />
|
||||||
Include="Areas\Identity\Pages\$(UIFrameworkVersion)\**\*.cshtml" />
|
|
||||||
|
|
||||||
<RazorGenerate
|
<RazorGenerate Include="@(_RazorGenerate)" Link="Areas\Identity\Pages\%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
Include="@(_RazorGenerate)"
|
|
||||||
Link="Areas\Identity\Pages\%(RecursiveDir)%(Filename)%(Extension)" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="BuildForUI" DependsOnTargets="SetupRazorInputs;RazorCompile" />
|
<Target Name="BuildForUI" DependsOnTargets="SetupRazorInputs;RazorCompile" />
|
||||||
|
|
||||||
<Target
|
<Target Name="_GetRazorDlls" BeforeTargets="GetCopyToOutputDirectoryItems">
|
||||||
Name="_GetRazorDlls" BeforeTargets="GetCopyToOutputDirectoryItems">
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<_GeneratedRazorViews Include="$(TargetDir)$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
|
<_GeneratedRazorViews Include="$(TargetDir)$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
|
||||||
|
|
@ -117,15 +123,13 @@
|
||||||
|
|
||||||
<Target Name="_AddRazorDlls" BeforeTargets="BuiltProjectOutputGroup">
|
<Target Name="_AddRazorDlls" BeforeTargets="BuiltProjectOutputGroup">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<BuiltProjectOutputGroupOutput
|
<BuiltProjectOutputGroupOutput Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
|
||||||
Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="_AddRazorPdbs" BeforeTargets="DebugSymbolsProjectOutputGroup">
|
<Target Name="_AddRazorPdbs" BeforeTargets="DebugSymbolsProjectOutputGroup">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DebugSymbolsProjectOutputGroupOutput
|
<DebugSymbolsProjectOutputGroupOutput Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).pdb" />
|
||||||
Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).pdb" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
|
@ -136,8 +140,34 @@
|
||||||
<ExpectedOutputFile Include="$(TargetDir)Microsoft.AspNetCore.Identity.UI.Views.V4.dll" />
|
<ExpectedOutputFile Include="$(TargetDir)Microsoft.AspNetCore.Identity.UI.Views.V4.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Error Text="Unable to find precompiled view file %(ExpectedOutputFile.Identity)"
|
<Error Text="Unable to find precompiled view file %(ExpectedOutputFile.Identity)" Condition="!Exists('%(ExpectedOutputFile.Identity)')" />
|
||||||
Condition="!Exists('%(ExpectedOutputFile.Identity)')" />
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_UpdatedIdentityUIStaticWebAssets">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<StaticWebAsset Remove="@(StaticWebAsset)" />
|
||||||
|
|
||||||
|
<_V3Content Include="wwwroot\V3\**" />
|
||||||
|
<_V4Content Include="wwwroot\V4\**" />
|
||||||
|
|
||||||
|
<StaticWebAsset Include="@(_V3Content->'%(FullPath)')" Condition="'$(IdentityUIFrameworkVersion)' == 'Bootstrap3'">
|
||||||
|
<SourceType></SourceType>
|
||||||
|
<SourceId>Microsoft.AspNetCore.Identity.UI</SourceId>
|
||||||
|
<ContentRoot>$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)wwwroot/V3'))</ContentRoot>
|
||||||
|
<BasePath>/Identity</BasePath>
|
||||||
|
<RelativePath>%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
|
||||||
|
</StaticWebAsset>
|
||||||
|
|
||||||
|
<StaticWebAsset Include="@(_V4Content->'%(FullPath)')" Condition="'$(IdentityUIFrameworkVersion)' == 'Bootstrap4'">
|
||||||
|
<SourceType></SourceType>
|
||||||
|
<SourceId>Microsoft.AspNetCore.Identity.UI</SourceId>
|
||||||
|
<ContentRoot>$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)wwwroot/V4'))</ContentRoot>
|
||||||
|
<BasePath>/Identity</BasePath>
|
||||||
|
<RelativePath>%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
|
||||||
|
</StaticWebAsset>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,13 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.UI
|
namespace Microsoft.AspNetCore.Identity.UI
|
||||||
{
|
{
|
||||||
/// <summary>
|
internal enum UIFramework
|
||||||
/// The list of supported presentation frameworks for the default UI
|
|
||||||
/// </summary>
|
|
||||||
public enum UIFramework
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
// The default framework for a given release must be 0.
|
||||||
/// Bootstrap 3
|
// So this needs to be updated in the future if we include more frameworks.
|
||||||
/// </summary>
|
Bootstrap4 = 0,
|
||||||
Bootstrap3 = 0,
|
Bootstrap3 = 1,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Bootstrap 4
|
|
||||||
/// </summary>
|
|
||||||
Bootstrap4 = 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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 System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Identity.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The UIFramework Identity UI will use on the application.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
|
||||||
|
public sealed class UIFrameworkAttribute : Attribute
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="UIFrameworkAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uiFramework"></param>
|
||||||
|
public UIFrameworkAttribute(string uiFramework)
|
||||||
|
{
|
||||||
|
UIFramework = uiFramework;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The UI Framework Identity UI will use.
|
||||||
|
/// </summary>
|
||||||
|
public string UIFramework { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<IdentityUIFrameworkVersion Condition="'$(IdentityUIFrameworkVersion)' == ''">Bootstrap4</IdentityUIFrameworkVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AssemblyAttribute Include="Microsoft.AspNetCore.Identity.UI.UIFrameworkAttribute">
|
||||||
|
<_Parameter1>$(IdentityUIFrameworkVersion)</_Parameter1>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(IdentityUIFrameworkVersion)' == 'Bootstrap3'">
|
||||||
|
<StaticWebAsset Include="$(MSBuildThisFileDirectory)..\staticwebassets\V3\**">
|
||||||
|
<SourceType>Package</SourceType>
|
||||||
|
<SourceId>Microsoft.AspNetCore.Identity.UI</SourceId>
|
||||||
|
<ContentRoot>$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)..\staticwebassets\V3'))</ContentRoot>
|
||||||
|
<BasePath>/Identity</BasePath>
|
||||||
|
<RelativePath>%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
|
||||||
|
</StaticWebAsset>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(IdentityUIFrameworkVersion)' == 'Bootstrap4'">
|
||||||
|
<StaticWebAsset Include="$(MSBuildThisFileDirectory)..\staticwebassets\V4\**">
|
||||||
|
<SourceType>Package</SourceType>
|
||||||
|
<SourceId>Microsoft.AspNetCore.Identity.UI</SourceId>
|
||||||
|
<ContentRoot>$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)..\staticwebassets\V4'))</ContentRoot>
|
||||||
|
<BasePath>/Identity</BasePath>
|
||||||
|
<RelativePath>%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
|
||||||
|
</StaticWebAsset>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
@{
|
|
||||||
Layout = "/Views/Shared/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Identity sample MVC application on ASP.NET Core using the default UI</Description>
|
<Description>Identity sample MVC application on ASP.NET Core using the default UI</Description>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<UserSecretsId>aspnetcore-2ff9bc27-5e8c-4484-90ca-e3aace89b72a</UserSecretsId>
|
<UserSecretsId>aspnetcore-2ff9bc27-5e8c-4484-90ca-e3aace89b72a</UserSecretsId>
|
||||||
|
<IdentityUIFrameworkVersion>Bootstrap4</IdentityUIFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Authentication.Facebook" />
|
<Reference Include="Microsoft.AspNetCore.Authentication.Facebook" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Authentication.Google" />
|
<Reference Include="Microsoft.AspNetCore.Authentication.Google" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Authentication.Twitter" />
|
<Reference Include="Microsoft.AspNetCore.Authentication.Twitter" />
|
||||||
|
|
@ -26,6 +28,7 @@
|
||||||
<Reference Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="All" />
|
<Reference Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="All" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
|
<Reference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration.UserSecrets" />
|
<Reference Include="Microsoft.Extensions.Configuration.UserSecrets" />
|
||||||
|
<Reference Include="Microsoft.Extensions.Hosting" />
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Debug" />
|
<Reference Include="Microsoft.Extensions.Logging.Debug" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
@ -34,4 +37,23 @@
|
||||||
<Folder Include="Properties\" />
|
<Folder Include="Properties\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Include an assembly attribute into the built application assembly to indicate which flavor of the UI framework to use -->
|
||||||
|
<ItemGroup>
|
||||||
|
<AssemblyAttribute Include="Microsoft.AspNetCore.Identity.UI.UIFrameworkAttribute">
|
||||||
|
<_Parameter1>$(IdentityUIFrameworkVersion)</_Parameter1>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<ResolveStaticWebAssetsInputsDependsOn>_SetBootstrapFrameworkVersion</ResolveStaticWebAssetsInputsDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="_SetBootstrapFrameworkVersion">
|
||||||
|
<ItemGroup>
|
||||||
|
<_StaticWebAssetsProjectReference Condition="'%(FileName)' == 'Microsoft.AspNetCore.identity.UI'">
|
||||||
|
<AdditionalProperties>IdentityUIFrameworkVersion=$(IdentityUIFrameworkVersion)</AdditionalProperties>
|
||||||
|
</_StaticWebAssetsProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
namespace IdentitySample.DefaultUI
|
namespace IdentitySample.DefaultUI
|
||||||
{
|
{
|
||||||
|
|
@ -7,17 +8,19 @@ namespace IdentitySample.DefaultUI
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var host = CreateWebHostBuilder(args)
|
CreateHostBuilder(args).Build().Run();
|
||||||
.Build();
|
|
||||||
|
|
||||||
host.Run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
public static bool UseStartup { get; set; } = true;
|
||||||
new WebHostBuilder()
|
|
||||||
.UseKestrel()
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
Host.CreateDefaultBuilder(args)
|
||||||
.UseIISIntegration()
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
.UseStartup<Startup>();
|
{
|
||||||
|
if (UseStartup)
|
||||||
|
{
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Identity.DefaultUI.WebSite;
|
using Identity.DefaultUI.WebSite;
|
||||||
|
|
@ -6,10 +6,11 @@ using Identity.DefaultUI.WebSite.Data;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.FunctionalTests.IdentityUserTests
|
namespace Microsoft.AspNetCore.Identity.FunctionalTests.IdentityUserTests
|
||||||
{
|
{
|
||||||
public class Bootstrap3AuthorizationTests : AuthorizationTests<Bootstrap3Startup, ApplicationDbContext>
|
public class Bootstrap3AuthorizationTests : AuthorizationTests<ApplicationUserStartup, ApplicationDbContext>
|
||||||
{
|
{
|
||||||
public Bootstrap3AuthorizationTests(ServerFactory<Bootstrap3Startup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
public Bootstrap3AuthorizationTests(ServerFactory<ApplicationUserStartup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
||||||
{
|
{
|
||||||
|
serverFactory.BootstrapFrameworkVersion = "V3";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Identity.DefaultUI.WebSite;
|
using Identity.DefaultUI.WebSite;
|
||||||
|
|
@ -6,10 +6,11 @@ using Identity.DefaultUI.WebSite.Data;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Bootstrap3Tests
|
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Bootstrap3Tests
|
||||||
{
|
{
|
||||||
public class Bootstrap3ManagementTests : ManagementTests<Bootstrap3Startup, ApplicationDbContext>
|
public class Bootstrap3ManagementTests : ManagementTests<ApplicationUserStartup, ApplicationDbContext>
|
||||||
{
|
{
|
||||||
public Bootstrap3ManagementTests(ServerFactory<Bootstrap3Startup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
public Bootstrap3ManagementTests(ServerFactory<ApplicationUserStartup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
||||||
{
|
{
|
||||||
|
serverFactory.BootstrapFrameworkVersion = "V3";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Identity.DefaultUI.WebSite;
|
using Identity.DefaultUI.WebSite;
|
||||||
|
|
@ -6,10 +6,11 @@ using Identity.DefaultUI.WebSite.Data;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Bootstrap3Tests
|
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Bootstrap3Tests
|
||||||
{
|
{
|
||||||
public class Bootstrap3RegistrationTests : RegistrationTests<Bootstrap3Startup, ApplicationDbContext>
|
public class Bootstrap3RegistrationTests : RegistrationTests<ApplicationUserStartup, ApplicationDbContext>
|
||||||
{
|
{
|
||||||
public Bootstrap3RegistrationTests(ServerFactory<Bootstrap3Startup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
public Bootstrap3RegistrationTests(ServerFactory<ApplicationUserStartup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
||||||
{
|
{
|
||||||
|
serverFactory.BootstrapFrameworkVersion = "V3";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Identity.DefaultUI.WebSite;
|
using Identity.DefaultUI.WebSite;
|
||||||
|
|
@ -6,10 +6,11 @@ using Identity.DefaultUI.WebSite.Data;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Bootstrap3Tests
|
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Bootstrap3Tests
|
||||||
{
|
{
|
||||||
public class Bootstrap3LoginTests : LoginTests<Bootstrap3Startup, ApplicationDbContext>
|
public class Bootstrap3LoginTests : LoginTests<ApplicationUserStartup, ApplicationDbContext>
|
||||||
{
|
{
|
||||||
public Bootstrap3LoginTests(ServerFactory<Bootstrap3Startup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
public Bootstrap3LoginTests(ServerFactory<ApplicationUserStartup, ApplicationDbContext> serverFactory) : base(serverFactory)
|
||||||
{
|
{
|
||||||
|
serverFactory.BootstrapFrameworkVersion = "V3";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,26 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using Identity.DefaultUI.WebSite;
|
using Identity.DefaultUI.WebSite;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Hosting.StaticWebAssets;
|
||||||
|
using Microsoft.AspNetCore.Identity.UI;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
using Microsoft.AspNetCore.Mvc.Testing;
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
using Microsoft.AspNetCore.TestHost;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
||||||
{
|
{
|
||||||
public class ServerFactory<TStartup,TContext>: WebApplicationFactory<TStartup>
|
public class ServerFactory<TStartup, TContext> : WebApplicationFactory<TStartup>
|
||||||
where TStartup : class
|
where TStartup : class
|
||||||
where TContext : DbContext
|
where TContext : DbContext
|
||||||
{
|
{
|
||||||
|
|
@ -29,6 +36,10 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
||||||
ClientOptions.BaseAddress = new Uri("https://localhost");
|
ClientOptions.BaseAddress = new Uri("https://localhost");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string BootstrapFrameworkVersion { get; set; } = "V4";
|
||||||
|
private bool IsHelixCI => typeof(ServerFactory<,>).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||||
|
.Any(a => a.Key == "Microsoft.AspNetCore.Testing.IsHelixCI");
|
||||||
|
|
||||||
protected override IHostBuilder CreateHostBuilder()
|
protected override IHostBuilder CreateHostBuilder()
|
||||||
{
|
{
|
||||||
Program.UseStartup = false;
|
Program.UseStartup = false;
|
||||||
|
|
@ -48,6 +59,70 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
||||||
// several places to pass important data in post-redirect-get flows.
|
// several places to pass important data in post-redirect-get flows.
|
||||||
.AddCookieTempDataProvider(o => o.Cookie.IsEssential = true);
|
.AddCookieTempDataProvider(o => o.Cookie.IsEssential = true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UpdateStaticAssets(builder);
|
||||||
|
UpdateApplicationParts(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateApplicationParts(IWebHostBuilder builder) =>
|
||||||
|
builder.ConfigureServices(services => AddRelatedParts(services, BootstrapFrameworkVersion));
|
||||||
|
|
||||||
|
private void UpdateStaticAssets(IWebHostBuilder builder)
|
||||||
|
{
|
||||||
|
var manifestPath = Path.GetDirectoryName(new Uri(typeof(ServerFactory<,>).Assembly.CodeBase).LocalPath);
|
||||||
|
builder.ConfigureAppConfiguration((ctx, cb) =>
|
||||||
|
{
|
||||||
|
if (ctx.HostingEnvironment.WebRootFileProvider is CompositeFileProvider composite)
|
||||||
|
{
|
||||||
|
var originalWebRoot = composite.FileProviders.First();
|
||||||
|
ctx.HostingEnvironment.WebRootFileProvider = originalWebRoot;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
string versionedPath = Path.Combine(manifestPath, $"Testing.DefaultWebSite.StaticWebAssets.{BootstrapFrameworkVersion}.xml");
|
||||||
|
UpdateManifest(versionedPath);
|
||||||
|
|
||||||
|
builder.ConfigureAppConfiguration((context, configBuilder) =>
|
||||||
|
{
|
||||||
|
using (var manifest = File.OpenRead(versionedPath))
|
||||||
|
{
|
||||||
|
typeof(StaticWebAssetsLoader)
|
||||||
|
.GetMethod("UseStaticWebAssetsCore", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
.Invoke(null, new object[] { context.HostingEnvironment, manifest });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateManifest(string versionedPath)
|
||||||
|
{
|
||||||
|
var content = File.ReadAllText(versionedPath);
|
||||||
|
var path = typeof(ServerFactory<,>).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||||
|
.Single(a => a.Key == "Microsoft.AspNetCore.Testing.IdentityUIProjectPath").Value;
|
||||||
|
|
||||||
|
path = Directory.Exists(path) ? Path.Combine(path, "wwwroot") : Path.Combine(FindHelixSlnFileDirectory(), "UI", "wwwroot");
|
||||||
|
|
||||||
|
var updatedContent = content.Replace("{TEST_PLACEHOLDER}", path);
|
||||||
|
|
||||||
|
File.WriteAllText(versionedPath, updatedContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FindHelixSlnFileDirectory()
|
||||||
|
{
|
||||||
|
var applicationPath = Path.GetDirectoryName(typeof(ServerFactory<,>).Assembly.Location);
|
||||||
|
var directoryInfo = new DirectoryInfo(applicationPath);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var solutionPath = Directory.EnumerateFiles(directoryInfo.FullName, "*.sln").FirstOrDefault();
|
||||||
|
if (solutionPath != null)
|
||||||
|
{
|
||||||
|
return directoryInfo.FullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryInfo = directoryInfo.Parent;
|
||||||
|
}
|
||||||
|
while (directoryInfo.Parent != null);
|
||||||
|
|
||||||
|
throw new InvalidOperationException($"Solution root could not be located using application root {applicationPath}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IHost CreateHost(IHostBuilder builder)
|
protected override IHost CreateHost(IHostBuilder builder)
|
||||||
|
|
@ -78,5 +153,76 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AddRelatedParts(IServiceCollection services, string framework)
|
||||||
|
{
|
||||||
|
var _assemblyMap =
|
||||||
|
new Dictionary<UIFramework, string>()
|
||||||
|
{
|
||||||
|
[UIFramework.Bootstrap3] = "Microsoft.AspNetCore.Identity.UI.Views.V3",
|
||||||
|
[UIFramework.Bootstrap4] = "Microsoft.AspNetCore.Identity.UI.Views.V4",
|
||||||
|
};
|
||||||
|
|
||||||
|
var mvcBuilder = services
|
||||||
|
.AddMvc()
|
||||||
|
.ConfigureApplicationPartManager(partManager =>
|
||||||
|
{
|
||||||
|
var thisAssembly = typeof(IdentityBuilderUIExtensions).Assembly;
|
||||||
|
var relatedAssemblies = RelatedAssemblyAttribute.GetRelatedAssemblies(thisAssembly, throwOnError: true);
|
||||||
|
var relatedParts = relatedAssemblies.ToDictionary(
|
||||||
|
ra => ra,
|
||||||
|
CompiledRazorAssemblyApplicationPartFactory.GetDefaultApplicationParts);
|
||||||
|
|
||||||
|
var selectedFrameworkAssembly = _assemblyMap[framework == "V3" ? UIFramework.Bootstrap3 : UIFramework.Bootstrap4];
|
||||||
|
|
||||||
|
foreach (var kvp in relatedParts)
|
||||||
|
{
|
||||||
|
var assemblyName = kvp.Key.GetName().Name;
|
||||||
|
if (!IsAssemblyForFramework(selectedFrameworkAssembly, assemblyName))
|
||||||
|
{
|
||||||
|
RemoveParts(partManager, kvp.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddParts(partManager, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAssemblyForFramework(string frameworkAssembly, string assemblyName) =>
|
||||||
|
string.Equals(assemblyName, frameworkAssembly, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
void RemoveParts(
|
||||||
|
ApplicationPartManager manager,
|
||||||
|
IEnumerable<ApplicationPart> partsToRemove)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < manager.ApplicationParts.Count; i++)
|
||||||
|
{
|
||||||
|
var part = manager.ApplicationParts[i];
|
||||||
|
if (partsToRemove.Any(p => string.Equals(
|
||||||
|
p.Name,
|
||||||
|
part.Name,
|
||||||
|
StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
manager.ApplicationParts.Remove(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddParts(
|
||||||
|
ApplicationPartManager manager,
|
||||||
|
IEnumerable<ApplicationPart> partsToAdd)
|
||||||
|
{
|
||||||
|
foreach (var part in partsToAdd)
|
||||||
|
{
|
||||||
|
if (!manager.ApplicationParts.Any(p => p.GetType() == part.GetType() &&
|
||||||
|
string.Equals(p.Name, part.Name, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
manager.ApplicationParts.Add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
<Compile Include="..\..\Extensions.Core\src\Base32.cs" Link="Infrastructure\Base32.cs" />
|
<Compile Include="..\..\Extensions.Core\src\Base32.cs" Link="Infrastructure\Base32.cs" />
|
||||||
<Compile Include="..\..\Extensions.Core\src\Rfc6238AuthenticationService.cs" Link="Infrastructure\Rfc6238AuthenticationService.cs" />
|
<Compile Include="..\..\Extensions.Core\src\Rfc6238AuthenticationService.cs" Link="Infrastructure\Rfc6238AuthenticationService.cs" />
|
||||||
|
<Compile Include="..\..\UI\src\UIFramework.cs" Link="Infrastructure\UIFramework.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -27,6 +28,39 @@
|
||||||
<Reference Include="AngleSharp" />
|
<Reference Include="AngleSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Testing.DefaultWebSite.StaticWebAssets.V4.xml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Testing.DefaultWebSite.StaticWebAssets.V4.xml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Testing.DefaultWebSite.StaticWebAssets.V3.xml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="AddProjectReferenceAssemblyInfo" BeforeTargets="GetAssemblyAttributes" DependsOnTargets="ResolveAssemblyReferences">
|
||||||
|
<ItemGroup>
|
||||||
|
<_IdentitUIDefaultWebSite Include="@(ReferencePath)" Condition="'%(ReferencePath.FileName)' == 'Identity.DefaultUI.WebSite'" />
|
||||||
|
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||||
|
<_Parameter1>Microsoft.AspNetCore.Testing.DefaultWebSiteProjectPath</_Parameter1>
|
||||||
|
<_Parameter2>$([System.IO.Path]::GetDirectoryName('%(_IdentitUIDefaultWebSite.MSBuildSourceProjectFile)'))</_Parameter2>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
|
||||||
|
<_IdentitUIProjectPath Include="@(ReferencePath)" Condition="'%(ReferencePath.FileName)' == 'Microsoft.AspNetCore.Identity.UI'" />
|
||||||
|
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||||
|
<_Parameter1>Microsoft.AspNetCore.Testing.IdentityUIProjectPath</_Parameter1>
|
||||||
|
<_Parameter2>$([System.IO.Path]::GetDirectoryName('%(_IdentitUIProjectPath.MSBuildSourceProjectFile)'))</_Parameter2>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
|
||||||
|
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="'$(HelixType)' == 'ci'">
|
||||||
|
<_Parameter1>Microsoft.AspNetCore.Testing.IsHelixCI</_Parameter1>
|
||||||
|
<_Parameter2>true</_Parameter2>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
<Target Name="PublishAssets" AfterTargets="Publish">
|
<Target Name="PublishAssets" AfterTargets="Publish">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<_PublishFiles Include="$(ArtifactsBinDir)Microsoft.AspNetCore.Identity.UI\$(Configuration)\netcoreapp3.0\Microsoft.AspNetCore.Identity.UI.Views.*.dll" />
|
<_PublishFiles Include="$(ArtifactsBinDir)Microsoft.AspNetCore.Identity.UI\$(Configuration)\netcoreapp3.0\Microsoft.AspNetCore.Identity.UI.Views.*.dll" />
|
||||||
|
|
@ -34,22 +68,16 @@
|
||||||
<_PublishFiles Include="$(ArtifactsBinDir)Identity.DefaultUI.WebSite\$(Configuration)\netcoreapp3.0\Identity.DefaultUI.WebSite.deps.json" />
|
<_PublishFiles Include="$(ArtifactsBinDir)Identity.DefaultUI.WebSite\$(Configuration)\netcoreapp3.0\Identity.DefaultUI.WebSite.deps.json" />
|
||||||
<_wwwrootFiles Include="$(MSBuildThisFileDirectory)..\..\testassets\Identity.DefaultUI.WebSite\wwwroot\**\*.*" />
|
<_wwwrootFiles Include="$(MSBuildThisFileDirectory)..\..\testassets\Identity.DefaultUI.WebSite\wwwroot\**\*.*" />
|
||||||
<_PagesFiles Include="$(MSBuildThisFileDirectory)..\..\testassets\Identity.DefaultUI.WebSite\Pages\**\*.*" />
|
<_PagesFiles Include="$(MSBuildThisFileDirectory)..\..\testassets\Identity.DefaultUI.WebSite\Pages\**\*.*" />
|
||||||
|
<_IdentityUIContent Include="$(MSBuildThisFileDirectory)..\..\UI\src\wwwroot\**\*" />
|
||||||
|
<_IdentityUIPages Include="$(MSBuildThisFileDirectory)..\..\UI\src\Areas\Identity\Pages\**\*" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Copy
|
<Copy SourceFiles="@(_PublishFiles)" DestinationFolder="$(PublishDir)" />
|
||||||
SourceFiles="@(_PublishFiles)"
|
<Copy SourceFiles="@(_PagesFiles)" DestinationFolder="$(PublishDir)\Identity.DefaultUI.WebSite\Pages" />
|
||||||
DestinationFolder="$(PublishDir)" />
|
<Copy SourceFiles="@(_wwwrootFiles)" DestinationFolder="$(PublishDir)\Identity.DefaultUI.WebSite\wwwroot" />
|
||||||
<Copy
|
<Copy SourceFiles="@(_IdentityUIContent)" DestinationFiles="$(PublishDir)\UI\wwwroot\%(_IdentityUIContent.RecursiveDir)\%(_IdentityUIContent.FileName)%(_IdentityUIContent.Extension)" />
|
||||||
SourceFiles="@(_PagesFiles)"
|
<Copy SourceFiles="@(_IdentityUIPages)" DestinationFiles="$(PublishDir)UI\Areas\Identity\Pages\%(_IdentityUIPages.RecursiveDir)\%(_IdentityUIPages.FileName)%(_IdentityUIPages.Extension)" />
|
||||||
DestinationFolder="$(PublishDir)\Identity.DefaultUI.WebSite\Pages" />
|
|
||||||
<Copy
|
|
||||||
SourceFiles="@(_wwwrootFiles)"
|
|
||||||
DestinationFolder="$(PublishDir)\Identity.DefaultUI.WebSite\wwwroot" />
|
|
||||||
<!-- Drop a dummy sln to specify content root location -->
|
<!-- Drop a dummy sln to specify content root location -->
|
||||||
<WriteLinesToFile
|
<WriteLinesToFile File="$(PublishDir)\contentroot.sln" Lines="Ignored" Overwrite="true" Encoding="Unicode" />
|
||||||
File="$(PublishDir)\contentroot.sln"
|
|
||||||
Lines="Ignored"
|
|
||||||
Overwrite="true"
|
|
||||||
Encoding="Unicode" />
|
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<StaticWebAssets Version="1.0">
|
||||||
|
<ContentRoot BasePath="/Identity" Path="{TEST_PLACEHOLDER}/V3" />
|
||||||
|
</StaticWebAssets>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<StaticWebAssets Version="1.0">
|
||||||
|
<ContentRoot BasePath="/Identity" Path="{TEST_PLACEHOLDER}/V4" />
|
||||||
|
</StaticWebAssets>
|
||||||
|
|
@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Identity.Test
|
namespace Microsoft.AspNetCore.Identity.Test
|
||||||
{
|
{
|
||||||
|
|
@ -83,11 +84,11 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2267", FlakyOn.AzP.macOS)]
|
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2267", FlakyOn.AzP.macOS)]
|
||||||
public async Task IdentityUI_ScriptTags_FallbackSourceContent_Matches_CDNContent(ScriptTag scriptTag)
|
public async Task IdentityUI_ScriptTags_FallbackSourceContent_Matches_CDNContent(ScriptTag scriptTag)
|
||||||
{
|
{
|
||||||
var wwwrootDir = Path.Combine(AppContext.BaseDirectory, "UI", "src", "wwwroot", scriptTag.Version);
|
var wwwrootDir = Path.Combine(GetProjectBasePath(), "wwwroot", scriptTag.Version);
|
||||||
|
|
||||||
var cdnContent = await _httpClient.GetStringAsync(scriptTag.Src);
|
var cdnContent = await _httpClient.GetStringAsync(scriptTag.Src);
|
||||||
var fallbackSrcContent = File.ReadAllText(
|
var fallbackSrcContent = File.ReadAllText(
|
||||||
Path.Combine(wwwrootDir, scriptTag.FallbackSrc.TrimStart('~').TrimStart('/')));
|
Path.Combine(wwwrootDir, scriptTag.FallbackSrc.Replace("Identity", "").TrimStart('~').TrimStart('/')));
|
||||||
|
|
||||||
Assert.Equal(RemoveLineEndings(cdnContent), RemoveLineEndings(fallbackSrcContent));
|
Assert.Equal(RemoveLineEndings(cdnContent), RemoveLineEndings(fallbackSrcContent));
|
||||||
}
|
}
|
||||||
|
|
@ -108,8 +109,8 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
|
|
||||||
private static List<ScriptTag> GetScriptTags()
|
private static List<ScriptTag> GetScriptTags()
|
||||||
{
|
{
|
||||||
var uiDirV3 = Path.Combine(AppContext.BaseDirectory, "UI", "src", "Areas", "Identity", "Pages", "V3");
|
var uiDirV3 = Path.Combine(GetProjectBasePath(), "Areas", "Identity", "Pages", "V3");
|
||||||
var uiDirV4 = Path.Combine(AppContext.BaseDirectory, "UI", "src", "Areas", "Identity", "Pages", "V4");
|
var uiDirV4 = Path.Combine(GetProjectBasePath(), "Areas", "Identity", "Pages", "V4");
|
||||||
var cshtmlFiles = GetRazorFiles(uiDirV3).Concat(GetRazorFiles(uiDirV4));
|
var cshtmlFiles = GetRazorFiles(uiDirV3).Concat(GetRazorFiles(uiDirV4));
|
||||||
|
|
||||||
var scriptTags = new List<ScriptTag>();
|
var scriptTags = new List<ScriptTag>();
|
||||||
|
|
@ -163,6 +164,32 @@ namespace Microsoft.AspNetCore.Identity.Test
|
||||||
_httpClient.Dispose();
|
_httpClient.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetProjectBasePath()
|
||||||
|
{
|
||||||
|
var projectPath = typeof(IdentityUIScriptsTest).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||||
|
.Single(a => a.Key == "Microsoft.AspNetCore.Testing.DefaultUIProjectPath").Value;
|
||||||
|
return Directory.Exists(projectPath) ? projectPath : Path.Combine(FindHelixSlnFileDirectory(), "UI");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FindHelixSlnFileDirectory()
|
||||||
|
{
|
||||||
|
var applicationPath = Path.GetDirectoryName(typeof(IdentityUIScriptsTest).Assembly.Location);
|
||||||
|
var directoryInfo = new DirectoryInfo(applicationPath);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var solutionPath = Directory.EnumerateFiles(directoryInfo.FullName, "*.sln").FirstOrDefault();
|
||||||
|
if (solutionPath != null)
|
||||||
|
{
|
||||||
|
return directoryInfo.FullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryInfo = directoryInfo.Parent;
|
||||||
|
}
|
||||||
|
while (directoryInfo.Parent != null);
|
||||||
|
|
||||||
|
throw new InvalidOperationException($"Solution root could not be located using application root {applicationPath}.");
|
||||||
|
}
|
||||||
|
|
||||||
class RetryHandler : DelegatingHandler
|
class RetryHandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
public RetryHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
|
public RetryHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="$(IdentityTestSharedSourceRoot)**\*.cs" />
|
<Compile Include="$(IdentityTestSharedSourceRoot)**\*.cs" />
|
||||||
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
|
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
|
||||||
<Content Include="..\..\UI\src\Areas\Identity\Pages\**\*.*" LinkBase="UI\src\Areas\Identity\Pages" />
|
|
||||||
<Content Include="..\..\UI\src\wwwroot\**\*.*" LinkBase="UI\src\wwwroot" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -17,8 +15,31 @@
|
||||||
<Reference Include="Microsoft.AspNetCore.Http" />
|
<Reference Include="Microsoft.AspNetCore.Http" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Identity.Specification.Tests" />
|
<Reference Include="Microsoft.AspNetCore.Identity.Specification.Tests" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Identity" />
|
<Reference Include="Microsoft.AspNetCore.Identity" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Identity.UI" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration" />
|
<Reference Include="Microsoft.Extensions.Configuration" />
|
||||||
<Reference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
|
<Reference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="AddProjectReferenceAssemblyInfo" BeforeTargets="GetAssemblyAttributes" DependsOnTargets="ResolveAssemblyReferences">
|
||||||
|
<ItemGroup>
|
||||||
|
<_IdentitUIDefaultUI Include="@(ReferencePath)" Condition="'%(ReferencePath.FileName)' == 'Microsoft.AspNetCore.Identity.UI'" />
|
||||||
|
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||||
|
<_Parameter1>Microsoft.AspNetCore.Testing.DefaultUIProjectPath</_Parameter1>
|
||||||
|
<_Parameter2>$([System.IO.Path]::GetDirectoryName('%(_IdentitUIDefaultUI.MSBuildSourceProjectFile)'))</_Parameter2>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishAssets" AfterTargets="Publish">
|
||||||
|
<ItemGroup>
|
||||||
|
<_IdentityUIContent Include="$(MSBuildThisFileDirectory)..\..\UI\src\wwwroot\**\*" />
|
||||||
|
<_IdentityUIPages Include="$(MSBuildThisFileDirectory)..\..\UI\src\Areas\Identity\Pages\**\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Copy SourceFiles="@(_IdentityUIContent)" DestinationFiles="$(PublishDir)\UI\wwwroot\%(_IdentityUIContent.RecursiveDir)\%(_IdentityUIContent.FileName)%(_IdentityUIContent.Extension)" />
|
||||||
|
<Copy SourceFiles="@(_IdentityUIPages)" DestinationFiles="$(PublishDir)UI\Areas\Identity\Pages\%(_IdentityUIPages.RecursiveDir)\%(_IdentityUIPages.FileName)%(_IdentityUIPages.Extension)" />
|
||||||
|
<!-- Drop a dummy sln to specify content root location -->
|
||||||
|
<WriteLinesToFile File="$(PublishDir)\contentroot.sln" Lines="Ignored" Overwrite="true" Encoding="Unicode" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +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 Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Identity.DefaultUI.WebSite
|
|
||||||
{
|
|
||||||
public class Bootstrap3Startup : ApplicationUserStartup
|
|
||||||
{
|
|
||||||
public Bootstrap3Startup(IConfiguration configuration) : base(configuration)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override UIFramework Framework => UIFramework.Bootstrap3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<UserSecretsId>aspnet-Identity.DefaultUI.WebSite-80C658D8-CED7-467F-9B47-75DA3BC1A16D</UserSecretsId>
|
<UserSecretsId>aspnet-Identity.DefaultUI.WebSite-80C658D8-CED7-467F-9B47-75DA3BC1A16D</UserSecretsId>
|
||||||
|
<IdentityDefaultUIFramework>Bootstrap3</IdentityDefaultUIFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -43,4 +44,15 @@
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Debug" />
|
<Reference Include="Microsoft.Extensions.Logging.Debug" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<ResolveStaticWebAssetsInputsDependsOn>_SetBootstrapFrameworkVersion</ResolveStaticWebAssetsInputsDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="_SetBootstrapFrameworkVersion">
|
||||||
|
<ItemGroup>
|
||||||
|
<_StaticWebAssetsProjectReference Condition="'%(FileName)' == 'Microsoft.AspNetCore.Identity.UI'">
|
||||||
|
<AdditionalProperties>IdentityDefaultUIFramework=$(IdentityDefaultUIFramework)</AdditionalProperties>
|
||||||
|
</_StaticWebAssetsProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ namespace Identity.DefaultUI.WebSite
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddDefaultIdentity<Microsoft.AspNetCore.Identity.Test.PocoUser>()
|
services.AddDefaultIdentity<Microsoft.AspNetCore.Identity.Test.PocoUser>()
|
||||||
.AddDefaultUI(UIFramework.Bootstrap4)
|
|
||||||
.AddUserManager<UserManager<Microsoft.AspNetCore.Identity.Test.PocoUser>>();
|
.AddUserManager<UserManager<Microsoft.AspNetCore.Identity.Test.PocoUser>>();
|
||||||
services.AddSingleton<IUserStore<Microsoft.AspNetCore.Identity.Test.PocoUser>, InMemoryUserStore<Microsoft.AspNetCore.Identity.Test.PocoUser>>();
|
services.AddSingleton<IUserStore<Microsoft.AspNetCore.Identity.Test.PocoUser>, InMemoryUserStore<Microsoft.AspNetCore.Identity.Test.PocoUser>>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ namespace Identity.DefaultUI.WebSite
|
||||||
|
|
||||||
public IConfiguration Configuration { get; }
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
public virtual UIFramework Framework { get; } = UIFramework.Bootstrap4;
|
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public virtual void ConfigureServices(IServiceCollection services)
|
public virtual void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
@ -49,7 +47,6 @@ namespace Identity.DefaultUI.WebSite
|
||||||
.UseSqlite("DataSource=:memory:"));
|
.UseSqlite("DataSource=:memory:"));
|
||||||
|
|
||||||
services.AddDefaultIdentity<TUser>()
|
services.AddDefaultIdentity<TUser>()
|
||||||
.AddDefaultUI(Framework)
|
|
||||||
.AddRoles<IdentityRole>()
|
.AddRoles<IdentityRole>()
|
||||||
.AddEntityFrameworkStores<TContext>();
|
.AddEntityFrameworkStores<TContext>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -41,11 +42,19 @@ namespace Templates.Test.Helpers
|
||||||
public ITestOutputHelper Output { get; set; }
|
public ITestOutputHelper Output { get; set; }
|
||||||
public IMessageSink DiagnosticsMessageSink { get; set; }
|
public IMessageSink DiagnosticsMessageSink { get; set; }
|
||||||
|
|
||||||
internal async Task<ProcessEx> RunDotNetNewAsync(string templateName, string auth = null, string language = null, bool useLocalDB = false, bool noHttps = false, string[] args = null)
|
internal async Task<ProcessEx> RunDotNetNewAsync(
|
||||||
|
string templateName,
|
||||||
|
string auth = null,
|
||||||
|
string language = null,
|
||||||
|
bool useLocalDB = false,
|
||||||
|
bool noHttps = false,
|
||||||
|
string[] args = null,
|
||||||
|
// Used to set special options in MSBuild
|
||||||
|
IDictionary<string, string> environmentVariables = null)
|
||||||
{
|
{
|
||||||
var hiveArg = $"--debug:custom-hive \"{TemplatePackageInstaller.CustomHivePath}\"";
|
var hiveArg = $"--debug:custom-hive \"{TemplatePackageInstaller.CustomHivePath}\"";
|
||||||
var argString = $"new {templateName} {hiveArg}";
|
var argString = $"new {templateName} {hiveArg}";
|
||||||
|
environmentVariables ??= new Dictionary<string, string>();
|
||||||
if (!string.IsNullOrEmpty(auth))
|
if (!string.IsNullOrEmpty(auth))
|
||||||
{
|
{
|
||||||
argString += $" --auth {auth}";
|
argString += $" --auth {auth}";
|
||||||
|
|
@ -86,7 +95,7 @@ namespace Templates.Test.Helpers
|
||||||
await DotNetNewLock.WaitAsync();
|
await DotNetNewLock.WaitAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString);
|
var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString, environmentVariables);
|
||||||
await execution.Exited;
|
await execution.Exited;
|
||||||
return execution;
|
return execution;
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +105,7 @@ namespace Templates.Test.Helpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false)
|
internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null)
|
||||||
{
|
{
|
||||||
Output.WriteLine("Publishing ASP.NET application...");
|
Output.WriteLine("Publishing ASP.NET application...");
|
||||||
|
|
||||||
|
|
@ -112,7 +121,7 @@ namespace Templates.Test.Helpers
|
||||||
await effectiveLock.WaitAsync();
|
await effectiveLock.WaitAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish -c Release {extraArgs}");
|
var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish -c Release {extraArgs}", packageOptions);
|
||||||
await result.Exited;
|
await result.Exited;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +131,7 @@ namespace Templates.Test.Helpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false)
|
internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null)
|
||||||
{
|
{
|
||||||
Output.WriteLine("Building ASP.NET application...");
|
Output.WriteLine("Building ASP.NET application...");
|
||||||
|
|
||||||
|
|
@ -133,7 +142,7 @@ namespace Templates.Test.Helpers
|
||||||
await effectiveLock.WaitAsync();
|
await effectiveLock.WaitAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), "build -c Debug");
|
var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), "build -c Debug", packageOptions);
|
||||||
await result.Exited;
|
await result.Exited;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,190 @@
|
||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Templates.Test.Helpers;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Templates.Test
|
||||||
|
{
|
||||||
|
public class IdentityUIPackageTest
|
||||||
|
{
|
||||||
|
public IdentityUIPackageTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
ProjectFactory = projectFactory;
|
||||||
|
Output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Project Project { get; set; }
|
||||||
|
|
||||||
|
public ProjectFactoryFixture ProjectFactory { get; set; }
|
||||||
|
|
||||||
|
public ITestOutputHelper Output { get; }
|
||||||
|
|
||||||
|
public static TheoryData<IDictionary<string, string>, string, string[]> MSBuildIdentityUIPackageOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var data = new TheoryData<IDictionary<string, string>, string, string[]>();
|
||||||
|
|
||||||
|
data.Add(new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["IdentityUIFrameworkVersion"] = "Bootstrap3"
|
||||||
|
},
|
||||||
|
"Bootstrap v3.4.1",
|
||||||
|
Bootstrap3ContentFiles);
|
||||||
|
|
||||||
|
data.Add(new Dictionary<string, string>(), "Bootstrap v4.3.1", Bootstrap4ContentFiles);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] Bootstrap3ContentFiles { get; } = new string[]
|
||||||
|
{
|
||||||
|
"Identity/css/site.css",
|
||||||
|
"Identity/js/site.js",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-theme.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-theme.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-theme.min.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-theme.min.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.min.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.min.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot",
|
||||||
|
"Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg",
|
||||||
|
"Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf",
|
||||||
|
"Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff",
|
||||||
|
"Identity/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.js",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.min.js",
|
||||||
|
"Identity/lib/bootstrap/dist/js/npm.js",
|
||||||
|
"Identity/lib/jquery/LICENSE.txt",
|
||||||
|
"Identity/lib/jquery/dist/jquery.js",
|
||||||
|
"Identity/lib/jquery/dist/jquery.min.js",
|
||||||
|
"Identity/lib/jquery/dist/jquery.min.map",
|
||||||
|
"Identity/lib/jquery-validation/LICENSE.md",
|
||||||
|
"Identity/lib/jquery-validation/dist/additional-methods.js",
|
||||||
|
"Identity/lib/jquery-validation/dist/additional-methods.min.js",
|
||||||
|
"Identity/lib/jquery-validation/dist/jquery.validate.js",
|
||||||
|
"Identity/lib/jquery-validation/dist/jquery.validate.min.js",
|
||||||
|
"Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js",
|
||||||
|
"Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js",
|
||||||
|
"Identity/lib/jquery-validation-unobtrusive/LICENSE.txt",
|
||||||
|
};
|
||||||
|
|
||||||
|
public static string[] Bootstrap4ContentFiles { get; } = new string[]
|
||||||
|
{
|
||||||
|
"Identity/favicon.ico",
|
||||||
|
"Identity/css/site.css",
|
||||||
|
"Identity/js/site.js",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-grid.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-grid.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-grid.min.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-grid.min.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-reboot.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-reboot.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-reboot.min.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.min.css",
|
||||||
|
"Identity/lib/bootstrap/dist/css/bootstrap.min.css.map",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.bundle.js",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.bundle.js.map",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.js",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.js.map",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.min.js",
|
||||||
|
"Identity/lib/bootstrap/dist/js/bootstrap.min.js.map",
|
||||||
|
"Identity/lib/jquery/LICENSE.txt",
|
||||||
|
"Identity/lib/jquery/dist/jquery.js",
|
||||||
|
"Identity/lib/jquery/dist/jquery.min.js",
|
||||||
|
"Identity/lib/jquery/dist/jquery.min.map",
|
||||||
|
"Identity/lib/jquery-validation/LICENSE.md",
|
||||||
|
"Identity/lib/jquery-validation/dist/additional-methods.js",
|
||||||
|
"Identity/lib/jquery-validation/dist/additional-methods.min.js",
|
||||||
|
"Identity/lib/jquery-validation/dist/jquery.validate.js",
|
||||||
|
"Identity/lib/jquery-validation/dist/jquery.validate.min.js",
|
||||||
|
"Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js",
|
||||||
|
"Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js",
|
||||||
|
"Identity/lib/jquery-validation-unobtrusive/LICENSE.txt",
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(MSBuildIdentityUIPackageOptions))]
|
||||||
|
public async Task IdentityUIPackage_WorksWithDifferentOptions(IDictionary<string, string> packageOptions, string versionValidator, string[] expectedFiles)
|
||||||
|
{
|
||||||
|
Project = await ProjectFactory.GetOrCreateProject("identityuipackage" + string.Concat(packageOptions.Values), Output);
|
||||||
|
var useLocalDB = false;
|
||||||
|
|
||||||
|
var createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB, environmentVariables: packageOptions);
|
||||||
|
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||||
|
|
||||||
|
var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj");
|
||||||
|
Assert.Contains(".db", projectFileContents);
|
||||||
|
|
||||||
|
var publishResult = await Project.RunDotNetPublishAsync(packageOptions: packageOptions);
|
||||||
|
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
|
||||||
|
|
||||||
|
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
|
||||||
|
// The output from publish will go into bin/Release/netcoreapp3.0/publish and won't be affected by calling build
|
||||||
|
// later, while the opposite is not true.
|
||||||
|
|
||||||
|
var buildResult = await Project.RunDotNetBuildAsync(packageOptions: packageOptions);
|
||||||
|
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
|
||||||
|
|
||||||
|
var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages");
|
||||||
|
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
|
||||||
|
Project.AssertEmptyMigration("razorpages");
|
||||||
|
|
||||||
|
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||||
|
{
|
||||||
|
Assert.False(
|
||||||
|
aspNetProcess.Process.HasExited,
|
||||||
|
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||||
|
|
||||||
|
var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Contains(versionValidator, await response.Content.ReadAsStringAsync());
|
||||||
|
await ValidatePublishedFiles(aspNetProcess, expectedFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var aspNetProcess = Project.StartPublishedProjectAsync())
|
||||||
|
{
|
||||||
|
Assert.False(
|
||||||
|
aspNetProcess.Process.HasExited,
|
||||||
|
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||||
|
|
||||||
|
var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Contains(versionValidator, await response.Content.ReadAsStringAsync());
|
||||||
|
await ValidatePublishedFiles(aspNetProcess, expectedFiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ValidatePublishedFiles(AspNetProcess aspNetProcess, string[] expectedContentFiles)
|
||||||
|
{
|
||||||
|
foreach (var file in expectedContentFiles)
|
||||||
|
{
|
||||||
|
var response = await aspNetProcess.SendRequest(file);
|
||||||
|
Assert.True(response?.StatusCode == HttpStatusCode.OK, $"Couldn't find file '{file}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ReadFile(string basePath, string path)
|
||||||
|
{
|
||||||
|
var fullPath = Path.Combine(basePath, path);
|
||||||
|
var doesExist = File.Exists(fullPath);
|
||||||
|
|
||||||
|
Assert.True(doesExist, $"Expected file to exist, but it doesn't: {path}");
|
||||||
|
return File.ReadAllText(Path.Combine(basePath, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue