443 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			443 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| // ***********************************************************************
 | |
| // <copyright file="UserController.cs">
 | |
| //     Heath
 | |
| // </copyright>
 | |
| // ***********************************************************************
 | |
| using Asp.Versioning;
 | |
| using Core.Blueprint.Storage.Adapters;
 | |
| using Core.Cerberos.Adapters;
 | |
| using Core.Cerberos.Adapters.Attributes;
 | |
| using Core.Cerberos.Adapters.Common.Constants;
 | |
| using Core.Cerberos.Adapters.Common.Enums;
 | |
| using Core.Cerberos.Provider.Contracts;
 | |
| using Microsoft.AspNetCore.Authorization;
 | |
| using Microsoft.AspNetCore.Mvc;
 | |
| using Microsoft.Graph;
 | |
| using UserRequest = Core.Cerberos.Domain.Contexts.Onboarding.Request.UserRequest;
 | |
| 
 | |
| namespace LSA.Core.Kerberos.API.Controllers
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Handles all requests for user authentication.
 | |
|     /// </summary>
 | |
|     [ApiVersion("1.0")]
 | |
|     [Route("api/v{api-version:apiVersion}/[controller]")]
 | |
|     [Produces(MimeTypes.ApplicationJson)]
 | |
|     [Consumes(MimeTypes.ApplicationJson)]
 | |
|     [ApiController]
 | |
|     public class UserController(IUserService service, ILogger<UserController> logger) : ControllerBase
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Gets all the users.
 | |
|         /// </summary>  
 | |
|         /// <returns>The <see cref="IEnumerable{UserAdapter}"/> found entity.</returns>
 | |
|         /// <response code="200">The users found.</response>
 | |
|         /// <response code="404">The users not found error.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpGet]
 | |
|         [ProducesResponseType(typeof(IEnumerable<UserAdapter>), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Read")]
 | |
|         public async Task<IActionResult> GetAllUsersService()
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.GetAllUsersService();
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in GetAllUsersService");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the user by identifier.
 | |
|         /// </summary>
 | |
|         /// <param name="id">The user identifier.</param>
 | |
|         /// <returns>The <see cref="UserAdapter"/> found entity.</returns>
 | |
|         /// <response code="200">The user found.</response>
 | |
|         /// <response code="404">The user not found error.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpGet]
 | |
|         [Route(Routes.Id)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Read")]
 | |
|         public async Task<IActionResult> GetUserByIdService([FromRoute] string id)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.GetUserByIdService(id);
 | |
| 
 | |
|                 if (result is null) return NotFound($"user with id: '{id}' not found");
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in GetUserByIdService");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the user by email.
 | |
|         /// </summary>
 | |
|         /// <param name="email">The user's email.</param>
 | |
|         /// <returns>The <see cref="UserAdapter"/> found entity.</returns>
 | |
|         /// <response code="200">The user found.</response>
 | |
|         /// <response code="404">The user not found error.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpGet]
 | |
|         [Route(Routes.Email)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")]
 | |
|         public async Task<IActionResult> GetUserByEmail([FromRoute] string email)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.GetUserByEmailService(email);
 | |
| 
 | |
|                 if (result is null) return NotFound($"user with email: '{email}' not found");
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in GetUserByIdEmail");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Validates if a user exists on the database.
 | |
|         /// </summary>
 | |
|         /// <param name="email">The user's email.</param>
 | |
|         /// <returns>The <see cref="UserExistenceAdapter"/> found entity.</returns>
 | |
|         /// <response code="200">The user found.</response>
 | |
|         /// <response code="404">The user not found error.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpGet]
 | |
|         [Route("{email}/ValidateExistence")]
 | |
|         [ProducesResponseType(typeof(UserExistenceAdapter), StatusCodes.Status200OK)]
 | |
|         [AllowAnonymous]
 | |
|         public async Task<IActionResult> ValidateUserExistence([FromRoute] string email)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.ValidateUserExistenceService(email);
 | |
| 
 | |
|                 var existence = new UserExistenceAdapter
 | |
|                 {
 | |
|                     Existence = (result is not null) ? true : false
 | |
|                 };
 | |
| 
 | |
|                 return Ok(existence);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in ValidateUserExistance");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Creates a new user.
 | |
|         /// </summary>
 | |
|         /// <param name="newUser">The user to be added.</param>
 | |
|         /// <param name="sendInvitation">Sends an invitation in case of third party access.</param>
 | |
|         /// <returns>The <see cref="UserAdapter"/> created entity.</returns>
 | |
|         /// <response code="201">The user created.</response>
 | |
|         /// <response code="422">The user could not be created.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPost(Routes.Register)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status201Created)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> CreateUserAsync([FromBody] UserRequest newUser, [FromRoute] bool sendInvitation)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var user = await service.GetUserByEmailService(newUser.Email).ConfigureAwait(false);
 | |
| 
 | |
|                 if (user is not null)
 | |
|                     return UnprocessableEntity("There is a user with the same email registered in the database");
 | |
| 
 | |
|                 var result = await service.CreateUserService(newUser).ConfigureAwait(false);
 | |
| 
 | |
|                 return Created("CreatedWithIdService", result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in CreateUserAsync");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Updates a full user by identifier.
 | |
|         /// </summary>
 | |
|         /// <param name="entity">The user to update.</param>
 | |
|         /// <param name="id">The user identifier.</param>
 | |
|         /// <returns>The <see cref="UserAdapter"/> updated entity.</returns>
 | |
|         /// <response code="200">The user updated.</response>
 | |
|         /// <response code="404">The user not found.</response>
 | |
|         /// <response code="422">The user could not be updated.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPut]
 | |
|         [Route(Routes.Id)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> UpdateUserAsync([FromBody] UserAdapter entity, [FromRoute] string id)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.UpdateUserService(entity, id);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in UpdateUserAsync");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Logs in the user.
 | |
|         /// </summary>
 | |
|         /// <param name="email">The User's email.</param>
 | |
|         /// <returns>A <see cref="UserAdapter"/> representing
 | |
|         /// the asynchronous execution of the service.</returns>
 | |
|         /// <response code="200">The User found.</response>
 | |
|         /// <response code="404">The User not found.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPatch(Routes.LogIn)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")]
 | |
|         public async Task<IActionResult> LoginUserAsync([FromRoute] string email)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.LogInUserService(email).ConfigureAwait(false);
 | |
| 
 | |
|                 if (result is null)
 | |
|                     return new NotFoundObjectResult($"The user with email: '{email}' was not found");
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in LogInUserService");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Logs out the user.
 | |
|         /// </summary>
 | |
|         /// <param name="email">The User's email.</param>
 | |
|         /// <returns>A <see cref="UserAdapter"/> representing
 | |
|         /// the asynchronous execution of the service.</returns>
 | |
|         /// <response code="200">The User updated.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPatch(Routes.LogOut)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")]
 | |
|         public async Task<IActionResult> LogOutUserSessionAsync([FromRoute] string email)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.LogOutUserSessionService(email).ConfigureAwait(false);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in LogOutUserSessionService");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Changes the status of the user.
 | |
|         /// </summary>
 | |
|         /// <param name="id">The user identifier.</param>
 | |
|         /// <param name="newStatus">The new status of the user.</param>
 | |
|         /// <returns>The <see cref="UserAdapter"/> updated entity.</returns>
 | |
|         /// <response code="200">The user updates.</response>
 | |
|         /// <response code="404">The user not found.</response>
 | |
|         /// <response code="422">The user could not be deleted.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPatch]
 | |
|         [Route(Routes.ChangeStatus)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> ChangeUserStatus([FromRoute] string id, [FromRoute] StatusEnum newStatus)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.ChangeUserStatusService(id, newStatus);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in ChangeUserStatus");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Adds a company to the user's list of companies.
 | |
|         /// </summary>
 | |
|         /// <param name="userId">The user identifier.</param>
 | |
|         /// <param name="companyId">The company identifier to add.</param>
 | |
|         /// <returns>The updated <see cref="UserAdapter"/> entity.</returns>
 | |
|         /// <response code="200">The user with the updated companies.</response>
 | |
|         /// <response code="404">The user or company not found.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPost]
 | |
|         [Route(Routes.AddCompany)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> AddCompanyToUserAsync([FromRoute] string userId, [FromRoute] string companyId)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.AddCompanyToUserService(userId, companyId);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in AddCompanyToUserAsync");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Removes a company from the user's list of companies.
 | |
|         /// </summary>
 | |
|         /// <param name="userId">The user identifier.</param>
 | |
|         /// <param name="companyId">The company identifier to remove.</param>
 | |
|         /// <returns>The updated <see cref="UserAdapter"/> entity.</returns>
 | |
|         /// <response code="200">The user with the updated companies.</response>
 | |
|         /// <response code="404">The user or company not found.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpDelete]
 | |
|         [Route(Routes.RemoveCompany)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> RemoveCompanyFromUserAsync([FromRoute] string userId, [FromRoute] string companyId)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.RemoveCompanyFromUserService(userId, companyId);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in RemoveCompanyFromUserAsync");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Adds a project to the user's list of projects.
 | |
|         /// </summary>
 | |
|         /// <param name="userId">The user identifier.</param>
 | |
|         /// <param name="projectId">The project identifier to add.</param>
 | |
|         /// <returns>The updated <see cref="UserAdapter"/> entity.</returns>
 | |
|         /// <response code="200">The user with the updated projects.</response>
 | |
|         /// <response code="404">The user or project not found.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpPost]
 | |
|         [Route(Routes.AddProject)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> AddProjectToUserAsync([FromRoute] string userId, [FromRoute] string projectId)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.AddProjectToUserService(userId, projectId);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in AddProjectToUserAsync");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Removes a project from the user's list of projects.
 | |
|         /// </summary>
 | |
|         /// <param name="userId">The user identifier.</param>
 | |
|         /// <param name="projectId">The project identifier to remove.</param>
 | |
|         /// <returns>The updated <see cref="UserAdapter"/> entity.</returns>
 | |
|         /// <response code="200">The user with the updated projects.</response>
 | |
|         /// <response code="404">The user or project not found.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpDelete]
 | |
|         [Route(Routes.RemoveProject)]
 | |
|         [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
 | |
|         [Permission("UserManagement.Write")]
 | |
|         public async Task<IActionResult> RemoveProjectFromUserAsync([FromRoute] string userId, [FromRoute] string projectId)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var result = await service.RemoveProjectFromUserService(userId, projectId);
 | |
| 
 | |
|                 return Ok(result);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in RemoveProjectFromUserAsync");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a token for the user, including roles, permissions, and modules.
 | |
|         /// </summary>
 | |
|         /// <param name="email">The user's email.</param>
 | |
|         /// <returns>The token adapter with user details, role, permissions, and modules.</returns>
 | |
|         /// <response code="200">The token adapter with user details.</response>
 | |
|         /// <response code="404">The user not found.</response>
 | |
|         /// <response code="500">The service internal error.</response>
 | |
|         [HttpGet]
 | |
|         [Route("{email}/GetTokenAdapter")]
 | |
|         [ProducesResponseType(typeof(TokenAdapter), StatusCodes.Status200OK)]
 | |
|         [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")]
 | |
|         public async Task<IActionResult> GetTokenAdapter([FromRoute] string email)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var tokenAdapter = await service.GetTokenAdapter(email);
 | |
| 
 | |
|                 if (tokenAdapter == null) return NotFound($"User with email: {email} not found");
 | |
| 
 | |
|                 return Ok(tokenAdapter);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 logger.LogError(ex, "Error in GetTokenAdapter");
 | |
|                 return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | 
