Add authentication and authorization #21

Merged
Egamorf merged 9 commits from feature/authentification-and-authorization into main 2025-04-21 01:53:59 +02:00
13 changed files with 1533 additions and 86 deletions
Showing only changes of commit 43bd22c1d7 - Show all commits

View File

@@ -37,6 +37,9 @@ Store your favorite games, intelligent game add, store game files and data, mana
| DB_USERNAME | Username for the database |
| DB_PASSWORD | Plain password for the database |
| DB_DATABASE | Name of the database |
| JWT_KEY | Key for your jwt tokens |
| JWT_ISSUER | Your domain name |
| JWT_AUDIENCE | Your domain name |
<!-- ## Installation

View File

@@ -6,4 +6,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="9.0.4" />
</ItemGroup>
</Project>

View File

@@ -15,9 +15,9 @@ public partial class Game
public string Title { get; set; } = null!;
public DateTime? ReleaseDate { get; set; }
public DateTime CreationDate { get; set; }
public int CreationUserId { get; set; }
public string CreationUserId { get; set; } = null!;
public DateTime? ModificationDate { get; set; }
public int? ModificationUserId { get; set; }
public string? ModificationUserId { get; set; }
public double? StorageSpace { get; set; }
public string? Description { get; set; }
public int Interest { get; set; }

View File

@@ -1,6 +1,8 @@
namespace GameIdeas.Shared.Model;
using Microsoft.AspNetCore.Identity;
public partial class User
namespace GameIdeas.Shared.Model;
public partial class User : IdentityUser
{
public User()
{
@@ -8,11 +10,6 @@ public partial class User
ModificationGames = new HashSet<Game>();
}
public int Id { get; set; }
public string Username { get; set; } = null!;
public string Password { get; set; } = null!;
public int Role { get; set; }
public virtual ICollection<Game> CreationGames { get; set; }
public virtual ICollection<Game> ModificationGames { get; set; }
}

View File

@@ -1,9 +1,10 @@
using GameIdeas.Shared.Model;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace GameIdeas.WebAPI.Context;
public class GameIdeasContext : DbContext
public class GameIdeasContext : IdentityDbContext<User>
{
public GameIdeasContext(DbContextOptions<GameIdeasContext> option)
: base(option)
@@ -12,7 +13,6 @@ public class GameIdeasContext : DbContext
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
}
public virtual DbSet<User> Users { get; set; } = null!;
public virtual DbSet<Developer> Developers { get; set; } = null!;
public virtual DbSet<Platform> Platforms { get; set; } = null!;
public virtual DbSet<Property> Properties { get; set; } = null!;
@@ -27,28 +27,51 @@ public class GameIdeasContext : DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>(entity => {
entity.ToTable("User");
modelBuilder.Entity<Developer>(entity => {
entity.ToTable("Developer");
entity.Property(e => e.Id)
.UseIdentityByDefaultColumn()
.HasIdentityOptions(startValue: 100000);
entity.HasIndex(e => e.Name)
.IsUnique();
});
modelBuilder.Entity<Developer>(entity => entity.ToTable("Developer"));
modelBuilder.Entity<Platform>(entity => {
entity.ToTable("Platform");
modelBuilder.Entity<Platform>(entity => entity.ToTable("Platform"));
entity.HasIndex(e => e.Label)
.IsUnique();
});
modelBuilder.Entity<Property>(entity => entity.ToTable("Property"));
modelBuilder.Entity<Property>(entity =>
{
entity.ToTable("Property");
modelBuilder.Entity<Publisher>(entity => entity.ToTable("Publisher"));
entity.HasIndex(e => e.Label)
.IsUnique();
});
modelBuilder.Entity<Tag>(entity => entity.ToTable("Tag"));
modelBuilder.Entity<Publisher>(entity =>
{
entity.ToTable("Publisher");
entity.HasIndex(e => e.Name)
.IsUnique();
});
modelBuilder.Entity<Tag>(entity =>
{
entity.ToTable("Tag");
entity.HasIndex(e => e.Label)
.IsUnique();
});
modelBuilder.Entity<Game>(entity =>
{
entity.ToTable("Game");
entity.HasIndex(e => e.Title)
.IsUnique();
entity.HasIndex(e => e.CreationUserId);
entity.HasIndex(e => e.ModificationUserId);

View File

@@ -4,6 +4,7 @@
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>c5ccfd3a-f458-4660-b6c4-81fcc2513737</UserSecretsId>
</PropertyGroup>
<ItemGroup>
@@ -12,6 +13,8 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.4" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.4">

View File

@@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace GameIdeas.WebAPI.Migrations
{
[DbContext(typeof(GameIdeasContext))]
[Migration("20250409225125_InitialCreate")]
[Migration("20250420153030_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@@ -39,6 +39,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Developer", (string)null);
});
@@ -53,11 +56,12 @@ namespace GameIdeas.WebAPI.Migrations
b.Property<DateTime>("CreationDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnType("timestamp without time zone")
.HasDefaultValueSql("now()");
b.Property<int>("CreationUserId")
.HasColumnType("integer");
b.Property<string>("CreationUserId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
@@ -66,13 +70,13 @@ namespace GameIdeas.WebAPI.Migrations
.HasColumnType("integer");
b.Property<DateTime?>("ModificationDate")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp without time zone");
b.Property<int?>("ModificationUserId")
.HasColumnType("integer");
b.Property<string>("ModificationUserId")
.HasColumnType("text");
b.Property<DateTime?>("ReleaseDate")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp without time zone");
b.Property<double?>("StorageSpace")
.HasColumnType("double precision");
@@ -87,6 +91,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasIndex("ModificationUserId");
b.HasIndex("Title")
.IsUnique();
b.ToTable("Game", (string)null);
});
@@ -182,6 +189,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Platform", (string)null);
});
@@ -199,6 +209,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Property", (string)null);
});
@@ -216,6 +229,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Publisher", (string)null);
});
@@ -233,32 +249,206 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Tag", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
NpgsqlPropertyBuilderExtensions.HasIdentityOptions(b.Property<int>("Id"), 100000L, null, null, null, null, null);
b.Property<string>("Password")
.IsRequired()
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("Username")
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("User", (string)null);
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Game", b =>
@@ -372,6 +562,57 @@ namespace GameIdeas.WebAPI.Migrations
b.Navigation("Tag");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("GameIdeas.Shared.Model.Developer", b =>
{
b.Navigation("GameDevelopers");

View File

@@ -12,6 +12,45 @@ namespace GameIdeas.WebAPI.Migrations
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "boolean", nullable: false),
PasswordHash = table.Column<string>(type: "text", nullable: true),
SecurityStamp = table.Column<string>(type: "text", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "text", nullable: true),
PhoneNumber = table.Column<string>(type: "text", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "boolean", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "boolean", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
LockoutEnabled = table.Column<bool>(type: "boolean", nullable: false),
AccessFailedCount = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Developer",
columns: table => new
@@ -78,19 +117,109 @@ namespace GameIdeas.WebAPI.Migrations
});
migrationBuilder.CreateTable(
name: "User",
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:IdentitySequenceOptions", "'100000', '1', '', '', 'False', '1'")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Username = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false),
Role = table.Column<int>(type: "integer", nullable: false)
RoleId = table.Column<string>(type: "text", nullable: false),
ClaimType = table.Column<string>(type: "text", nullable: true),
ClaimValue = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_User", x => x.Id);
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
UserId = table.Column<string>(type: "text", nullable: false),
ClaimType = table.Column<string>(type: "text", nullable: true),
ClaimValue = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(type: "text", nullable: false),
ProviderKey = table.Column<string>(type: "text", nullable: false),
ProviderDisplayName = table.Column<string>(type: "text", nullable: true),
UserId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(type: "text", nullable: false),
RoleId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(type: "text", nullable: false),
LoginProvider = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Value = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
@@ -101,11 +230,11 @@ namespace GameIdeas.WebAPI.Migrations
.Annotation("Npgsql:IdentitySequenceOptions", "'100000', '1', '', '', 'False', '1'")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Title = table.Column<string>(type: "text", nullable: false),
ReleaseDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
CreationUserId = table.Column<int>(type: "integer", nullable: false),
ModificationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
ModificationUserId = table.Column<int>(type: "integer", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false, defaultValueSql: "now()"),
CreationUserId = table.Column<string>(type: "text", nullable: false),
ModificationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
ModificationUserId = table.Column<string>(type: "text", nullable: true),
StorageSpace = table.Column<double>(type: "double precision", nullable: true),
Description = table.Column<string>(type: "text", nullable: true),
Interest = table.Column<int>(type: "integer", nullable: false)
@@ -114,14 +243,14 @@ namespace GameIdeas.WebAPI.Migrations
{
table.PrimaryKey("PK_Game", x => x.Id);
table.ForeignKey(
name: "FK_Game_User_CreationUserId",
name: "FK_Game_AspNetUsers_CreationUserId",
column: x => x.CreationUserId,
principalTable: "User",
principalTable: "AspNetUsers",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Game_User_ModificationUserId",
name: "FK_Game_AspNetUsers_ModificationUserId",
column: x => x.ModificationUserId,
principalTable: "User",
principalTable: "AspNetUsers",
principalColumn: "Id");
});
@@ -246,6 +375,49 @@ namespace GameIdeas.WebAPI.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Developer_Name",
table: "Developer",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Game_CreationUserId",
table: "Game",
@@ -256,6 +428,12 @@ namespace GameIdeas.WebAPI.Migrations
table: "Game",
column: "ModificationUserId");
migrationBuilder.CreateIndex(
name: "IX_Game_Title",
table: "Game",
column: "Title",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_GameDeveloper_DeveloperId",
table: "GameDeveloper",
@@ -280,11 +458,50 @@ namespace GameIdeas.WebAPI.Migrations
name: "IX_GameTag_TagId",
table: "GameTag",
column: "TagId");
migrationBuilder.CreateIndex(
name: "IX_Platform_Label",
table: "Platform",
column: "Label",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Property_Label",
table: "Property",
column: "Label",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Publisher_Name",
table: "Publisher",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Tag_Label",
table: "Tag",
column: "Label",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "GameDeveloper");
@@ -300,6 +517,9 @@ namespace GameIdeas.WebAPI.Migrations
migrationBuilder.DropTable(
name: "GameTag");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "Developer");
@@ -319,7 +539,7 @@ namespace GameIdeas.WebAPI.Migrations
name: "Tag");
migrationBuilder.DropTable(
name: "User");
name: "AspNetUsers");
}
}
}

View File

@@ -0,0 +1,663 @@
// <auto-generated />
using System;
using GameIdeas.WebAPI.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace GameIdeas.WebAPI.Migrations
{
[DbContext(typeof(GameIdeasContext))]
[Migration("20250420153439_SeedRoles")]
partial class SeedRoles
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("GameIdeas.Shared.Model.Developer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Developer", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Game", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
NpgsqlPropertyBuilderExtensions.HasIdentityOptions(b.Property<int>("Id"), 100000L, null, null, null, null, null);
b.Property<DateTime>("CreationDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp without time zone")
.HasDefaultValueSql("now()");
b.Property<string>("CreationUserId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<int>("Interest")
.HasColumnType("integer");
b.Property<DateTime?>("ModificationDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("ModificationUserId")
.HasColumnType("text");
b.Property<DateTime?>("ReleaseDate")
.HasColumnType("timestamp without time zone");
b.Property<double?>("StorageSpace")
.HasColumnType("double precision");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CreationUserId");
b.HasIndex("ModificationUserId");
b.HasIndex("Title")
.IsUnique();
b.ToTable("Game", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.GameDeveloper", b =>
{
b.Property<int>("GameId")
.HasColumnType("integer");
b.Property<int>("DeveloperId")
.HasColumnType("integer");
b.HasKey("GameId", "DeveloperId");
b.HasIndex("DeveloperId");
b.ToTable("GameDeveloper", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.GamePlatform", b =>
{
b.Property<int>("GameId")
.HasColumnType("integer");
b.Property<int>("PlatformId")
.HasColumnType("integer");
b.Property<string>("Url")
.HasColumnType("text");
b.HasKey("GameId", "PlatformId");
b.HasIndex("PlatformId");
b.ToTable("GamePlatform", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.GameProperty", b =>
{
b.Property<int>("GameId")
.HasColumnType("integer");
b.Property<int>("PropertyId")
.HasColumnType("integer");
b.HasKey("GameId", "PropertyId");
b.HasIndex("PropertyId");
b.ToTable("GameProperty", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.GamePublisher", b =>
{
b.Property<int>("GameId")
.HasColumnType("integer");
b.Property<int>("PublisherId")
.HasColumnType("integer");
b.HasKey("GameId", "PublisherId");
b.HasIndex("PublisherId");
b.ToTable("GamePublisher", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.GameTag", b =>
{
b.Property<int>("GameId")
.HasColumnType("integer");
b.Property<int>("TagId")
.HasColumnType("integer");
b.HasKey("GameId", "TagId");
b.HasIndex("TagId");
b.ToTable("GameTag", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Platform", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Label")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Platform", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Property", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Label")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Property", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Publisher", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Publisher", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Tag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Label")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Tag", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Game", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", "CreationUser")
.WithMany("CreationGames")
.HasForeignKey("CreationUserId")
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.User", "ModificationUser")
.WithMany("ModificationGames")
.HasForeignKey("ModificationUserId");
b.Navigation("CreationUser");
b.Navigation("ModificationUser");
});
modelBuilder.Entity("GameIdeas.Shared.Model.GameDeveloper", b =>
{
b.HasOne("GameIdeas.Shared.Model.Developer", "Developer")
.WithMany("GameDevelopers")
.HasForeignKey("DeveloperId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.Game", "Game")
.WithMany("GameDevelopers")
.HasForeignKey("GameId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Developer");
b.Navigation("Game");
});
modelBuilder.Entity("GameIdeas.Shared.Model.GamePlatform", b =>
{
b.HasOne("GameIdeas.Shared.Model.Game", "Game")
.WithMany("GamePlatforms")
.HasForeignKey("GameId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.Platform", "Platform")
.WithMany("GamePlatforms")
.HasForeignKey("PlatformId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Game");
b.Navigation("Platform");
});
modelBuilder.Entity("GameIdeas.Shared.Model.GameProperty", b =>
{
b.HasOne("GameIdeas.Shared.Model.Game", "Game")
.WithMany("GameProperties")
.HasForeignKey("GameId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.Property", "Property")
.WithMany("GameProperties")
.HasForeignKey("PropertyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Game");
b.Navigation("Property");
});
modelBuilder.Entity("GameIdeas.Shared.Model.GamePublisher", b =>
{
b.HasOne("GameIdeas.Shared.Model.Game", "Game")
.WithMany("GamePublishers")
.HasForeignKey("GameId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.Publisher", "Publisher")
.WithMany("GamePublishers")
.HasForeignKey("PublisherId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Game");
b.Navigation("Publisher");
});
modelBuilder.Entity("GameIdeas.Shared.Model.GameTag", b =>
{
b.HasOne("GameIdeas.Shared.Model.Game", "Game")
.WithMany("GameTags")
.HasForeignKey("GameId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.Tag", "Tag")
.WithMany("GameTags")
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Game");
b.Navigation("Tag");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("GameIdeas.Shared.Model.Developer", b =>
{
b.Navigation("GameDevelopers");
});
modelBuilder.Entity("GameIdeas.Shared.Model.Game", b =>
{
b.Navigation("GameDevelopers");
b.Navigation("GamePlatforms");
b.Navigation("GameProperties");
b.Navigation("GamePublishers");
b.Navigation("GameTags");
});
modelBuilder.Entity("GameIdeas.Shared.Model.Platform", b =>
{
b.Navigation("GamePlatforms");
});
modelBuilder.Entity("GameIdeas.Shared.Model.Property", b =>
{
b.Navigation("GameProperties");
});
modelBuilder.Entity("GameIdeas.Shared.Model.Publisher", b =>
{
b.Navigation("GamePublishers");
});
modelBuilder.Entity("GameIdeas.Shared.Model.Tag", b =>
{
b.Navigation("GameTags");
});
modelBuilder.Entity("GameIdeas.Shared.Model.User", b =>
{
b.Navigation("CreationGames");
b.Navigation("ModificationGames");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameIdeas.WebAPI.Migrations
{
/// <inheritdoc />
public partial class SeedRoles : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: ["Id", "Name", "NormalizedName", "ConcurrencyStamp"],
values: new object[,]
{
{
Guid.NewGuid().ToString(),
"Administrateur",
"ADMINISTRATEUR",
Guid.NewGuid().ToString()
},
{
Guid.NewGuid().ToString(),
"Membre",
"MEMBRE",
Guid.NewGuid().ToString()
}
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM [AspNetRoles] WHERE [Name] IN ('Administrateur', 'Membre')");
}
}
}

View File

@@ -36,6 +36,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Developer", (string)null);
});
@@ -50,11 +53,12 @@ namespace GameIdeas.WebAPI.Migrations
b.Property<DateTime>("CreationDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnType("timestamp without time zone")
.HasDefaultValueSql("now()");
b.Property<int>("CreationUserId")
.HasColumnType("integer");
b.Property<string>("CreationUserId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
@@ -63,13 +67,13 @@ namespace GameIdeas.WebAPI.Migrations
.HasColumnType("integer");
b.Property<DateTime?>("ModificationDate")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp without time zone");
b.Property<int?>("ModificationUserId")
.HasColumnType("integer");
b.Property<string>("ModificationUserId")
.HasColumnType("text");
b.Property<DateTime?>("ReleaseDate")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp without time zone");
b.Property<double?>("StorageSpace")
.HasColumnType("double precision");
@@ -84,6 +88,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasIndex("ModificationUserId");
b.HasIndex("Title")
.IsUnique();
b.ToTable("Game", (string)null);
});
@@ -179,6 +186,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Platform", (string)null);
});
@@ -196,6 +206,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Property", (string)null);
});
@@ -213,6 +226,9 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Publisher", (string)null);
});
@@ -230,32 +246,206 @@ namespace GameIdeas.WebAPI.Migrations
b.HasKey("Id");
b.HasIndex("Label")
.IsUnique();
b.ToTable("Tag", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
NpgsqlPropertyBuilderExtensions.HasIdentityOptions(b.Property<int>("Id"), 100000L, null, null, null, null, null);
b.Property<string>("Password")
.IsRequired()
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("Username")
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("User", (string)null);
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("GameIdeas.Shared.Model.Game", b =>
@@ -369,6 +559,57 @@ namespace GameIdeas.WebAPI.Migrations
b.Navigation("Tag");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("GameIdeas.Shared.Model.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("GameIdeas.Shared.Model.Developer", b =>
{
b.Navigation("GameDevelopers");

View File

@@ -1,20 +0,0 @@
using AutoMapper;
using GameIdeas.Shared.Dto;
using GameIdeas.Shared.Enum;
using GameIdeas.Shared.Model;
namespace GameIdeas.WebAPI.Profiles;
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<User, UserDto>()
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
.ForMember(d => d.Username, o => o.MapFrom(s => s.Username))
.ForMember(d => d.Password, o => o.MapFrom(s => s.Password))
.ForMember(d => d.Role, o => o.MapFrom(s => s.Role))
.ReverseMap();
}
}

View File

@@ -1,8 +1,13 @@
using GameIdeas.Resources;
using GameIdeas.Shared.Model;
using GameIdeas.WebAPI.Context;
using GameIdeas.WebAPI.Services.Categories;
using GameIdeas.WebAPI.Services.Games;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
@@ -27,6 +32,34 @@ Action<DbContextOptionsBuilder> dbContextOptions = options =>
// Add services to the container.
services.AddDbContext<GameIdeasContext>(dbContextOptions);
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<GameIdeasContext>()
.AddDefaultTokenProviders();
var jwtKey = Environment.GetEnvironmentVariable("JWT_KEY")
?? throw new ArgumentNullException(message: "Invalid key for JWT token", null);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Environment.GetEnvironmentVariable("JWT_ISSUER"),
ValidAudience = Environment.GetEnvironmentVariable("JWT_AUDIENCE"),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
};
});
services.AddAuthorization();
services.AddSingleton<TranslationService>();
services.AddSingleton<Translations>();