diff --git a/backend/API/BusinessLogic/RecipeLogic.cs b/backend/API/BusinessLogic/RecipeLogic.cs index 687c22f..3ff9987 100644 --- a/backend/API/BusinessLogic/RecipeLogic.cs +++ b/backend/API/BusinessLogic/RecipeLogic.cs @@ -15,9 +15,8 @@ namespace API.BusinessLogic public async Task GetPrefereredRecipes(int userId) { - PrefereredRecipes recipes = await _dbAccess.ReadPrefereredRecipes(userId); - if (recipes == null) { recipes = await _dbAccess.CreateMissingLists(userId); } - if (recipes == null || recipes.Id == 0) { return new ConflictObjectResult(new { message = "Could not find any recipes" }); } + var recipes = await _dbAccess.ReadRecipes(userId); + if (recipes == null || recipes.Count == 0) { return new ConflictObjectResult(new { message = "Could not find any recipes" }); } return new OkObjectResult(recipes); } @@ -62,10 +61,10 @@ namespace API.BusinessLogic public async Task EditRecipe(RecipeDTO recipe, int recipeId, int userId) { - var prefereredRecipes = await _dbAccess.ReadPrefereredRecipes(userId); + var recipes = await _dbAccess.ReadRecipes(userId); var dish = await _dbAccess.ReadRecipe(recipeId); - foreach (var item in prefereredRecipes.Recipes) + foreach (var item in recipes) { if (item.Name == recipe.Name) { diff --git a/backend/API/BusinessLogic/UserLogic.cs b/backend/API/BusinessLogic/UserLogic.cs index c257631..1e3604b 100644 --- a/backend/API/BusinessLogic/UserLogic.cs +++ b/backend/API/BusinessLogic/UserLogic.cs @@ -61,8 +61,7 @@ namespace API.BusinessLogic string salt = Guid.NewGuid().ToString(); string hashedPassword = ComputeHash(userDTO.Password, SHA256.Create(), salt); - PrefereredRecipes recipes = new PrefereredRecipes(); - recipes.Recipes = new List(); + User user = new User { @@ -70,7 +69,7 @@ namespace API.BusinessLogic Email = userDTO.Email, Password = hashedPassword, Salt = salt, - PrefereredRecipes = recipes, + Recipes = new List(), ShoppingList = new List(), }; diff --git a/backend/API/DBAccess/RecipeDBaccess.cs b/backend/API/DBAccess/RecipeDBaccess.cs index 7c276a3..c17589b 100644 --- a/backend/API/DBAccess/RecipeDBaccess.cs +++ b/backend/API/DBAccess/RecipeDBaccess.cs @@ -14,11 +14,11 @@ namespace API.DBAccess _context = context; } - public async Task ReadPrefereredRecipes(int userId) + public async Task> ReadRecipes(int userId) { - var recipes = await _context.Users.Include(u => u.PrefereredRecipes).ThenInclude(p => p.Recipes).FirstOrDefaultAsync(u => u.Id == userId); + var recipes = await _context.Users.Include(p => p.Recipes).FirstOrDefaultAsync(u => u.Id == userId); - return recipes.PrefereredRecipes; + return recipes.Recipes; } public async Task ReadAllRecipe(int prefereredRecipesId) @@ -31,17 +31,6 @@ namespace API.DBAccess return await _context.Recipes.Include(r => r.Ingredients).FirstOrDefaultAsync(r => r.Id == recipeId); } - public async Task CreateMissingLists(int userId) - { - var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId); - user.PrefereredRecipes = new PrefereredRecipes(); - user.PrefereredRecipes.Recipes = new List(); - - _context.SaveChangesAsync(); - - return await ReadPrefereredRecipes(userId); - } - public async Task CreateRecipe(Recipe recipe, int prefereredRecipeId) { var recipes = await _context.PrefereredRecipes.Include(p => p.Recipes).FirstOrDefaultAsync(p => p.Id == prefereredRecipeId); diff --git a/backend/API/Migrations/20250429115336_RecipeModelAdded.cs b/backend/API/Migrations/20250429115336_RecipeModelAdded.cs deleted file mode 100644 index 907b867..0000000 --- a/backend/API/Migrations/20250429115336_RecipeModelAdded.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace API.Migrations -{ - /// - public partial class RecipeModelAdded : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "UserName", - table: "Users", - type: "TEXT", - nullable: false, - oldClrType: typeof(string), - oldType: "longtext"); - - migrationBuilder.AlterColumn( - name: "Salt", - table: "Users", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "longtext", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "RefreshTokenExpireAt", - table: "Users", - type: "TEXT", - nullable: false, - oldClrType: typeof(DateTime), - oldType: "datetime(6)"); - - migrationBuilder.AlterColumn( - name: "RefreshToken", - table: "Users", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "longtext", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Password", - table: "Users", - type: "TEXT", - nullable: false, - oldClrType: typeof(string), - oldType: "longtext"); - - migrationBuilder.AlterColumn( - name: "Email", - table: "Users", - type: "TEXT", - nullable: false, - oldClrType: typeof(string), - oldType: "longtext"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Users", - type: "INTEGER", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("Sqlite:Autoincrement", true) - .OldAnnotation("Sqlite:Autoincrement", true); - - migrationBuilder.AddColumn( - name: "PrefereredRecipesId", - table: "Users", - type: "INTEGER", - nullable: false, - defaultValue: 0); - - migrationBuilder.CreateTable( - name: "PrefereredRecipes", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true) - }, - constraints: table => - { - table.PrimaryKey("PK_PrefereredRecipes", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ShoppingList", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Amount = table.Column(type: "REAL", nullable: false), - Unit = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: false), - Checked = table.Column(type: "INTEGER", nullable: false), - UserId = table.Column(type: "INTEGER", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_ShoppingList", x => x.Id); - table.ForeignKey( - name: "FK_ShoppingList_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "Recipes", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Name = table.Column(type: "TEXT", nullable: false), - Description = table.Column(type: "TEXT", nullable: false), - Directions = table.Column(type: "TEXT", nullable: false), - PrefereredRecipesId = table.Column(type: "INTEGER", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Recipes", x => x.Id); - table.ForeignKey( - name: "FK_Recipes_PrefereredRecipes_PrefereredRecipesId", - column: x => x.PrefereredRecipesId, - principalTable: "PrefereredRecipes", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "Ingredient", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Amount = table.Column(type: "INTEGER", nullable: false), - Unit = table.Column(type: "TEXT", nullable: false), - Element = table.Column(type: "TEXT", nullable: false), - RecipeId = table.Column(type: "INTEGER", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Ingredient", x => x.Id); - table.ForeignKey( - name: "FK_Ingredient_Recipes_RecipeId", - column: x => x.RecipeId, - principalTable: "Recipes", - principalColumn: "Id"); - }); - - migrationBuilder.CreateIndex( - name: "IX_Users_PrefereredRecipesId", - table: "Users", - column: "PrefereredRecipesId"); - - migrationBuilder.CreateIndex( - name: "IX_Ingredient_RecipeId", - table: "Ingredient", - column: "RecipeId"); - - migrationBuilder.CreateIndex( - name: "IX_Recipes_PrefereredRecipesId", - table: "Recipes", - column: "PrefereredRecipesId"); - - migrationBuilder.CreateIndex( - name: "IX_ShoppingList_UserId", - table: "ShoppingList", - column: "UserId"); - - migrationBuilder.AddForeignKey( - name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", - table: "Users", - column: "PrefereredRecipesId", - principalTable: "PrefereredRecipes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", - table: "Users"); - - migrationBuilder.DropTable( - name: "Ingredient"); - - migrationBuilder.DropTable( - name: "ShoppingList"); - - migrationBuilder.DropTable( - name: "Recipes"); - - migrationBuilder.DropTable( - name: "PrefereredRecipes"); - - migrationBuilder.DropIndex( - name: "IX_Users_PrefereredRecipesId", - table: "Users"); - - migrationBuilder.DropColumn( - name: "PrefereredRecipesId", - table: "Users"); - - migrationBuilder.AlterColumn( - name: "UserName", - table: "Users", - type: "longtext", - nullable: false, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Salt", - table: "Users", - type: "longtext", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "RefreshTokenExpireAt", - table: "Users", - type: "datetime(6)", - nullable: false, - oldClrType: typeof(DateTime), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "RefreshToken", - table: "Users", - type: "longtext", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Password", - table: "Users", - type: "longtext", - nullable: false, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Email", - table: "Users", - type: "longtext", - nullable: false, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Users", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "INTEGER") - .Annotation("Sqlite:Autoincrement", true) - .OldAnnotation("Sqlite:Autoincrement", true); - } - } -} diff --git a/backend/API/Migrations/20250429115336_RecipeModelAdded.Designer.cs b/backend/API/Migrations/20250430091216_RecipeModelAdded.Designer.cs similarity index 78% rename from backend/API/Migrations/20250429115336_RecipeModelAdded.Designer.cs rename to backend/API/Migrations/20250430091216_RecipeModelAdded.Designer.cs index 48ed828..fa2ae6d 100644 --- a/backend/API/Migrations/20250429115336_RecipeModelAdded.Designer.cs +++ b/backend/API/Migrations/20250430091216_RecipeModelAdded.Designer.cs @@ -11,34 +11,36 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace API.Migrations { [DbContext(typeof(DBContext))] - [Migration("20250429115336_RecipeModelAdded")] + [Migration("20250430091216_RecipeModelAdded")] partial class RecipeModelAdded { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("API.Models.RecipeModels.Ingredient", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Amount") - .HasColumnType("INTEGER"); + .HasColumnType("int"); - b.Property("Element") + b.Property("Name") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("RecipeId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Unit") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.HasKey("Id"); @@ -51,7 +53,7 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.HasKey("Id"); @@ -62,22 +64,22 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Description") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Directions") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Name") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("PrefereredRecipesId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.HasKey("Id"); @@ -90,24 +92,24 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Amount") - .HasColumnType("REAL"); + .HasColumnType("double"); b.Property("Checked") - .HasColumnType("INTEGER"); + .HasColumnType("tinyint(1)"); b.Property("Name") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Unit") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("UserId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.HasKey("Id"); @@ -120,31 +122,31 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Email") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Password") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("PrefereredRecipesId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("RefreshToken") - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("RefreshTokenExpireAt") - .HasColumnType("TEXT"); + .HasColumnType("datetime(6)"); b.Property("Salt") - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("UserName") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.HasKey("Id"); diff --git a/backend/API/Migrations/20250430091216_RecipeModelAdded.cs b/backend/API/Migrations/20250430091216_RecipeModelAdded.cs new file mode 100644 index 0000000..0602e82 --- /dev/null +++ b/backend/API/Migrations/20250430091216_RecipeModelAdded.cs @@ -0,0 +1,158 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using MySql.EntityFrameworkCore.Metadata; + +#nullable disable + +namespace API.Migrations +{ + /// + public partial class RecipeModelAdded : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PrefereredRecipesId", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateTable( + name: "PrefereredRecipes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn) + }, + constraints: table => + { + table.PrimaryKey("PK_PrefereredRecipes", x => x.Id); + }) + .Annotation("MySQL:Charset", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ShoppingList", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn), + Amount = table.Column(type: "double", nullable: false), + Unit = table.Column(type: "longtext", nullable: false), + Name = table.Column(type: "longtext", nullable: false), + Checked = table.Column(type: "tinyint(1)", nullable: false), + UserId = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ShoppingList", x => x.Id); + table.ForeignKey( + name: "FK_ShoppingList_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id"); + }) + .Annotation("MySQL:Charset", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Recipes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "longtext", nullable: false), + Description = table.Column(type: "longtext", nullable: false), + Directions = table.Column(type: "longtext", nullable: false), + PrefereredRecipesId = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Recipes", x => x.Id); + table.ForeignKey( + name: "FK_Recipes_PrefereredRecipes_PrefereredRecipesId", + column: x => x.PrefereredRecipesId, + principalTable: "PrefereredRecipes", + principalColumn: "Id"); + }) + .Annotation("MySQL:Charset", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Ingredient", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn), + Amount = table.Column(type: "int", nullable: false), + Unit = table.Column(type: "longtext", nullable: false), + Name = table.Column(type: "longtext", nullable: false), + RecipeId = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Ingredient", x => x.Id); + table.ForeignKey( + name: "FK_Ingredient_Recipes_RecipeId", + column: x => x.RecipeId, + principalTable: "Recipes", + principalColumn: "Id"); + }) + .Annotation("MySQL:Charset", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Users_PrefereredRecipesId", + table: "Users", + column: "PrefereredRecipesId"); + + migrationBuilder.CreateIndex( + name: "IX_Ingredient_RecipeId", + table: "Ingredient", + column: "RecipeId"); + + migrationBuilder.CreateIndex( + name: "IX_Recipes_PrefereredRecipesId", + table: "Recipes", + column: "PrefereredRecipesId"); + + migrationBuilder.CreateIndex( + name: "IX_ShoppingList_UserId", + table: "ShoppingList", + column: "UserId"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users", + column: "PrefereredRecipesId", + principalTable: "PrefereredRecipes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users"); + + migrationBuilder.DropTable( + name: "Ingredient"); + + migrationBuilder.DropTable( + name: "ShoppingList"); + + migrationBuilder.DropTable( + name: "Recipes"); + + migrationBuilder.DropTable( + name: "PrefereredRecipes"); + + migrationBuilder.DropIndex( + name: "IX_Users_PrefereredRecipesId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "PrefereredRecipesId", + table: "Users"); + } + } +} diff --git a/backend/API/Migrations/20250430092324_PreferedRecipesisnullable.Designer.cs b/backend/API/Migrations/20250430092324_PreferedRecipesisnullable.Designer.cs new file mode 100644 index 0000000..8e47348 --- /dev/null +++ b/backend/API/Migrations/20250430092324_PreferedRecipesisnullable.Designer.cs @@ -0,0 +1,205 @@ +// +using System; +using API.DBAccess; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace API.Migrations +{ + [DbContext(typeof(DBContext))] + [Migration("20250430092324_PreferedRecipesisnullable")] + partial class PreferedRecipesisnullable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("API.Models.RecipeModels.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RecipeId"); + + b.ToTable("Ingredient"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.PrefereredRecipes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PrefereredRecipes"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Recipe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Directions") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PrefereredRecipesId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PrefereredRecipesId"); + + b.ToTable("Recipes"); + }); + + modelBuilder.Entity("API.Models.ShoppingListModels.ShoppingList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("Checked") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ShoppingList"); + }); + + modelBuilder.Entity("API.Models.UserModels.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PrefereredRecipesId") + .HasColumnType("int"); + + b.Property("RefreshToken") + .HasColumnType("longtext"); + + b.Property("RefreshTokenExpireAt") + .HasColumnType("datetime(6)"); + + b.Property("Salt") + .HasColumnType("longtext"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("PrefereredRecipesId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Ingredient", b => + { + b.HasOne("API.Models.RecipeModels.Recipe", null) + .WithMany("Ingredients") + .HasForeignKey("RecipeId"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Recipe", b => + { + b.HasOne("API.Models.RecipeModels.PrefereredRecipes", null) + .WithMany("Recipes") + .HasForeignKey("PrefereredRecipesId"); + }); + + modelBuilder.Entity("API.Models.ShoppingListModels.ShoppingList", b => + { + b.HasOne("API.Models.UserModels.User", null) + .WithMany("ShoppingList") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("API.Models.UserModels.User", b => + { + b.HasOne("API.Models.RecipeModels.PrefereredRecipes", "PrefereredRecipes") + .WithMany() + .HasForeignKey("PrefereredRecipesId"); + + b.Navigation("PrefereredRecipes"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.PrefereredRecipes", b => + { + b.Navigation("Recipes"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Recipe", b => + { + b.Navigation("Ingredients"); + }); + + modelBuilder.Entity("API.Models.UserModels.User", b => + { + b.Navigation("ShoppingList"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/API/Migrations/20250430092324_PreferedRecipesisnullable.cs b/backend/API/Migrations/20250430092324_PreferedRecipesisnullable.cs new file mode 100644 index 0000000..9da7a86 --- /dev/null +++ b/backend/API/Migrations/20250430092324_PreferedRecipesisnullable.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace API.Migrations +{ + /// + public partial class PreferedRecipesisnullable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users"); + + migrationBuilder.AlterColumn( + name: "PrefereredRecipesId", + table: "Users", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users", + column: "PrefereredRecipesId", + principalTable: "PrefereredRecipes", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users"); + + migrationBuilder.AlterColumn( + name: "PrefereredRecipesId", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users", + column: "PrefereredRecipesId", + principalTable: "PrefereredRecipes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/backend/API/Migrations/20250430093427_RemovedPreferedRecipes.Designer.cs b/backend/API/Migrations/20250430093427_RemovedPreferedRecipes.Designer.cs new file mode 100644 index 0000000..1ea1ef4 --- /dev/null +++ b/backend/API/Migrations/20250430093427_RemovedPreferedRecipes.Designer.cs @@ -0,0 +1,202 @@ +// +using System; +using API.DBAccess; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace API.Migrations +{ + [DbContext(typeof(DBContext))] + [Migration("20250430093427_RemovedPreferedRecipes")] + partial class RemovedPreferedRecipes + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("API.Models.RecipeModels.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RecipeId"); + + b.ToTable("Ingredient"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.PrefereredRecipes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PrefereredRecipes"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Recipe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Directions") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PrefereredRecipesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PrefereredRecipesId"); + + b.HasIndex("UserId"); + + b.ToTable("Recipes"); + }); + + modelBuilder.Entity("API.Models.ShoppingListModels.ShoppingList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("Checked") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ShoppingList"); + }); + + modelBuilder.Entity("API.Models.UserModels.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RefreshToken") + .HasColumnType("longtext"); + + b.Property("RefreshTokenExpireAt") + .HasColumnType("datetime(6)"); + + b.Property("Salt") + .HasColumnType("longtext"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Ingredient", b => + { + b.HasOne("API.Models.RecipeModels.Recipe", null) + .WithMany("Ingredients") + .HasForeignKey("RecipeId"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Recipe", b => + { + b.HasOne("API.Models.RecipeModels.PrefereredRecipes", null) + .WithMany("Recipes") + .HasForeignKey("PrefereredRecipesId"); + + b.HasOne("API.Models.UserModels.User", null) + .WithMany("Recipes") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("API.Models.ShoppingListModels.ShoppingList", b => + { + b.HasOne("API.Models.UserModels.User", null) + .WithMany("ShoppingList") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.PrefereredRecipes", b => + { + b.Navigation("Recipes"); + }); + + modelBuilder.Entity("API.Models.RecipeModels.Recipe", b => + { + b.Navigation("Ingredients"); + }); + + modelBuilder.Entity("API.Models.UserModels.User", b => + { + b.Navigation("Recipes"); + + b.Navigation("ShoppingList"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/API/Migrations/20250430093427_RemovedPreferedRecipes.cs b/backend/API/Migrations/20250430093427_RemovedPreferedRecipes.cs new file mode 100644 index 0000000..247aca1 --- /dev/null +++ b/backend/API/Migrations/20250430093427_RemovedPreferedRecipes.cs @@ -0,0 +1,78 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace API.Migrations +{ + /// + public partial class RemovedPreferedRecipes : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Users_PrefereredRecipesId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "PrefereredRecipesId", + table: "Users"); + + migrationBuilder.AddColumn( + name: "UserId", + table: "Recipes", + type: "int", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Recipes_UserId", + table: "Recipes", + column: "UserId"); + + migrationBuilder.AddForeignKey( + name: "FK_Recipes_Users_UserId", + table: "Recipes", + column: "UserId", + principalTable: "Users", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Recipes_Users_UserId", + table: "Recipes"); + + migrationBuilder.DropIndex( + name: "IX_Recipes_UserId", + table: "Recipes"); + + migrationBuilder.DropColumn( + name: "UserId", + table: "Recipes"); + + migrationBuilder.AddColumn( + name: "PrefereredRecipesId", + table: "Users", + type: "int", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Users_PrefereredRecipesId", + table: "Users", + column: "PrefereredRecipesId"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_PrefereredRecipes_PrefereredRecipesId", + table: "Users", + column: "PrefereredRecipesId", + principalTable: "PrefereredRecipes", + principalColumn: "Id"); + } + } +} diff --git a/backend/API/Migrations/DBContextModelSnapshot.cs b/backend/API/Migrations/DBContextModelSnapshot.cs index 1366ca7..61fb5f3 100644 --- a/backend/API/Migrations/DBContextModelSnapshot.cs +++ b/backend/API/Migrations/DBContextModelSnapshot.cs @@ -15,27 +15,29 @@ namespace API.Migrations protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("API.Models.RecipeModels.Ingredient", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Amount") - .HasColumnType("INTEGER"); + .HasColumnType("int"); - b.Property("Element") + b.Property("Name") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("RecipeId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Unit") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.HasKey("Id"); @@ -48,7 +50,7 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.HasKey("Id"); @@ -59,27 +61,32 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Description") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Directions") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Name") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("PrefereredRecipesId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); b.HasKey("Id"); b.HasIndex("PrefereredRecipesId"); + b.HasIndex("UserId"); + b.ToTable("Recipes"); }); @@ -87,24 +94,24 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Amount") - .HasColumnType("REAL"); + .HasColumnType("double"); b.Property("Checked") - .HasColumnType("INTEGER"); + .HasColumnType("tinyint(1)"); b.Property("Name") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Unit") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("UserId") - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.HasKey("Id"); @@ -117,36 +124,31 @@ namespace API.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("int"); b.Property("Email") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("Password") .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PrefereredRecipesId") - .HasColumnType("INTEGER"); + .HasColumnType("longtext"); b.Property("RefreshToken") - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("RefreshTokenExpireAt") - .HasColumnType("TEXT"); + .HasColumnType("datetime(6)"); b.Property("Salt") - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.Property("UserName") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("longtext"); b.HasKey("Id"); - b.HasIndex("PrefereredRecipesId"); - b.ToTable("Users"); }); @@ -162,6 +164,10 @@ namespace API.Migrations b.HasOne("API.Models.RecipeModels.PrefereredRecipes", null) .WithMany("Recipes") .HasForeignKey("PrefereredRecipesId"); + + b.HasOne("API.Models.UserModels.User", null) + .WithMany("Recipes") + .HasForeignKey("UserId"); }); modelBuilder.Entity("API.Models.ShoppingListModels.ShoppingList", b => @@ -171,17 +177,6 @@ namespace API.Migrations .HasForeignKey("UserId"); }); - modelBuilder.Entity("API.Models.UserModels.User", b => - { - b.HasOne("API.Models.RecipeModels.PrefereredRecipes", "PrefereredRecipes") - .WithMany() - .HasForeignKey("PrefereredRecipesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("PrefereredRecipes"); - }); - modelBuilder.Entity("API.Models.RecipeModels.PrefereredRecipes", b => { b.Navigation("Recipes"); @@ -194,6 +189,8 @@ namespace API.Migrations modelBuilder.Entity("API.Models.UserModels.User", b => { + b.Navigation("Recipes"); + b.Navigation("ShoppingList"); }); #pragma warning restore 612, 618 diff --git a/backend/API/Models/UserModels/User.cs b/backend/API/Models/UserModels/User.cs index abca1fa..3b13e51 100644 --- a/backend/API/Models/UserModels/User.cs +++ b/backend/API/Models/UserModels/User.cs @@ -19,7 +19,7 @@ namespace API.Models.UserModels public DateTime RefreshTokenExpireAt { get; set; } - public PrefereredRecipes PrefereredRecipes { get; set; } + public List Recipes { get; set; } public List ShoppingList { get; set; } }