Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/Identity/IdentityNoDeps.slnf
Original file line number Diff line number Diff line change
@@ -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"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,15 @@ namespace Microsoft.AspNetCore.Identity
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, Microsoft.AspNetCore.Identity.UI.UIFramework framework) { throw null; }
}
}
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 Microsoft.AspNetCore.Identity.UI.UIFramework UIFramework { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public enum UIFramework
{
Bootstrap3 = 0,
Bootstrap4 = 1,
public UIFrameworkAttribute(string uiFramework) { }
public string UIFramework { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
}
namespace Microsoft.AspNetCore.Identity.UI.Services
Expand Down
16 changes: 0 additions & 16 deletions src/Identity/UI/src/DefaultUIOptions.cs

This file was deleted.

71 changes: 49 additions & 22 deletions src/Identity/UI/src/IdentityBuilderUIExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
Expand All @@ -30,35 +31,16 @@ public static class IdentityBuilderUIExtensions
/// </remarks>
/// <param name="builder">The <see cref="IdentityBuilder"/>.</param>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder) => builder.AddDefaultUI(UIFramework.Bootstrap4);


/// <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)
public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder)
{
builder.AddSignInManager();
AddRelatedParts(builder, framework);
AddRelatedParts(builder);

builder.Services.ConfigureOptions(
typeof(IdentityDefaultUIConfigureOptions<>)
.MakeGenericType(builder.UserType));
builder.Services.TryAddTransient<IEmailSender, EmailSender>();

builder.Services.Configure<DefaultUIOptions>(o => o.UIFramework = framework);

return builder;
}

Expand All @@ -69,8 +51,20 @@ public static IdentityBuilder AddDefaultUI(
[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
.AddMvc()
.ConfigureApplicationPartManager(partManager =>
Expand Down Expand Up @@ -131,5 +125,38 @@ void AddParts(
}
});
}

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;
}
}
}
34 changes: 3 additions & 31 deletions src/Identity/UI/src/IdentityDefaultUIConfigureOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,26 @@

using System;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.UI.Areas.Identity.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;

namespace Microsoft.AspNetCore.Identity.UI
{
internal class IdentityDefaultUIConfigureOptions<TUser> :
IPostConfigureOptions<RazorPagesOptions>,
IPostConfigureOptions<StaticFileOptions>,
IConfigureNamedOptions<CookieAuthenticationOptions> where TUser : class
{
private const string IdentityUIDefaultAreaName = "Identity";

public IdentityDefaultUIConfigureOptions(
IWebHostEnvironment environment,
IOptions<DefaultUIOptions> uiOptions)
{
IWebHostEnvironment environment) {
Environment = environment;
UiOptions = uiOptions;
}

public IWebHostEnvironment Environment { get; }
public IOptions<DefaultUIOptions> UiOptions { get; }

public void PostConfigure(string name, RazorPagesOptions options)
{
Expand All @@ -50,30 +42,10 @@ public void PostConfigure(string name, RazorPagesOptions options)
pam => pam.Filters.Add(new ExternalLoginsPageFilter<TUser>()));
}

public void PostConfigure(string name, StaticFileOptions options)
{
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) {
// Nothing to do here as Configure(string name, CookieAuthenticationOptions options) is hte one setting things up.
}

public void Configure(CookieAuthenticationOptions options) { }

public void Configure(string name, CookieAuthenticationOptions options)
{
name = name ?? throw new ArgumentNullException(nameof(name));
Expand Down
80 changes: 55 additions & 25 deletions src/Identity/UI/src/Microsoft.AspNetCore.Identity.UI.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Description>ASP.NET Core Identity UI is the default Razor Pages built-in UI for the ASP.NET Core Identity framework.</Description>
Expand All @@ -7,23 +7,30 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;identity;membership;razorpages</PackageTags>
<IsShippingPackage>true</IsShippingPackage>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<ProvideApplicationPartFactoryAttributeTypeName>Microsoft.AspNetCore.Mvc.ApplicationParts.NullApplicationPartFactory, Microsoft.AspNetCore.Mvc.Core</ProvideApplicationPartFactoryAttributeTypeName>
<RazorCompileOnBuild>false</RazorCompileOnBuild>
<RazorCompileOnPublish>false</RazorCompileOnPublish>
<EnableDefaultRazorGenerateItems>false</EnableDefaultRazorGenerateItems>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>

<DisableStaticWebAssetsBuildPropsFileGeneration>true</DisableStaticWebAssetsBuildPropsFileGeneration>
<StaticWebAssetsDisableProjectBuildPropsFileGeneration>true</StaticWebAssetsDisableProjectBuildPropsFileGeneration>

<GetCurrentProjectStaticWebAssetsDependsOn>
$(GetCurrentProjectStaticWebAssetsDependsOn);
_UpdatedIdentityUIStaticWebAssets
</GetCurrentProjectStaticWebAssetsDependsOn>

<IdentityUIFrameworkVersion Condition="'$(IdentityUIFrameworkVersion)' == ''">Bootstrap4</IdentityUIFrameworkVersion>

</PropertyGroup>

<ItemGroup>
<EmbeddedResource Include="wwwroot/**/*" />
<EmbeddedResource Remove="wwwroot/**/LICENSE*" />
<None Remove="wwwroot/**/LICENSE*" />
<Content Remove="@(Content)" />
<Content Include="wwwroot\**\*" Pack="true" />
<None Include="build\*" Pack="true" PackagePath="build\" />
<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>
Expand All @@ -40,6 +47,10 @@
<UIFrameworkVersionMoniker Include="V4" />
</ItemGroup>

<ItemGroup>
<Folder Include="build\" />
</ItemGroup>

<!-- Source build doesn't build this package -->
<Target Name="BuildRazorViews" DependsOnTargets="Compile" BeforeTargets="Build" Condition="'$(DotNetBuildFromSource)' != 'true'">
<Message Text="Building razor views assemblies" Importance="High" />
Expand All @@ -63,6 +74,7 @@

<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
<Output TaskParameter="DestinationFiles" ItemName="_RazorAssembly"/>

</Copy>

<Copy
Expand All @@ -75,12 +87,10 @@
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)">

<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
</Copy>

<Message
Importance="High"
Text="$(MSBuildProjectName) -&gt; %(_RazorAssembly.FullPath)" />
<Message Importance="High" Text="$(MSBuildProjectName) -&gt; %(_RazorAssembly.FullPath)" />

</Target>

Expand All @@ -90,19 +100,15 @@

<Target Name="SetupRazorInputs">
<ItemGroup>
<_RazorGenerate
Include="Areas\Identity\Pages\$(UIFrameworkVersion)\**\*.cshtml" />
<_RazorGenerate Include="Areas\Identity\Pages\$(UIFrameworkVersion)\**\*.cshtml" />

<RazorGenerate
Include="@(_RazorGenerate)"
Link="Areas\Identity\Pages\%(RecursiveDir)%(Filename)%(Extension)" />
<RazorGenerate Include="@(_RazorGenerate)" Link="Areas\Identity\Pages\%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
</Target>

<Target Name="BuildForUI" DependsOnTargets="SetupRazorInputs;RazorCompile" />

<Target
Name="_GetRazorDlls" BeforeTargets="GetCopyToOutputDirectoryItems">
<Target Name="_GetRazorDlls" BeforeTargets="GetCopyToOutputDirectoryItems">

<ItemGroup>
<_GeneratedRazorViews Include="$(TargetDir)$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
Expand All @@ -117,15 +123,13 @@

<Target Name="_AddRazorDlls" BeforeTargets="BuiltProjectOutputGroup">
<ItemGroup>
<BuiltProjectOutputGroupOutput
Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
<BuiltProjectOutputGroupOutput Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).dll" />
</ItemGroup>
</Target>

<Target Name="_AddRazorPdbs" BeforeTargets="DebugSymbolsProjectOutputGroup">
<ItemGroup>
<DebugSymbolsProjectOutputGroupOutput
Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).pdb" />
<DebugSymbolsProjectOutputGroupOutput Include="$(IntermediateOutputPath)%(UIFrameworkVersionMoniker.Identity)\$(TargetName).Views.%(UIFrameworkVersionMoniker.Identity).pdb" />
</ItemGroup>
</Target>

Expand All @@ -136,8 +140,34 @@
<ExpectedOutputFile Include="$(TargetDir)Microsoft.AspNetCore.Identity.UI.Views.V4.dll" />
</ItemGroup>

<Error Text="Unable to find precompiled view file %(ExpectedOutputFile.Identity)"
Condition="!Exists('%(ExpectedOutputFile.Identity)')" />
<Error Text="Unable to find precompiled view file %(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>

</Project>
Loading