Compare commits

...

3 Commits

Author SHA1 Message Date
OlgunR
dc3fb100b1 FlexibleQueries+GetUsersByRole 2024-09-17 16:54:38 +02:00
OlgunR
556571ae78 PasswordHashed 2024-09-13 10:40:07 +02:00
OlgunR
cedf5f0ca8 User Role many to many 2024-09-12 15:42:28 +02:00
36 changed files with 1447 additions and 287 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
{ {
@ -29,8 +29,8 @@ namespace UserManagement.API.Controllers
public async Task<IActionResult> Login([FromBody] LoginDto login) public async Task<IActionResult> Login([FromBody] LoginDto login)
{ {
// Validate user // Validate user
var user = await _userService.GetByUsernameAsync(login.Username); var user = await _userService.GetByUsernameAsync(login.Username, includeRoles: true);
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
@ -61,9 +63,9 @@ namespace UserManagement.API.Controllers
[HttpGet] [HttpGet]
[SwaggerOperation(Summary = "Get all Users")] [SwaggerOperation(Summary = "Get all Users")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> GetAllUsers() public async Task<IActionResult> GetAllUsers([FromQuery] bool includeRoles = true)
{ {
var users = await _userService.GetUsersAsync(); var users = await _userService.GetUsersAsync(includeRoles);
return Ok(users); return Ok(users);
} }
@ -73,13 +75,13 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUserById(int id) public async Task<IActionResult> GetUserById(int id, [FromQuery] bool includeRoles = true)
{ {
if (id <= 0) if (id <= 0)
{ {
return BadRequest("Invalid Id"); return BadRequest("Invalid Id");
} }
var user = await _userService.GetByIdAsync(id); var user = await _userService.GetByIdAsync(id, includeRoles);
if (user == null) if (user == null)
{ {
return NotFound(); return NotFound();
@ -93,13 +95,13 @@ namespace UserManagement.API.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUserByUsername(string username) public async Task<IActionResult> GetUserByUsername(string username, [FromQuery] bool includeRoles = true)
{ {
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))
{ {
return BadRequest("Username connot be empty"); return BadRequest("Username connot be empty");
} }
var user = await _userService.GetByUsernameAsync(username); var user = await _userService.GetByUsernameAsync(username, includeRoles);
if (user == null) if (user == null)
{ {
return NotFound(); return NotFound();
@ -107,6 +109,22 @@ namespace UserManagement.API.Controllers
return Ok(user); return Ok(user);
} }
// READ BY ROLE
[HttpGet("role/{role}", Name = "GetUsersByRole")]
[SwaggerOperation(Summary = "Get Users by Role")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUsersByRole(string role)
{
if (string.IsNullOrEmpty(role))
{
return BadRequest("Role cannot be empty");
}
var users = await _userService.GetByRoleAsync(role);
return Ok(users);
}
// UPDATE // UPDATE
[HttpPut("id/{id}", Name = "UpdateUser")] [HttpPut("id/{id}", Name = "UpdateUser")]
[SwaggerOperation(Summary = "Update User")] [SwaggerOperation(Summary = "Update User")]
@ -114,7 +132,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 +155,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

@ -1,107 +1,133 @@
// <auto-generated /> // <auto-generated />
using System; using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using UserManagement.Infrastructure; using UserManagement.Infrastructure;
#nullable disable #nullable disable
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)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "8.0.8") .HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 128); .HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("UserManagement.Domain.Entities.Role", b => modelBuilder.Entity("UserManagement.Domain.Entities.Role", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int") .HasColumnType("int")
.HasColumnName("ID"); .HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationDate") b.Property<DateTime>("CreationDate")
.HasColumnType("datetime") .HasColumnType("datetime")
.HasColumnName("CREATION_DATE"); .HasColumnName("CREATION_DATE");
b.Property<string>("Name") b.Property<string>("Name")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ROLE"); .HasColumnName("ROLE");
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Roles"); b.ToTable("Roles");
}); });
modelBuilder.Entity("UserManagement.Domain.Entities.User", b => modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int") .HasColumnType("int")
.HasColumnName("ID"); .HasColumnName("ID");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FirstName") b.Property<string>("FirstName")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("FIRST_NAME"); .HasColumnName("FIRST_NAME");
b.Property<string>("LastName") b.Property<string>("LastName")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("LAST_NAME"); .HasColumnName("LAST_NAME");
b.Property<string>("Password") b.Property<string>("Password")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD"); .HasColumnName("PASSWORD");
b.Property<int?>("ROLE") b.Property<string>("UserName")
.HasColumnType("int"); .IsRequired()
.HasColumnType("nvarchar(max)")
b.Property<int>("RoleId") .HasColumnName("USER_NAME");
.HasColumnType("int")
.HasColumnName("ROLE_ID"); b.HasKey("Id");
b.Property<string>("UserName") b.ToTable("Users");
.IsRequired() });
.HasColumnType("nvarchar(max)")
.HasColumnName("USER_NAME"); modelBuilder.Entity("UserManagement.Domain.Entities.UserRoles", b =>
{
b.HasKey("Id"); b.Property<int>("UserId")
.HasColumnType("int")
b.HasIndex("RoleId"); .HasColumnName("USER_ID");
b.ToTable("Users"); b.Property<int>("RoleId")
}); .HasColumnType("int")
.HasColumnName("ROLE_ID");
modelBuilder.Entity("UserManagement.Domain.Entities.User", b =>
{ b.HasKey("UserId", "RoleId");
b.HasOne("UserManagement.Domain.Entities.Role", "Role")
.WithMany() b.HasIndex("RoleId");
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade) b.ToTable("UserRoles");
.IsRequired(); });
b.Navigation("Role"); modelBuilder.Entity("UserManagement.Domain.Entities.UserRoles", b =>
}); {
#pragma warning restore 612, 618 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

@ -1,68 +1,87 @@
using System; using System;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable
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)
{ {
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Roles", name: "Roles",
columns: table => new columns: table => new
{ {
ID = table.Column<int>(type: "int", nullable: false) ID = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"), .Annotation("SqlServer:Identity", "1, 1"),
ROLE = table.Column<string>(type: "nvarchar(max)", nullable: false), ROLE = table.Column<string>(type: "nvarchar(max)", nullable: false),
CREATION_DATE = table.Column<DateTime>(type: "datetime", nullable: false) CREATION_DATE = table.Column<DateTime>(type: "datetime", nullable: false)
}, },
constraints: table => constraints: table =>
{ {
table.PrimaryKey("PK_Roles", x => x.ID); table.PrimaryKey("PK_Roles", x => x.ID);
}); });
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Users", name: "Users",
columns: table => new columns: table => new
{ {
ID = table.Column<int>(type: "int", nullable: false) ID = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"), .Annotation("SqlServer:Identity", "1, 1"),
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);
table.ForeignKey( migrationBuilder.CreateTable(
name: "FK_Users_Roles_ROLE_ID", name: "UserRoles",
column: x => x.ROLE_ID, columns: table => new
principalTable: "Roles", {
principalColumn: "ID", USER_ID = table.Column<int>(type: "int", nullable: false),
onDelete: ReferentialAction.Cascade); ROLE_ID = table.Column<int>(type: "int", nullable: false)
}); },
constraints: table =>
migrationBuilder.CreateIndex( {
name: "IX_Users_ROLE_ID", table.PrimaryKey("PK_UserRoles", x => new { x.USER_ID, x.ROLE_ID });
table: "Users", table.ForeignKey(
column: "ROLE_ID"); name: "FK_UserRoles_Roles_ROLE_ID",
} column: x => x.ROLE_ID,
principalTable: "Roles",
/// <inheritdoc /> principalColumn: "ID",
protected override void Down(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade);
{ table.ForeignKey(
migrationBuilder.DropTable( name: "FK_UserRoles_Users_USER_ID",
name: "Users"); column: x => x.USER_ID,
principalTable: "Users",
migrationBuilder.DropTable( principalColumn: "ID",
name: "Roles"); onDelete: ReferentialAction.Cascade);
} });
}
} migrationBuilder.CreateIndex(
name: "IX_UserRoles_ROLE_ID",
table: "UserRoles",
column: "ROLE_ID");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
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

@ -0,0 +1,144 @@
// <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("20240912141329_PasswordHash")]
partial class PasswordHash
{
/// <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>("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.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,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserManagement.API.Migrations
{
/// <inheritdoc />
public partial class PasswordHash : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PASSWORD_HASH",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PASSWORD_HASH",
table: "Users");
}
}
}

View File

@ -0,0 +1,144 @@
// <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("20240912143537_RemoveObsoleteFromPassword")]
partial class RemoveObsoleteFromPassword
{
/// <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>("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.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 RemoveObsoleteFromPassword : 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("20240913081538_RemovePasswordFromUser")]
partial class RemovePasswordFromUser
{
/// <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.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,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserManagement.API.Migrations
{
/// <inheritdoc />
public partial class RemovePasswordFromUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PASSWORD",
table: "Users");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PASSWORD",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
}
}
}

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");
}); });
@ -64,39 +67,68 @@ namespace UserManagement.API.Migrations
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("LAST_NAME"); .HasColumnName("LAST_NAME");
b.Property<string>("Password") b.Property<string>("PasswordHash")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD"); .HasColumnName("PASSWORD_HASH");
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
{ {
@ -8,8 +10,8 @@
public string LastName { get; set; } public string LastName { get; set; }
public string Password { get; init; } public string Password { get; set; }
public int RoleId { get; set; } public ICollection<int> RoleIds { get; set; }
} }
} }

View File

@ -10,8 +10,8 @@
public string LastName { get; set; } public string LastName { get; set; }
public string Password { get; init; } public string Password { get; set; }
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,9 @@
namespace UserManagement.Application.Dtos.Outgoing
{
public class ReadingUserRolesDto
{
public int RoleId { get; set; }
public string RoleName { get; set; }
}
}

View File

@ -10,20 +10,20 @@ namespace UserManagement.Application.Interfaces
Task<User?> AddUserAsync(CreatingUserDto creatingUserDto); Task<User?> AddUserAsync(CreatingUserDto creatingUserDto);
// READ ALL // READ ALL
Task<IEnumerable<ReadingUserDto>> GetUsersAsync(); Task<IEnumerable<ReadingUserDto>> GetUsersAsync(bool includeRoles = true);
// READ BY ID // READ BY ID
Task<ReadingUserDto> GetByIdAsync(int id); Task<ReadingUserDto> GetByIdAsync(int id, bool includeRoles = true);
// READ BY USERNAME // READ BY USERNAME
Task<ReadingUserDto> GetByUsernameAsync(string username); Task<ReadingUserDto> GetByUsernameAsync(string username, bool includeRoles = true);
// READ BY ROLE
Task<IEnumerable<ReadingUserDto>> GetByRoleAsync(string role);
// UPDATE // UPDATE
Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto); Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto);
// UPDATE USER ROLE
Task UpdateUserRoleAsync(int userId, int roleId);
// DELETE // DELETE
Task<bool> DeleteUserAsync(int id); Task<bool> DeleteUserAsync(int id);
} }

View File

@ -11,13 +11,47 @@ 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();
dest.PasswordHash = BCrypt.Net.BCrypt.HashPassword(src.Password);
});
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();
dest.PasswordHash = BCrypt.Net.BCrypt.HashPassword(src.Password);
});
} }
} }
} }

View File

@ -15,9 +15,9 @@ namespace UserManagement.Application.Services
// AUTHENTICATE // AUTHENTICATE
public async Task<bool> ValidateAsync(string username, string password) public async Task<bool> ValidateAsync(string username, string password)
{ {
var user = await _userRepository.GetByUsernameAsync(username); var user = await _userRepository.GetByUsernameAsync(username, includeRoles: true);
return user?.Password == password; return BCrypt.Net.BCrypt.Verify(password, user!.PasswordHash);
} }
} }
} }

View File

@ -23,70 +23,100 @@ 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) if (!string.IsNullOrEmpty(creatingUserDto.Password))
{ {
throw new ArgumentException("Role not found"); 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");
}
} }
// 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;
} }
// READ ALL // READ ALL
public async Task<IEnumerable<ReadingUserDto>> GetUsersAsync() public async Task<IEnumerable<ReadingUserDto>> GetUsersAsync(bool includeRoles = true)
{ {
var users = await _userRepository.GetAllAsync(); var users = await _userRepository.GetAllAsync(includeRoles);
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) public async Task<ReadingUserDto> GetByIdAsync(int id, bool includeRoles = true)
{ {
var user = await _userRepository.GetByIdAsync(id); var user = await _userRepository.GetByIdAsync(id, includeRoles);
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) public async Task<ReadingUserDto> GetByUsernameAsync(string username, bool includeRoles = true)
{ {
var user = await _userRepository.GetByUsernameAsync(username); var user = await _userRepository.GetByUsernameAsync(username, includeRoles);
var readDto = _mapper.Map<ReadingUserDto>(user); var readDto = _mapper.Map<ReadingUserDto>(user);
return readDto; return readDto;
} }
// READ BY ROLE
public async Task<IEnumerable<ReadingUserDto>> GetByRoleAsync(string role)
{
var users = await _userRepository.GetByRoleAsync(role);
var readDto = _mapper.Map<IEnumerable<ReadingUserDto>>(users);
return readDto;
}
// 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);
if (!string.IsNullOrEmpty(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;
} }
// 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");
}
user.RoleId = roleId;
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; set; } = 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
@ -23,13 +24,9 @@ namespace UserManagement.Domain.Entities
public string LastName { get; set; } public string LastName { get; set; }
[Required] [Required]
[Column("PASSWORD")] [Column("PASSWORD_HASH")]
public string Password { get; init; } public required string PasswordHash { get; set; }
[Column("ROLE_ID")] public ICollection<UserRole>? UserRoles { get; set; } = new Collection<UserRole>();
public int RoleId { get; set; }
[ForeignKey("ROLE")]
public Role? Role { get; set; }
} }
} }

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

@ -8,21 +8,21 @@ namespace UserManagement.Infrastructure.Interfaces
Task<User?> AddAsync(User user); Task<User?> AddAsync(User user);
// READ ALL // READ ALL
Task<IEnumerable<User>> GetAllAsync(); Task<IEnumerable<User>> GetAllAsync(bool includeRoles = true);
// READ BY ID // READ BY ID
Task<User?> GetByIdAsync(int id); Task<User?> GetByIdAsync(int id, bool includeRoles = true);
// READ BY USERNAME // READ BY USERNAME
Task<User?> GetByUsernameAsync(string username); Task<User?> GetByUsernameAsync(string username, bool includeRoles = true);
// READ BY ROLE
Task<IEnumerable<User>> GetByRoleAsync(string role);
// UPDATE // UPDATE
Task<bool> UpdateAsync(User user); Task<bool> UpdateAsync(User user);
// DELETE // DELETE
Task<bool> DeleteAsync(User user); Task<bool> DeleteAsync(User user);
// SAVE
Task<bool> SaveAsync();
} }
} }

View File

@ -22,21 +22,52 @@ namespace UserManagement.Infrastructure.Repositories
} }
// READ ALL // READ ALL
public async Task<IEnumerable<User>> GetAllAsync() public async Task<IEnumerable<User>> GetAllAsync(bool includeRoles = true)
{ {
return await _context.Users.Include(u => u.Role).ToListAsync(); var query = _context.Users.AsNoTracking();
if (includeRoles)
query = query.Include(user => user.UserRoles)!.ThenInclude(ur => ur.Role);
return await query.ToListAsync();
} }
// READ BY ID // READ BY ID
public async Task<User?> GetByIdAsync(int id) public async Task<User?> GetByIdAsync(int id, bool includeRoles = true)
{ {
return await _context.Users.Where(user => user.Id == id).Include(user => user.Role).FirstAsync(); var query = _context.Users.AsNoTracking();
if (id > 0)
query = query.Where(u => u.Id == id);
if (includeRoles)
query = query.Include(user => user.UserRoles)!.ThenInclude(ur => ur.Role);
return await query.FirstOrDefaultAsync();
} }
// READ BY USERNAME // READ BY USERNAME
public async Task<User?> GetByUsernameAsync(string username) public async Task<User?> GetByUsernameAsync(string username, bool includeRoles = true)
{ {
return await _context.Users.Include(user => user.Role).FirstOrDefaultAsync(u => u.UserName == username); var query = _context.Users.AsNoTracking();
if (!string.IsNullOrEmpty(username))
query = query.Where(u => u.UserName == username);
if (includeRoles)
query = query.Include(user => user.UserRoles)!.ThenInclude(ur => ur.Role);
return await query.FirstOrDefaultAsync();
}
// READ BY ROLE
public async Task<IEnumerable<User>> GetByRoleAsync(string role)
{
return await _context.Users
.Include(u => u.UserRoles)!
.ThenInclude(ur => ur.Role)
.Where(ur => ur.UserRoles!.Any(r => r.Role!.Name == role))
.ToListAsync();
} }
// UPDATE // UPDATE
@ -54,12 +85,5 @@ namespace UserManagement.Infrastructure.Repositories
var result = await _context.SaveChangesAsync(); var result = await _context.SaveChangesAsync();
return result > 0; return result > 0;
} }
// SAVE
public async Task<bool> SaveAsync()
{
var saved = await _context.SaveChangesAsync();
return saved > 0 ? true : false;
}
} }
} }

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">