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.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Security.Claims;
using UserManagement.Application.Dtos.Auth;
using UserManagement.Application.Interfaces;
using Swashbuckle.AspNetCore.Annotations;
namespace UserManagement.API.Controllers
{
@ -30,7 +30,7 @@ namespace UserManagement.API.Controllers
{
// Validate user
var user = await _userService.GetByUsernameAsync(login.Username);
if (user == null)
if (user is null)
{
return Unauthorized();
}
@ -49,9 +49,13 @@ namespace UserManagement.API.Controllers
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Surname, user.LastName ?? ""),
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
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
@ -82,5 +86,10 @@ namespace UserManagement.API.Controllers
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 UserManagement.Application.Dtos.Incomming;
using UserManagement.Application.Interfaces;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace UserManagement.API.Controllers
{
@ -114,7 +115,18 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UpdateRole(int id, UpdatingRoleDto updatingRoleDto)
{
if (id <= 0)
{
return BadRequest("Invalid Id");
}
var updated = await _roleService.UpdateRoleAsync(updatingRoleDto);
if (!updated)
{
return BadRequest("Update failed");
}
return Ok(updated);
}
@ -126,7 +138,18 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)]
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();
}
}

View File

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

View File

@ -12,8 +12,8 @@ using UserManagement.Infrastructure;
namespace UserManagement.API.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20240821105311_Initial")]
partial class Initial
[Migration("20240910064554_Init")]
partial class Init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -72,13 +72,6 @@ namespace UserManagement.API.Migrations
.HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD");
b.Property<int?>("ROLE")
.HasColumnType("int");
b.Property<int>("RoleId")
.HasColumnType("int")
.HasColumnName("ROLE_ID");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("nvarchar(max)")
@ -86,20 +79,53 @@ namespace UserManagement.API.Migrations
b.HasKey("Id");
b.HasIndex("RoleId");
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")
.WithMany()
.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

@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace UserManagement.API.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -34,24 +34,40 @@ namespace UserManagement.API.Migrations
USER_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),
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)
PASSWORD = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
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(
name: "FK_Users_Roles_ROLE_ID",
name: "FK_UserRoles_Roles_ROLE_ID",
column: x => x.ROLE_ID,
principalTable: "Roles",
principalColumn: "ID",
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(
name: "IX_Users_ROLE_ID",
table: "Users",
name: "IX_UserRoles_ROLE_ID",
table: "UserRoles",
column: "ROLE_ID");
}
@ -59,10 +75,13 @@ namespace UserManagement.API.Migrations
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
name: "UserRoles");
migrationBuilder.DropTable(
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")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnType("nvarchar(450)")
.HasColumnName("ROLE");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Roles");
});
@ -69,34 +72,63 @@ namespace UserManagement.API.Migrations
.HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD");
b.Property<int?>("ROLE")
.HasColumnType("int");
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.Property<string>("UserName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("USER_NAME");
b.HasKey("Id");
b.HasKey("UserId", "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")
.WithMany()
.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

@ -8,6 +8,7 @@
<ItemGroup>
<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.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">

View File

@ -1,6 +1,6 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=UserManagement;Trusted_Connection=True;TrustServerCertificate=True;"
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ProjectUserManagement;Trusted_Connection=True;TrustServerCertificate=True;"
},
"Logging": {
"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
{
@ -10,6 +12,6 @@
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 int RoleId { get; set; }
public ICollection<int> RoleIds { get; set; }
}
}

View File

@ -4,6 +4,6 @@
{
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 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
Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto);
// UPDATE USER ROLE
Task UpdateUserRoleAsync(int userId, int roleId);
//// UPDATE USER ROLE
//Task UpdateUserRoleAsync(int userId, int roleId);
// DELETE
Task<bool> DeleteUserAsync(int id);

View File

@ -11,13 +11,43 @@ namespace UserManagement.Application.MappingProfiles
{
// ROLE
CreateMap<Role, CreatingRoleDto>().ReverseMap();
CreateMap<Role, ReadingRoleDto>().ReverseMap();
CreateMap<Role, UpdatingRoleDto>().ReverseMap();
// USER
CreateMap<User, CreatingUserDto>().ReverseMap();
CreateMap<User, ReadingUserDto>().ReverseMap();
CreateMap<User, UpdatingUserDto>().ReverseMap();
CreateMap<User, CreatingUserDto>()
.ForMember(dest => dest.RoleIds, opt => opt.Ignore())
.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
public async Task<User?> AddUserAsync(CreatingUserDto creatingUserDto)
{
// validating role
var role = await _roleRepository.GetByIdAsync(creatingUserDto.RoleId);
if (role == null)
var user = _mapper.Map<User>(creatingUserDto);
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);
return created;
}
@ -63,29 +71,52 @@ namespace UserManagement.Application.Services
// UPDATE
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);
return isUpdated;
}
// UPDATE USER ROLE -- die Rolle eines Users aktualisieren
public async Task UpdateUserRoleAsync(int userId, int roleId)
{
var user = await _userRepository.GetByIdAsync(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
//// UPDATE USER ROLE -- die Rolle eines Users aktualisieren
//public async Task UpdateUserRoleAsync(int userId, int roleId)
//{
// var user = await _userRepository.GetByIdAsync(userId);
// if (user == null)
// {
// throw new ArgumentException("User not found");
// }
var role = await _roleRepository.GetByIdAsync(roleId);
if (role == null)
{
throw new ArgumentException("Role not found");
}
// var role = await _roleRepository.GetByIdAsync(roleId);
// if (role == null)
// {
// throw new ArgumentException("Role not found");
// }
user.RoleId = roleId;
await _userRepository.SaveAsync();
}
// user.UserRoles = roleId;
// await _userRepository.SaveAsync();
//}
// DELETE
public async Task<bool> DeleteUserAsync(int id)

View File

@ -8,6 +8,7 @@
<ItemGroup>
<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.SqlServer" 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;
namespace UserManagement.Domain.Entities
@ -12,7 +13,10 @@ namespace UserManagement.Domain.Entities
[Required]
[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]
[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;
namespace UserManagement.Domain.Entities
@ -22,14 +23,14 @@ namespace UserManagement.Domain.Entities
[Column("LAST_NAME")]
public string LastName { get; set; }
//[Obsolete("Use password hash")]
[Required]
[Column("PASSWORD")]
public string Password { get; init; }
public required string Password { get; init; }
[Column("ROLE_ID")]
public int RoleId { get; set; }
//public required string PasswordHash { get; init; }
[ForeignKey("ROLE")]
public Role? Role { get; set; }
[Column("ROLES")]
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>
<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.SqlServer" 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<Role> Roles { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOne(u => u.Role)
.WithMany()
.HasForeignKey(u => u.RoleId);
.HasIndex(u => u.UserName)
.IsUnique();
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
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
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
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

View File

@ -8,6 +8,7 @@
<ItemGroup>
<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.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">