diff options
author | HombreLaser <sebastian-440@live.com> | 2022-11-06 02:10:44 -0600 |
---|---|---|
committer | HombreLaser <sebastian-440@live.com> | 2022-11-06 02:10:44 -0600 |
commit | 08819c6738a4f82ccf07ae5ed60835b087f7bb34 (patch) | |
tree | 9c0c77626587136d41002769fb5a030e1be2f5b8 | |
parent | f060c4f88f635af3295ea7652cbbbd08dbf1c6cf (diff) |
Añadidos grupos y usuarios
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; + } + } +} @@ -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()); + } + } +} |