diff options
-rw-r--r-- | .dockerignore | 4 | ||||
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | Controllers/AccountController.cs | 80 | ||||
-rw-r--r-- | Controllers/BundleController.cs | 2 | ||||
-rw-r--r-- | Controllers/FigureController.cs | 2 | ||||
-rw-r--r-- | Migrations/20230303041621_Init.Designer.cs (renamed from Migrations/20230221044417_Init.Designer.cs) | 2 | ||||
-rw-r--r-- | Migrations/20230303041621_Init.cs (renamed from Migrations/20230221044417_Init.cs) | 0 | ||||
-rw-r--r-- | Migrations/Identity/20230303041342_Init.Designer.cs | 268 | ||||
-rw-r--r-- | Migrations/Identity/20230303041342_Init.cs | 222 | ||||
-rw-r--r-- | Migrations/Identity/IdentityContextModelSnapshot.cs | 265 | ||||
-rw-r--r-- | Models/IdentityContext.cs | 13 | ||||
-rw-r--r-- | Models/LoginModel.cs | 13 | ||||
-rw-r--r-- | Models/SeedData.cs | 64 | ||||
-rw-r--r-- | MyDarling.csproj | 1 | ||||
-rw-r--r-- | Program.cs | 13 | ||||
-rw-r--r-- | Views/Account/Create.cshtml | 35 | ||||
-rw-r--r-- | Views/Account/List.cshtml | 54 | ||||
-rw-r--r-- | Views/Account/Login.cshtml | 31 | ||||
-rw-r--r-- | Views/Bundle/Index.cshtml | 10 | ||||
-rw-r--r-- | appsettings.json | 3 |
20 files changed, 1014 insertions, 76 deletions
diff --git a/.dockerignore b/.dockerignore index f11c5d6..858d1b3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,2 @@ # database file -Database/MyDarlingDb.db -Database/MyDarlingDb.db-shm -Database/MyDarlingDb.db-wal
\ No newline at end of file +Database/*
\ No newline at end of file @@ -456,10 +456,8 @@ $RECYCLE.BIN/ # libman libraries wwwroot/lib/* -# database image content +# image content wwwroot/content/* -# database file -Database/MyDarlingDb.db -Database/MyDarlingDb.db-shm -Database/MyDarlingDb.db-wal
\ No newline at end of file +# database files +Database/*
\ No newline at end of file diff --git a/Controllers/AccountController.cs b/Controllers/AccountController.cs new file mode 100644 index 0000000..432b671 --- /dev/null +++ b/Controllers/AccountController.cs @@ -0,0 +1,80 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using MyDarling.Models; + +namespace MyDarling.Controllers; + +public class AccountController : Controller +{ + public UserManager<IdentityUser> UserManager { get; set; } + private SignInManager<IdentityUser> SignInManager; + + public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager) + { + UserManager = userManager; + SignInManager = signInManager; + } + + public IActionResult List() + { + return View(UserManager.Users); + } + + public IActionResult Create() + { + return View(new IdentityUser()); + } + + [HttpPost] + public async Task<IActionResult> Create([Bind] IdentityUser user, [Bind] string Password) + { + if (ModelState.IsValid) + { + IdentityResult result = await UserManager.CreateAsync(user, Password); + if (result.Succeeded) + { + return RedirectToAction(nameof(List)); + } + + foreach (IdentityError error in result.Errors) + { + ModelState.AddModelError("", error.Description); + } + } + return View(); + } + + public ViewResult Login(string returlUrl) + { + return View(new LoginModel { ReturnUrl = returlUrl }); + } + + [HttpPost] + public async Task<IActionResult> Login(LoginModel loginModel) + { + if (ModelState.IsValid) + { + IdentityUser user = await UserManager.FindByNameAsync(loginModel.Name); + if (user != null) + { + await SignInManager.SignOutAsync(); + if ((await SignInManager.PasswordSignInAsync(user, + loginModel.Password, false, false)) + .Succeeded) + { + return Redirect(loginModel?.ReturnUrl ?? "/Bundle"); + } + } + ModelState.AddModelError("", "Invalid name or password"); + } + return View(loginModel); + } + + [Authorize] + public async Task<RedirectResult> Logout(string returlUrl = "/Account/Login") + { + await SignInManager.SignOutAsync(); + return Redirect(returlUrl); + } +}
\ No newline at end of file diff --git a/Controllers/BundleController.cs b/Controllers/BundleController.cs index 9e5c2d9..b1d61fd 100644 --- a/Controllers/BundleController.cs +++ b/Controllers/BundleController.cs @@ -1,10 +1,12 @@ using System.Data; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using MyDarling.Models; namespace MyDarling.Controllers { + [Authorize] public class BundleController : Controller { private DataContext context; diff --git a/Controllers/FigureController.cs b/Controllers/FigureController.cs index 3329968..9f6cf0c 100644 --- a/Controllers/FigureController.cs +++ b/Controllers/FigureController.cs @@ -1,10 +1,12 @@ using System.Data; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using MyDarling.Models; namespace MyDarling.Controllers { + [Authorize] public class FigureController : Controller { private DataContext context; diff --git a/Migrations/20230221044417_Init.Designer.cs b/Migrations/20230303041621_Init.Designer.cs index 658e6b7..833e097 100644 --- a/Migrations/20230221044417_Init.Designer.cs +++ b/Migrations/20230303041621_Init.Designer.cs @@ -11,7 +11,7 @@ using MyDarling.Models; namespace MyDarling.Migrations { [DbContext(typeof(DataContext))] - [Migration("20230221044417_Init")] + [Migration("20230303041621_Init")] partial class Init { /// <inheritdoc /> diff --git a/Migrations/20230221044417_Init.cs b/Migrations/20230303041621_Init.cs index 788d447..788d447 100644 --- a/Migrations/20230221044417_Init.cs +++ b/Migrations/20230303041621_Init.cs diff --git a/Migrations/Identity/20230303041342_Init.Designer.cs b/Migrations/Identity/20230303041342_Init.Designer.cs new file mode 100644 index 0000000..bdac6bd --- /dev/null +++ b/Migrations/Identity/20230303041342_Init.Designer.cs @@ -0,0 +1,268 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyDarling.Models; + +#nullable disable + +namespace MyDarling.Migrations.Identity +{ + [DbContext(typeof(IdentityContext))] + [Migration("20230303041342_Init")] + partial class Init + { + /// <inheritdoc /> + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<string>("PasswordHash") + .HasColumnType("TEXT"); + + b.Property<string>("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property<string>("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property<string>("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("TEXT"); + + b.Property<string>("ProviderKey") + .HasColumnType("TEXT"); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("LoginProvider") + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasColumnType("TEXT"); + + b.Property<string>("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/Identity/20230303041342_Init.cs b/Migrations/Identity/20230303041342_Init.cs new file mode 100644 index 0000000..fd7f4e6 --- /dev/null +++ b/Migrations/Identity/20230303041342_Init.cs @@ -0,0 +1,222 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyDarling.Migrations.Identity +{ + /// <inheritdoc /> + public partial class Init : Migration + { + /// <inheritdoc /> + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column<string>(type: "TEXT", nullable: false), + Name = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true), + NormalizedName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column<string>(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column<string>(type: "TEXT", nullable: false), + UserName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true), + NormalizedUserName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true), + Email = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true), + NormalizedEmail = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true), + EmailConfirmed = table.Column<bool>(type: "INTEGER", nullable: false), + PasswordHash = table.Column<string>(type: "TEXT", nullable: true), + SecurityStamp = table.Column<string>(type: "TEXT", nullable: true), + ConcurrencyStamp = table.Column<string>(type: "TEXT", nullable: true), + PhoneNumber = table.Column<string>(type: "TEXT", nullable: true), + PhoneNumberConfirmed = table.Column<bool>(type: "INTEGER", nullable: false), + TwoFactorEnabled = table.Column<bool>(type: "INTEGER", nullable: false), + LockoutEnd = table.Column<DateTimeOffset>(type: "TEXT", nullable: true), + LockoutEnabled = table.Column<bool>(type: "INTEGER", nullable: false), + AccessFailedCount = table.Column<int>(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column<int>(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column<string>(type: "TEXT", nullable: false), + ClaimType = table.Column<string>(type: "TEXT", nullable: true), + ClaimValue = table.Column<string>(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column<int>(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column<string>(type: "TEXT", nullable: false), + ClaimType = table.Column<string>(type: "TEXT", nullable: true), + ClaimValue = table.Column<string>(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column<string>(type: "TEXT", nullable: false), + ProviderKey = table.Column<string>(type: "TEXT", nullable: false), + ProviderDisplayName = table.Column<string>(type: "TEXT", nullable: true), + UserId = table.Column<string>(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column<string>(type: "TEXT", nullable: false), + RoleId = table.Column<string>(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column<string>(type: "TEXT", nullable: false), + LoginProvider = table.Column<string>(type: "TEXT", nullable: false), + Name = table.Column<string>(type: "TEXT", nullable: false), + Value = table.Column<string>(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); + } + + /// <inheritdoc /> + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/Migrations/Identity/IdentityContextModelSnapshot.cs b/Migrations/Identity/IdentityContextModelSnapshot.cs new file mode 100644 index 0000000..bb1e61f --- /dev/null +++ b/Migrations/Identity/IdentityContextModelSnapshot.cs @@ -0,0 +1,265 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyDarling.Models; + +#nullable disable + +namespace MyDarling.Migrations.Identity +{ + [DbContext(typeof(IdentityContext))] + partial class IdentityContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property<string>("Id") + .HasColumnType("TEXT"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property<string>("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<string>("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<string>("PasswordHash") + .HasColumnType("TEXT"); + + b.Property<string>("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property<string>("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property<string>("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClaimType") + .HasColumnType("TEXT"); + + b.Property<string>("ClaimValue") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("TEXT"); + + b.Property<string>("ProviderKey") + .HasColumnType("TEXT"); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property<string>("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.Property<string>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("LoginProvider") + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasColumnType("TEXT"); + + b.Property<string>("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Models/IdentityContext.cs b/Models/IdentityContext.cs new file mode 100644 index 0000000..888bc7a --- /dev/null +++ b/Models/IdentityContext.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; + +namespace MyDarling.Models; + +public class IdentityContext : IdentityDbContext<IdentityUser> +{ + public IdentityContext(DbContextOptions<IdentityContext> options) : base(options) + { + + } +}
\ No newline at end of file diff --git a/Models/LoginModel.cs b/Models/LoginModel.cs new file mode 100644 index 0000000..93485c8 --- /dev/null +++ b/Models/LoginModel.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace MyDarling.Models; +public class LoginModel +{ + [Required] + public string? Name { get; set; } + + [Required] + public string? Password { get; set; } + + public string ReturnUrl { get; set; } = "/Bundle"; +}
\ No newline at end of file diff --git a/Models/SeedData.cs b/Models/SeedData.cs deleted file mode 100644 index 3a15543..0000000 --- a/Models/SeedData.cs +++ /dev/null @@ -1,64 +0,0 @@ -// using Microsoft.EntityFrameworkCore; -// namespace MyDarling.Models -// { -// public static class SeedData -// { -// public static void SeedDatabase(DataContext context) -// { -// context.Database.Migrate(); -// if (context.UnderwearBundles.Count() == 0) -// { -// var aliceFigures = new List<Figure> -// { -// new Figure() -// { -// Description = @"Комплект из бежевого эластичного кружева с голубой отделкой.", -// FilePath = "/content/0/img/IMG_4896.JPG" -// }, -// new Figure() -// { -// Description = @"В комплект входит бра, 2 трусиков (на высокой посадке и стандартной на регуляции) и чокер. Низ можно сделать на выбор стринги/бразильянки.", -// FilePath = "/content/0/img/IMG_4902.JPG" -// } -// }; - -// var nikkiFigures = new List<Figure> -// { -// new Figure() -// { -// Description = @"Базовый сет из мягкой эластичной сетки.", -// FilePath = "/content/1/img/IMG_4897.JPG" -// }, -// new Figure() -// { -// Description = @"В комплект входит лиф на косточках и 2 трусиков – бразильянки на высокой посадке и стринги на стандартной посадке с регуляцией. Доступен в цветах: желтый, черный, бежевый молочный.", -// FilePath = "/content/1/img/IMG_4898.JPG" -// } -// }; - -// context.Figures.AddRange(aliceFigures); -// context.Figures.AddRange(nikkiFigures); -// context.SaveChanges(); - -// var alice = new UnderwearBundle -// { -// Name = "Alice", -// Figures = aliceFigures, -// Description = @"Комплект из бежевого эластичного кружева с голубой отделкой.", -// Price = 3000 -// }; - -// var nikki = new UnderwearBundle -// { -// Name = "Nikki", -// Figures = nikkiFigures, -// Description = @"Базовый сет из мягкой эластичной сетки.", -// Price = 3800 -// }; - -// context.UnderwearBundles.AddRange(alice, nikki); -// context.SaveChanges(); -// } -// } -// } -// }
\ No newline at end of file diff --git a/MyDarling.csproj b/MyDarling.csproj index f2e24bf..7ed30cd 100644 --- a/MyDarling.csproj +++ b/MyDarling.csproj @@ -7,6 +7,7 @@ </PropertyGroup> <ItemGroup> + <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.2"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using MyDarling.Models; +using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); @@ -9,6 +10,14 @@ builder.Services.AddDbContext<DataContext>(opts => opts.EnableSensitiveDataLogging(true); }); +builder.Services.AddDbContext<IdentityContext>(opts => +{ + opts.UseSqlite(builder.Configuration["ConnectionStrings:IdentityDb"]); +}); + +builder.Services.AddIdentity<IdentityUser, IdentityRole>() + .AddEntityFrameworkStores<IdentityContext>(); + builder.Services.AddControllersWithViews(); var app = builder.Build(); @@ -17,7 +26,7 @@ app.UseStaticFiles(); app.MapControllers(); app.MapDefaultControllerRoute(); -// var context = app.Services.CreateScope().ServiceProvider.GetRequiredService<DataContext>(); -// SeedData.SeedDatabase(context); +app.UseAuthentication(); +app.UseAuthorization(); app.Run();
\ No newline at end of file diff --git a/Views/Account/Create.cshtml b/Views/Account/Create.cshtml new file mode 100644 index 0000000..2fff64a --- /dev/null +++ b/Views/Account/Create.cshtml @@ -0,0 +1,35 @@ +@using Microsoft.AspNetCore.Identity +@model IdentityUser + +<!DOCTYPE html> +<html> + +<head> + <title>User Acccounts</title> + <link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> +</head> + +<body> + <h5 class="bg-primary text-white text-center p-2">Create User</h5> + <form method="post"> + <div asp-validation-summary="All" class="text-danger"></div> + <div class="form-group"> + <label>User Name</label> + <input name="UserName" class="form-control" value="@Model.UserName" /> + </div> + <div class="form-group"> + <label>Email</label> + <input name="Email" class="form-control" value="@Model.Email" /> + </div> + <div class="form-group"> + <label>Password</label> + <input name="Password" class="form-control" value="" /> + </div> + <div class="py-2"> + <button type="submit" class="btn btn-primary">Submit</button> + <a class="btn btn-secondary" asp-page="list">Back</a> + </div> + </form> +</body> + +</html>
\ No newline at end of file diff --git a/Views/Account/List.cshtml b/Views/Account/List.cshtml new file mode 100644 index 0000000..7f17543 --- /dev/null +++ b/Views/Account/List.cshtml @@ -0,0 +1,54 @@ +@using Microsoft.AspNetCore.Identity +@model IQueryable<IdentityUser> + +<!DOCTYPE html> +<html> + +<head> + <title>Users</title> + <link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> +</head> + +<body> + <div class="m-2"> + <h5 class="bg-info text-white text-center p-2">User Administration</h5> + <table class="table table-sm table-bordered"> + <tr> + <th>ID</th> + <th>Name</th> + <th>Email</th> + <th></th> + </tr> + @if (Model.Count() == 0) + { + <tr> + <td colspan="4" class="text-center">No User Accounts</td> + </tr> + } + else + { + foreach (IdentityUser user in Model) + { + <tr> + <td>@user.Id</td> + <td>@user.UserName</td> + <td>@user.Email</td> + <td class="text-center"> + <form asp-page="List" method="post"> + <input type="hidden" name="Id" value="@user.Id" /> + <a class="btn btn-sm btn-warning" asp-page="Editor" asp-route-id="@user.Id" + asp-route-mode="edit">Edit</a> + <button type="submit" class="btn btn-sm btn-danger"> + Delete + </button> + </form> + </td> + </tr> + } + } + </table> + <a class="btn btn-primary" asp-page="create">Create</a> + </div> +</body> + +</html>
\ No newline at end of file diff --git a/Views/Account/Login.cshtml b/Views/Account/Login.cshtml new file mode 100644 index 0000000..893155c --- /dev/null +++ b/Views/Account/Login.cshtml @@ -0,0 +1,31 @@ +@model MyDarling.Models.LoginModel +<!DOCTYPE html> +<html> + +<head> + <meta name="viewport" content="width=device-width" /> + <title>Login Page</title> + <link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> +</head> + +<body> + <div class="m-1 p-1"> + <div class="text-danger" asp-validation-summary="All"></div> + <form asp-action="Login" asp-controller="Account" method="post"> + <input type="hidden" asp-for="ReturnUrl" /> + <div class="form-group"> + <label asp-for="Name"></label> + <div asp-validation-for="Name" class="text-danger"></div> + <input name="Name" class="form-control" value="@Model.Name"/> + </div> + <div class="form-group"> + <label asp-for="Password"></label> + <div asp-validation-for="Password" class="text-danger"></div> + <input name="Password" type="password" class="form-control" value="@Model.Password"/> + </div> + <button class="btn btn-primary mt-2" type="submit">Log In</button> + </form> + </div> +</body> + +</html>
\ No newline at end of file diff --git a/Views/Bundle/Index.cshtml b/Views/Bundle/Index.cshtml index 678caf0..9e1f293 100644 --- a/Views/Bundle/Index.cshtml +++ b/Views/Bundle/Index.cshtml @@ -10,6 +10,16 @@ </head> <body> + <div class="container-fluid"> + <div class="row"> + <div class="col"> + <span class="navbar-brand ml-2">Underwear bundle list</span> + </div> + <div class="col-2 text-right"> + <a class="btn btn-sm btn-primary" href="/account/logout">Log Out</a> + </div> + </div> + </div> <container> <table class="table table-striped"> <thead> diff --git a/appsettings.json b/appsettings.json index 6f63f2f..fc9c46a 100644 --- a/appsettings.json +++ b/appsettings.json @@ -7,6 +7,7 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "MyDarlingDb": "Data Source=Database/MyDarlingDb.db" + "MyDarlingDb": "Data Source=Database/MyDarlingDb.db", + "IdentityDb": "Data Source=Database/IdentityDb.db" } } |