User Role many to many

This commit is contained in:
OlgunR 2024-09-12 15:42:28 +02:00
parent b811be2226
commit cedf5f0ca8
28 changed files with 864 additions and 242 deletions

View File

@ -1,11 +1,11 @@
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Security.Claims; using System.Security.Claims;
using UserManagement.Application.Dtos.Auth; using UserManagement.Application.Dtos.Auth;
using UserManagement.Application.Interfaces; using UserManagement.Application.Interfaces;
using Swashbuckle.AspNetCore.Annotations;
namespace UserManagement.API.Controllers namespace UserManagement.API.Controllers
{ {
@ -30,7 +30,7 @@ namespace UserManagement.API.Controllers
{ {
// Validate user // Validate user
var user = await _userService.GetByUsernameAsync(login.Username); var user = await _userService.GetByUsernameAsync(login.Username);
if (user == null) if (user is null)
{ {
return Unauthorized(); return Unauthorized();
} }
@ -49,9 +49,13 @@ namespace UserManagement.API.Controllers
new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Surname, user.LastName ?? ""), new Claim(ClaimTypes.Surname, user.LastName ?? ""),
new Claim(ClaimTypes.GivenName, user.FirstName ?? ""), new Claim(ClaimTypes.GivenName, user.FirstName ?? ""),
new Claim(ClaimTypes.Role, user?.Role?.Name.ToString() ?? "")
}; };
foreach (var userRole in user.UserRoles)
{
claims.Add(new Claim(ClaimTypes.Role, userRole!.Name));
}
// Create a ClaimsIdentity based on the created claims // Create a ClaimsIdentity based on the created claims
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
@ -82,5 +86,10 @@ namespace UserManagement.API.Controllers
return Ok(); return Ok();
} }
// AUTH CHECK
[HttpGet]
[SwaggerOperation(Summary = "Authentication Check")]
public IActionResult IsAuth() => Ok(User?.Identity?.IsAuthenticated ?? false);
} }
} }

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
using UserManagement.Application.Dtos.Incomming; using UserManagement.Application.Dtos.Incomming;
using UserManagement.Application.Interfaces; using UserManagement.Application.Interfaces;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace UserManagement.API.Controllers namespace UserManagement.API.Controllers
{ {
@ -114,7 +115,18 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UpdateRole(int id, UpdatingRoleDto updatingRoleDto) public async Task<IActionResult> UpdateRole(int id, UpdatingRoleDto updatingRoleDto)
{ {
if (id <= 0)
{
return BadRequest("Invalid Id");
}
var updated = await _roleService.UpdateRoleAsync(updatingRoleDto); var updated = await _roleService.UpdateRoleAsync(updatingRoleDto);
if (!updated)
{
return BadRequest("Update failed");
}
return Ok(updated); return Ok(updated);
} }
@ -126,7 +138,18 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> DeleteRole([FromRoute] int id) public async Task<IActionResult> DeleteRole([FromRoute] int id)
{ {
await _roleService.DeleteRoleAsync(id); if (id <= 0)
{
return BadRequest("Invalid Id");
}
var deleted = await _roleService.DeleteRoleAsync(id);
if (!deleted)
{
return BadRequest("Deletion failed");
}
return Ok(); return Ok();
} }
} }

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
using UserManagement.Application.Dtos.Incomming; using UserManagement.Application.Dtos.Incomming;
using UserManagement.Application.Interfaces; using UserManagement.Application.Interfaces;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace UserManagement.API.Controllers namespace UserManagement.API.Controllers
{ {
@ -24,6 +25,7 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status500InternalServerError)]
//[Authorize(Roles = "Admin")]
public async Task<IActionResult> CreateUser([FromBody] CreatingUserDto creatingUserDto) public async Task<IActionResult> CreateUser([FromBody] CreatingUserDto creatingUserDto)
{ {
// Validate incomming model // Validate incomming model
@ -114,7 +116,18 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UpdateUser(int id, UpdatingUserDto updatingUserDto) public async Task<IActionResult> UpdateUser(int id, UpdatingUserDto updatingUserDto)
{ {
if (id <= 0)
{
return BadRequest("Invalid Id");
}
var updated = await _userService.UpdateUserAsync(updatingUserDto); var updated = await _userService.UpdateUserAsync(updatingUserDto);
if (!updated)
{
return BadRequest("Update failed");
}
return Ok(updated); return Ok(updated);
} }
@ -126,7 +139,18 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> DeleteUser([FromBody] int id) public async Task<IActionResult> DeleteUser([FromBody] int id)
{ {
await _userService.DeleteUserAsync(id); if (id <= 0)
{
return BadRequest("Invalid Id");
}
var deleted = await _userService.DeleteUserAsync(id);
if (!deleted)
{
return BadRequest("Deletion failed");
}
return Ok(); return Ok();
} }
} }

View File

@ -12,8 +12,8 @@ using UserManagement.Infrastructure;
namespace UserManagement.API.Migrations namespace UserManagement.API.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
[Migration("20240821105311_Initial")] [Migration("20240910064554_Init")]
partial class Initial partial class Init
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -72,13 +72,6 @@ namespace UserManagement.API.Migrations
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD"); .HasColumnName("PASSWORD");
b.Property<int?>("ROLE")
.HasColumnType("int");
b.Property<int>("RoleId")
.HasColumnType("int")
.HasColumnName("ROLE_ID");
b.Property<string>("UserName") b.Property<string>("UserName")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
@ -86,20 +79,53 @@ namespace UserManagement.API.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users"); b.ToTable("Users");
}); });
modelBuilder.Entity("UserManagement.Domain.Entities.User", b => modelBuilder.Entity("UserManagement.Domain.Entities.UserRoles", b =>
{
b.Property<int>("UserId")
.HasColumnType("int")
.HasColumnName("USER_ID");
b.Property<int>("RoleId")
.HasColumnType("int")
.HasColumnName("ROLE_ID");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.UserRoles", b =>
{ {
b.HasOne("UserManagement.Domain.Entities.Role", "Role") b.HasOne("UserManagement.Domain.Entities.Role", "Role")
.WithMany() .WithMany("UserRoles")
.HasForeignKey("RoleId") .HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("UserManagement.Domain.Entities.User", "User")
.WithMany("UserRoles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role"); b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{
b.Navigation("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{
b.Navigation("UserRoles");
}); });
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }

View File

@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace UserManagement.API.Migrations namespace UserManagement.API.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class Initial : Migration public partial class Init : Migration
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
@ -34,24 +34,40 @@ namespace UserManagement.API.Migrations
USER_NAME = table.Column<string>(type: "nvarchar(max)", nullable: false), USER_NAME = table.Column<string>(type: "nvarchar(max)", nullable: false),
FIRST_NAME = table.Column<string>(type: "nvarchar(max)", nullable: false), FIRST_NAME = table.Column<string>(type: "nvarchar(max)", nullable: false),
LAST_NAME = table.Column<string>(type: "nvarchar(max)", nullable: false), LAST_NAME = table.Column<string>(type: "nvarchar(max)", nullable: false),
PASSWORD = table.Column<string>(type: "nvarchar(max)", nullable: false), PASSWORD = table.Column<string>(type: "nvarchar(max)", nullable: false)
ROLE_ID = table.Column<int>(type: "int", nullable: false),
ROLE = table.Column<int>(type: "int", nullable: true)
}, },
constraints: table => constraints: table =>
{ {
table.PrimaryKey("PK_Users", x => x.ID); table.PrimaryKey("PK_Users", x => x.ID);
});
migrationBuilder.CreateTable(
name: "UserRoles",
columns: table => new
{
USER_ID = table.Column<int>(type: "int", nullable: false),
ROLE_ID = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserRoles", x => new { x.USER_ID, x.ROLE_ID });
table.ForeignKey( table.ForeignKey(
name: "FK_Users_Roles_ROLE_ID", name: "FK_UserRoles_Roles_ROLE_ID",
column: x => x.ROLE_ID, column: x => x.ROLE_ID,
principalTable: "Roles", principalTable: "Roles",
principalColumn: "ID", principalColumn: "ID",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UserRoles_Users_USER_ID",
column: x => x.USER_ID,
principalTable: "Users",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
}); });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_Users_ROLE_ID", name: "IX_UserRoles_ROLE_ID",
table: "Users", table: "UserRoles",
column: "ROLE_ID"); column: "ROLE_ID");
} }
@ -59,10 +75,13 @@ namespace UserManagement.API.Migrations
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "Users"); name: "UserRoles");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "Roles"); name: "Roles");
migrationBuilder.DropTable(
name: "Users");
} }
} }
} }

View File

@ -0,0 +1,133 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using UserManagement.Infrastructure;
#nullable disable
namespace UserManagement.API.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20240910112722_Second")]
partial class Second
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime")
.HasColumnName("CREATION_DATE");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ROLE");
b.HasKey("Id");
b.ToTable("Roles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("FIRST_NAME");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("LAST_NAME");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("USER_NAME");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b =>
{
b.Property<int>("UserId")
.HasColumnType("int")
.HasColumnName("USER_ID");
b.Property<int>("RoleId")
.HasColumnType("int")
.HasColumnName("ROLE_ID");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b =>
{
b.HasOne("UserManagement.Domain.Entities.Role", "Role")
.WithMany("UserRoles")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("UserManagement.Domain.Entities.User", "User")
.WithMany("UserRoles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{
b.Navigation("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{
b.Navigation("UserRoles");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserManagement.API.Migrations
{
/// <inheritdoc />
public partial class Second : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@ -0,0 +1,139 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using UserManagement.Infrastructure;
#nullable disable
namespace UserManagement.API.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20240911113732_UniqueProperties")]
partial class UniqueProperties
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime")
.HasColumnName("CREATION_DATE");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(450)")
.HasColumnName("ROLE");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Roles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("FIRST_NAME");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("LAST_NAME");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("nvarchar(450)")
.HasColumnName("USER_NAME");
b.HasKey("Id");
b.HasIndex("UserName")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b =>
{
b.Property<int>("UserId")
.HasColumnType("int")
.HasColumnName("USER_ID");
b.Property<int>("RoleId")
.HasColumnType("int")
.HasColumnName("ROLE_ID");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b =>
{
b.HasOne("UserManagement.Domain.Entities.Role", "Role")
.WithMany("UserRoles")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("UserManagement.Domain.Entities.User", "User")
.WithMany("UserRoles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{
b.Navigation("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{
b.Navigation("UserRoles");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,70 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserManagement.API.Migrations
{
/// <inheritdoc />
public partial class UniqueProperties : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "USER_NAME",
table: "Users",
type: "nvarchar(450)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ROLE",
table: "Roles",
type: "nvarchar(450)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.CreateIndex(
name: "IX_Users_USER_NAME",
table: "Users",
column: "USER_NAME",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Roles_ROLE",
table: "Roles",
column: "ROLE",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Users_USER_NAME",
table: "Users");
migrationBuilder.DropIndex(
name: "IX_Roles_ROLE",
table: "Roles");
migrationBuilder.AlterColumn<string>(
name: "USER_NAME",
table: "Users",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(450)");
migrationBuilder.AlterColumn<string>(
name: "ROLE",
table: "Roles",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(450)");
}
}
}

View File

@ -37,11 +37,14 @@ namespace UserManagement.API.Migrations
b.Property<string>("Name") b.Property<string>("Name")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(450)")
.HasColumnName("ROLE"); .HasColumnName("ROLE");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Roles"); b.ToTable("Roles");
}); });
@ -69,34 +72,63 @@ namespace UserManagement.API.Migrations
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD"); .HasColumnName("PASSWORD");
b.Property<int?>("ROLE") b.Property<string>("UserName")
.HasColumnType("int"); .IsRequired()
.HasColumnType("nvarchar(450)")
.HasColumnName("USER_NAME");
b.HasKey("Id");
b.HasIndex("UserName")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b =>
{
b.Property<int>("UserId")
.HasColumnType("int")
.HasColumnName("USER_ID");
b.Property<int>("RoleId") b.Property<int>("RoleId")
.HasColumnType("int") .HasColumnType("int")
.HasColumnName("ROLE_ID"); .HasColumnName("ROLE_ID");
b.Property<string>("UserName") b.HasKey("UserId", "RoleId");
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("USER_NAME");
b.HasKey("Id");
b.HasIndex("RoleId"); b.HasIndex("RoleId");
b.ToTable("Users"); b.ToTable("UserRoles");
}); });
modelBuilder.Entity("UserManagement.Domain.Entities.User", b => modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b =>
{ {
b.HasOne("UserManagement.Domain.Entities.Role", "Role") b.HasOne("UserManagement.Domain.Entities.Role", "Role")
.WithMany() .WithMany("UserRoles")
.HasForeignKey("RoleId") .HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("UserManagement.Domain.Entities.User", "User")
.WithMany("UserRoles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role"); b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{
b.Navigation("UserRoles");
});
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{
b.Navigation("UserRoles");
}); });
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">

View File

@ -1,6 +1,6 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=UserManagement;Trusted_Connection=True;TrustServerCertificate=True;" "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ProjectUserManagement;Trusted_Connection=True;TrustServerCertificate=True;"
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {

View File

@ -1,4 +1,6 @@
namespace UserManagement.Application.Dtos.Incomming using UserManagement.Application.Dtos.Outgoing;
namespace UserManagement.Application.Dtos.Incomming
{ {
public class CreatingUserDto public class CreatingUserDto
{ {
@ -10,6 +12,6 @@
public string Password { get; init; } public string Password { get; init; }
public int RoleId { get; set; } public ICollection<int> RoleIds { get; set; }
} }
} }

View File

@ -12,6 +12,6 @@
public string Password { get; init; } public string Password { get; init; }
public int RoleId { get; set; } public ICollection<int> RoleIds { get; set; }
} }
} }

View File

@ -4,6 +4,6 @@
{ {
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public required string Name { get; set; }
} }
} }

View File

@ -10,6 +10,6 @@
public string LastName { get; set; } public string LastName { get; set; }
public ReadingRoleDto? Role { get; set; } public ICollection<ReadingRoleDto> UserRoles { get; set; }
} }
} }

View File

@ -0,0 +1,8 @@
namespace UserManagement.Application.Dtos.Outgoing
{
public class ReadingUserRolesDto
{
public int RoleId { get; set; }
public string RoleName { get; set; }
}
}

View File

@ -21,8 +21,8 @@ namespace UserManagement.Application.Interfaces
// UPDATE // UPDATE
Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto); Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto);
// UPDATE USER ROLE //// UPDATE USER ROLE
Task UpdateUserRoleAsync(int userId, int roleId); //Task UpdateUserRoleAsync(int userId, int roleId);
// DELETE // DELETE
Task<bool> DeleteUserAsync(int id); Task<bool> DeleteUserAsync(int id);

View File

@ -11,13 +11,43 @@ namespace UserManagement.Application.MappingProfiles
{ {
// ROLE // ROLE
CreateMap<Role, CreatingRoleDto>().ReverseMap(); CreateMap<Role, CreatingRoleDto>().ReverseMap();
CreateMap<Role, ReadingRoleDto>().ReverseMap(); CreateMap<Role, ReadingRoleDto>().ReverseMap();
CreateMap<Role, UpdatingRoleDto>().ReverseMap(); CreateMap<Role, UpdatingRoleDto>().ReverseMap();
// USER // USER
CreateMap<User, CreatingUserDto>().ReverseMap(); CreateMap<User, CreatingUserDto>()
CreateMap<User, ReadingUserDto>().ReverseMap(); .ForMember(dest => dest.RoleIds, opt => opt.Ignore())
CreateMap<User, UpdatingUserDto>().ReverseMap(); .ReverseMap()
.AfterMap((src, dest) =>
{
dest.UserRoles = src.RoleIds?.Select(roleId => new UserRole
{
RoleId = roleId,
User = dest
}).ToList();
});
CreateMap<User, ReadingUserDto>()
.ForMember(dest => dest.UserRoles, opt => opt.MapFrom(src =>
src.UserRoles.Select(ur => new ReadingRoleDto
{
Id = ur.Role.Id,
Name = ur.Role.Name
}).ToList()));
CreateMap<User, UpdatingUserDto>()
.ForMember(dest => dest.RoleIds, opt => opt.Ignore())
.ReverseMap()
.AfterMap((src, dest) =>
{
dest.UserRoles = src.RoleIds?.Select(roleId => new UserRole
{
RoleId = roleId,
UserId = dest.Id
}).ToList();
});
} }
} }
} }

View File

@ -23,15 +23,23 @@ namespace UserManagement.Application.Services
// CREATE // CREATE
public async Task<User?> AddUserAsync(CreatingUserDto creatingUserDto) public async Task<User?> AddUserAsync(CreatingUserDto creatingUserDto)
{ {
// validating role var user = _mapper.Map<User>(creatingUserDto);
var role = await _roleRepository.GetByIdAsync(creatingUserDto.RoleId);
if (role == null) user.UserRoles = new List<UserRole>();
foreach (var roleId in creatingUserDto.RoleIds)
{ {
throw new ArgumentException("Role not found"); var role = await _roleRepository.GetByIdAsync(roleId);
if (role is not null)
{
user.UserRoles.Add(new UserRole { UserId = user.Id, RoleId = role.Id });
}
else
{
throw new ArgumentException($"Role with Id {roleId} not found");
}
} }
// mapping dto to entity
var user = _mapper.Map<User>(creatingUserDto);
var created = await _userRepository.AddAsync(user); var created = await _userRepository.AddAsync(user);
return created; return created;
} }
@ -63,29 +71,52 @@ namespace UserManagement.Application.Services
// UPDATE // UPDATE
public async Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto) public async Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto)
{ {
var user = _mapper.Map<User>(updatingUserDto); var user = await _userRepository.GetByIdAsync(updatingUserDto.Id);
if (user is null)
{
return false;
}
_mapper.Map(updatingUserDto, user);
user.UserRoles.Clear();
foreach(var roleId in updatingUserDto.RoleIds)
{
var role = await _roleRepository.GetByIdAsync(roleId);
if (role is not null)
{
user.UserRoles.Add(new UserRole { UserId = user.Id, RoleId = role.Id });
}
else
{
throw new ArgumentException($"Role with Id {roleId} not found");
}
}
bool isUpdated = await _userRepository.UpdateAsync(user); bool isUpdated = await _userRepository.UpdateAsync(user);
return isUpdated; return isUpdated;
} }
// UPDATE USER ROLE -- die Rolle eines Users aktualisieren //// UPDATE USER ROLE -- die Rolle eines Users aktualisieren
public async Task UpdateUserRoleAsync(int userId, int roleId) //public async Task UpdateUserRoleAsync(int userId, int roleId)
{ //{
var user = await _userRepository.GetByIdAsync(userId); // var user = await _userRepository.GetByIdAsync(userId);
if (user == null) // if (user == null)
{ // {
throw new ArgumentException("User not found"); // throw new ArgumentException("User not found");
} // }
var role = await _roleRepository.GetByIdAsync(roleId); // var role = await _roleRepository.GetByIdAsync(roleId);
if (role == null) // if (role == null)
{ // {
throw new ArgumentException("Role not found"); // throw new ArgumentException("Role not found");
} // }
user.RoleId = roleId; // user.UserRoles = roleId;
await _userRepository.SaveAsync(); // await _userRepository.SaveAsync();
} //}
// DELETE // DELETE
public async Task<bool> DeleteUserAsync(int id) public async Task<bool> DeleteUserAsync(int id)

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace UserManagement.Domain.Entities namespace UserManagement.Domain.Entities
@ -12,7 +13,10 @@ namespace UserManagement.Domain.Entities
[Required] [Required]
[Column("ROLE")] [Column("ROLE")]
public string Name { get; set; } public required string Name { get; set; }
[Column("USERS")]
public ICollection<UserRole>? UserRoles { get; init; } = new Collection<UserRole>();
[Required] [Required]
[Column("CREATION_DATE", TypeName = "datetime")] [Column("CREATION_DATE", TypeName = "datetime")]

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace UserManagement.Domain.Entities namespace UserManagement.Domain.Entities
@ -22,14 +23,14 @@ namespace UserManagement.Domain.Entities
[Column("LAST_NAME")] [Column("LAST_NAME")]
public string LastName { get; set; } public string LastName { get; set; }
//[Obsolete("Use password hash")]
[Required] [Required]
[Column("PASSWORD")] [Column("PASSWORD")]
public string Password { get; init; } public required string Password { get; init; }
[Column("ROLE_ID")] //public required string PasswordHash { get; init; }
public int RoleId { get; set; }
[ForeignKey("ROLE")] [Column("ROLES")]
public Role? Role { get; set; } public ICollection<UserRole>? UserRoles { get; set; } = new Collection<UserRole>();
} }
} }

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace UserManagement.Domain.Entities
{
public class UserRole
{
[Column("USER_ID")]
public int UserId { get; set; }
[ForeignKey("UserId")]
public User? User { get; set; }
[Column("ROLE_ID")]
public int RoleId { get; set; }
[ForeignKey("RoleId")]
public Role? Role { get; set; }
}
}

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">

View File

@ -12,15 +12,32 @@ namespace UserManagement.Infrastructure
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; } public DbSet<Role> Roles { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>() modelBuilder.Entity<User>()
.HasOne(u => u.Role) .HasIndex(u => u.UserName)
.WithMany() .IsUnique();
.HasForeignKey(u => u.RoleId);
modelBuilder.Entity<Role>()
.HasIndex(r => r.Name)
.IsUnique();
modelBuilder.Entity<UserRole>()
.HasKey(ur => new { ur.UserId, ur.RoleId });
modelBuilder.Entity<UserRole>()
.HasOne(ur => ur.User)
.WithMany(u => u.UserRoles)
.HasForeignKey(ur => ur.UserId);
modelBuilder.Entity<UserRole>()
.HasOne(ur => ur.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId);
} }
} }
} }

View File

@ -24,19 +24,28 @@ namespace UserManagement.Infrastructure.Repositories
// READ ALL // READ ALL
public async Task<IEnumerable<User>> GetAllAsync() public async Task<IEnumerable<User>> GetAllAsync()
{ {
return await _context.Users.Include(u => u.Role).ToListAsync(); return await _context.Users
.Include(u => u.UserRoles)
.ThenInclude(ur => ur.Role)
.ToListAsync();
} }
// READ BY ID // READ BY ID
public async Task<User?> GetByIdAsync(int id) public async Task<User?> GetByIdAsync(int id)
{ {
return await _context.Users.Where(user => user.Id == id).Include(user => user.Role).FirstAsync(); return await _context.Users.Where(user => user.Id == id)
.Include(user => user.UserRoles)
.ThenInclude(ur =>ur.Role)
.FirstAsync();
} }
// READ BY USERNAME // READ BY USERNAME
public async Task<User?> GetByUsernameAsync(string username) public async Task<User?> GetByUsernameAsync(string username)
{ {
return await _context.Users.Include(user => user.Role).FirstOrDefaultAsync(u => u.UserName == username); return await _context.Users
.Include(user => user.UserRoles)
.ThenInclude(ur => ur.Role)
.FirstOrDefaultAsync(u => u.UserName == username);
} }
// UPDATE // UPDATE

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">