From a03477b7b6d37a38b417ce184208df769fdc5dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Astijus=20Arimavi=C4=8Dius?= Date: Sun, 5 Nov 2023 16:36:53 +0200 Subject: [PATCH] Make migrations for user and jwt --- src/API/API.csproj | 2 + src/API/Extensions/ServiceExtensions.cs | 30 ++ .../ApplicationContextModelSnapshot.cs | 181 -------- src/API/Program.cs | 6 + src/API/appsettings.json | 6 +- ...0230929174824_InitialMigration.Designer.cs | 2 +- .../20230929174824_InitialMigration.cs | 2 +- ...0231009095307_MakeNoteNullable.Designer.cs | 2 +- .../20231009095307_MakeNoteNullable.cs | 2 +- ...keExerciseInstructionsNullable.Designer.cs | 2 +- ...122030_MakeExerciseInstructionsNullable.cs | 2 +- .../20231105143417_AddUser.Designer.cs | 436 ++++++++++++++++++ .../Migrations/20231105143417_AddUser.cs | 225 +++++++++ .../ApplicationContextModelSnapshot.cs | 433 +++++++++++++++++ src/Repository/Models/ApplicationContext.cs | 5 +- src/Repository/Models/User.cs | 9 + src/Repository/Repository.csproj | 2 + 17 files changed, 1157 insertions(+), 190 deletions(-) delete mode 100644 src/API/Migrations/ApplicationContextModelSnapshot.cs rename src/{API => Repository}/Migrations/20230929174824_InitialMigration.Designer.cs (99%) rename src/{API => Repository}/Migrations/20230929174824_InitialMigration.cs (99%) rename src/{API => Repository}/Migrations/20231009095307_MakeNoteNullable.Designer.cs (99%) rename src/{API => Repository}/Migrations/20231009095307_MakeNoteNullable.cs (97%) rename src/{API => Repository}/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs (99%) rename src/{API => Repository}/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs (96%) create mode 100644 src/Repository/Migrations/20231105143417_AddUser.Designer.cs create mode 100644 src/Repository/Migrations/20231105143417_AddUser.cs create mode 100644 src/Repository/Migrations/ApplicationContextModelSnapshot.cs create mode 100644 src/Repository/Models/User.cs diff --git a/src/API/API.csproj b/src/API/API.csproj index dc19e4a..bdc5849 100644 --- a/src/API/API.csproj +++ b/src/API/API.csproj @@ -21,6 +21,8 @@ + + diff --git a/src/API/Extensions/ServiceExtensions.cs b/src/API/Extensions/ServiceExtensions.cs index 1900517..87109c4 100644 --- a/src/API/Extensions/ServiceExtensions.cs +++ b/src/API/Extensions/ServiceExtensions.cs @@ -1,6 +1,10 @@ using System.Reflection; +using System.Text; using API.Filters; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json.Converters; using Repository; using Repository.Interfaces; @@ -50,5 +54,31 @@ public static void ConfigureSwagger(this IServiceCollection services) s.IncludeXmlComments(xmlPath); }); } + + public static void ConfigureIdentity(this IServiceCollection services) + { + services.AddIdentity() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); + } + + public static void ConfigureAuthenticationAndAuthorization(this IServiceCollection services, IConfiguration configuration) + { + services.AddAuthentication(opt => + { + opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + opt.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(opt => + { + opt.TokenValidationParameters.ValidAudience = configuration["Jwt:ValidAudience"]; + opt.TokenValidationParameters.ValidIssuer = configuration["Jwt:ValidIssuer"]; + opt.TokenValidationParameters.IssuerSigningKey = + new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Secret"])); + }); + + services.AddAuthorization(); + } } } diff --git a/src/API/Migrations/ApplicationContextModelSnapshot.cs b/src/API/Migrations/ApplicationContextModelSnapshot.cs deleted file mode 100644 index 0998e9e..0000000 --- a/src/API/Migrations/ApplicationContextModelSnapshot.cs +++ /dev/null @@ -1,181 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Repository.Models; - -#nullable disable - -namespace API.Migrations -{ - [DbContext(typeof(ApplicationContext))] - partial class ApplicationContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("API.Models.Exercise", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("ExerciseId"); - - b.Property("EquipmentType") - .HasColumnType("int"); - - b.Property("Instructions") - .HasColumnType("nvarchar(max)"); - - b.Property("MuscleGroup") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Id"); - - b.ToTable("Exercises"); - }); - - modelBuilder.Entity("API.Models.Workout", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("WorkoutId"); - - b.Property("End") - .HasColumnType("datetime2"); - - b.Property("IsTemplate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(60) - .HasColumnType("nvarchar(60)"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Start") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.ToTable("Workouts"); - }); - - modelBuilder.Entity("API.Models.WorkoutExercise", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("WorkoutExerciseId"); - - b.Property("ExerciseId") - .HasColumnType("uniqueidentifier"); - - b.Property("Order") - .HasColumnType("int"); - - b.Property("WorkoutId") - .HasColumnType("uniqueidentifier"); - - b.HasKey("Id"); - - b.HasIndex("ExerciseId"); - - b.HasIndex("WorkoutId"); - - b.ToTable("workout_exercise"); - }); - - modelBuilder.Entity("API.Models.WorkoutExerciseSet", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("WorkoutExerciseSetId"); - - b.Property("MeasurementType") - .HasColumnType("int"); - - b.Property("Order") - .HasColumnType("int"); - - b.Property("Reps") - .HasColumnType("int"); - - b.Property("Weight") - .HasColumnType("decimal(18, 2)"); - - b.Property("WorkoutExerciseId") - .HasColumnType("uniqueidentifier"); - - b.HasKey("Id"); - - b.HasIndex("WorkoutExerciseId"); - - b.ToTable("workout_exercise_set"); - }); - - modelBuilder.Entity("API.Models.WorkoutExercise", b => - { - b.HasOne("API.Models.Exercise", "Exercise") - .WithMany("WorkoutExercises") - .HasForeignKey("ExerciseId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("API.Models.Workout", "Workout") - .WithMany("Exercises") - .HasForeignKey("WorkoutId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Exercise"); - - b.Navigation("Workout"); - }); - - modelBuilder.Entity("API.Models.WorkoutExerciseSet", b => - { - b.HasOne("API.Models.WorkoutExercise", "WorkoutExercise") - .WithMany("Sets") - .HasForeignKey("WorkoutExerciseId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("WorkoutExercise"); - }); - - modelBuilder.Entity("API.Models.Exercise", b => - { - b.Navigation("WorkoutExercises"); - }); - - modelBuilder.Entity("API.Models.Workout", b => - { - b.Navigation("Exercises"); - }); - - modelBuilder.Entity("API.Models.WorkoutExercise", b => - { - b.Navigation("Sets"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/API/Program.cs b/src/API/Program.cs index f2586cf..b81e878 100644 --- a/src/API/Program.cs +++ b/src/API/Program.cs @@ -1,7 +1,10 @@ +using System.IdentityModel.Tokens.Jwt; using API.Extensions; using Microsoft.AspNetCore.Mvc; using Repository.Models.Mapping; +JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + var builder = WebApplication.CreateBuilder(args); builder.Services.Configure(opt => @@ -18,6 +21,8 @@ builder.Services.ConfigureControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.ConfigureSwagger(); +builder.Services.ConfigureIdentity(); +builder.Services.ConfigureAuthenticationAndAuthorization(builder.Configuration); var app = builder.Build(); @@ -29,6 +34,7 @@ app.UseHttpsRedirection(); +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/src/API/appsettings.json b/src/API/appsettings.json index 10f68b8..138e2be 100644 --- a/src/API/appsettings.json +++ b/src/API/appsettings.json @@ -5,5 +5,9 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Jwt": { + "ValidIssuer": "WorkoutTrackerAPI", + "ValidAudience": "WorkoutTrackerWebUI" + } } diff --git a/src/API/Migrations/20230929174824_InitialMigration.Designer.cs b/src/Repository/Migrations/20230929174824_InitialMigration.Designer.cs similarity index 99% rename from src/API/Migrations/20230929174824_InitialMigration.Designer.cs rename to src/Repository/Migrations/20230929174824_InitialMigration.Designer.cs index 3e0ed58..8b98bde 100644 --- a/src/API/Migrations/20230929174824_InitialMigration.Designer.cs +++ b/src/Repository/Migrations/20230929174824_InitialMigration.Designer.cs @@ -9,7 +9,7 @@ #nullable disable -namespace API.Migrations +namespace Repository.Migrations { [DbContext(typeof(ApplicationContext))] [Migration("20230929174824_InitialMigration")] diff --git a/src/API/Migrations/20230929174824_InitialMigration.cs b/src/Repository/Migrations/20230929174824_InitialMigration.cs similarity index 99% rename from src/API/Migrations/20230929174824_InitialMigration.cs rename to src/Repository/Migrations/20230929174824_InitialMigration.cs index 1cc1560..0fcea02 100644 --- a/src/API/Migrations/20230929174824_InitialMigration.cs +++ b/src/Repository/Migrations/20230929174824_InitialMigration.cs @@ -3,7 +3,7 @@ #nullable disable -namespace API.Migrations +namespace Repository.Migrations { /// public partial class InitialMigration : Migration diff --git a/src/API/Migrations/20231009095307_MakeNoteNullable.Designer.cs b/src/Repository/Migrations/20231009095307_MakeNoteNullable.Designer.cs similarity index 99% rename from src/API/Migrations/20231009095307_MakeNoteNullable.Designer.cs rename to src/Repository/Migrations/20231009095307_MakeNoteNullable.Designer.cs index d0d13b1..fecfc8b 100644 --- a/src/API/Migrations/20231009095307_MakeNoteNullable.Designer.cs +++ b/src/Repository/Migrations/20231009095307_MakeNoteNullable.Designer.cs @@ -9,7 +9,7 @@ #nullable disable -namespace API.Migrations +namespace Repository.Migrations { [DbContext(typeof(ApplicationContext))] [Migration("20231009095307_MakeNoteNullable")] diff --git a/src/API/Migrations/20231009095307_MakeNoteNullable.cs b/src/Repository/Migrations/20231009095307_MakeNoteNullable.cs similarity index 97% rename from src/API/Migrations/20231009095307_MakeNoteNullable.cs rename to src/Repository/Migrations/20231009095307_MakeNoteNullable.cs index 9d26c3b..7a2e3a4 100644 --- a/src/API/Migrations/20231009095307_MakeNoteNullable.cs +++ b/src/Repository/Migrations/20231009095307_MakeNoteNullable.cs @@ -2,7 +2,7 @@ #nullable disable -namespace API.Migrations +namespace Repository.Migrations { /// public partial class MakeNoteNullable : Migration diff --git a/src/API/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs b/src/Repository/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs similarity index 99% rename from src/API/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs rename to src/Repository/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs index a77dea2..6c4445c 100644 --- a/src/API/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs +++ b/src/Repository/Migrations/20231009122030_MakeExerciseInstructionsNullable.Designer.cs @@ -9,7 +9,7 @@ #nullable disable -namespace API.Migrations +namespace Repository.Migrations { [DbContext(typeof(ApplicationContext))] [Migration("20231009122030_MakeExerciseInstructionsNullable")] diff --git a/src/API/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs b/src/Repository/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs similarity index 96% rename from src/API/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs rename to src/Repository/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs index a529ea8..c650245 100644 --- a/src/API/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs +++ b/src/Repository/Migrations/20231009122030_MakeExerciseInstructionsNullable.cs @@ -2,7 +2,7 @@ #nullable disable -namespace API.Migrations +namespace Repository.Migrations { /// public partial class MakeExerciseInstructionsNullable : Migration diff --git a/src/Repository/Migrations/20231105143417_AddUser.Designer.cs b/src/Repository/Migrations/20231105143417_AddUser.Designer.cs new file mode 100644 index 0000000..d6ea11a --- /dev/null +++ b/src/Repository/Migrations/20231105143417_AddUser.Designer.cs @@ -0,0 +1,436 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Repository.Models; + +#nullable disable + +namespace Repository.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20231105143417_AddUser")] + partial class AddUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Repository.Models.Exercise", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("ExerciseId"); + + b.Property("EquipmentType") + .HasColumnType("int"); + + b.Property("Instructions") + .HasColumnType("nvarchar(max)"); + + b.Property("MuscleGroup") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Exercises"); + }); + + modelBuilder.Entity("Repository.Models.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("ForceRelogin") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Repository.Models.Workout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("WorkoutId"); + + b.Property("End") + .HasColumnType("datetime2"); + + b.Property("IsTemplate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Start") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Workouts"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExercise", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("WorkoutExerciseId"); + + b.Property("ExerciseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("WorkoutId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId"); + + b.HasIndex("WorkoutId"); + + b.ToTable("workout_exercise"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExerciseSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("WorkoutExerciseSetId"); + + b.Property("MeasurementType") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Reps") + .HasColumnType("int"); + + b.Property("Weight") + .HasColumnType("decimal(18, 2)"); + + b.Property("WorkoutExerciseId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("WorkoutExerciseId"); + + b.ToTable("workout_exercise_set"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExercise", b => + { + b.HasOne("Repository.Models.Exercise", "Exercise") + .WithMany("WorkoutExercises") + .HasForeignKey("ExerciseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Repository.Models.Workout", "Workout") + .WithMany("Exercises") + .HasForeignKey("WorkoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Exercise"); + + b.Navigation("Workout"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExerciseSet", b => + { + b.HasOne("Repository.Models.WorkoutExercise", "WorkoutExercise") + .WithMany("Sets") + .HasForeignKey("WorkoutExerciseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WorkoutExercise"); + }); + + modelBuilder.Entity("Repository.Models.Exercise", b => + { + b.Navigation("WorkoutExercises"); + }); + + modelBuilder.Entity("Repository.Models.Workout", b => + { + b.Navigation("Exercises"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExercise", b => + { + b.Navigation("Sets"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Repository/Migrations/20231105143417_AddUser.cs b/src/Repository/Migrations/20231105143417_AddUser.cs new file mode 100644 index 0000000..198aab2 --- /dev/null +++ b/src/Repository/Migrations/20231105143417_AddUser.cs @@ -0,0 +1,225 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Repository.Migrations +{ + /// + public partial class AddUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + ForceRelogin = table.Column(type: "bit", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", 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(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", 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(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", 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(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", 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(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/src/Repository/Migrations/ApplicationContextModelSnapshot.cs b/src/Repository/Migrations/ApplicationContextModelSnapshot.cs new file mode 100644 index 0000000..59c3073 --- /dev/null +++ b/src/Repository/Migrations/ApplicationContextModelSnapshot.cs @@ -0,0 +1,433 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Repository.Models; + +#nullable disable + +namespace Repository.Migrations +{ + [DbContext(typeof(ApplicationContext))] + partial class ApplicationContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Repository.Models.Exercise", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("ExerciseId"); + + b.Property("EquipmentType") + .HasColumnType("int"); + + b.Property("Instructions") + .HasColumnType("nvarchar(max)"); + + b.Property("MuscleGroup") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Exercises"); + }); + + modelBuilder.Entity("Repository.Models.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("ForceRelogin") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Repository.Models.Workout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("WorkoutId"); + + b.Property("End") + .HasColumnType("datetime2"); + + b.Property("IsTemplate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Start") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Workouts"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExercise", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("WorkoutExerciseId"); + + b.Property("ExerciseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("WorkoutId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId"); + + b.HasIndex("WorkoutId"); + + b.ToTable("workout_exercise"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExerciseSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("WorkoutExerciseSetId"); + + b.Property("MeasurementType") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Reps") + .HasColumnType("int"); + + b.Property("Weight") + .HasColumnType("decimal(18, 2)"); + + b.Property("WorkoutExerciseId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("WorkoutExerciseId"); + + b.ToTable("workout_exercise_set"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Repository.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExercise", b => + { + b.HasOne("Repository.Models.Exercise", "Exercise") + .WithMany("WorkoutExercises") + .HasForeignKey("ExerciseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Repository.Models.Workout", "Workout") + .WithMany("Exercises") + .HasForeignKey("WorkoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Exercise"); + + b.Navigation("Workout"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExerciseSet", b => + { + b.HasOne("Repository.Models.WorkoutExercise", "WorkoutExercise") + .WithMany("Sets") + .HasForeignKey("WorkoutExerciseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WorkoutExercise"); + }); + + modelBuilder.Entity("Repository.Models.Exercise", b => + { + b.Navigation("WorkoutExercises"); + }); + + modelBuilder.Entity("Repository.Models.Workout", b => + { + b.Navigation("Exercises"); + }); + + modelBuilder.Entity("Repository.Models.WorkoutExercise", b => + { + b.Navigation("Sets"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Repository/Models/ApplicationContext.cs b/src/Repository/Models/ApplicationContext.cs index b8fb62b..2d0f3f0 100644 --- a/src/Repository/Models/ApplicationContext.cs +++ b/src/Repository/Models/ApplicationContext.cs @@ -1,8 +1,9 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; namespace Repository.Models { - public class ApplicationContext : DbContext + public class ApplicationContext : IdentityDbContext { public ApplicationContext(DbContextOptions options) : base(options) diff --git a/src/Repository/Models/User.cs b/src/Repository/Models/User.cs new file mode 100644 index 0000000..a24271f --- /dev/null +++ b/src/Repository/Models/User.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Identity; + +namespace Repository.Models +{ + public class User : IdentityUser + { + public bool ForceRelogin { get; set; } + } +} diff --git a/src/Repository/Repository.csproj b/src/Repository/Repository.csproj index c06917d..ec852d4 100644 --- a/src/Repository/Repository.csproj +++ b/src/Repository/Repository.csproj @@ -8,7 +8,9 @@ + +