Moved Role Assignment from User to UserRoles

This commit is contained in:
OlgunR 2024-09-30 08:45:48 +02:00
parent dc3fb100b1
commit ebd07204b3
26 changed files with 652 additions and 132 deletions

View File

@ -32,14 +32,14 @@ namespace UserManagement.API.Controllers
var user = await _userService.GetByUsernameAsync(login.Username, includeRoles: true); var user = await _userService.GetByUsernameAsync(login.Username, includeRoles: true);
if (user is null) if (user is null)
{ {
return Unauthorized(); return Unauthorized("Benutzername und Passwort stimmen nicht überein!");
} }
// Validate login credentials // Validate login credentials
var isValid = await _authService.ValidateAsync(login.Username, login.Password); var isValid = await _authService.ValidateAsync(login.Username, login.Password);
if (!isValid) if (!isValid)
{ {
return Unauthorized(); return Unauthorized("Benutzername und Passwort stimmen nicht überein!");
} }
// Create claims based on the user information // Create claims based on the user information

View File

@ -3,7 +3,6 @@ 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
{ {

View File

@ -3,7 +3,6 @@ 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
{ {
@ -14,9 +13,11 @@ namespace UserManagement.API.Controllers
{ {
// CTOR // CTOR
private readonly IUserService _userService; private readonly IUserService _userService;
public UserController(IUserService userService) private readonly ILogger<UserController> _logger;
public UserController(IUserService userService, ILogger<UserController> logger)
{ {
_userService = userService; _userService = userService;
_logger = logger;
} }
// CREATE // CREATE
@ -28,7 +29,6 @@ namespace UserManagement.API.Controllers
[Authorize(Roles = "Admin")] [Authorize(Roles = "Admin")]
public async Task<IActionResult> CreateUser([FromBody] CreatingUserDto creatingUserDto) public async Task<IActionResult> CreateUser([FromBody] CreatingUserDto creatingUserDto)
{ {
// Validate incomming model
if (!ModelState.IsValid) if (!ModelState.IsValid)
{ {
return BadRequest(ModelState); return BadRequest(ModelState);
@ -36,21 +36,15 @@ namespace UserManagement.API.Controllers
try try
{ {
// Try to add user asynchronously var createdUser = await _userService.AddUserAsync(creatingUserDto);
var result = await _userService.AddUserAsync(creatingUserDto);
// If user is successfully created, return a CreatedAtAction response with the created resource if (createdUser is not null)
if (result is not null)
{ {
var id = result.Id; return CreatedAtAction(nameof(GetUserById), new { id = createdUser.Id }, createdUser);
var createdResource = new { Id = id };
var actionName = nameof(GetUserById);
var routeValue = new { id = createdResource.Id };
return CreatedAtAction(actionName, routeValue, createdResource);
} }
else else
{ {
return BadRequest("Creation failed"); return BadRequest("Erstellung des Benutzers fehlgeschlagen!");
} }
} }
catch (Exception ex) catch (Exception ex)
@ -63,10 +57,18 @@ namespace UserManagement.API.Controllers
[HttpGet] [HttpGet]
[SwaggerOperation(Summary = "Get all Users")] [SwaggerOperation(Summary = "Get all Users")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetAllUsers([FromQuery] bool includeRoles = true) public async Task<IActionResult> GetAllUsers([FromQuery] bool includeRoles = true)
{ {
var users = await _userService.GetUsersAsync(includeRoles); try
return Ok(users); {
var users = await _userService.GetUsersAsync(includeRoles);
return Ok(users);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
}
} }
// READ BY ID // READ BY ID
@ -77,16 +79,19 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUserById(int id, [FromQuery] bool includeRoles = true) public async Task<IActionResult> GetUserById(int id, [FromQuery] bool includeRoles = true)
{ {
if (id <= 0) try
{ {
return BadRequest("Invalid Id"); var user = await _userService.GetByIdAsync(id, includeRoles);
return Ok(user);
} }
var user = await _userService.GetByIdAsync(id, includeRoles); catch (ArgumentException ex)
if (user == null)
{ {
return NotFound(); return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
} }
return Ok(user);
} }
// READ BY USERNAME // READ BY USERNAME
@ -97,16 +102,19 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUserByUsername(string username, [FromQuery] bool includeRoles = true) public async Task<IActionResult> GetUserByUsername(string username, [FromQuery] bool includeRoles = true)
{ {
if (string.IsNullOrEmpty(username)) try
{ {
return BadRequest("Username connot be empty"); var user = await _userService.GetByUsernameAsync(username, includeRoles);
return Ok(user);
} }
var user = await _userService.GetByUsernameAsync(username, includeRoles); catch (ArgumentException ex)
if (user == null)
{ {
return NotFound(); return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
} }
return Ok(user);
} }
// READ BY ROLE // READ BY ROLE
@ -117,12 +125,19 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUsersByRole(string role) public async Task<IActionResult> GetUsersByRole(string role)
{ {
if (string.IsNullOrEmpty(role)) try
{ {
return BadRequest("Role cannot be empty"); var users = await _userService.GetByRoleAsync(role);
return Ok(users);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
} }
var users = await _userService.GetByRoleAsync(role);
return Ok(users);
} }
// UPDATE // UPDATE
@ -130,21 +145,27 @@ namespace UserManagement.API.Controllers
[SwaggerOperation(Summary = "Update User")] [SwaggerOperation(Summary = "Update User")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUser(int id, UpdatingUserDto updatingUserDto) public async Task<IActionResult> UpdateUser(int id, UpdatingUserDto updatingUserDto)
{ {
if (id <= 0) try
{ {
return BadRequest("Invalid Id"); var updated = await _userService.UpdateUserAsync(updatingUserDto);
return Ok(updated);
} }
catch (ArgumentException ex)
var updated = await _userService.UpdateUserAsync(updatingUserDto);
if (!updated)
{ {
return BadRequest("Update failed"); return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
}
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
} }
return Ok(updated);
} }
// DELETE // DELETE
@ -155,19 +176,19 @@ 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)
{ {
if (id <= 0) try
{ {
return BadRequest("Invalid Id"); var deleted = await _userService.DeleteUserAsync(id);
return Ok(deleted);
} }
catch (ArgumentException ex)
var deleted = await _userService.DeleteUserAsync(id);
if (!deleted)
{ {
return BadRequest("Deletion failed"); return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
} }
return Ok();
} }
} }
} }

View File

@ -0,0 +1,82 @@
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using UserManagement.Application.Dtos.Incomming;
using UserManagement.Application.Dtos.Outgoing;
using UserManagement.Application.Interfaces;
namespace UserManagement.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UserRolesController : Controller
{
// CTOR
private readonly IUserRolesService _userRolesService;
public UserRolesController(IUserRolesService userRolesService)
{
_userRolesService = userRolesService;
}
// CREATE ASSIGNMENT
[HttpPost("AssignRoleToUser")]
[SwaggerOperation(Summary = "Assign Role to User the better way")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> CreateAssignmentAsync(CreatingUserRolesDto creatingUserRolesDto)
{
try
{
var result = await _userRolesService.CreateAssignmentAsync(creatingUserRolesDto);
if (result)
{
return Ok("Rolle erfolgreich zugewiesen!");
}
else
{
return BadRequest("Zuweisen der Rolle fehlgeschlagen!");
}
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
}
}
// REMOVE ROLE FROM USER
[HttpDelete("RemoveRoleFromUser")]
[SwaggerOperation(Summary = "Remove Role from User")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> RemoveRoleFromUser(CreatingUserRolesDto creatingUserRolesDto)
{
try
{
var result = await _userRolesService.RemoveRoleFromUserAsync(creatingUserRolesDto);
if (result)
{
return Ok("Rolle erfolgreich entfernt!");
}
else
{
return BadRequest("Entfernung der Rolle fehlgeschlagen!");
}
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
catch (KeyNotFoundException ex)
{
return NotFound(ex.Message);
}
}
}
}

View File

@ -0,0 +1,146 @@
// <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("20240926093702_AddIdColumnToUserRoles")]
partial class AddIdColumnToUserRoles
{
/// <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>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD_HASH");
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.UserRoles", b =>
{
b.Property<int>("UserId")
.HasColumnType("int")
.HasColumnName("USER_ID");
b.Property<int>("RoleId")
.HasColumnType("int")
.HasColumnName("ROLE_ID");
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("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("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,30 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserManagement.API.Migrations
{
/// <inheritdoc />
public partial class AddIdColumnToUserRoles : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "ID",
table: "UserRoles",
type: "int",
nullable: false,
defaultValue: 0)
.Annotation("SqlServer:Identity", "1, 1");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ID",
table: "UserRoles");
}
}
}

View File

@ -85,7 +85,7 @@ namespace UserManagement.API.Migrations
b.ToTable("Users"); b.ToTable("Users");
}); });
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b => modelBuilder.Entity("UserManagement.Domain.Entities.UserRoles", b =>
{ {
b.Property<int>("UserId") b.Property<int>("UserId")
.HasColumnType("int") .HasColumnType("int")
@ -95,6 +95,13 @@ namespace UserManagement.API.Migrations
.HasColumnType("int") .HasColumnType("int")
.HasColumnName("ROLE_ID"); .HasColumnName("ROLE_ID");
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.HasKey("UserId", "RoleId"); b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId"); b.HasIndex("RoleId");
@ -102,7 +109,7 @@ namespace UserManagement.API.Migrations
b.ToTable("UserRoles"); b.ToTable("UserRoles");
}); });
modelBuilder.Entity("UserManagement.Domain.Entities.UserRole", b => modelBuilder.Entity("UserManagement.Domain.Entities.UserRoles", b =>
{ {
b.HasOne("UserManagement.Domain.Entities.Role", "Role") b.HasOne("UserManagement.Domain.Entities.Role", "Role")
.WithMany("UserRoles") .WithMany("UserRoles")

View File

@ -18,11 +18,14 @@ builder.Services.AddSwaggerGen(s => s.EnableAnnotations());
builder.Services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); builder.Services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
builder.Services.AddScoped<IRoleService, RoleService>();
builder.Services.AddScoped<IRoleRepository, RoleRepository>();
builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IUserRepository, UserRepository>(); builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IRoleService, RoleService>(); builder.Services.AddScoped<IUserRolesService, UserRolesService>();
builder.Services.AddScoped<IRoleRepository, RoleRepository>(); builder.Services.AddScoped<IUserRolesRepository, UserRolesRepository>();
builder.Services.AddScoped<IAuthService, AuthService>(); builder.Services.AddScoped<IAuthService, AuthService>();

View File

@ -0,0 +1,15 @@
DECLARE @__role_0 nvarchar(450) = N'admin';
SELECT [u].[ID], [u].[FIRST_NAME], [u].[LAST_NAME], [u].[PASSWORD_HASH], [u].[USER_NAME], [t].[USER_ID], [t].[ROLE_ID], [t].[ID], [t].[CREATION_DATE], [t].[ROLE]
FROM [Users] AS [u]
LEFT JOIN (
SELECT [u1].[USER_ID], [u1].[ROLE_ID], [r0].[ID], [r0].[CREATION_DATE], [r0].[ROLE]
FROM [UserRoles] AS [u1]
INNER JOIN [Roles] AS [r0] ON [u1].[ROLE_ID] = [r0].[ID]
) AS [t] ON [u].[ID] = [t].[USER_ID]
WHERE EXISTS (
SELECT 1
FROM [UserRoles] AS [u0]
INNER JOIN [Roles] AS [r] ON [u0].[ROLE_ID] = [r].[ID]
WHERE [u].[ID] = [u0].[USER_ID] AND [r].[ROLE] = @__role_0)
ORDER BY [u].[ID], [t].[USER_ID], [t].[ROLE_ID]

View File

@ -1,6 +1,4 @@
using UserManagement.Application.Dtos.Outgoing; namespace UserManagement.Application.Dtos.Incomming
namespace UserManagement.Application.Dtos.Incomming
{ {
public class CreatingUserDto public class CreatingUserDto
{ {
@ -11,7 +9,5 @@ namespace UserManagement.Application.Dtos.Incomming
public string LastName { get; set; } public string LastName { get; set; }
public string Password { get; set; } public string Password { get; set; }
public ICollection<int> RoleIds { get; set; }
} }
} }

View File

@ -0,0 +1,8 @@
namespace UserManagement.Application.Dtos.Incomming
{
public class CreatingUserRolesDto
{
public int UserId { get; set; }
public int RoleId { get; set; }
}
}

View File

@ -1,4 +1,6 @@
namespace UserManagement.Application.Dtos.Incomming using UserManagement.Domain.Entities;
namespace UserManagement.Application.Dtos.Incomming
{ {
public class UpdatingUserDto public class UpdatingUserDto
{ {
@ -11,7 +13,5 @@
public string LastName { get; set; } public string LastName { get; set; }
public string Password { get; set; } public string Password { get; set; }
public ICollection<int> RoleIds { get; set; }
} }
} }

View File

@ -0,0 +1,8 @@
namespace UserManagement.Application.Dtos.Incomming
{
public class UpdatingUserRolesDto
{
public int UserId { get; set; }
public int RoleId { get; set; }
}
}

View File

@ -2,6 +2,10 @@
{ {
public class ReadingUserRolesDto public class ReadingUserRolesDto
{ {
public int UserId { get; set; }
public string UserName { get; set; }
public int RoleId { get; set; } public int RoleId { get; set; }
public string RoleName { get; set; } public string RoleName { get; set; }

View File

@ -0,0 +1,14 @@
using UserManagement.Application.Dtos.Incomming;
using UserManagement.Application.Dtos.Outgoing;
namespace UserManagement.Application.Interfaces
{
public interface IUserRolesService
{
// CREATE ASSIGNMENT
Task<bool> CreateAssignmentAsync(CreatingUserRolesDto creatingUserRolesDto);
// REMOVE ROLE FORM USER
Task<bool> RemoveRoleFromUserAsync(CreatingUserRolesDto creatingUserRolesDto);
}
}

View File

@ -11,23 +11,18 @@ 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 ROLES
CreateMap<UserRoles, CreatingUserRolesDto>().ReverseMap();
CreateMap<UserRoles, ReadingUserRolesDto>().ReverseMap();
// USER // USER
CreateMap<User, CreatingUserDto>() CreateMap<User, CreatingUserDto>()
.ForMember(dest => dest.RoleIds, opt => opt.Ignore())
.ReverseMap() .ReverseMap()
.AfterMap((src, dest) => .AfterMap((src, dest) =>
{ {
dest.UserRoles = src.RoleIds?.Select(roleId => new UserRole
{
RoleId = roleId,
User = dest
}).ToList();
dest.PasswordHash = BCrypt.Net.BCrypt.HashPassword(src.Password); dest.PasswordHash = BCrypt.Net.BCrypt.HashPassword(src.Password);
}); });
@ -40,16 +35,9 @@ namespace UserManagement.Application.MappingProfiles
}).ToList())); }).ToList()));
CreateMap<User, UpdatingUserDto>() CreateMap<User, UpdatingUserDto>()
.ForMember(dest => dest.RoleIds, opt => opt.Ignore())
.ReverseMap() .ReverseMap()
.AfterMap((src, dest) => .AfterMap((src, dest) =>
{ {
dest.UserRoles = src.RoleIds?.Select(roleId => new UserRole
{
RoleId = roleId,
UserId = dest.Id
}).ToList();
dest.PasswordHash = BCrypt.Net.BCrypt.HashPassword(src.Password); dest.PasswordHash = BCrypt.Net.BCrypt.HashPassword(src.Password);
}); });
} }

View File

@ -6,7 +6,7 @@ namespace UserManagement.Application.Services
public class AuthService : IAuthService public class AuthService : IAuthService
{ {
// CTOR // CTOR
private IUserRepository _userRepository; private readonly IUserRepository _userRepository;
public AuthService(IUserRepository userRepository) public AuthService(IUserRepository userRepository)
{ {
_userRepository = userRepository; _userRepository = userRepository;

View File

@ -0,0 +1,119 @@
using AutoMapper;
using UserManagement.Application.Dtos.Incomming;
using UserManagement.Application.Dtos.Outgoing;
using UserManagement.Application.Interfaces;
using UserManagement.Domain.Entities;
using UserManagement.Infrastructure.Interfaces;
namespace UserManagement.Application.Services
{
public class UserRolesService : IUserRolesService
{
// CTOR
private readonly IUserRolesRepository _userRolesRepository;
private readonly IUserRepository _userRepository;
private readonly IRoleRepository _roleRepository;
private readonly IMapper _mapper;
public UserRolesService(IUserRolesRepository userRolesRepository, IUserRepository userRepository, IRoleRepository roleRepository, IMapper mapper)
{
_userRolesRepository = userRolesRepository;
_userRepository = userRepository;
_roleRepository = roleRepository;
_mapper = mapper;
}
// CREATE ASSIGNMENT
public async Task<bool> CreateAssignmentAsync(CreatingUserRolesDto creatingUserRolesDto)
{
if (creatingUserRolesDto.UserId <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
var user = await _userRepository.GetByIdAsync(creatingUserRolesDto.UserId);
if (user == null)
{
throw new KeyNotFoundException("Benutzer nicht gefunden!");
}
if (creatingUserRolesDto.RoleId <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
var role = await _roleRepository.GetByIdAsync(creatingUserRolesDto.RoleId);
if (role == null)
{
throw new KeyNotFoundException("Rolle nicht gefunden!");
}
var userRoles = _mapper.Map<UserRoles>(creatingUserRolesDto);
var assigned = await _userRolesRepository.CreateAssignmentAsync(userRoles);
return assigned;
}
//// ASSIGNING ROLES BY NAMES
//public async Task<bool> AssignAsync(string username, string roleName)
//{
// var user = await _userRepository.GetByUsernameAsync(username);
// var role = await _roleRepository.GetByNameAsync(roleName);
// if (user is null || role is null)
// {
// return false;
// }
// var dto = new CreatingUserRolesDto()
// {
// RoleId = role.Id,
// UserId = user.Id
// };
// return await CreateAssignmentAsync(dto);
//}
// REMOVE ROLE FROM USER
public async Task<bool> RemoveRoleFromUserAsync(CreatingUserRolesDto creatingUserRolesDto)
{
if (creatingUserRolesDto.UserId <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
var user = await _userRepository.GetByIdAsync(creatingUserRolesDto.UserId);
if (user == null)
{
throw new KeyNotFoundException("Benutzer nicht gefunden!");
}
if (creatingUserRolesDto.RoleId <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
var role = await _roleRepository.GetByIdAsync(creatingUserRolesDto.RoleId);
if (role == null)
{
throw new KeyNotFoundException("Rolle nicht gefunden!");
}
var userRole = _mapper.Map<UserRoles>(creatingUserRolesDto);
if (userRole == null)
{
throw new KeyNotFoundException("Die Rolle ist dem Benutzer nicht zugewiesen!");
}
var result = await _userRolesRepository.DeleteAssignmentAsync(userRole);
return result;
}
}
}

View File

@ -30,22 +30,8 @@ namespace UserManagement.Application.Services
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(creatingUserDto.Password); user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(creatingUserDto.Password);
} }
user.UserRoles = new List<UserRole>();
foreach (var roleId in creatingUserDto.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");
}
}
var created = await _userRepository.AddAsync(user); var created = await _userRepository.AddAsync(user);
return created; return created;
} }
@ -53,42 +39,90 @@ namespace UserManagement.Application.Services
public async Task<IEnumerable<ReadingUserDto>> GetUsersAsync(bool includeRoles = true) public async Task<IEnumerable<ReadingUserDto>> GetUsersAsync(bool includeRoles = true)
{ {
var users = await _userRepository.GetAllAsync(includeRoles); var users = await _userRepository.GetAllAsync(includeRoles);
if (users == null)
{
throw new KeyNotFoundException("Keine Benutzer gefunden!");
}
var readDto = _mapper.Map<IEnumerable<ReadingUserDto>>(users); var readDto = _mapper.Map<IEnumerable<ReadingUserDto>>(users);
return readDto; return readDto;
} }
// READ BY ID // READ BY ID
public async Task<ReadingUserDto> GetByIdAsync(int id, bool includeRoles = true) public async Task<ReadingUserDto> GetByIdAsync(int id, bool includeRoles = true)
{ {
if (id <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
var user = await _userRepository.GetByIdAsync(id, includeRoles); var user = await _userRepository.GetByIdAsync(id, includeRoles);
if (user == null)
{
throw new KeyNotFoundException("Benutzer nicht gefunden!");
}
var readDto = _mapper.Map<ReadingUserDto>(user); var readDto = _mapper.Map<ReadingUserDto>(user);
return readDto; return readDto;
} }
// READ BY USERNAME // READ BY USERNAME
public async Task<ReadingUserDto> GetByUsernameAsync(string username, bool includeRoles = true) public async Task<ReadingUserDto> GetByUsernameAsync(string username, bool includeRoles = true)
{ {
if (string.IsNullOrEmpty(username))
{
throw new ArgumentException("Ungültiger Benutzername!");
}
var user = await _userRepository.GetByUsernameAsync(username, includeRoles); var user = await _userRepository.GetByUsernameAsync(username, includeRoles);
if (user == null)
{
throw new KeyNotFoundException("Benutzer nicht gefunden!");
}
var readDto = _mapper.Map<ReadingUserDto>(user); var readDto = _mapper.Map<ReadingUserDto>(user);
return readDto; return readDto;
} }
// READ BY ROLE // READ BY ROLE
public async Task<IEnumerable<ReadingUserDto>> GetByRoleAsync(string role) public async Task<IEnumerable<ReadingUserDto>> GetByRoleAsync(string role)
{ {
if (string.IsNullOrEmpty(role))
{
throw new ArgumentException("Ungültige Rolle!");
}
var users = await _userRepository.GetByRoleAsync(role); var users = await _userRepository.GetByRoleAsync(role);
if (users == null)
{
throw new KeyNotFoundException("Keine Benutzer in dieser Rolle gefunden!");
}
var readDto = _mapper.Map<IEnumerable<ReadingUserDto>>(users); var readDto = _mapper.Map<IEnumerable<ReadingUserDto>>(users);
return readDto; return readDto;
} }
// UPDATE // UPDATE
public async Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto) public async Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto)
{ {
if (updatingUserDto.Id <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
var user = await _userRepository.GetByIdAsync(updatingUserDto.Id); var user = await _userRepository.GetByIdAsync(updatingUserDto.Id);
if (user is null) if (user == null)
{ {
return false; throw new KeyNotFoundException("Benutzer nicht gefunden!");
} }
_mapper.Map(updatingUserDto, user); _mapper.Map(updatingUserDto, user);
@ -98,34 +132,28 @@ namespace UserManagement.Application.Services
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(updatingUserDto.Password); user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(updatingUserDto.Password);
} }
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;
} }
// DELETE // DELETE
public async Task<bool> DeleteUserAsync(int id) public async Task<bool> DeleteUserAsync(int id)
{ {
User? user = await _userRepository.GetByIdAsync(id); if (id <= 0)
{
throw new ArgumentException("Ungültige Id!");
}
if (user is null) var user = await _userRepository.GetByIdAsync(id);
return false;
if (user == null)
{
throw new KeyNotFoundException("Benutzer nicht gefunden!");
}
bool isDeleted = await _userRepository.DeleteAsync(user); bool isDeleted = await _userRepository.DeleteAsync(user);
return isDeleted; return isDeleted;
} }
} }

View File

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

View File

@ -1,5 +1,4 @@
using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace UserManagement.Domain.Entities namespace UserManagement.Domain.Entities
@ -27,6 +26,6 @@ namespace UserManagement.Domain.Entities
[Column("PASSWORD_HASH")] [Column("PASSWORD_HASH")]
public required string PasswordHash { get; set; } public required string PasswordHash { get; set; }
public ICollection<UserRole>? UserRoles { get; set; } = new Collection<UserRole>(); public ICollection<UserRoles>? UserRoles { get; set; }
} }
} }

View File

@ -1,9 +1,15 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace UserManagement.Domain.Entities namespace UserManagement.Domain.Entities
{ {
public class UserRole public class UserRoles
{ {
[Column("ID")]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("USER_ID")] [Column("USER_ID")]
public int UserId { get; set; } public int UserId { get; set; }

View File

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

View File

@ -0,0 +1,13 @@
using UserManagement.Domain.Entities;
namespace UserManagement.Infrastructure.Interfaces
{
public interface IUserRolesRepository
{
// CREATE ASSIGNMENT
Task<bool> CreateAssignmentAsync(UserRoles userRoles);
// DELETE ASSIGNMENT
Task<bool> DeleteAssignmentAsync(UserRoles userRoles);
}
}

View File

@ -63,11 +63,14 @@ namespace UserManagement.Infrastructure.Repositories
// READ BY ROLE // READ BY ROLE
public async Task<IEnumerable<User>> GetByRoleAsync(string role) public async Task<IEnumerable<User>> GetByRoleAsync(string role)
{ {
return await _context.Users var query = _context.Users
.Include(u => u.UserRoles)! .Include(u => u.UserRoles)!
.ThenInclude(ur => ur.Role) .ThenInclude(ur => ur.Role)
.Where(ur => ur.UserRoles!.Any(r => r.Role!.Name == role)) .Where(ur => ur.UserRoles!.Any(r => r.Role!.Name == role));
.ToListAsync();
var sql = query.ToQueryString();
return await query.ToListAsync();
} }
// UPDATE // UPDATE

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore;
using UserManagement.Domain.Entities;
using UserManagement.Infrastructure.Interfaces;
namespace UserManagement.Infrastructure.Repositories
{
public class UserRolesRepository : IUserRolesRepository
{
// CTOR
private readonly ApplicationDbContext _context;
public UserRolesRepository(ApplicationDbContext context)
{
_context = context;
}
// CREATE ASSIGNMENT
public async Task<bool> CreateAssignmentAsync(UserRoles userRoles)
{
await _context.UserRoles.AddAsync(userRoles);
var results = await _context.SaveChangesAsync();
return results > 0;
}
// DELETE ASSIGNMENT
public async Task<bool> DeleteAssignmentAsync(UserRoles userRoles)
{
_context.UserRoles.Remove(userRoles);
var result = await _context.SaveChangesAsync();
return result > 0;
}
}
}