feat: Integrate ASP.NET Core Identity for user authentication
This commit integrates ASP.NET Core Identity into the application to enable user registration, login, and management. This lays the groundwork for securing data per user.
**Key Changes:**
*   **DbContext Configuration:**
    *   Modified `ApplicationDbContext.cs` to inherit from `IdentityDbContext<IdentityUser>`.
    *   Removed an unnecessary `using` statement from `ApplicationDbContext.cs`.
*   **Program.cs Setup:**
    *   Configured `AddDefaultIdentity<IdentityUser>` with `AddEntityFrameworkStores<ApplicationDbContext>()` to register Identity services.
    *   Ensured correct ordering of `UseAuthentication()` and `UseAuthorization()` middleware.
    *   Added `app.MapRazorPages()` to enable the Identity UI pages.
    *   Verified core package versions in `turf_tasker.csproj` for consistency across EF Core and Identity components (`8.0.6`).
*   **Identity UI:**
    *   Scaffolded ASP.NET Core Identity pages (Login, Register, Manage, etc.) to provide the user interface for authentication.
    *   Added a `_LoginPartial.cshtml` partial view to the `Views/Shared` folder.
    *   Rendered `_LoginPartial` in `Views/Shared/_Layout.cshtml` to display login/register/logout links in the navigation bar.
*   **Migrations:**
    *   Created and applied a new migration (`AddIdentitySchema`) to create the necessary ASP.NET Core Identity database tables (e.g., `AspNetUsers`, `AspNetRoles`).
			
			
This commit is contained in:
		
							parent
							
								
									60567d7969
								
							
						
					
					
						commit
						b24beb3154
					
				
					 79 changed files with 5246 additions and 12 deletions
				
			
		
							
								
								
									
										333
									
								
								Migrations/20250621230711_AddIdentitySchema.Designer.cs
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								Migrations/20250621230711_AddIdentitySchema.Designer.cs
									
										
									
										generated
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,333 @@ | |||
| // <auto-generated /> | ||||
| using System; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore.Infrastructure; | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||||
| using turf_tasker.Data; | ||||
| 
 | ||||
| #nullable disable | ||||
| 
 | ||||
| namespace turf_tasker.Migrations | ||||
| { | ||||
|     [DbContext(typeof(ApplicationDbContext))] | ||||
|     [Migration("20250621230711_AddIdentitySchema")] | ||||
|     partial class AddIdentitySchema | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         protected override void BuildTargetModel(ModelBuilder modelBuilder) | ||||
|         { | ||||
| #pragma warning disable 612, 618 | ||||
|             modelBuilder.HasAnnotation("ProductVersion", "8.0.6"); | ||||
| 
 | ||||
|             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") | ||||
|                         .HasMaxLength(128) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<string>("ProviderKey") | ||||
|                         .HasMaxLength(128) | ||||
|                         .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") | ||||
|                         .HasMaxLength(128) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<string>("Name") | ||||
|                         .HasMaxLength(128) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<string>("Value") | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.HasKey("UserId", "LoginProvider", "Name"); | ||||
| 
 | ||||
|                     b.ToTable("AspNetUserTokens", (string)null); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("turf_tasker.Models.LawnCareEvent", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("INTEGER"); | ||||
| 
 | ||||
|                     b.Property<decimal?>("AppliedAmount") | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<DateTime>("EventDate") | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<int>("EventType") | ||||
|                         .HasColumnType("INTEGER"); | ||||
| 
 | ||||
|                     b.Property<decimal?>("MowerHeightInches") | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<int?>("MowingPattern") | ||||
|                         .HasColumnType("INTEGER"); | ||||
| 
 | ||||
|                     b.Property<string>("Notes") | ||||
|                         .HasMaxLength(500) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<string>("ProblemObserved") | ||||
|                         .HasMaxLength(250) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<string>("ProductUsed") | ||||
|                         .HasMaxLength(200) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.HasKey("Id"); | ||||
| 
 | ||||
|                     b.ToTable("LawnCareEvents"); | ||||
|                 }); | ||||
| 
 | ||||
|             modelBuilder.Entity("turf_tasker.Models.LawnCareTip", b => | ||||
|                 { | ||||
|                     b.Property<int>("Id") | ||||
|                         .ValueGeneratedOnAdd() | ||||
|                         .HasColumnType("INTEGER"); | ||||
| 
 | ||||
|                     b.Property<int>("Category") | ||||
|                         .HasColumnType("INTEGER"); | ||||
| 
 | ||||
|                     b.Property<string>("Content") | ||||
|                         .IsRequired() | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.Property<string>("Title") | ||||
|                         .IsRequired() | ||||
|                         .HasMaxLength(100) | ||||
|                         .HasColumnType("TEXT"); | ||||
| 
 | ||||
|                     b.HasKey("Id"); | ||||
| 
 | ||||
|                     b.ToTable("LawnCareTips"); | ||||
|                 }); | ||||
| 
 | ||||
|             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 | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Blake Ridgway
						Blake Ridgway