Server-side Blazor template with authentication (#10444)

This commit is contained in:
Steve Sanderson 2019-05-24 18:10:52 +01:00 committed by GitHub
parent 3be11f6544
commit 54fff2b168
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 2198 additions and 41 deletions

View File

@ -250,7 +250,7 @@ namespace Microsoft.AspNetCore.Components.Routing
[Microsoft.AspNetCore.Components.ParameterAttribute]
public System.Reflection.Assembly AppAssembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }}
[Microsoft.AspNetCore.Components.ParameterAttribute]
public System.Type FallbackComponent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }}
public Microsoft.AspNetCore.Components.RenderFragment NotFoundContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } private set { throw null; }}
public void Configure(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { }
public void Dispose() { }
protected virtual void Render(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, System.Type handler, System.Collections.Generic.IDictionary<string, object> parameters) { }

View File

@ -3,8 +3,31 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<UserSecretsId Condition="'$(IndividualAuth)' == 'True' OR '$(OrganizationalAuth)' == 'True'">aspnet-RazorComponentsWeb_CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502</UserSecretsId>
<WebProject_DirectoryAccessLevelKey Condition="'$(OrganizationalAuth)' == 'True' AND '$(OrgReadAccess)' != 'True'">0</WebProject_DirectoryAccessLevelKey>
<WebProject_DirectoryAccessLevelKey Condition="'$(OrganizationalAuth)' == 'True' AND '$(OrgReadAccess)' == 'True'">1</WebProject_DirectoryAccessLevelKey>
<NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">RazorComponentsWeb_CSharp</RootNamespace>
</PropertyGroup>
<!--#if (IndividualLocalAuth && UseLocalDB) -->
<ItemGroup>
<None Update="app.db" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<!--#endif -->
<!--#if (IndividualAuth || OrganizationalAuth) -->
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="${MicrosoftAspNetCoreAuthenticationAzureADUIPackageVersion}" Condition="'$(OrganizationalAuth)' == 'True'" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="${MicrosoftAspNetCoreAuthenticationAzureADB2CUIPackageVersion}" Condition="'$(IndividualB2CAuth)' == 'True'" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="${MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="${MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="${MicrosoftAspNetCoreIdentityUIPackageVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="${MicrosoftAspNetCoreMvcNewtonsoftJsonPackageVersion}" Condition="'$(OrganizationalAuth)' == 'True'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="${MicrosoftEntityFrameworkCoreSqlServerPackageVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' AND '$(UseLocalDB)' == 'True'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="${MicrosoftEntityFrameworkCoreSqlitePackageVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' AND '$(UseLocalDB)' != 'True'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="${MicrosoftEntityFrameworkCoreToolsPackageVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
</ItemGroup>
<!--#endif -->
</Project>

View File

@ -1,6 +1,49 @@
{
"$schema": "http://json.schemastore.org/dotnetcli.host",
"symbolInfo": {
"UseLocalDB": {
"longName": "use-local-db"
},
"AADInstance": {
"longName": "aad-instance",
"shortName": ""
},
"AAdB2CInstance": {
"longName": "aad-b2c-instance",
"shortName": ""
},
"SignUpSignInPolicyId": {
"longName": "susi-policy-id",
"shortName": "ssp"
},
"ResetPasswordPolicyId": {
"longName": "reset-password-policy-id",
"shortName": "rp"
},
"EditProfilePolicyId": {
"longName": "edit-profile-policy-id",
"shortName": "ep"
},
"OrgReadAccess": {
"longName": "org-read-access",
"shortName": "r"
},
"ClientId": {
"longName": "client-id",
"shortName": ""
},
"CallbackPath": {
"longName": "callback-path",
"shortName": ""
},
"Domain": {
"longName": "domain",
"shortName": ""
},
"TenantId": {
"longName": "tenant-id",
"shortName": ""
},
"Framework": {
"longName": "framework"
},
@ -18,12 +61,15 @@
"longName": "exclude-launch-settings",
"shortName": ""
},
"UserSecretsId": {
"isHidden": true
},
"NoHttps": {
"longName": "no-https",
"shortName": ""
}
},
"usageExamples": [
""
"--auth Individual"
]
}

View File

@ -12,25 +12,174 @@
"precedence": "5000",
"identity": "Microsoft.Web.RazorComponents.CSharp.3.0",
"shortName": "blazorserverside",
"thirdPartyNotices": "https://aka.ms/aspnetcore-template-3pn-210",
"tags": {
"language": "C#",
"type": "project"
},
"sourceName": "RazorComponentsWeb-CSharp",
"preferNameDirectory": true,
"guids": [
"09732173-2cef-46b7-83db-1334bcb079d3", // Tenant ID
"53bc9b9d-9d6a-45d4-8429-2a2761773502" // Client ID
],
"sources": [
{
"modifiers": [
{
"condition": "(!IndividualLocalAuth || UseLocalDB)",
"exclude": [
"app.db"
]
},
{
"condition": "(!IndividualLocalAuth)",
"exclude": [
"Data/SqlLite/**",
"Data/SqlServer/**",
"Data/ApplicationDbContext.cs",
"Areas/**"
]
},
{
"condition": "(ExcludeLaunchSettings)",
"exclude": [
"Properties/launchSettings.json"
]
},
{
"condition": "(IndividualLocalAuth && UseLocalDB)",
"rename": {
"Data/SqlServer/": "Data/Migrations/"
},
"exclude": [
"Data/SqlLite/**"
]
},
{
"condition": "(IndividualLocalAuth && !UseLocalDB)",
"rename": {
"Data/SqlLite/": "Data/Migrations/"
},
"exclude": [
"Data/SqlServer/**"
]
},
{
"condition": "(NoAuth)",
"exclude": [
"Shared/LoginDisplay.razor"
]
}
]
}
],
"symbols": {
"auth": {
"type": "parameter",
"datatype": "choice",
"choices": [
{
"choice": "None",
"description": "No authentication"
},
{
"choice": "Individual",
"description": "Individual authentication"
},
{
"choice": "IndividualB2C",
"description": "Individual authentication with Azure AD B2C"
},
{
"choice": "SingleOrg",
"description": "Organizational authentication for a single tenant"
},
{
"choice": "MultiOrg",
"description": "Organizational authentication for multiple tenants"
},
{
"choice": "Windows",
"description": "Windows authentication"
}
],
"defaultValue": "None",
"description": "The type of authentication to use"
},
"AAdB2CInstance": {
"type": "parameter",
"datatype": "string",
"defaultValue": "https://login.microsoftonline.com/tfp/",
"replaces": "https:////login.microsoftonline.com/tfp/",
"description": "The Azure Active Directory B2C instance to connect to (use with IndividualB2C auth)."
},
"SignUpSignInPolicyId": {
"type": "parameter",
"datatype": "string",
"defaultValue": "",
"replaces": "MySignUpSignInPolicyId",
"description": "The sign-in and sign-up policy ID for this project (use with IndividualB2C auth)."
},
"ResetPasswordPolicyId": {
"type": "parameter",
"datatype": "string",
"defaultValue": "",
"replaces": "MyResetPasswordPolicyId",
"description": "The reset password policy ID for this project (use with IndividualB2C auth)."
},
"EditProfilePolicyId": {
"type": "parameter",
"datatype": "string",
"defaultValue": "",
"replaces": "MyEditProfilePolicyId",
"description": "The edit profile policy ID for this project (use with IndividualB2C auth)."
},
"AADInstance": {
"type": "parameter",
"datatype": "string",
"defaultValue": "https://login.microsoftonline.com/",
"replaces": "https:////login.microsoftonline.com/",
"description": "The Azure Active Directory instance to connect to (use with SingleOrg or MultiOrg auth)."
},
"ClientId": {
"type": "parameter",
"datatype": "string",
"replaces": "11111111-1111-1111-11111111111111111",
"description": "The Client ID for this project (use with IndividualB2C, SingleOrg or MultiOrg auth)."
},
"Domain": {
"type": "parameter",
"datatype": "string",
"replaces": "qualified.domain.name",
"description": "The domain for the directory tenant (use with SingleOrg or IndividualB2C auth)."
},
"TenantId": {
"type": "parameter",
"datatype": "string",
"replaces": "22222222-2222-2222-2222-222222222222",
"description": "The TenantId ID of the directory to connect to (use with SingleOrg auth)."
},
"CallbackPath": {
"type": "parameter",
"datatype": "string",
"replaces": "/signin-oidc",
"defaultValue": "/signin-oidc",
"description": "The request path within the application's base path of the redirect URI (use with SingleOrg or IndividualB2C auth)."
},
"OrgReadAccess": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Whether or not to allow this application read access to the directory (only applies to SingleOrg or MultiOrg auth)."
},
"UserSecretsId": {
"type": "parameter",
"datatype": "string",
"replaces": "aspnet-RazorComponentsWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502",
"defaultValue": "aspnet-RazorComponentsWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502",
"description": "The ID to use for secrets (use with OrgReadAccess or Individual auth)."
},
"ExcludeLaunchSettings": {
"type": "parameter",
"datatype": "bool",
@ -77,6 +226,54 @@
},
"replaces": "44300"
},
"OrganizationalAuth": {
"type": "computed",
"value": "(auth == \"SingleOrg\" || auth == \"MultiOrg\")"
},
"WindowsAuth": {
"type": "computed",
"value": "(auth == \"Windows\")"
},
"MultiOrgAuth": {
"type": "computed",
"value": "(auth == \"MultiOrg\")"
},
"SingleOrgAuth": {
"type": "computed",
"value": "(auth == \"SingleOrg\")"
},
"IndividualLocalAuth": {
"type": "computed",
"value": "(auth == \"Individual\")"
},
"IndividualAuth": {
"type": "computed",
"value": "(auth == \"Individual\" || auth == \"IndividualB2C\")"
},
"IndividualB2CAuth": {
"type": "computed",
"value": "(auth == \"IndividualB2C\")"
},
"NoAuth": {
"type": "computed",
"value": "(!(IndividualAuth || OrganizationalAuth || WindowsAuth))"
},
"RequiresHttps": {
"type": "computed",
"value": "(OrganizationalAuth || IndividualAuth || !NoHttps)"
},
"NoHttps": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Whether to turn off HTTPS. This option only applies if Individual, IndividualB2C, SingleOrg, or MultiOrg aren't used for --auth."
},
"UseLocalDB": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Whether to use LocalDB instead of SQLite. This option only applies if --auth Individual or --auth IndividualB2C is specified."
},
"Framework": {
"type": "parameter",
"description": "The target framework for the project.",
@ -103,16 +300,6 @@
"datatype": "bool",
"description": "If specified, skips the automatic restore of the project on create.",
"defaultValue": "false"
},
"RequiresHttps": {
"type": "computed",
"value": "(!NoHttps)"
},
"NoHttps": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Whether to turn off HTTPS. This option only applies if Individual, IndividualB2C, SingleOrg, or MultiOrg aren't used for --auth."
}
},
"primaryOutputs": [

View File

@ -16,6 +16,38 @@
"uiFilters": [
"oneaspnet"
],
"usesOidc": true,
"supportedAuthentications": [
{
"auth": "None",
"authenticationType": "NoAuth",
"allowUnsecured": true
},
{
"auth": "Individual",
"authenticationType": "IndividualAuth",
"b2cAuthenticationOptions": "CloudExisting"
},
{
"auth": "Individual",
"authenticationType": "IndividualAuth",
"b2cAuthenticationOptions": "Local"
},
{
"auth": "SingleOrg",
"authenticationType": "OrgAuth",
"orgAuthenticationOptions": "SSO"
},
{
"auth": "MultiOrg",
"authenticationType": "OrgAuth",
"orgAuthenticationOptions": "MultiOrg"
},
{
"auth": "Windows",
"authenticationType": "WindowsAuth"
}
],
"ports": [
{
"name": "HttpPort",
@ -27,6 +59,7 @@
}
],
"excludeLaunchSettings": false,
"azureReplyUrlPortName": "HttpsPort",
"minFullFrameworkVersion": "4.6.1",
"disableHttpsSymbol": "NoHttps"
}

View File

@ -1,5 +1,8 @@
@*
The Router component displays whichever component has a @page
directive matching the current URI.
*@
<Router AppAssembly="typeof(Startup).Assembly" />
<CascadingAuthenticationState>
<Router AppAssembly="typeof(Startup).Assembly">
<NotFoundContent>
<h3>Page not found</h3>
<p>Sorry, there's nothing at this address.</p>
</NotFoundContent>
</Router>
</CascadingAuthenticationState>

View File

@ -0,0 +1,14 @@
@page
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@functions {
public async Task<IActionResult> OnGet()
{
if (SignInManager.IsSignedIn(User))
{
await SignInManager.SignOutAsync();
}
return Redirect("~/");
}
}

View File

@ -0,0 +1,25 @@
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/LogOut">Logout</a>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace RazorComponentsWeb_CSharp.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
}

View File

@ -0,0 +1,229 @@
// <auto-generated />
using System;
using RazorComponentsWeb_CSharp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace RazorComponentsWeb_CSharp.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("00000000000000_CreateIdentitySchema")]
partial class CreateIdentitySchema
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview1");
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,217 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace RazorComponentsWeb_CSharp.Data.Migrations
{
public partial class CreateIdentitySchema : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
ProviderKey = table.Column<string>(maxLength: 128, nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
Name = table.Column<string>(maxLength: 128, nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

View File

@ -0,0 +1,227 @@
// <auto-generated />
using System;
using RazorComponentsWeb_CSharp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace RazorComponentsWeb_CSharp.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview1");
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,236 @@
// <auto-generated />
using System;
using RazorComponentsWeb_CSharp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace RazorComponentsWeb_CSharp.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("00000000000000_CreateIdentitySchema")]
partial class CreateIdentitySchema
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview1")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,220 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace RazorComponentsWeb_CSharp.Data.Migrations
{
public partial class CreateIdentitySchema : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
ProviderKey = table.Column<string>(maxLength: 128, nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
Name = table.Column<string>(maxLength: 128, nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true,
filter: "[NormalizedName] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true,
filter: "[NormalizedUserName] IS NOT NULL");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

View File

@ -0,0 +1,234 @@
// <auto-generated />
using System;
using RazorComponentsWeb_CSharp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace RazorComponentsWeb_CSharp.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview1")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,57 @@
@*#if (IndividualLocalAuth)
<AuthorizeView>
<Authorized>
<a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
<a href="Identity/Account/LogOut">Log out</a>
</Authorized>
<NotAuthorized>
<a href="Identity/Account/Register">Register</a>
<a href="Identity/Account/Login">Log in</a>
</NotAuthorized>
</AuthorizeView>
#elseif (IndividualB2CAuth)
@using Microsoft.AspNetCore.Authentication.AzureADB2C.UI
@using Microsoft.Extensions.Options
@inject IOptionsMonitor<AzureADB2COptions> AzureADB2COptions
<AuthorizeView>
<Authorized>
@if (canEditProfile)
{
<a href="AzureADB2C/Account/EditProfile">Hello, @context.User.Identity.Name!</a>
}
else
{
<text>Hello, @context.User.Identity.Name!</text>
}
<a href="AzureADB2C/Account/SignOut">Log out</a>
</Authorized>
<NotAuthorized>
<a href="AzureADB2C/Account/SignIn">Log in</a>
</NotAuthorized>
</AuthorizeView>
@functions {
bool canEditProfile;
protected override void OnInit()
{
var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme);
canEditProfile = !string.IsNullOrEmpty(options.EditProfilePolicyId);
}
}
#elseif (OrganizationalAuth)
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<a href="AzureAD/Account/SignOut">Log out</a>
</Authorized>
<NotAuthorized>
<a href="AzureAD/Account/SignIn">Log in</a>
</NotAuthorized>
</AuthorizeView>
#elseif (WindowsAuth)
<AuthorizeView>
Hello, @context.User.Identity.Name!
</AuthorizeView>
#endif*@

View File

@ -6,7 +6,10 @@
<div class="main">
<div class="top-row px-4">
<a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank" class="ml-md-auto">About</a>
@*#if (!NoAuth)
<LogInDisplay />
#endif*@
<a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank">About</a>
</div>
<div class="content px-4">

View File

@ -2,24 +2,125 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
#if (OrganizationalAuth || IndividualB2CAuth)
using Microsoft.AspNetCore.Authentication;
#endif
#if (OrganizationalAuth)
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
#if (MultiOrgAuth)
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
#endif
using Microsoft.AspNetCore.Authorization;
#endif
#if (IndividualB2CAuth)
using Microsoft.AspNetCore.Authentication.AzureADB2C.UI;
#endif
using Microsoft.AspNetCore.Builder;
#if (IndividualLocalAuth)
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
#endif
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
#if (RequiresHttps)
using Microsoft.AspNetCore.HttpsPolicy;
#endif
#if (OrganizationalAuth)
using Microsoft.AspNetCore.Mvc.Authorization;
#endif
#if (IndividualLocalAuth)
using Microsoft.EntityFrameworkCore;
#endif
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
#if(MultiOrgAuth)
using Microsoft.IdentityModel.Tokens;
#endif
using RazorComponentsWeb_CSharp.Data;
namespace RazorComponentsWeb_CSharp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
#if (IndividualLocalAuth)
services.AddDbContext<ApplicationDbContext>(options =>
#if (UseLocalDB)
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
#else
options.UseSqlite(
Configuration.GetConnectionString("DefaultConnection")));
#endif
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
#elif (OrganizationalAuth)
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
#if (MultiOrgAuth)
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
// Instead of using the default validation (validating against a single issuer value, as we do in
// line of business apps), we inject our own multitenant validation logic
ValidateIssuer = false,
// If the app is meant to be accessed by entire organizations, add your issuer validation logic here.
//IssuerValidator = (issuer, securityToken, validationParameters) => {
// if (myIssuerValidationLogic(issuer)) return issuer;
//}
};
options.Events = new OpenIdConnectEvents
{
OnTicketReceived = context =>
{
// If your authentication logic is based on users then add your logic here
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
context.Response.Redirect("/Error");
context.HandleResponse(); // Suppress the exception
return Task.CompletedTask;
},
// If your application needs to authenticate single users, add your user validation below.
//OnTokenValidated = context =>
//{
// return myUserValidationLogic(context.Ticket.Principal);
//}
};
});
#endif
#elif (IndividualB2CAuth)
services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
.AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options));
#endif
#if (OrganizationalAuth)
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddNewtonsoftJson();
#endif
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
@ -31,25 +132,37 @@ namespace RazorComponentsWeb_CSharp
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
#if (IndividualLocalAuth)
app.UseDatabaseErrorPage();
#endif
}
#if (RequiresHttps)
else
{
app.UseExceptionHandler("/Home/Error");
#if (RequiresHttps)
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
#endif
#if (RequiresHttps)
app.UseHttpsRedirection();
#else
}
#endif
app.UseStaticFiles();
app.UseRouting();
#if (OrganizationalAuth || IndividualAuth)
app.UseAuthentication();
app.UseAuthorization();
#endif
app.UseEndpoints(endpoints =>
{
#if (OrganizationalAuth || IndividualAuth)
endpoints.MapControllers();
#endif
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});

View File

@ -1,4 +1,36 @@
{
////#if (IndividualB2CAuth)
// "AzureAdB2C": {
// "Instance": "https:////login.microsoftonline.com/tfp/",
// "ClientId": "11111111-1111-1111-11111111111111111",
// "CallbackPath": "/signin-oidc",
// "Domain": "qualified.domain.name",
// "SignUpSignInPolicyId": "MySignUpSignInPolicyId",
// "ResetPasswordPolicyId": "MyResetPasswordPolicyId",
// "EditProfilePolicyId": "MyEditProfilePolicyId"
// },
////#elseif (OrganizationalAuth)
// "AzureAd": {
//#if (MultiOrgAuth)
// "Instance": "https:////login.microsoftonline.com/common",
//#elseif (SingleOrgAuth)
// "Instance": "https:////login.microsoftonline.com/",
// "Domain": "qualified.domain.name",
// "TenantId": "22222222-2222-2222-2222-222222222222",
//#endif
// "ClientId": "11111111-1111-1111-11111111111111111",
// "CallbackPath": "/signin-oidc"
// },
//#endif
////#if (IndividualLocalAuth)
// "ConnectionStrings": {
////#if (UseLocalDB)
// "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-RazorComponentsWeb-CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true"
////#else
// "DefaultConnection": "DataSource=app.db"
//#endif
// },
//#endif
"Logging": {
"LogLevel": {
"Default": "Information",

View File

@ -27,8 +27,13 @@ app {
.main .top-row {
background-color: #e6e6e6;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
}
.main .top-row > a {
margin-left: 1.5rem;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

View File

@ -27,9 +27,9 @@ namespace Templates.Test
[Fact]
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2407", FlakyOn.AzP.Windows)]
public async Task RazorComponentsTemplateWorks()
public async Task RazorComponentsTemplateWorks_NoAuth()
{
Project = await ProjectFactory.GetOrCreateProject("blazorserverside", Output);
Project = await ProjectFactory.GetOrCreateProject("blazorserversidenoauth", Output);
var createResult = await Project.RunDotNetNewAsync("blazorserverside");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
@ -73,6 +73,56 @@ namespace Templates.Test
}
}
[Theory]
[InlineData(true)]
[InlineData(false)]
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2407", FlakyOn.AzP.Windows)]
public async Task RazorComponentsTemplateWorks_IndividualAuth(bool useLocalDB)
{
Project = await ProjectFactory.GetOrCreateProject("blazorserversideindividual" + (useLocalDB ? "uld" : ""), Output);
var createResult = await Project.RunDotNetNewAsync("blazorserverside", auth: "Individual", useLocalDB: useLocalDB);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var publishResult = await Project.RunDotNetPublishAsync();
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();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
using (var aspNetProcess = Project.StartBuiltProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html");
if (BrowserFixture.IsHostAutomationSupported())
{
aspNetProcess.VisitInBrowser(Browser);
TestBasicNavigation();
}
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html");
if (BrowserFixture.IsHostAutomationSupported())
{
aspNetProcess.VisitInBrowser(Browser);
TestBasicNavigation();
}
}
}
private void TestBasicNavigation()
{
// Give components.server enough time to load so that it can replace

View File

@ -889,39 +889,226 @@
}
},
"razorcomponents": {
"None": {
"Individual": {
"Template": "blazorserverside",
"Arguments": "new blazorserverside",
"Arguments": "new blazorserverside -au Individual",
"Files": [
"Pages/_Imports.razor",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/_Host.cshtml",
"Pages/Index.razor",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"_Imports.razor",
"app.db",
"App.razor",
"Properties/launchSettings.json",
"appsettings.Development.json",
"appsettings.json",
"Program.cs",
"Startup.cs",
"_Imports.razor",
"Areas/Identity/Pages/Account/LogOut.cshtml",
"Areas/Identity/Pages/Shared/_LoginPartial.cshtml",
"Data/ApplicationDbContext.cs",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Data/Migrations/00000000000000_CreateIdentitySchema.cs",
"Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs",
"Data/Migrations/ApplicationDbContextModelSnapshot.cs",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
"Pages/_Imports.razor",
"Properties/launchSettings.json",
"Shared/LoginDisplay.razor",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"wwwroot/favicon.ico",
"wwwroot/css/site.css",
"wwwroot/css/bootstrap/bootstrap.min.css",
"wwwroot/css/bootstrap/bootstrap.min.css.map",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/site.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff"
]
},
"IndividualB2C": {
"Template": "blazorserverside",
"Arguments": "new blazorserverside -au IndividualB2C",
"Files": [
"App.razor",
"appsettings.Development.json",
"appsettings.json",
"Program.cs",
"Startup.cs"
"Startup.cs",
"_Imports.razor",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
"Pages/_Imports.razor",
"Properties/launchSettings.json",
"Shared/LoginDisplay.razor",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"wwwroot/favicon.ico",
"wwwroot/css/site.css",
"wwwroot/css/bootstrap/bootstrap.min.css",
"wwwroot/css/bootstrap/bootstrap.min.css.map",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff"
]
},
"MultiOrg": {
"Template": "blazorserverside",
"Arguments": "new blazorserverside -au MultiOrg",
"Files": [
"App.razor",
"appsettings.Development.json",
"appsettings.json",
"Program.cs",
"Startup.cs",
"_Imports.razor",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
"Pages/_Imports.razor",
"Properties/launchSettings.json",
"Shared/LoginDisplay.razor",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"wwwroot/favicon.ico",
"wwwroot/css/site.css",
"wwwroot/css/bootstrap/bootstrap.min.css",
"wwwroot/css/bootstrap/bootstrap.min.css.map",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff"
]
},
"None": {
"Template": "blazorserverside",
"Arguments": "new blazorserverside",
"Files": [
"App.razor",
"appsettings.Development.json",
"appsettings.json",
"Program.cs",
"Startup.cs",
"_Imports.razor",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
"Pages/_Imports.razor",
"Properties/launchSettings.json",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"wwwroot/favicon.ico",
"wwwroot/css/site.css",
"wwwroot/css/bootstrap/bootstrap.min.css",
"wwwroot/css/bootstrap/bootstrap.min.css.map",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff"
]
},
"SingleOrg": {
"Template": "blazorserverside",
"Arguments": "new blazorserverside -au SingleOrg",
"Files": [
"App.razor",
"appsettings.Development.json",
"appsettings.json",
"Program.cs",
"Startup.cs",
"_Imports.razor",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
"Pages/_Imports.razor",
"Properties/launchSettings.json",
"Shared/LoginDisplay.razor",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"wwwroot/favicon.ico",
"wwwroot/css/site.css",
"wwwroot/css/bootstrap/bootstrap.min.css",
"wwwroot/css/bootstrap/bootstrap.min.css.map",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff"
]
},
"Windows": {
"Template": "blazorserverside",
"Arguments": "new blazorserverside -au Windows",
"Files": [
"App.razor",
"appsettings.Development.json",
"appsettings.json",
"Program.cs",
"Startup.cs",
"_Imports.razor",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
"Pages/_Imports.razor",
"Properties/launchSettings.json",
"Shared/LoginDisplay.razor",
"Shared/MainLayout.razor",
"Shared/NavMenu.razor",
"wwwroot/favicon.ico",
"wwwroot/css/site.css",
"wwwroot/css/bootstrap/bootstrap.min.css",
"wwwroot/css/bootstrap/bootstrap.min.css.map",
"wwwroot/css/open-iconic/FONT-LICENSE",
"wwwroot/css/open-iconic/ICON-LICENSE",
"wwwroot/css/open-iconic/README.md",
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff"
]
}
},