Skip to content

Commit

Permalink
Merge pull request #127 from amosproj/112-BE-user-management
Browse files Browse the repository at this point in the history
feat: user management endpoints
  • Loading branch information
woerndle authored Dec 12, 2022
2 parents c0cb411 + 9dad378 commit cf2464d
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 31 deletions.
100 changes: 85 additions & 15 deletions src/deskstar-backend/Deskstar/Controllers/UserController.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.IdentityModel.Tokens.Jwt;
using Deskstar.Core;
using Deskstar.Entities;
using Deskstar.Models;
using Deskstar.Usecases;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;

namespace Deskstar.Controllers;

Expand All @@ -24,6 +24,46 @@ public UserController(ILogger<UserController> logger, IUserUsecases userUsecases
_autoMapperConfiguration = autoMapperConfiguration;
}
/// <summary>
/// Returns all users for a specific company
/// </summary>
/// <returns> List of user information in JSON Format </returns>
/// <remarks>
/// Sample request:
/// Get /users with JWT Token
/// </remarks>
///
/// <response code="200">List of user information in JSON Format</response>
/// <response code="500">Internal Server Error</response>
/// <response code="400">Bad Request</response>
[HttpGet]
[Authorize(Policy = "Admin")]
[ProducesResponseType(typeof(UserProfileDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[Produces("application/json")]
public IActionResult Get()
{
var userId = RequestInteractions.ExtractIdFromRequest(Request);
try
{
var entities = _userUsecases.ReadAllUsers(userId);
var mapper = _autoMapperConfiguration.GetConfiguration().CreateMapper();
var users = entities.Select<User, UserProfileDto>(user => mapper.Map<User, UserProfileDto>(user)).ToList();

return Ok(users);
}
catch (ArgumentException e)
{
_logger.LogError(e, e.Message);
return Problem(detail: e.Message, statusCode: 400);
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
return Problem(statusCode: 500);
}
}
/// <summary>
/// Returns user specific information
/// </summary>
/// <returns> User information in JSON Format </returns>
Expand All @@ -43,10 +83,7 @@ public UserController(ILogger<UserController> logger, IUserUsecases userUsecases
[Produces("application/json")]
public IActionResult GetMe()
{
var accessToken = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", string.Empty);
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(accessToken);
var userId = new Guid(jwtSecurityToken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.NameId).Value);
var userId = RequestInteractions.ExtractIdFromRequest(Request);

try
{
Expand All @@ -67,7 +104,7 @@ public IActionResult GetMe()
}
}

/// <summary>
/// <summary>
/// Lets an admin approve a users registration for their company
/// </summary>
/// <returns> empty response </returns>
Expand All @@ -86,10 +123,7 @@ public IActionResult GetMe()
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult ApproveUser(string userId)
{
var accessToken = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", string.Empty);
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(accessToken);
var adminId = new Guid(jwtSecurityToken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.NameId).Value);
var adminId = RequestInteractions.ExtractIdFromRequest(Request);

try
{
Expand Down Expand Up @@ -127,10 +161,7 @@ public IActionResult ApproveUser(string userId)
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult DeclineUser(string userId)
{
var accessToken = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", string.Empty);
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(accessToken);
var adminId = new Guid(jwtSecurityToken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.NameId).Value);
var adminId = RequestInteractions.ExtractIdFromRequest(Request);

try
{
Expand All @@ -148,4 +179,43 @@ public IActionResult DeclineUser(string userId)
return Problem(statusCode: 500);
}
}
/// <summary>
/// Update user information
/// </summary>
/// <returns> empty response </returns>
/// <remarks>
/// Sample request:
/// Post /users/me
/// </remarks>
///
/// <response code="200">Empty Response</response>
/// <response code="500">Internal Server Error</response>
/// <response code="400">Bad Request</response>
[HttpPost("me")]
[Authorize]
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult UpdateUser(UserProfileDto userDto)
{
var userId = RequestInteractions.ExtractIdFromRequest(Request);

try
{
var mapper = _autoMapperConfiguration.GetConfiguration().CreateMapper();
var user = mapper.Map<UserProfileDto, User>(userDto);
_userUsecases.UpdateUser(user);
return Ok();
}
catch (ArgumentException e)
{
_logger.LogError(e, e.Message);
return Problem(detail: e.Message, statusCode: 400);
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
return Problem(statusCode: 500);
}
}
}
15 changes: 15 additions & 0 deletions src/deskstar-backend/Deskstar/Core/RequestInteractions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.IdentityModel.Tokens.Jwt;
using Microsoft.Net.Http.Headers;

namespace Deskstar.Core;

public class RequestInteractions
{
public static Guid ExtractIdFromRequest(HttpRequest request)
{
var accessToken = request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", string.Empty);
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(accessToken);
return new Guid(jwtSecurityToken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.NameId).Value);
}
}
2 changes: 2 additions & 0 deletions src/deskstar-backend/Deskstar/Models/UserProfileDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public static void createMappings(IMapperConfigurationExpression cfg)
{
cfg.CreateMap<Entities.User, UserProfileDto>()
.ForMember(dest => dest.Company, act => act.MapFrom(src => src.Company));
cfg.CreateMap<UserProfileDto, Entities.User>()
.ForMember(dest => dest.Company, act => act.MapFrom(src => src.Company));
}

public Guid UserId { get; set; }
Expand Down
30 changes: 30 additions & 0 deletions src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace Deskstar.Usecases;

public interface IUserUsecases
{
public List<User> ReadAllUsers(Guid adminId);
public Guid UpdateUser(User user);
public User ReadSpecificUser(Guid userId);
public Guid ApproveUser(Guid adminId, string userId);
public Guid DeclineUser(Guid adminId, string userId);
Expand Down Expand Up @@ -86,4 +88,32 @@ public Guid DeclineUser(Guid adminId, string userId)
throw new ArgumentException($"There is no user with id '{userId}'");
}
}

public List<User> ReadAllUsers(Guid adminId)
{
try
{
var admin = _context.Users.Single(user => user.UserId == adminId);
return _context.Users.Where(user => user.CompanyId == admin.CompanyId).ToList();
}
catch (InvalidOperationException)
{
throw new ArgumentException($"There is no admin with id '{adminId}'");
}
}

public Guid UpdateUser(User user)
{
try
{
_context.Users.Single(u => u.UserId == user.UserId);
_context.Users.Update(user);
_context.SaveChanges();
return user.UserId;
}
catch (InvalidOperationException)
{
throw new ArgumentException($"There is no user with id '{user.UserId}'");
}
}
}
Loading

0 comments on commit cf2464d

Please sign in to comment.