Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Advanced HTTP Methods for Users #61

Merged
merged 13 commits into from
Dec 23, 2023
Prev Previous commit
Next Next commit
Implement UsersService.UpdateUserRoles
  • Loading branch information
romandykyi committed Dec 23, 2023
commit 36d353a0e6ac9f5843c3bfe3a30009ae2dcf0ef6
17 changes: 15 additions & 2 deletions Core/Services/Users/IUsersService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,26 @@ Task<Page<UserPreviewDto>> GetAllUsersAsync(PaginationProperties? properties = n
/// <summary>
/// Updates an existing user identified by its unique identifier asynchronously.
/// </summary>
/// <param name="id">The unique identifier of the user to update.</param>
/// <param name="dto">The DTO containing data for updating the user.</param>
/// <param name="userId">The unique identifier of the user to update.</param>
/// <param name="editUserDto">The DTO containing data for updating the user.</param>
/// <returns>
/// A task that represents the asynchronous operation. If the
/// user is updated successfully, it returns <see langword="true" />.
/// If the user with the specified identifier is not found(or deleted),
/// it returns <see langword="false" />.
/// </returns>
Task<bool> UpdateUserAsync(string userId, EditUserDto editUserDto);

/// <summary>
/// Updates an existing user's roles.
/// </summary>
/// <param name="userId">The unique identifier of the user whose roles will be updated.</param>
/// <param name="dto">The DTO containing data for updating the user's roles.</param>
/// <returns>
/// A task that represents the asynchronous operation. If the
/// user's roles are updated successfully, it returns <see langword="true" />.
/// If the user with the specified identifier is not found(or deleted),
/// it returns <see langword="false" />.
/// </returns>
public Task<bool> UpdateUserRolesAsync(string userId, ChangeRolesDto dto);
}
58 changes: 51 additions & 7 deletions Infrastructure/Services/Users/UsersService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@
using EUniversity.Core.Filters;
using EUniversity.Core.Models;
using EUniversity.Core.Pagination;
using EUniversity.Core.Policy;
using EUniversity.Core.Services.Users;
using EUniversity.Infrastructure.Data;
using EUniversity.Infrastructure.Pagination;
using IdentityModel;
using Microsoft.AspNetCore.Identity;

namespace EUniversity.Infrastructure.Services.Users;

/// <inheritdoc />
public class UsersService : IUsersService
{
private readonly ApplicationDbContext _dbContext;
private readonly UserManager<ApplicationUser> _userManager;

public UsersService(ApplicationDbContext dbContext)
public UsersService(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager)
{
_dbContext = dbContext;
_userManager = userManager;
}

private static async Task<Page<UserPreviewDto>> SelectUsersAsync(
Expand All @@ -31,6 +35,13 @@ private static async Task<Page<UserPreviewDto>> SelectUsersAsync(
return await query.ToPageAsync<ApplicationUser, UserPreviewDto>(properties);
}

private async Task<ApplicationUser?> GetExistingUserById(string id)
{
return await _dbContext.Users
.Where(u => u.Id == id && !u.IsDeleted)
.FirstOrDefaultAsync();
}

/// <inheritdoc />
public async Task<Page<UserPreviewDto>> GetAllUsersAsync(PaginationProperties? properties,
IFilter<ApplicationUser>? filter = null, bool onlyDeleted = false)
Expand Down Expand Up @@ -79,9 +90,7 @@ public async Task<Page<UserPreviewDto>> GetUsersInRoleAsync(string role, Paginat
public async Task<bool> DeleteUserAsync(string userId)
{
// Find a user by its ID
var user = await _dbContext.Users
.Where(u => u.Id == userId && !u.IsDeleted)
.FirstOrDefaultAsync();
var user = await GetExistingUserById(userId);
// User does not exist(or deleted) - return false
if (user == null) return false;

Expand All @@ -96,9 +105,7 @@ public async Task<bool> DeleteUserAsync(string userId)
public async Task<bool> UpdateUserAsync(string userId, EditUserDto editUserDto)
{
// Find a user by its ID
var user = await _dbContext.Users
.Where(u => u.Id == userId && !u.IsDeleted)
.FirstOrDefaultAsync();
var user = await GetExistingUserById(userId);
// User does not exist(or deleted) - return false
if (user == null) return false;

Expand All @@ -109,4 +116,41 @@ public async Task<bool> UpdateUserAsync(string userId, EditUserDto editUserDto)

return true;
}

/// <inheritdoc />
public async Task<bool> UpdateUserRolesAsync(string userId, ChangeRolesDto dto)
{
// Find a user by its ID
var user = await GetExistingUserById(userId);
// User does not exist(or deleted) - return false
if (user == null) return false;

// Needs refactor if many roles will be added
if (dto.IsTeacher == true)
{
await _userManager.AddToRoleAsync(user, Roles.Teacher);
}
else if (dto.IsTeacher == false)
{
await _userManager.RemoveFromRoleAsync(user, Roles.Teacher);
}
if (dto.IsAdministrator == true)
{
await _userManager.AddToRoleAsync(user, Roles.Administrator);
}
else if (dto.IsAdministrator == false)
{
await _userManager.RemoveFromRoleAsync(user, Roles.Administrator);
}
if (dto.IsStudent == true)
{
await _userManager.AddToRoleAsync(user, Roles.Student);
}
else if (dto.IsStudent == false)
{
await _userManager.RemoveFromRoleAsync(user, Roles.Student);
}

return true;
}
}
51 changes: 51 additions & 0 deletions IntegrationTests/Services/UsersServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,4 +325,55 @@ public virtual async Task UpdateUser_UserIsDeleted_ReturnsFalse()
// Assert
Assert.That(result, Is.False);
}

[Test]
public virtual async Task UpdateUserRoles_UserExists_Succeeds()
{
// Arrange
var user = await RegisterTestUserAsync(Roles.Teacher);
string[] expectedRoles = { Roles.Administrator };
ChangeRolesDto dto = new(IsTeacher: false, IsAdministrator: true);

// Act
bool result = await _usersService.UpdateUserRolesAsync(user.Id, dto);

// Assert
Assert.That(result);
List<string> actualRoles = await DbContext.UserRoles
.AsNoTracking()
.Where(ur => ur.UserId == user.Id)
.Join(DbContext.Roles, ur => ur.RoleId, r => r.Id, (ur, r) => r)
.Select(r => r.Name!)
.ToListAsync();
Assert.That(actualRoles, Is.EquivalentTo(expectedRoles));
}

[Test]
public virtual async Task UpdateUserRoles_UserDoesNotExist_ReturnsFalse()
{
// Arrange
ChangeRolesDto dto = new();

// Act
bool result = await _usersService.UpdateUserRolesAsync("null", dto);

// Assert
Assert.That(result, Is.False);
}

[Test]
public virtual async Task UpdateUserRoles_UserIsDeleted_ReturnsFalse()
{
// Arrange
var user = await RegisterTestUserAsync();
user.IsDeleted = true;
await DbContext.SaveChangesAsync();
ChangeRolesDto dto = new();

// Act
bool result = await _usersService.UpdateUserRolesAsync(user.Id, dto);

// Assert
Assert.That(result, Is.False);
}
}