diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs index 73ee830f5c..41b4d9a028 100644 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs +++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.Manual.cs @@ -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 parameters) { } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/RazorComponentsWeb-CSharp.csproj.in b/src/ProjectTemplates/Web.ProjectTemplates/RazorComponentsWeb-CSharp.csproj.in index a5d1fdc23a..9b6510bf6f 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/RazorComponentsWeb-CSharp.csproj.in +++ b/src/ProjectTemplates/Web.ProjectTemplates/RazorComponentsWeb-CSharp.csproj.in @@ -3,8 +3,31 @@ netcoreapp3.0 7.3 + aspnet-RazorComponentsWeb_CSharp-53bc9b9d-9d6a-45d4-8429-2a2761773502 + 0 + 1 True RazorComponentsWeb_CSharp + + + + + + + + + + + + + + + + + + + + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/dotnetcli.host.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/dotnetcli.host.json index 79c2dc39e3..2473827568 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/dotnetcli.host.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/dotnetcli.host.json @@ -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" ] } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/template.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/template.json index 5e1f178915..106e9fcc39 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/template.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/template.json @@ -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": [ diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/vs-2017.3.host.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/vs-2017.3.host.json index d7c0347fe3..a41e7e76d7 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/vs-2017.3.host.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/.template.config/vs-2017.3.host.json @@ -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" } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/App.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/App.razor index 03eee81cef..844a2b2455 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/App.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/App.razor @@ -1,5 +1,8 @@ -@* - The Router component displays whichever component has a @page - directive matching the current URI. -*@ - + + + +

Page not found

+

Sorry, there's nothing at this address.

+
+
+
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Areas/Identity/Pages/Account/LogOut.cshtml b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Areas/Identity/Pages/Account/LogOut.cshtml new file mode 100644 index 0000000000..4ea81fc052 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Areas/Identity/Pages/Account/LogOut.cshtml @@ -0,0 +1,14 @@ +@page +@using Microsoft.AspNetCore.Identity +@inject SignInManager SignInManager +@functions { + public async Task OnGet() + { + if (SignInManager.IsSignedIn(User)) + { + await SignInManager.SignOutAsync(); + } + + return Redirect("~/"); + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Areas/Identity/Pages/Shared/_LoginPartial.cshtml b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Areas/Identity/Pages/Shared/_LoginPartial.cshtml new file mode 100644 index 0000000000..e55bafe6a7 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Areas/Identity/Pages/Shared/_LoginPartial.cshtml @@ -0,0 +1,25 @@ +@using Microsoft.AspNetCore.Identity +@inject SignInManager SignInManager +@inject UserManager UserManager +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/ApplicationDbContext.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/ApplicationDbContext.cs new file mode 100644 index 0000000000..6a343d68c3 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/ApplicationDbContext.cs @@ -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 options) + : base(options) + { + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs new file mode 100644 index 0000000000..7366f582d3 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.Designer.cs @@ -0,0 +1,229 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(128); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.cs new file mode 100644 index 0000000000..3fb498bc9a --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/00000000000000_CreateIdentitySchema.cs @@ -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(nullable: false), + Name = table.Column(maxLength: 256, nullable: true), + NormalizedName = table.Column(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(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(maxLength: 128, nullable: false), + ProviderKey = table.Column(maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(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(nullable: false), + RoleId = table.Column(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(nullable: false), + LoginProvider = table.Column(maxLength: 128, nullable: false), + Name = table.Column(maxLength: 128, nullable: false), + Value = table.Column(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"); + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/ApplicationDbContextModelSnapshot.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000000..b3309a77ea --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlLite/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,227 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(128); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs new file mode 100644 index 0000000000..784684d257 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.Designer.cs @@ -0,0 +1,236 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(128); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.cs new file mode 100644 index 0000000000..d7cf2c926d --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/00000000000000_CreateIdentitySchema.cs @@ -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(nullable: false), + Name = table.Column(maxLength: 256, nullable: true), + NormalizedName = table.Column(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + RoleId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(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(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(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(maxLength: 128, nullable: false), + ProviderKey = table.Column(maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(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(nullable: false), + RoleId = table.Column(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(nullable: false), + LoginProvider = table.Column(maxLength: 128, nullable: false), + Name = table.Column(maxLength: 128, nullable: false), + Value = table.Column(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"); + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/ApplicationDbContextModelSnapshot.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000000..2f6c07f6ae --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Data/SqlServer/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,234 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(128); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/LoginDisplay.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/LoginDisplay.razor new file mode 100644 index 0000000000..6ccbbd20ae --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/LoginDisplay.razor @@ -0,0 +1,57 @@ +@*#if (IndividualLocalAuth) + + + Hello, @context.User.Identity.Name! + Log out + + + Register + Log in + + +#elseif (IndividualB2CAuth) +@using Microsoft.AspNetCore.Authentication.AzureADB2C.UI +@using Microsoft.Extensions.Options +@inject IOptionsMonitor AzureADB2COptions + + + + @if (canEditProfile) + { + Hello, @context.User.Identity.Name! + } + else + { + Hello, @context.User.Identity.Name! + } + Log out + + + Log in + + + +@functions { + bool canEditProfile; + + protected override void OnInit() + { + var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme); + canEditProfile = !string.IsNullOrEmpty(options.EditProfilePolicyId); + } +} +#elseif (OrganizationalAuth) + + + Hello, @context.User.Identity.Name! + Log out + + + Log in + + +#elseif (WindowsAuth) + + Hello, @context.User.Identity.Name! + +#endif*@ diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/MainLayout.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/MainLayout.razor index 97e764d353..e2c2d6500e 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/MainLayout.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Shared/MainLayout.razor @@ -6,7 +6,10 @@
- About +@*#if (!NoAuth) + +#endif*@ + About
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs index ae6a05a3bb..828c349c43 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs @@ -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(options => +#if (UseLocalDB) + options.UseSqlServer( + Configuration.GetConnectionString("DefaultConnection"))); +#else + options.UseSqlite( + Configuration.GetConnectionString("DefaultConnection"))); +#endif + services.AddDefaultIdentity() + .AddEntityFrameworkStores(); +#elif (OrganizationalAuth) + services.AddAuthentication(AzureADDefaults.AuthenticationScheme) + .AddAzureAD(options => Configuration.Bind("AzureAd", options)); +#if (MultiOrgAuth) + + services.Configure(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(); @@ -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"); }); diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/app.db b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/app.db new file mode 100644 index 0000000000..ec163057f1 Binary files /dev/null and b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/app.db differ diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/appsettings.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/appsettings.json index d9d9a9bff6..a1b1d1c212 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/appsettings.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/appsettings.json @@ -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", diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/wwwroot/css/site.css b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/wwwroot/css/site.css index 222f33c61d..546810a185 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/wwwroot/css/site.css +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/wwwroot/css/site.css @@ -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%); } diff --git a/src/ProjectTemplates/test/RazorComponentsTemplateTest.cs b/src/ProjectTemplates/test/RazorComponentsTemplateTest.cs index 9477d08134..b8c8e34ace 100644 --- a/src/ProjectTemplates/test/RazorComponentsTemplateTest.cs +++ b/src/ProjectTemplates/test/RazorComponentsTemplateTest.cs @@ -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 diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json index e9a93ffe8a..279d5a6852 100644 --- a/src/ProjectTemplates/test/template-baselines.json +++ b/src/ProjectTemplates/test/template-baselines.json @@ -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" ] } },