main
Peace 9 months ago
parent 3aef36ff14
commit 99f3eeb2a4
  1. 2
      AppIdentity/AppIdentity/AppIdentity/AppIdentity/AppIdentity.csproj
  2. 92
      AppIdentity/AppIdentity/AppIdentity/AppIdentity/Migrations/20240812045157_createIdentityMariaDB.Designer.cs
  3. 138
      AppIdentity/AppIdentity/AppIdentity/AppIdentity/Migrations/20240812045157_createIdentityMariaDB.cs
  4. 88
      AppIdentity/AppIdentity/AppIdentity/AppIdentity/Migrations/ApplicationDbContextModelSnapshot.cs
  5. 5
      AppIdentity/AppIdentity/AppIdentity/AppIdentity/Program.cs
  6. 2
      AppIdentity/AppIdentity/AppIdentity/AppIdentity/appsettings.json
  7. 25
      BlazorPolicyAuth/BlazorPolicyAuth.sln
  8. 18
      BlazorPolicyAuth/BlazorPolicyAuth/BlazorPolicyAuth.csproj
  9. 20
      BlazorPolicyAuth/BlazorPolicyAuth/Components/App.razor
  10. 31
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Layout/MainLayout.razor
  11. 96
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Layout/MainLayout.razor.css
  12. 46
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Layout/NavMenu.razor
  13. 105
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Layout/NavMenu.razor.css
  14. 16
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Account/AccessDenied.razor
  15. 80
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Account/Login.razor
  16. 33
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Account/Logout.razor
  17. 19
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Counter.razor
  18. 36
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Error.razor
  19. 11
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Home.razor
  20. 30
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Product/Products.razor
  21. 64
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Pages/Weather.razor
  22. 7
      BlazorPolicyAuth/BlazorPolicyAuth/Components/Routes.razor
  23. 11
      BlazorPolicyAuth/BlazorPolicyAuth/Components/_Imports.razor
  24. 17
      BlazorPolicyAuth/BlazorPolicyAuth/Data/AppDbContext.cs
  25. 96
      BlazorPolicyAuth/BlazorPolicyAuth/Migrations/20240813053357_createIdentityMariaDB.Designer.cs
  26. 81
      BlazorPolicyAuth/BlazorPolicyAuth/Migrations/20240813053357_createIdentityMariaDB.cs
  27. 93
      BlazorPolicyAuth/BlazorPolicyAuth/Migrations/AppDbContextModelSnapshot.cs
  28. 17
      BlazorPolicyAuth/BlazorPolicyAuth/Models/Entities/Product.cs
  29. 15
      BlazorPolicyAuth/BlazorPolicyAuth/Models/Entities/User.cs
  30. 10
      BlazorPolicyAuth/BlazorPolicyAuth/Models/Entities/UserPolicy.cs
  31. 13
      BlazorPolicyAuth/BlazorPolicyAuth/Models/ViewModels/LoginViewModel.cs
  32. 21
      BlazorPolicyAuth/BlazorPolicyAuth/Policy.cs
  33. 62
      BlazorPolicyAuth/BlazorPolicyAuth/Program.cs
  34. 38
      BlazorPolicyAuth/BlazorPolicyAuth/Properties/launchSettings.json
  35. 8
      BlazorPolicyAuth/BlazorPolicyAuth/appsettings.Development.json
  36. 12
      BlazorPolicyAuth/BlazorPolicyAuth/appsettings.json
  37. 51
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/app.css
  38. 7
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/bootstrap/bootstrap.min.css
  39. 1
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/bootstrap/bootstrap.min.css.map
  40. BIN
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/favicon.png
  41. BIN
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/images/access-denied.png
  42. BIN
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/images/login.png
  43. BIN
      BlazorPolicyAuth/BlazorPolicyAuth/wwwroot/images/logout.png

@ -12,8 +12,8 @@
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -1,81 +1,81 @@
// <auto-generated /> // <auto-generated />
using System;
using AppIdentity.Data; using AppIdentity.Data;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using System;
#nullable disable #nullable disable
namespace AppIdentity.Migrations namespace AppIdentity.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
[Migration("00000000000000_CreateIdentitySchema")] [Migration("20240812045157_createIdentityMariaDB")]
partial class CreateIdentitySchema partial class createIdentityMariaDB
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "8.0.0") .HasAnnotation("ProductVersion", "8.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 128); .HasAnnotation("Relational:MaxIdentifierLength", 64);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("AppIdentity.Data.ApplicationUser", b => modelBuilder.Entity("AppIdentity.Data.ApplicationUser", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<int>("AccessFailedCount") b.Property<int>("AccessFailedCount")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("Email") b.Property<string>("Email")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<bool>("EmailConfirmed") b.Property<bool>("EmailConfirmed")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<bool>("LockoutEnabled") b.Property<bool>("LockoutEnabled")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<DateTimeOffset?>("LockoutEnd") b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset"); .HasColumnType("datetime(6)");
b.Property<string>("NormalizedEmail") b.Property<string>("NormalizedEmail")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<string>("NormalizedUserName") b.Property<string>("NormalizedUserName")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<string>("PasswordHash") b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("PhoneNumber") b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<bool>("PhoneNumberConfirmed") b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<string>("SecurityStamp") b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<bool>("TwoFactorEnabled") b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<string>("UserName") b.Property<string>("UserName")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.HasKey("Id"); b.HasKey("Id");
@ -84,8 +84,7 @@ namespace AppIdentity.Migrations
b.HasIndex("NormalizedUserName") b.HasIndex("NormalizedUserName")
.IsUnique() .IsUnique()
.HasDatabaseName("UserNameIndex") .HasDatabaseName("UserNameIndex");
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null); b.ToTable("AspNetUsers", (string)null);
}); });
@ -93,26 +92,25 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("Name") b.Property<string>("Name")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<string>("NormalizedName") b.Property<string>("NormalizedName")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("NormalizedName") b.HasIndex("NormalizedName")
.IsUnique() .IsUnique()
.HasDatabaseName("RoleNameIndex") .HasDatabaseName("RoleNameIndex");
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null); b.ToTable("AspNetRoles", (string)null);
}); });
@ -123,17 +121,17 @@ namespace AppIdentity.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int"); .HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType") b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("ClaimValue") b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("RoleId") b.Property<string>("RoleId")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("Id"); b.HasKey("Id");
@ -148,17 +146,17 @@ namespace AppIdentity.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int"); .HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType") b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("ClaimValue") b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("UserId") b.Property<string>("UserId")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("Id"); b.HasKey("Id");
@ -170,17 +168,17 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{ {
b.Property<string>("LoginProvider") b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("ProviderKey") b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("ProviderDisplayName") b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("UserId") b.Property<string>("UserId")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("LoginProvider", "ProviderKey"); b.HasKey("LoginProvider", "ProviderKey");
@ -192,10 +190,10 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{ {
b.Property<string>("UserId") b.Property<string>("UserId")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("RoleId") b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("UserId", "RoleId"); b.HasKey("UserId", "RoleId");
@ -207,16 +205,16 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{ {
b.Property<string>("UserId") b.Property<string>("UserId")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("LoginProvider") b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("Name") b.Property<string>("Name")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("Value") b.Property<string>("Value")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.HasKey("UserId", "LoginProvider", "Name"); b.HasKey("UserId", "LoginProvider", "Name");

@ -1,64 +1,86 @@
using Microsoft.EntityFrameworkCore.Migrations; using System;
using System; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable
namespace AppIdentity.Migrations namespace AppIdentity.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class CreateIdentitySchema : Migration public partial class createIdentityMariaDB : Migration
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetRoles", name: "AspNetRoles",
columns: table => new columns: table => new
{ {
Id = table.Column<string>(type: "nvarchar(450)", nullable: false), Id = table.Column<string>(type: "varchar(255)", nullable: false)
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), Name = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true) .Annotation("MySql:CharSet", "utf8mb4"),
NormalizedName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
}, },
constraints: table => constraints: table =>
{ {
table.PrimaryKey("PK_AspNetRoles", x => x.Id); table.PrimaryKey("PK_AspNetRoles", x => x.Id);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetUsers", name: "AspNetUsers",
columns: table => new columns: table => new
{ {
Id = table.Column<string>(type: "nvarchar(450)", nullable: false), Id = table.Column<string>(type: "varchar(255)", nullable: false)
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
NormalizedEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false), .Annotation("MySql:CharSet", "utf8mb4"),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true), Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
SecurityStamp = table.Column<string>(type: "nvarchar(max)", nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true), NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false), EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "bit", nullable: false), PasswordHash = table.Column<string>(type: "longtext", nullable: true)
LockoutEnd = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
LockoutEnabled = table.Column<bool>(type: "bit", nullable: false), SecurityStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumber = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false) AccessFailedCount = table.Column<int>(type: "int", nullable: false)
}, },
constraints: table => constraints: table =>
{ {
table.PrimaryKey("PK_AspNetUsers", x => x.Id); table.PrimaryKey("PK_AspNetUsers", x => x.Id);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetRoleClaims", name: "AspNetRoleClaims",
columns: table => new columns: table => new
{ {
Id = table.Column<int>(type: "int", nullable: false) Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"), .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false), RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true) ClaimType = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
}, },
constraints: table => constraints: table =>
{ {
@ -69,17 +91,21 @@ namespace AppIdentity.Migrations
principalTable: "AspNetRoles", principalTable: "AspNetRoles",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetUserClaims", name: "AspNetUserClaims",
columns: table => new columns: table => new
{ {
Id = table.Column<int>(type: "int", nullable: false) Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"), .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false), UserId = table.Column<string>(type: "varchar(255)", nullable: false)
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true), .Annotation("MySql:CharSet", "utf8mb4"),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true) ClaimType = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
}, },
constraints: table => constraints: table =>
{ {
@ -90,16 +116,21 @@ namespace AppIdentity.Migrations
principalTable: "AspNetUsers", principalTable: "AspNetUsers",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetUserLogins", name: "AspNetUserLogins",
columns: table => new columns: table => new
{ {
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false), LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
ProviderKey = table.Column<string>(type: "nvarchar(450)", nullable: false), .Annotation("MySql:CharSet", "utf8mb4"),
ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true), ProviderKey = table.Column<string>(type: "varchar(255)", nullable: false)
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false) .Annotation("MySql:CharSet", "utf8mb4"),
ProviderDisplayName = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
}, },
constraints: table => constraints: table =>
{ {
@ -110,14 +141,17 @@ namespace AppIdentity.Migrations
principalTable: "AspNetUsers", principalTable: "AspNetUsers",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetUserRoles", name: "AspNetUserRoles",
columns: table => new columns: table => new
{ {
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false), UserId = table.Column<string>(type: "varchar(255)", nullable: false)
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false) .Annotation("MySql:CharSet", "utf8mb4"),
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
}, },
constraints: table => constraints: table =>
{ {
@ -134,16 +168,21 @@ namespace AppIdentity.Migrations
principalTable: "AspNetUsers", principalTable: "AspNetUsers",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AspNetUserTokens", name: "AspNetUserTokens",
columns: table => new columns: table => new
{ {
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false), UserId = table.Column<string>(type: "varchar(255)", nullable: false)
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false), .Annotation("MySql:CharSet", "utf8mb4"),
Name = table.Column<string>(type: "nvarchar(450)", nullable: false), LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
Value = table.Column<string>(type: "nvarchar(max)", nullable: true) .Annotation("MySql:CharSet", "utf8mb4"),
Name = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Value = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
}, },
constraints: table => constraints: table =>
{ {
@ -154,7 +193,8 @@ namespace AppIdentity.Migrations
principalTable: "AspNetUsers", principalTable: "AspNetUsers",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); })
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId", name: "IX_AspNetRoleClaims_RoleId",
@ -165,8 +205,7 @@ namespace AppIdentity.Migrations
name: "RoleNameIndex", name: "RoleNameIndex",
table: "AspNetRoles", table: "AspNetRoles",
column: "NormalizedName", column: "NormalizedName",
unique: true, unique: true);
filter: "[NormalizedName] IS NOT NULL");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId", name: "IX_AspNetUserClaims_UserId",
@ -192,8 +231,7 @@ namespace AppIdentity.Migrations
name: "UserNameIndex", name: "UserNameIndex",
table: "AspNetUsers", table: "AspNetUsers",
column: "NormalizedUserName", column: "NormalizedUserName",
unique: true, unique: true);
filter: "[NormalizedUserName] IS NOT NULL");
} }
/// <inheritdoc /> /// <inheritdoc />

@ -1,10 +1,10 @@
// <auto-generated /> // <auto-generated />
using System;
using AppIdentity.Data; using AppIdentity.Data;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using System;
#nullable disable #nullable disable
@ -17,62 +17,62 @@ namespace AppIdentity.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "8.0.0") .HasAnnotation("ProductVersion", "8.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 128); .HasAnnotation("Relational:MaxIdentifierLength", 64);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("AppIdentity.Data.ApplicationUser", b => modelBuilder.Entity("AppIdentity.Data.ApplicationUser", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<int>("AccessFailedCount") b.Property<int>("AccessFailedCount")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("Email") b.Property<string>("Email")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<bool>("EmailConfirmed") b.Property<bool>("EmailConfirmed")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<bool>("LockoutEnabled") b.Property<bool>("LockoutEnabled")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<DateTimeOffset?>("LockoutEnd") b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset"); .HasColumnType("datetime(6)");
b.Property<string>("NormalizedEmail") b.Property<string>("NormalizedEmail")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<string>("NormalizedUserName") b.Property<string>("NormalizedUserName")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<string>("PasswordHash") b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("PhoneNumber") b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<bool>("PhoneNumberConfirmed") b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<string>("SecurityStamp") b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<bool>("TwoFactorEnabled") b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit"); .HasColumnType("tinyint(1)");
b.Property<string>("UserName") b.Property<string>("UserName")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.HasKey("Id"); b.HasKey("Id");
@ -81,8 +81,7 @@ namespace AppIdentity.Migrations
b.HasIndex("NormalizedUserName") b.HasIndex("NormalizedUserName")
.IsUnique() .IsUnique()
.HasDatabaseName("UserNameIndex") .HasDatabaseName("UserNameIndex");
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null); b.ToTable("AspNetUsers", (string)null);
}); });
@ -90,26 +89,25 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("Name") b.Property<string>("Name")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.Property<string>("NormalizedName") b.Property<string>("NormalizedName")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("varchar(256)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("NormalizedName") b.HasIndex("NormalizedName")
.IsUnique() .IsUnique()
.HasDatabaseName("RoleNameIndex") .HasDatabaseName("RoleNameIndex");
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null); b.ToTable("AspNetRoles", (string)null);
}); });
@ -120,17 +118,17 @@ namespace AppIdentity.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int"); .HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType") b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("ClaimValue") b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("RoleId") b.Property<string>("RoleId")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("Id"); b.HasKey("Id");
@ -145,17 +143,17 @@ namespace AppIdentity.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int"); .HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType") b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("ClaimValue") b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("UserId") b.Property<string>("UserId")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("Id"); b.HasKey("Id");
@ -167,17 +165,17 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{ {
b.Property<string>("LoginProvider") b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("ProviderKey") b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("ProviderDisplayName") b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.Property<string>("UserId") b.Property<string>("UserId")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("LoginProvider", "ProviderKey"); b.HasKey("LoginProvider", "ProviderKey");
@ -189,10 +187,10 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{ {
b.Property<string>("UserId") b.Property<string>("UserId")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("RoleId") b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.HasKey("UserId", "RoleId"); b.HasKey("UserId", "RoleId");
@ -204,16 +202,16 @@ namespace AppIdentity.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{ {
b.Property<string>("UserId") b.Property<string>("UserId")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("LoginProvider") b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("Name") b.Property<string>("Name")
.HasColumnType("nvarchar(450)"); .HasColumnType("varchar(255)");
b.Property<string>("Value") b.Property<string>("Value")
.HasColumnType("nvarchar(max)"); .HasColumnType("longtext");
b.HasKey("UserId", "LoginProvider", "Name"); b.HasKey("UserId", "LoginProvider", "Name");

@ -5,6 +5,7 @@ using AppIdentity.Data;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System;
namespace AppIdentity namespace AppIdentity
{ {
@ -33,7 +34,9 @@ namespace AppIdentity
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options => builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString)); {
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
});
builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)

@ -1,6 +1,6 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-AppIdentity-8ce3ac08-489c-4e92-9a9f-090045dd22bd;Trusted_Connection=True;MultipleActiveResultSets=true" "DefaultConnection": "Server=peacecloud.synology.me; Port=23306; Database=BLAZORAPPTEST; Uid=pds; Pwd=Pds92070983!@"
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35013.160
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorPolicyAuth", "BlazorPolicyAuth\BlazorPolicyAuth.csproj", "{8D4AF366-9E35-4A81-9737-A85A4AAF5759}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8D4AF366-9E35-4A81-9737-A85A4AAF5759}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D4AF366-9E35-4A81-9737-A85A4AAF5759}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D4AF366-9E35-4A81-9737-A85A4AAF5759}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D4AF366-9E35-4A81-9737-A85A4AAF5759}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2CF72230-2129-4C0A-932B-261F15B5A3B0}
EndGlobalSection
EndGlobal

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
</ItemGroup>
</Project>

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="BlazorPolicyAuth.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>
<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
</body>
</html>

@ -0,0 +1,31 @@
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
<AuthorizeView>
<Authorized>
<a href="/logout">Logout</a>
</Authorized>
<NotAuthorized>
<a href="/login">Login</a>
</NotAuthorized>
</AuthorizeView>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

@ -0,0 +1,96 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}
.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}
.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}
.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}

@ -0,0 +1,46 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">BlazorPolicyAuth</a>
</div>
</div>
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<AuthorizeView Policy="@Policy.VIEW_PRODUCT">
<Authorized>
<div class="nav-item px-3">
<NavLink class="nav-link" href="product">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Product
</NavLink>
</div>
</Authorized>
<NotAuthorized>
</NotAuthorized>
</AuthorizeView>
<AuthorizeView>
<Authorized>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="weather">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
</NavLink>
</div>
</Authorized>
</AuthorizeView>
</nav>
</div>

@ -0,0 +1,105 @@
.navbar-toggler {
appearance: none;
cursor: pointer;
width: 3.5rem;
height: 2.5rem;
color: white;
position: absolute;
top: 0.5rem;
right: 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}
.navbar-toggler:checked {
background-color: rgba(255, 255, 255, 0.5);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.bi {
display: inline-block;
position: relative;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.75rem;
top: -1px;
background-size: cover;
}
.bi-house-door-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}
.bi-plus-square-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}
.bi-list-nested-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep .nav-link {
color: #d7d7d7;
background: none;
border: none;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
width: 100%;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.37);
color: white;
}
.nav-item ::deep .nav-link:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
.nav-scrollable {
display: none;
}
.navbar-toggler:checked ~ .nav-scrollable {
display: block;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.nav-scrollable {
/* Never collapse the sidebar for wide screens */
display: block;
/* Allow sidebar to scroll for tall menus */
height: calc(100vh - 3.5rem);
overflow-y: auto;
}
}

@ -0,0 +1,16 @@
@page "/access-denied"
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body flex-column">
<div class="text-center">
<img src="/images/access-denied.png" style="max-height:5rem"/>
</div>
<div class="text-center mt-2">
<span class="text-danger fw-bolder">You don't have permission to access this page.</span>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,80 @@
@page "/login"
@using BlazorPolicyAuth.Data
@using BlazorPolicyAuth.Models.Entities
@using BlazorPolicyAuth.Models.ViewModels
@using System.Security.Claims
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@using Microsoft.EntityFrameworkCore
@inject AppDbContext AppDbContext
@inject NavigationManager NavManager
<div class="row">
<div class="col-lg-4 offset-lg-4 pt-4 pb-4 border rounded">
<EditForm Model="@Model" OnSubmit="Authenticate" FormName="LoginForm">
<DataAnnotationsValidator />
<div class="mb-3 text-center flex-column">
<img src="/images/login.png" style="max-height:5rem"/>
<h3>LOGIN</h3>
</div>
<div class="mb-3">
<label>User name</label>
<InputText @bind-Value="Model.UserName" class="form-control" placeholder="User name"/>
<ValidationMessage For="@(() => Model.UserName)"/>
</div>
<div class="mb-3">
<label>Password</label>
<InputText @bind-Value="Model.Password" class="form-control" type="password" placeholder="Password" />
<ValidationMessage For="@(() => Model.Password)" />
</div>
<div class="mb-3 text-center">
<span class="text-danger">@errorMessage?.ToString()</span>
</div>
<div class="mb-3 d-grid gap-2">
<button type="submit" class="btn btn-primary">Login</button>
</div>
</EditForm>
</div>
</div>
@code {
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
[SupplyParameterFromForm]
public LoginViewModel Model { get; set; } = new();
private string? errorMessage;
private async Task Authenticate()
{
if (string.IsNullOrWhiteSpace(Model.UserName) ||
string.IsNullOrWhiteSpace(Model.Password))
{
errorMessage = "Invalid account information";
return;
}
var user = AppDbContext.Users.Where(u => u.Name == Model.UserName).FirstOrDefault();
if (user is null || user.Password != Model.Password)
{
errorMessage = "Invalid account information";
return;
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, Model.UserName),
};
var policies = await AppDbContext.UserPolicies.Where(p => p.UserId == user.Id && p.IsEnable).ToListAsync();
foreach (var policy in policies)
claims.Add(new Claim(policy.Policy, "true"));
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await HttpContext?.SignInAsync(principal);
NavManager.NavigateTo("/");
}
}

@ -0,0 +1,33 @@
@page "/logout"
@using Microsoft.AspNetCore.Authentication
@inject NavigationManager NavManager
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body flex-column">
<div class="text-center">
<img src="/images/logout.png" style="max-height:5rem"/>
</div>
<div class="text-center mt-2">
<span class="text-danger fw-bolder">You've successfully logged out of the application.'</span>
</div>
</div>
</div>
</div>
</div>
@code {
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
if (HttpContext.User.Identity.IsAuthenticated)
{
await HttpContext.SignOutAsync();
NavManager.NavigateTo("/logout", true);
}
}
}

@ -0,0 +1,19 @@
@page "/counter"
@rendermode InteractiveServer
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

@ -0,0 +1,36 @@
@page "/Error"
@using System.Diagnostics
<PageTitle>Error</PageTitle>
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
@code{
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
private string? RequestId { get; set; }
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
protected override void OnInitialized() =>
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
}

@ -0,0 +1,11 @@
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, welcome to <b class="text-danger">BLAZOR 🔥</b></h1>
<AuthorizeView>
<Authorized>
<h4>Logged in as <b>@context.User.Identity.Name</b></h4>
</Authorized>
</AuthorizeView>

@ -0,0 +1,30 @@
@page "/products"
@using BlazorPolicyAuth.Data
@using Microsoft.AspNetCore.Authorization
@inject AppDbContext AppDbContext
@rendermode RenderMode.InteractiveServer
@attribute [Authorize(Policy = Policy.VIEW_PRODUCT)]
<div class="card">
<div class="card-body p-0">
<table class="table table-striped mb-0">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>
</td>
</tr>
</tbody>
</table>
</div>
</div>
@code {
}

@ -0,0 +1,64 @@
@page "/weather"
@attribute [StreamRendering]
<PageTitle>Weather</PageTitle>
<h1>Weather</h1>
<p>This component demonstrates showing data.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
// Simulate asynchronous loading to demonstrate streaming rendering
await Task.Delay(500);
var startDate = DateOnly.FromDateTime(DateTime.Now);
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
}
private class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

@ -0,0 +1,7 @@
@using Microsoft.AspNetCore.Components.Authorization
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>

@ -0,0 +1,11 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorPolicyAuth
@using BlazorPolicyAuth.Components
@using Microsoft.AspNetCore.Components.Authorization

@ -0,0 +1,17 @@
using BlazorPolicyAuth.Models.Entities;
using Microsoft.EntityFrameworkCore;
namespace BlazorPolicyAuth.Data
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<UserPolicy> UserPolicies { get; set; }
public DbSet<Product> Products { get; set; }
}
}

@ -0,0 +1,96 @@
// <auto-generated />
using System;
using BlazorPolicyAuth.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BlazorPolicyAuth.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20240813053357_createIdentityMariaDB")]
partial class createIdentityMariaDB
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("BlazorPolicyAuth.Models.Entities.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<int?>("Price")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Products");
});
modelBuilder.Entity("BlazorPolicyAuth.Models.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("BlazorPolicyAuth.Models.Entities.UserPolicy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("IsEnable")
.HasColumnType("tinyint(1)");
b.Property<string>("Policy")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("UserPolicies");
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,81 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BlazorPolicyAuth.Migrations
{
/// <inheritdoc />
public partial class createIdentityMariaDB : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Price = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserPolicies",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
Policy = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
IsEnable = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserPolicies", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Password = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "UserPolicies");
migrationBuilder.DropTable(
name: "Users");
}
}
}

@ -0,0 +1,93 @@
// <auto-generated />
using System;
using BlazorPolicyAuth.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BlazorPolicyAuth.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("BlazorPolicyAuth.Models.Entities.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<int?>("Price")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Products");
});
modelBuilder.Entity("BlazorPolicyAuth.Models.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("BlazorPolicyAuth.Models.Entities.UserPolicy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("IsEnable")
.HasColumnType("tinyint(1)");
b.Property<string>("Policy")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("UserPolicies");
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace BlazorPolicyAuth.Models.Entities
{
public class Product
{
public int Id { get; set; }
[MaxLength(100)]
public string Code { get; set; }
[MaxLength(100)]
public string Name { get; set; }
public int? Price { get; set; }
}
}

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace BlazorPolicyAuth.Models.Entities
{
public class User
{
public int Id { get; set; }
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(100)]
public string Password { get; set; }
}
}

@ -0,0 +1,10 @@
namespace BlazorPolicyAuth.Models.Entities
{
public class UserPolicy
{
public int Id { get; set; }
public int UserId { get; set; }
public string? Policy { get; set; }
public bool IsEnable { get; set; }
}
}

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace BlazorPolicyAuth.Models.ViewModels
{
public class LoginViewModel
{
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter user name")]
public string? UserName { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter password")]
public string? Password { get; set; }
}
}

@ -0,0 +1,21 @@
namespace BlazorPolicyAuth
{
public class Policy
{
public const string VIEW_PRODUCT = "VIEW_PRODUCT";
public const string ADD_PRODUCT = "ADD_PRODUCT";
public const string EDIT_PRODUCT = "EDIT_PRODUCT";
public const string DELETE_PRODUCT = "DELETE_PRODUCT";
public static List<string> GetPoilicies()
{
return new List<string>
{
VIEW_PRODUCT,
ADD_PRODUCT,
EDIT_PRODUCT,
DELETE_PRODUCT
};
}
}
}

@ -0,0 +1,62 @@
using BlazorPolicyAuth.Components;
using BlazorPolicyAuth.Data;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.EntityFrameworkCore;
namespace BlazorPolicyAuth
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
// For authentication
builder.Services.AddAuthorization(config =>
{
foreach (var userPolicy in Policy.GetPoilicies())
config.AddPolicy(userPolicy, c => c.RequireClaim(userPolicy, "true"));
});
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "auth_token";
options.LoginPath = "/login";
options.Cookie.MaxAge = TimeSpan.FromMinutes(30);
options.AccessDeniedPath = "/access-denied";
});
builder.Services.AddCascadingAuthenticationState();
// For database
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
}
}
}

@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:39353",
"sslPort": 44372
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5032",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7230;http://localhost:5032",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

@ -0,0 +1,12 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=peacecloud.synology.me; Port=23306; Database=BLAZORAUTH; Uid=pds; Pwd=Pds92070983!@"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

@ -0,0 +1,51 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
a, .btn-link {
color: #006bb7;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
.content {
padding-top: 1.1rem;
}
h1:focus {
outline: none;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid #e50000;
}
.validation-message {
color: #e50000;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.darker-border-checkbox.form-check-input {
border-color: #929292;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Loading…
Cancel
Save