summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHombreLaser <sebastian-440@live.com>2022-11-06 02:10:44 -0600
committerHombreLaser <sebastian-440@live.com>2022-11-06 02:10:44 -0600
commit08819c6738a4f82ccf07ae5ed60835b087f7bb34 (patch)
tree9c0c77626587136d41002769fb5a030e1be2f5b8
parentf060c4f88f635af3295ea7652cbbbd08dbf1c6cf (diff)
Añadidos grupos y usuarios
-rw-r--r--Controllers/GroupsController.cs24
-rw-r--r--Controllers/UserAccountsController.cs24
-rw-r--r--LibraryAPI.csproj3
-rw-r--r--Migrations/20221106035140_AddUser.Designer.cs132
-rw-r--r--Migrations/20221106035140_AddUser.cs146
-rw-r--r--Migrations/20221106041635_AddGroup.Designer.cs179
-rw-r--r--Migrations/20221106041635_AddGroup.cs64
-rw-r--r--Migrations/20221106055650_FixGroupModel.Designer.cs179
-rw-r--r--Migrations/20221106055650_FixGroupModel.cs19
-rw-r--r--Migrations/20221106061015_ConfigureManyToMany.Designer.cs213
-rw-r--r--Migrations/20221106061015_ConfigureManyToMany.cs47
-rw-r--r--Migrations/20221106062230_AddJoinTableReferences.Designer.cs193
-rw-r--r--Migrations/20221106062230_AddJoinTableReferences.cs47
-rw-r--r--Migrations/20221106062917_AddJoinTableId.Designer.cs196
-rw-r--r--Migrations/20221106062917_AddJoinTableId.cs26
-rw-r--r--Migrations/20221106063041_AddJoinTablePrimaryKey.Designer.cs196
-rw-r--r--Migrations/20221106063041_AddJoinTablePrimaryKey.cs19
-rw-r--r--Migrations/20221106063220_DeleteJoinTableId.Designer.cs193
-rw-r--r--Migrations/20221106063220_DeleteJoinTableId.cs26
-rw-r--r--Migrations/20221106063641_AddNullableFields.Designer.cs193
-rw-r--r--Migrations/20221106063641_AddNullableFields.cs19
-rw-r--r--Migrations/LibraryContextModelSnapshot.cs94
-rw-r--r--Models/Book.cs2
-rw-r--r--Models/Group.cs12
-rw-r--r--Models/GroupUserAccount.cs10
-rw-r--r--Models/LibraryContext.cs9
-rw-r--r--Models/UserAccount.cs30
-rw-r--r--Program.cs23
-rw-r--r--Services/LoggerService.cs18
-rw-r--r--Validators/NameAttribute.cs20
30 files changed, 2337 insertions, 19 deletions
diff --git a/Controllers/GroupsController.cs b/Controllers/GroupsController.cs
new file mode 100644
index 0000000..f81cc56
--- /dev/null
+++ b/Controllers/GroupsController.cs
@@ -0,0 +1,24 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using LibraryAPI.Models;
+using LibraryAPI.Filters;
+
+namespace LibraryAPI.Controllers {
+ [Route("api/groups")]
+ [ApiController]
+ public class GroupsController : ControllerBase {
+ private readonly LibraryContext _context;
+
+ public GroupsController(LibraryContext context) {
+ _context = context;
+ }
+
+ [HttpPost]
+ public async Task<ActionResult> PostGroup(Group g) {
+ _context.Add(g);
+ await _context.SaveChangesAsync();
+
+ return Ok();
+ }
+ }
+}
diff --git a/Controllers/UserAccountsController.cs b/Controllers/UserAccountsController.cs
new file mode 100644
index 0000000..d93ad31
--- /dev/null
+++ b/Controllers/UserAccountsController.cs
@@ -0,0 +1,24 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using LibraryAPI.Models;
+using LibraryAPI.Filters;
+
+namespace LibraryAPI.Controllers {
+ [Route("api/users")]
+ [ApiController]
+ public class UserAccountsController : ControllerBase {
+ private readonly LibraryContext _context;
+
+ public UserAccountsController(LibraryContext context) {
+ _context = context;
+ }
+
+ [HttpPost("signup")]
+ public async Task<ActionResult> PostUserAccount(UserAccount user) {
+ _context.Add(user);
+ await _context.SaveChangesAsync();
+
+ return Ok();
+ }
+ }
+}
diff --git a/LibraryAPI.csproj b/LibraryAPI.csproj
index 335e82a..42a0ec5 100644
--- a/LibraryAPI.csproj
+++ b/LibraryAPI.csproj
@@ -7,6 +7,9 @@
</PropertyGroup>
<ItemGroup>
+ <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
+ <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.10" />
+ <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.9">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
diff --git a/Migrations/20221106035140_AddUser.Designer.cs b/Migrations/20221106035140_AddUser.Designer.cs
new file mode 100644
index 0000000..5144011
--- /dev/null
+++ b/Migrations/20221106035140_AddUser.Designer.cs
@@ -0,0 +1,132 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106035140_AddUser")]
+ partial class AddUser
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106035140_AddUser.cs b/Migrations/20221106035140_AddUser.cs
new file mode 100644
index 0000000..de69f56
--- /dev/null
+++ b/Migrations/20221106035140_AddUser.cs
@@ -0,0 +1,146 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class AddUser : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn<string>(
+ name: "Title",
+ table: "Books",
+ type: "character varying(128)",
+ maxLength: 128,
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "text",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "ISBN",
+ table: "Books",
+ type: "text",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "text",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string[]>(
+ name: "Genres",
+ table: "Books",
+ type: "text[]",
+ nullable: false,
+ defaultValue: new string[0],
+ oldClrType: typeof(string[]),
+ oldType: "text[]",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string[]>(
+ name: "languages",
+ table: "Authors",
+ type: "text[]",
+ nullable: false,
+ defaultValue: new string[0],
+ oldClrType: typeof(string[]),
+ oldType: "text[]",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "Name",
+ table: "Authors",
+ type: "character varying(64)",
+ maxLength: 64,
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "text",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "Country",
+ table: "Authors",
+ type: "text",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "text",
+ oldNullable: true);
+
+ migrationBuilder.CreateTable(
+ name: "Users",
+ columns: table => new
+ {
+ Id = table.Column<long>(type: "bigint", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ Email = table.Column<string>(type: "text", nullable: false),
+ Password = table.Column<string>(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Users", x => x.Id);
+ });
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Users");
+
+ migrationBuilder.AlterColumn<string>(
+ name: "Title",
+ table: "Books",
+ type: "text",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "character varying(128)",
+ oldMaxLength: 128);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "ISBN",
+ table: "Books",
+ type: "text",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "text");
+
+ migrationBuilder.AlterColumn<string[]>(
+ name: "Genres",
+ table: "Books",
+ type: "text[]",
+ nullable: true,
+ oldClrType: typeof(string[]),
+ oldType: "text[]");
+
+ migrationBuilder.AlterColumn<string[]>(
+ name: "languages",
+ table: "Authors",
+ type: "text[]",
+ nullable: true,
+ oldClrType: typeof(string[]),
+ oldType: "text[]");
+
+ migrationBuilder.AlterColumn<string>(
+ name: "Name",
+ table: "Authors",
+ type: "text",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "character varying(64)",
+ oldMaxLength: 64);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "Country",
+ table: "Authors",
+ type: "text",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "text");
+ }
+ }
+}
diff --git a/Migrations/20221106041635_AddGroup.Designer.cs b/Migrations/20221106041635_AddGroup.Designer.cs
new file mode 100644
index 0000000..3db1b6d
--- /dev/null
+++ b/Migrations/20221106041635_AddGroup.Designer.cs
@@ -0,0 +1,179 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106041635_AddGroup")]
+ partial class AddGroup
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("GroupUserAccount", b =>
+ {
+ b.Property<long>("GroupsId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("UsersId")
+ .HasColumnType("bigint");
+
+ b.HasKey("GroupsId", "UsersId");
+
+ b.HasIndex("UsersId");
+
+ b.ToTable("GroupUserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", null)
+ .WithMany()
+ .HasForeignKey("GroupsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", null)
+ .WithMany()
+ .HasForeignKey("UsersId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106041635_AddGroup.cs b/Migrations/20221106041635_AddGroup.cs
new file mode 100644
index 0000000..23f5fc9
--- /dev/null
+++ b/Migrations/20221106041635_AddGroup.cs
@@ -0,0 +1,64 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class AddGroup : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Groups",
+ columns: table => new
+ {
+ Id = table.Column<long>(type: "bigint", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ Name = table.Column<string>(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Groups", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "GroupUserAccount",
+ columns: table => new
+ {
+ GroupsId = table.Column<long>(type: "bigint", nullable: false),
+ UsersId = table.Column<long>(type: "bigint", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_GroupUserAccount", x => new { x.GroupsId, x.UsersId });
+ table.ForeignKey(
+ name: "FK_GroupUserAccount_Groups_GroupsId",
+ column: x => x.GroupsId,
+ principalTable: "Groups",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_GroupUserAccount_Users_UsersId",
+ column: x => x.UsersId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_GroupUserAccount_UsersId",
+ table: "GroupUserAccount",
+ column: "UsersId");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "GroupUserAccount");
+
+ migrationBuilder.DropTable(
+ name: "Groups");
+ }
+ }
+}
diff --git a/Migrations/20221106055650_FixGroupModel.Designer.cs b/Migrations/20221106055650_FixGroupModel.Designer.cs
new file mode 100644
index 0000000..a474608
--- /dev/null
+++ b/Migrations/20221106055650_FixGroupModel.Designer.cs
@@ -0,0 +1,179 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106055650_FixGroupModel")]
+ partial class FixGroupModel
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("GroupUserAccount", b =>
+ {
+ b.Property<long>("GroupsId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("UsersId")
+ .HasColumnType("bigint");
+
+ b.HasKey("GroupsId", "UsersId");
+
+ b.HasIndex("UsersId");
+
+ b.ToTable("GroupUserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", null)
+ .WithMany()
+ .HasForeignKey("GroupsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", null)
+ .WithMany()
+ .HasForeignKey("UsersId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106055650_FixGroupModel.cs b/Migrations/20221106055650_FixGroupModel.cs
new file mode 100644
index 0000000..391d6f3
--- /dev/null
+++ b/Migrations/20221106055650_FixGroupModel.cs
@@ -0,0 +1,19 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class FixGroupModel : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/Migrations/20221106061015_ConfigureManyToMany.Designer.cs b/Migrations/20221106061015_ConfigureManyToMany.Designer.cs
new file mode 100644
index 0000000..79f0241
--- /dev/null
+++ b/Migrations/20221106061015_ConfigureManyToMany.Designer.cs
@@ -0,0 +1,213 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106061015_ConfigureManyToMany")]
+ partial class ConfigureManyToMany
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("GroupUserAccount", b =>
+ {
+ b.Property<long>("GroupsId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("UsersId")
+ .HasColumnType("bigint");
+
+ b.HasKey("GroupsId", "UsersId");
+
+ b.HasIndex("UsersId");
+
+ b.ToTable("GroupUserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", null)
+ .WithMany()
+ .HasForeignKey("GroupsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", null)
+ .WithMany()
+ .HasForeignKey("UsersId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany()
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany()
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106061015_ConfigureManyToMany.cs b/Migrations/20221106061015_ConfigureManyToMany.cs
new file mode 100644
index 0000000..9300ac2
--- /dev/null
+++ b/Migrations/20221106061015_ConfigureManyToMany.cs
@@ -0,0 +1,47 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class ConfigureManyToMany : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "GroupUserAccounts",
+ columns: table => new
+ {
+ GroupId = table.Column<long>(type: "bigint", nullable: false),
+ UserAccountId = table.Column<long>(type: "bigint", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_GroupUserAccounts", x => new { x.UserAccountId, x.GroupId });
+ table.ForeignKey(
+ name: "FK_GroupUserAccounts_Groups_GroupId",
+ column: x => x.GroupId,
+ principalTable: "Groups",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_GroupUserAccounts_Users_UserAccountId",
+ column: x => x.UserAccountId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_GroupUserAccounts_GroupId",
+ table: "GroupUserAccounts",
+ column: "GroupId");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "GroupUserAccounts");
+ }
+ }
+}
diff --git a/Migrations/20221106062230_AddJoinTableReferences.Designer.cs b/Migrations/20221106062230_AddJoinTableReferences.Designer.cs
new file mode 100644
index 0000000..0b2d767
--- /dev/null
+++ b/Migrations/20221106062230_AddJoinTableReferences.Designer.cs
@@ -0,0 +1,193 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106062230_AddJoinTableReferences")]
+ partial class AddJoinTableReferences
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany("Users")
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany("Groups")
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Navigation("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Navigation("Groups");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106062230_AddJoinTableReferences.cs b/Migrations/20221106062230_AddJoinTableReferences.cs
new file mode 100644
index 0000000..d7f1f8e
--- /dev/null
+++ b/Migrations/20221106062230_AddJoinTableReferences.cs
@@ -0,0 +1,47 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class AddJoinTableReferences : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "GroupUserAccount");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "GroupUserAccount",
+ columns: table => new
+ {
+ GroupsId = table.Column<long>(type: "bigint", nullable: false),
+ UsersId = table.Column<long>(type: "bigint", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_GroupUserAccount", x => new { x.GroupsId, x.UsersId });
+ table.ForeignKey(
+ name: "FK_GroupUserAccount_Groups_GroupsId",
+ column: x => x.GroupsId,
+ principalTable: "Groups",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_GroupUserAccount_Users_UsersId",
+ column: x => x.UsersId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_GroupUserAccount_UsersId",
+ table: "GroupUserAccount",
+ column: "UsersId");
+ }
+ }
+}
diff --git a/Migrations/20221106062917_AddJoinTableId.Designer.cs b/Migrations/20221106062917_AddJoinTableId.Designer.cs
new file mode 100644
index 0000000..0c6f633
--- /dev/null
+++ b/Migrations/20221106062917_AddJoinTableId.Designer.cs
@@ -0,0 +1,196 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106062917_AddJoinTableId")]
+ partial class AddJoinTableId
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("Id")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany("Users")
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany("Groups")
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Navigation("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Navigation("Groups");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106062917_AddJoinTableId.cs b/Migrations/20221106062917_AddJoinTableId.cs
new file mode 100644
index 0000000..b585b43
--- /dev/null
+++ b/Migrations/20221106062917_AddJoinTableId.cs
@@ -0,0 +1,26 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class AddJoinTableId : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn<long>(
+ name: "Id",
+ table: "GroupUserAccounts",
+ type: "bigint",
+ nullable: false,
+ defaultValue: 0L);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "Id",
+ table: "GroupUserAccounts");
+ }
+ }
+}
diff --git a/Migrations/20221106063041_AddJoinTablePrimaryKey.Designer.cs b/Migrations/20221106063041_AddJoinTablePrimaryKey.Designer.cs
new file mode 100644
index 0000000..42930be
--- /dev/null
+++ b/Migrations/20221106063041_AddJoinTablePrimaryKey.Designer.cs
@@ -0,0 +1,196 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106063041_AddJoinTablePrimaryKey")]
+ partial class AddJoinTablePrimaryKey
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("Id")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany("Users")
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany("Groups")
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Navigation("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Navigation("Groups");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106063041_AddJoinTablePrimaryKey.cs b/Migrations/20221106063041_AddJoinTablePrimaryKey.cs
new file mode 100644
index 0000000..ea5f3d7
--- /dev/null
+++ b/Migrations/20221106063041_AddJoinTablePrimaryKey.cs
@@ -0,0 +1,19 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class AddJoinTablePrimaryKey : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/Migrations/20221106063220_DeleteJoinTableId.Designer.cs b/Migrations/20221106063220_DeleteJoinTableId.Designer.cs
new file mode 100644
index 0000000..7ca0cb0
--- /dev/null
+++ b/Migrations/20221106063220_DeleteJoinTableId.Designer.cs
@@ -0,0 +1,193 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106063220_DeleteJoinTableId")]
+ partial class DeleteJoinTableId
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany("Users")
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany("Groups")
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Navigation("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Navigation("Groups");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106063220_DeleteJoinTableId.cs b/Migrations/20221106063220_DeleteJoinTableId.cs
new file mode 100644
index 0000000..20cea64
--- /dev/null
+++ b/Migrations/20221106063220_DeleteJoinTableId.cs
@@ -0,0 +1,26 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class DeleteJoinTableId : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "Id",
+ table: "GroupUserAccounts");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn<long>(
+ name: "Id",
+ table: "GroupUserAccounts",
+ type: "bigint",
+ nullable: false,
+ defaultValue: 0L);
+ }
+ }
+}
diff --git a/Migrations/20221106063641_AddNullableFields.Designer.cs b/Migrations/20221106063641_AddNullableFields.Designer.cs
new file mode 100644
index 0000000..c09fe61
--- /dev/null
+++ b/Migrations/20221106063641_AddNullableFields.Designer.cs
@@ -0,0 +1,193 @@
+// <auto-generated />
+using System;
+using LibraryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ [DbContext(typeof(LibraryContext))]
+ [Migration("20221106063641_AddNullableFields")]
+ partial class AddNullableFields
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Country")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property<int>("YearOfBirth")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("languages")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<long>("AuthorId")
+ .HasColumnType("bigint");
+
+ b.Property<int>("Edition")
+ .HasColumnType("integer");
+
+ b.Property<string[]>("Genres")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property<string>("ISBN")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<int>("PublicationYear")
+ .HasColumnType("integer");
+
+ b.Property<string>("Title")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Book", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Author", "Author")
+ .WithMany("Books")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany("Users")
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany("Groups")
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Author", b =>
+ {
+ b.Navigation("Books");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Navigation("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Navigation("Groups");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20221106063641_AddNullableFields.cs b/Migrations/20221106063641_AddNullableFields.cs
new file mode 100644
index 0000000..a860b2f
--- /dev/null
+++ b/Migrations/20221106063641_AddNullableFields.cs
@@ -0,0 +1,19 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace LibraryAPI.Migrations
+{
+ public partial class AddNullableFields : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/Migrations/LibraryContextModelSnapshot.cs b/Migrations/LibraryContextModelSnapshot.cs
index 0fa3e9b..a523712 100644
--- a/Migrations/LibraryContextModelSnapshot.cs
+++ b/Migrations/LibraryContextModelSnapshot.cs
@@ -31,15 +31,19 @@ namespace LibraryAPI.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("Country")
+ .IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
- .HasColumnType("text");
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
b.Property<int>("YearOfBirth")
.HasColumnType("integer");
b.Property<string[]>("languages")
+ .IsRequired()
.HasColumnType("text[]");
b.HasKey("Id");
@@ -62,16 +66,20 @@ namespace LibraryAPI.Migrations
.HasColumnType("integer");
b.Property<string[]>("Genres")
+ .IsRequired()
.HasColumnType("text[]");
b.Property<string>("ISBN")
+ .IsRequired()
.HasColumnType("text");
b.Property<int>("PublicationYear")
.HasColumnType("integer");
b.Property<string>("Title")
- .HasColumnType("text");
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
b.HasKey("Id");
@@ -80,6 +88,59 @@ namespace LibraryAPI.Migrations
b.ToTable("Books");
});
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Groups");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.Property<long>("UserAccountId")
+ .HasColumnType("bigint");
+
+ b.Property<long>("GroupId")
+ .HasColumnType("bigint");
+
+ b.HasKey("UserAccountId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.ToTable("GroupUserAccounts");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
+
+ b.Property<string>("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
modelBuilder.Entity("LibraryAPI.Models.Book", b =>
{
b.HasOne("LibraryAPI.Models.Author", "Author")
@@ -91,10 +152,39 @@ namespace LibraryAPI.Migrations
b.Navigation("Author");
});
+ modelBuilder.Entity("LibraryAPI.Models.GroupUserAccount", b =>
+ {
+ b.HasOne("LibraryAPI.Models.Group", "Group")
+ .WithMany("Users")
+ .HasForeignKey("GroupId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("LibraryAPI.Models.UserAccount", "UserAccount")
+ .WithMany("Groups")
+ .HasForeignKey("UserAccountId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Group");
+
+ b.Navigation("UserAccount");
+ });
+
modelBuilder.Entity("LibraryAPI.Models.Author", b =>
{
b.Navigation("Books");
});
+
+ modelBuilder.Entity("LibraryAPI.Models.Group", b =>
+ {
+ b.Navigation("Users");
+ });
+
+ modelBuilder.Entity("LibraryAPI.Models.UserAccount", b =>
+ {
+ b.Navigation("Groups");
+ });
#pragma warning restore 612, 618
}
}
diff --git a/Models/Book.cs b/Models/Book.cs
index 49bd527..4a05865 100644
--- a/Models/Book.cs
+++ b/Models/Book.cs
@@ -19,4 +19,4 @@ namespace LibraryAPI.Models {
[StringLength(128, ErrorMessage = "Title too long")]
public string? Title { get; set; }
}
-} \ No newline at end of file
+}
diff --git a/Models/Group.cs b/Models/Group.cs
new file mode 100644
index 0000000..f5ed59d
--- /dev/null
+++ b/Models/Group.cs
@@ -0,0 +1,12 @@
+using System.ComponentModel.DataAnnotations;
+using LibraryAPI.Validators;
+
+namespace LibraryAPI.Models {
+ public class Group {
+ public long Id { get; set; }
+ public ICollection<GroupUserAccount>? Users { get; set; }
+ [Required]
+ [Name]
+ public string? Name {get; set; }
+ }
+}
diff --git a/Models/GroupUserAccount.cs b/Models/GroupUserAccount.cs
new file mode 100644
index 0000000..706c2e9
--- /dev/null
+++ b/Models/GroupUserAccount.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace LibraryAPI.Models {
+ public class GroupUserAccount {
+ public long GroupId { get; set; }
+ public Group? Group { get; set; }
+ public long UserAccountId { get; set; }
+ public UserAccount? UserAccount { get; set; }
+ }
+}
diff --git a/Models/LibraryContext.cs b/Models/LibraryContext.cs
index b07ba54..3f56b0c 100644
--- a/Models/LibraryContext.cs
+++ b/Models/LibraryContext.cs
@@ -4,6 +4,13 @@ namespace LibraryAPI.Models {
public class LibraryContext : DbContext {
public DbSet<Author>? Authors { get; set; }
public DbSet<Book>? Books { get; set; }
+ public DbSet<UserAccount>? Users { get; set; }
+ public DbSet<Group>? Groups { get; set; }
+ public DbSet<GroupUserAccount>? GroupUserAccounts { get; set; }
public LibraryContext(DbContextOptions<LibraryContext> options) : base(options) {}
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder) {
+ modelBuilder.Entity<GroupUserAccount>().HasKey(sc => new { sc.UserAccountId, sc.GroupId });
+ }
}
-} \ No newline at end of file
+}
diff --git a/Models/UserAccount.cs b/Models/UserAccount.cs
new file mode 100644
index 0000000..e3184ed
--- /dev/null
+++ b/Models/UserAccount.cs
@@ -0,0 +1,30 @@
+using System.ComponentModel.DataAnnotations;
+using Microsoft.AspNetCore.Identity;
+
+namespace LibraryAPI.Models {
+ public class UserAccount {
+ public long Id { get; set; }
+ [Required]
+ public string? Email { get; set; }
+ private string? _password;
+ [Required]
+ public string? Password { get { return _password; } set { _password = HashPassword(value); } }
+ public ICollection<GroupUserAccount>? Groups { get; set; }
+ private PasswordHasher<UserAccount> _hasher;
+
+ public UserAccount() {
+ _hasher = new PasswordHasher<UserAccount>();
+ }
+
+ public PasswordVerificationResult VerifyPassword(string to_verify) {
+ return _hasher.VerifyHashedPassword(this, Password, to_verify);
+ }
+
+ private string? HashPassword(string? unhashed_password) {
+ if(unhashed_password != null)
+ return _hasher.HashPassword(this, unhashed_password);
+
+ return null;
+ }
+ }
+}
diff --git a/Program.cs b/Program.cs
index d717af7..2678a94 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,4 +1,10 @@
using Microsoft.EntityFrameworkCore;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.IdentityModel.Tokens;
+using Microsoft.OpenApi.Models;
+using System.IdentityModel.Tokens.Jwt;
+using System.Text;
using LibraryAPI.Models;
using LibraryAPI.Filters;
using LibraryAPI.Services;
@@ -11,6 +17,21 @@ builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHostedService<LoggerService>();
builder.Services.AddScoped<ActionFilter>();
+// JWT Config.
+builder.Services.AddAuthentication(options => {
+ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
+}).AddJwtBearer(options =>
+ options.TokenValidationParameters = new TokenValidationParameters {
+ ValidateIssuer = false,
+ ValidateAudience = false,
+ ValidateLifetime = true,
+ ValidateIssuerSigningKey = true,
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["keyjwt"])),
+ ClockSkew = TimeSpan.Zero
+ });
+builder.Services.AddAuthorization();
var app = builder.Build();
@@ -22,6 +43,8 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection();
+app.UseAuthentication();
+
app.UseAuthorization();
app.MapControllers();
diff --git a/Services/LoggerService.cs b/Services/LoggerService.cs
index dd78e23..64eecb1 100644
--- a/Services/LoggerService.cs
+++ b/Services/LoggerService.cs
@@ -1,15 +1,11 @@
-using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
+// Singleton service.
namespace LibraryAPI.Services {
- public class LoggerService : IHostedService {
- private readonly IWebHostEnvironment env;
- private readonly string log_file = "Log.txt";
+ public class LoggerService : BaseService, IHostedService {
private Timer timer;
- public LoggerService(IWebHostEnvironment env) {
- this.env = env;
- }
+ public LoggerService(IWebHostEnvironment env) : base(env) { }
public Task StartAsync(CancellationToken cancel_token) {
timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
@@ -25,13 +21,5 @@ namespace LibraryAPI.Services {
timer.Dispose();
return Task.CompletedTask;
}
-
- private void LogToFile(string message) {
- var path = $@"{env.ContentRootPath}/wwwroot/{log_file}";
-
- using (StreamWriter w = new StreamWriter(path, append: true)) {
- w.WriteLine(message);
- }
- }
}
}
diff --git a/Validators/NameAttribute.cs b/Validators/NameAttribute.cs
new file mode 100644
index 0000000..2f1a5ae
--- /dev/null
+++ b/Validators/NameAttribute.cs
@@ -0,0 +1,20 @@
+using System.ComponentModel.DataAnnotations;
+using LibraryAPI.Models;
+
+namespace LibraryAPI.Validators {
+ public class NameAttribute : ValidationAttribute {
+ public string[] valid_names = { "regular", "librarian" };
+ public string GetErrorMessage() {
+ return "Group name must be \"regular\" or \"librarian\"";
+ }
+
+ protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) {
+ var group = (Group) validationContext.ObjectInstance;
+
+ if(Array.Exists(valid_names, s => s == group.Name))
+ return ValidationResult.Success;
+
+ return new ValidationResult(GetErrorMessage());
+ }
+ }
+}