Update Identity server dependency for preview4 (#9104)

* Updates Identity server dependency for preview4
* Infrastructure improvements.
* Updates react versions.
* Updates migrations.
* Makes templates show up in Visual Studio
This commit is contained in:
Javier Calvarro Nelson 2019-04-08 17:06:58 +02:00 committed by GitHub
parent 74bba27f43
commit 4abf766c3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 14320 additions and 9108 deletions

View File

@ -26,7 +26,9 @@ and are generated based on the last package release.
<LatestPackageReference Include="Google.ProtoBuf" Version="$(GoogleProtoBufPackageVersion)" />
<LatestPackageReference Include="IdentityServer4.AspNetIdentity" Version="$(IdentityServer4AspNetIdentityPackageVersion)" />
<LatestPackageReference Include="IdentityServer4.EntityFramework" Version="$(IdentityServer4EntityFrameworkPackageVersion)" />
<LatestPackageReference Include="IdentityServer4.EntityFramework.Storage" Version="$(IdentityServer4EntityFrameworkStoragePackageVersion)" />
<LatestPackageReference Include="IdentityServer4" Version="$(IdentityServer4PackageVersion)" />
<LatestPackageReference Include="IdentityServer4.Storage" Version="$(IdentityServer4StoragePackageVersion)" />
<LatestPackageReference Include="Libuv" Version="$(LibuvPackageVersion)" />
<LatestPackageReference Include="MessagePack" Version="$(MessagePackPackageVersion)" />
<LatestPackageReference Include="Microsoft.AspNet.WebApi.Client" Version="$(MicrosoftAspNetWebApiClientPackageVersion)" />

View File

@ -176,9 +176,11 @@
<GoogleProtobufPackageVersion>3.7.0</GoogleProtobufPackageVersion>
<GrpcAspNetCoreServerPackageVersion>0.1.19-pre2</GrpcAspNetCoreServerPackageVersion>
<GrpcToolsPackageVersion>1.20.0-pre1</GrpcToolsPackageVersion>
<IdentityServer4AspNetIdentityPackageVersion>2.3.0</IdentityServer4AspNetIdentityPackageVersion>
<IdentityServer4EntityFrameworkPackageVersion>2.3.0</IdentityServer4EntityFrameworkPackageVersion>
<IdentityServer4PackageVersion>2.3.0</IdentityServer4PackageVersion>
<IdentityServer4AspNetIdentityPackageVersion>3.0.0-preview3.4</IdentityServer4AspNetIdentityPackageVersion>
<IdentityServer4EntityFrameworkPackageVersion>3.0.0-preview3.4</IdentityServer4EntityFrameworkPackageVersion>
<IdentityServer4PackageVersion>3.0.0-preview3.4</IdentityServer4PackageVersion>
<IdentityServer4StoragePackageVersion>3.0.0-preview3.4</IdentityServer4StoragePackageVersion>
<IdentityServer4EntityFrameworkStoragePackageVersion>3.0.0-preview3.4</IdentityServer4EntityFrameworkStoragePackageVersion>
<MessagePackPackageVersion>1.7.3.4</MessagePackPackageVersion>
<MoqPackageVersion>4.10.0</MoqPackageVersion>
<MonoCecilPackageVersion>0.10.1</MonoCecilPackageVersion>

View File

@ -7,7 +7,9 @@
<Compile Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer.netcoreapp3.0.cs" />
<Reference Include="IdentityServer4.AspNetIdentity" />
<Reference Include="IdentityServer4.EntityFramework" />
<Reference Include="IdentityServer4.EntityFramework.Storage" />
<Reference Include="IdentityServer4" />
<Reference Include="IdentityServer4.Storage" />
<Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<Reference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<Reference Include="Microsoft.AspNetCore.Identity.UI" />

View File

@ -1,4 +1,4 @@
@page
@page
@addTagHelper *, Microsoft.AspNetCore.ApiAuthorization.IdentityServer
@model ApiAuthSample.Pages.IndexModel
@ -9,6 +9,7 @@
<!DOCTYPE html>
<html>
<head>
<base href="~/" />
<title>@ViewData["Title"]</title>
</head>
<body>
@ -18,7 +19,7 @@
<button id="call-api" disabled>Call API</button>
<div id="login-result"></div>
<div id="api-result"></div>
<script src="js/oidc-client.js"></script>
<script src="/js/oidc-client.js"></script>
<script id="apiauth" type="text/javascript" asp-apiauth-parameters="ApiAuthSampleSPA">
let $data = document.querySelector("#apiauth");
let configuration = {};
@ -30,4 +31,4 @@
</script>
<script src="js/app.js"></script>
</body>
</html>
</html>

View File

@ -67,6 +67,7 @@ namespace ApiAuthSample
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapFallbackToPage("/Index");
});
}
}

View File

@ -51,46 +51,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
ConfigureGrantContext(builder, _operationalStoreOptions.Value);
builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
}
private void ConfigureGrantContext(ModelBuilder modelBuilder, OperationalStoreOptions storeOptions)
{
if (!string.IsNullOrWhiteSpace(storeOptions.DefaultSchema)) modelBuilder.HasDefaultSchema(storeOptions.DefaultSchema);
modelBuilder.Entity<PersistedGrant>(grant =>
{
grant.ToTable("PersistedGrants");
grant.Property(x => x.Key).HasMaxLength(200).ValueGeneratedNever();
grant.Property(x => x.Type).HasMaxLength(50).IsRequired();
grant.Property(x => x.SubjectId).HasMaxLength(200);
grant.Property(x => x.ClientId).HasMaxLength(200).IsRequired();
grant.Property(x => x.CreationTime).IsRequired();
grant.Property(x => x.Data).HasMaxLength(50000).IsRequired();
grant.HasKey(x => x.Key);
grant.HasIndex(x => new { x.SubjectId, x.ClientId, x.Type });
});
modelBuilder.Entity<DeviceFlowCodes>(codes =>
{
codes.ToTable("DeviceCodes");
codes.Property(x => x.DeviceCode).HasMaxLength(200).IsRequired();
codes.Property(x => x.UserCode).HasMaxLength(200).IsRequired();
codes.Property(x => x.SubjectId).HasMaxLength(200);
codes.Property(x => x.ClientId).HasMaxLength(200).IsRequired();
codes.Property(x => x.CreationTime).IsRequired();
codes.Property(x => x.Expiration).IsRequired();
codes.Property(x => x.Data).HasMaxLength(50000).IsRequired();
codes.HasKey(x => new { x.UserCode });
codes.HasIndex(x => x.DeviceCode).IsUnique();
codes.HasIndex(x => x.UserCode).IsUnique();
});
}
}
}

View File

@ -12,7 +12,9 @@
<ItemGroup>
<Reference Include="IdentityServer4.AspNetIdentity" />
<Reference Include="IdentityServer4.EntityFramework" />
<Reference Include="IdentityServer4.EntityFramework.Storage" />
<Reference Include="IdentityServer4" />
<Reference Include="IdentityServer4.Storage" />
<Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<Reference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<Reference Include="Microsoft.AspNetCore.Identity.UI" />

View File

@ -21,6 +21,11 @@
"auth": "None",
"authenticationType": "NoAuth",
"allowUnsecured": true
},
{
"auth": "Individual",
"authenticationType": "IndividualAuth",
"b2cAuthenticationOptions": "Local"
}
],
"ports": [
@ -36,4 +41,4 @@
"excludeLaunchSettings": false,
"minFullFrameworkVersion": "4.6.1",
"disableHttpsSymbol": "NoHttps"
}
}

View File

@ -50,6 +50,10 @@ interface IAuthenticationState {
providedIn: 'root'
})
export class AuthorizeService {
// By default pop ups are disabled because they don't work properly on Edge.
// If you want to enable pop up authentication simply set this flag to false.
private popUpDisabled = true;
private userManager: UserManager;
private userSubject: BehaviorSubject<IUser | null> = new BehaviorSubject(null);
@ -90,6 +94,9 @@ export class AuthorizeService {
console.log('Silent authentication error: ', silentError);
try {
if (this.popUpDisabled) {
throw new Error('Popup disabled. Change \'authorize.service.ts:AuthorizeService.popupDisabled\' to false to enable it.');
}
user = await this.userManager.signinPopup(this.createArguments(LoginMode.PopUp));
this.userSubject.next(user.profile);
return this.success(state);
@ -97,8 +104,9 @@ export class AuthorizeService {
if (popupError.message === 'Popup window closed') {
// The user explicitly cancelled the login action by closing an opened popup.
return this.error('The user closed the window.');
} else if (!this.popUpDisabled) {
console.log('Popup authentication error: ', popupError);
}
console.log('Popup authentication error: ', popupError);
// PopUps might be blocked by the user, fallback to redirect
try {
@ -174,6 +182,7 @@ export class AuthorizeService {
throw new Error(`Invalid login mode '${mode}'.`);
}
}
// We try to sign out the user in two different ways:
// 1) We try to do a sign-out using a PopUp Window. This might fail if there is a
// Pop-Up blocker or the user has disabled PopUps.

View File

@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Company.WebApplication1.Data;
using Microsoft.EntityFrameworkCore;
@ -17,14 +17,13 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1")
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -75,7 +74,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -103,9 +101,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -142,8 +137,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -256,47 +250,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -232,12 +232,6 @@ namespace Company.WebApplication1.Data.Migrations
column: "DeviceCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_UserCode",
table: "DeviceCodes",
column: "UserCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",

View File

@ -15,14 +15,13 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1")
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -73,7 +72,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -101,9 +99,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -140,8 +135,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -254,47 +248,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Company.WebApplication1.Data;
using Microsoft.EntityFrameworkCore;
@ -16,12 +16,11 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1");
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3");
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -71,7 +70,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -99,9 +97,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -138,8 +133,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -249,47 +243,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -229,12 +229,6 @@ namespace Company.WebApplication1.Data.Migrations
column: "DeviceCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_UserCode",
table: "DeviceCodes",
column: "UserCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",

View File

@ -14,12 +14,11 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1");
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3");
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -69,7 +68,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -97,9 +95,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -136,8 +131,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -247,47 +241,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -21,6 +21,11 @@
"auth": "None",
"authenticationType": "NoAuth",
"allowUnsecured": true
},
{
"auth": "Individual",
"authenticationType": "IndividualAuth",
"b2cAuthenticationOptions": "Local"
}
],
"ports": [
@ -36,4 +41,4 @@
"excludeLaunchSettings": false,
"minFullFrameworkVersion": "4.6.1",
"disableHttpsSymbol": "NoHttps"
}
}

View File

@ -11,17 +11,17 @@
"react-dom": "^16.0.0",
"react-router-bootstrap": "^0.24.4",
"react-router-dom": "^4.2.2",
"react-scripts": "^1.1.5",
"react-scripts": "^2.1.8",
"reactstrap": "^6.3.0",
"rimraf": "^2.6.2"
},
"devDependencies": {
"ajv": "^6.0.0",
"babel-eslint": "^7.2.3",
"ajv": "^6.9.1",
"babel-eslint": "^9.0.0",
"cross-env": "^5.2.0",
"eslint": "^4.1.1",
"eslint-config-react-app": "^2.1.0",
"eslint-plugin-flowtype": "^2.50.3",
"eslint": "^5.12.0",
"eslint-config-react-app": "^3.0.8",
"eslint-plugin-flowtype": "^3.5.1",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-react": "^7.11.1"

View File

@ -7,6 +7,10 @@ export class AuthorizeService {
_user = null;
_isAuthenticated = false;
// By default pop ups are disabled because they don't work properly on Edge.
// If you want to enable pop up authentication simply set this flag to false.
_popUpDisabled = true;
async isAuthenticated() {
const user = await this.getUser();
return !!user;
@ -47,6 +51,10 @@ export class AuthorizeService {
console.log("Silent authentication error: ", silentError);
try {
if (this._popUpDisabled) {
throw new Error('Popup disabled. Change \'AuthorizeService.js:AuthorizeService._popupDisabled\' to false to enable it.')
}
const popUpUser = await this.userManager.signinPopup(this.createArguments(LoginMode.PopUp));
this.updateState(popUpUser);
return this.success(state);
@ -54,8 +62,9 @@ export class AuthorizeService {
if (popUpError.message === "Popup window closed") {
// The user explicitly cancelled the login action by closing an opened popup.
return this.error("The user closed the window.");
} else if (!this._popUpDisabled) {
console.log("Popup authentication error: ", popUpError);
}
console.log("Popup authentication error: ", popUpError);
// PopUps might be blocked by the user, fallback to redirect
try {

View File

@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Company.WebApplication1.Data;
using Microsoft.EntityFrameworkCore;
@ -17,14 +17,13 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1")
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -75,7 +74,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -103,9 +101,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -142,8 +137,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -256,47 +250,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
@ -232,12 +232,6 @@ namespace Company.WebApplication1.Data.Migrations
column: "DeviceCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_UserCode",
table: "DeviceCodes",
column: "UserCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",

View File

@ -15,14 +15,13 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1")
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -73,7 +72,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -101,9 +99,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -140,8 +135,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -254,47 +248,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Company.WebApplication1.Data;
using Microsoft.EntityFrameworkCore;
@ -16,12 +16,11 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1");
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3");
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -71,7 +70,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -99,9 +97,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -138,8 +133,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -249,47 +243,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -229,12 +229,6 @@ namespace Company.WebApplication1.Data.Migrations
column: "DeviceCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_UserCode",
table: "DeviceCodes",
column: "UserCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",

View File

@ -14,12 +14,11 @@ namespace Company.WebApplication1.Data.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview.19080.1");
.HasAnnotation("ProductVersion", "3.0.0-preview4.19174.3");
modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
@ -69,7 +68,6 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.ValueGeneratedOnAdd()
.HasMaxLength(200);
b.Property<string>("ClientId")
@ -97,9 +95,6 @@ namespace Company.WebApplication1.Data.Migrations
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("UserCode")
.IsUnique();
b.ToTable("DeviceCodes");
});
@ -136,8 +131,7 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Id");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
@ -247,47 +241,53 @@ namespace Company.WebApplication1.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Company.WebApplication1.Models.ApplicationUser")
b.HasOne("Company.WebApplication1.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}

View File

@ -294,6 +294,31 @@ namespace Templates.Test.Helpers
}
}
internal async Task<ProcessEx> RunDotNetEfUpdateDatabaseAsync()
{
var assembly = typeof(ProjectFactoryFixture).Assembly;
var dotNetEfFullPath = assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.First(attribute => attribute.Key == "DotNetEfFullPath")
.Value;
var args = $"\"{dotNetEfFullPath}\" --verbose --no-build database update";
// Only run one instance of 'dotnet new' at once, as a workaround for
// https://github.com/aspnet/templating/issues/63
await DotNetNewLock.WaitAsync();
try
{
var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), args);
await result.Exited;
return result;
}
finally
{
DotNetNewLock.Release();
}
}
// If this fails, you should generate new migrations via migrations/updateMigrations.cmd
public void AssertEmptyMigration(string migration)
{

View File

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.E2ETesting;
using Newtonsoft.Json.Linq;
@ -80,11 +81,20 @@ namespace Templates.Test.SpaTemplateTest
var buildResult = await Project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
// localdb is not installed on the CI machines, so skip it.
var shouldVisitFetchData = !useLocalDb;
if (usesAuth)
{
var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync(template);
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
Project.AssertEmptyMigration(template);
if (shouldVisitFetchData)
{
var dbUpdateResult = await Project.RunDotNetEfUpdateDatabaseAsync();
Assert.True(0 == dbUpdateResult.ExitCode, ErrorMessages.GetFailedProcessMessage("update database", Project, dbUpdateResult));
}
}
using (var aspNetProcess = Project.StartBuiltProjectAsync())
@ -98,8 +108,9 @@ namespace Templates.Test.SpaTemplateTest
if (BrowserFixture.IsHostAutomationSupported())
{
aspNetProcess.VisitInBrowser(Browser);
TestBasicNavigation(visitFetchData: !usesAuth);
var (browser, logs) = await BrowserFixture.GetOrCreateBrowserAsync(Output, $"{Project.ProjectName}.build");
aspNetProcess.VisitInBrowser(browser);
TestBasicNavigation(visitFetchData: shouldVisitFetchData, usesAuth, browser);
}
}
@ -119,8 +130,9 @@ namespace Templates.Test.SpaTemplateTest
if (BrowserFixture.IsHostAutomationSupported())
{
aspNetProcess.VisitInBrowser(Browser);
TestBasicNavigation(visitFetchData: !usesAuth);
var (browser, logs) = await BrowserFixture.GetOrCreateBrowserAsync(Output, $"{Project.ProjectName}.publish");
aspNetProcess.VisitInBrowser(browser);
TestBasicNavigation(visitFetchData: shouldVisitFetchData, usesAuth, browser);
}
}
}
@ -167,36 +179,52 @@ namespace Templates.Test.SpaTemplateTest
File.WriteAllText(Path.Combine(Project.TemplatePublishDir, "appsettings.json"), testAppSettings);
}
private void TestBasicNavigation(bool visitFetchData)
private void TestBasicNavigation(bool visitFetchData, bool usesAuth, IWebDriver browser)
{
Browser.Exists(By.TagName("ul"));
browser.Exists(By.TagName("ul"));
// <title> element gets project ID injected into it during template execution
Browser.Contains(Project.ProjectGuid, () => Browser.Title);
browser.Contains(Project.ProjectGuid, () => browser.Title);
// Initially displays the home page
Browser.Equal("Hello, world!", () => Browser.FindElement(By.TagName("h1")).Text);
browser.Equal("Hello, world!", () => browser.FindElement(By.TagName("h1")).Text);
// Can navigate to the counter page
Browser.FindElement(By.PartialLinkText("Counter")).Click();
Browser.Contains("counter", () => Browser.Url);
browser.FindElement(By.PartialLinkText("Counter")).Click();
browser.Contains("counter", () => browser.Url);
Browser.Equal("Counter", () => Browser.FindElement(By.TagName("h1")).Text);
browser.Equal("Counter", () => browser.FindElement(By.TagName("h1")).Text);
// Clicking the counter button works
Browser.Equal("0", () => Browser.FindElement(By.CssSelector("p>strong")).Text);
Browser.FindElement(By.CssSelector("p+button")).Click();
Browser.Equal("1", () => Browser.FindElement(By.CssSelector("p>strong")).Text);
browser.Equal("0", () => browser.FindElement(By.CssSelector("p>strong")).Text);
browser.FindElement(By.CssSelector("p+button")).Click();
browser.Equal("1", () => browser.FindElement(By.CssSelector("p>strong")).Text);
if (visitFetchData)
{
browser.FindElement(By.PartialLinkText("Fetch data")).Click();
if (usesAuth)
{
// We will be redirected to the identity UI
browser.Contains("/Identity/Account/Login", () => browser.Url);
browser.FindElement(By.PartialLinkText("Register as a new user")).Click();
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
browser.Exists(By.Name("Input.Email"));
browser.FindElement(By.Name("Input.Email")).SendKeys(userName);
browser.FindElement(By.Name("Input.Password")).SendKeys(password);
browser.FindElement(By.Name("Input.ConfirmPassword")).SendKeys(password);
browser.FindElement(By.Id("registerSubmit")).Click();
}
// Can navigate to the 'fetch data' page
Browser.FindElement(By.PartialLinkText("Fetch data")).Click();
Browser.Contains("fetch-data", () => Browser.Url);
Browser.Equal("Weather forecast", () => Browser.FindElement(By.TagName("h1")).Text);
browser.Contains("fetch-data", () => browser.Url);
browser.Equal("Weather forecast", () => browser.FindElement(By.TagName("h1")).Text);
// Asynchronously loads and displays the table of weather forecasts
Browser.Exists(By.CssSelector("table>tbody>tr"));
Browser.Equal(5, () => Browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count);
browser.Exists(By.CssSelector("table>tbody>tr"));
browser.Equal(5, () => browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count);
}
}

View File

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@ -14,8 +16,8 @@ namespace Microsoft.AspNetCore.E2ETesting
{
public class BrowserFixture : IDisposable
{
private RemoteWebDriver _browser;
private RemoteLogs _logs;
private ConcurrentDictionary<string, Task<(IWebDriver browser, ILogs log)>> _browsers = new ConcurrentDictionary<string, Task<(IWebDriver, ILogs)>>();
private List<IWebDriver> _browsersToDispose = new List<IWebDriver>();
public BrowserFixture(IMessageSink diagnosticsMessageSink)
{
@ -52,22 +54,25 @@ namespace Microsoft.AspNetCore.E2ETesting
public void Dispose()
{
_browser?.Dispose();
foreach (var browser in _browsersToDispose)
{
browser.Dispose();
}
}
public async Task<(IWebDriver, ILogs)> GetOrCreateBrowserAsync(ITestOutputHelper output)
public Task<(IWebDriver, ILogs)> GetOrCreateBrowserAsync(ITestOutputHelper output, string isolationContext = "")
{
if (!IsHostAutomationSupported())
{
output.WriteLine($"{nameof(BrowserFixture)}: Host does not support browser automation.");
return default;
return Task.FromResult<(IWebDriver, ILogs)>(default);
}
if ((_browser, _logs) != (null, null))
{
return (_browser, _logs);
}
return _browsers.GetOrAdd(isolationContext, CreateBrowserAsync, output);
}
private async Task<(IWebDriver browser, ILogs log)> CreateBrowserAsync(string context, ITestOutputHelper output)
{
var opts = new ChromeOptions();
// Comment this out if you want to watch or interact with the browser (e.g., for debugging)
@ -110,10 +115,8 @@ namespace Microsoft.AspNetCore.E2ETesting
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);
var logs = new RemoteLogs(driver);
_browser = driver;
_logs = logs;
return (_browser, _logs);
_browsersToDispose.Add(driver);
return (driver, logs);
}
catch
{