// *********************************************************************** // // Heath // // *********************************************************************** 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 { /// /// Handles all requests for user authentication. /// [ApiVersion("1.0")] [Route("api/v{api-version:apiVersion}/[controller]")] [Produces(MimeTypes.ApplicationJson)] [Consumes(MimeTypes.ApplicationJson)] [ApiController] public class UserController(IUserService service, ILogger logger) : ControllerBase { /// /// Gets all the users. /// /// The found entity. /// The users found. /// The users not found error. /// The service internal error. [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Read")] public async Task 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}"); } } /// /// Gets the user by identifier. /// /// The user identifier. /// The found entity. /// The user found. /// The user not found error. /// The service internal error. [HttpGet] [Route(Routes.Id)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Read")] public async Task 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}"); } } /// /// Gets the user by email. /// /// The user's email. /// The found entity. /// The user found. /// The user not found error. /// The service internal error. [HttpGet] [Route(Routes.Email)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] public async Task 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}"); } } /// /// Validates if a user exists on the database. /// /// The user's email. /// The found entity. /// The user found. /// The user not found error. /// The service internal error. [HttpGet] [Route("{email}/ValidateExistence")] [ProducesResponseType(typeof(UserExistenceAdapter), StatusCodes.Status200OK)] [AllowAnonymous] public async Task 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}"); } } /// /// Creates a new user. /// /// The user to be added. /// Sends an invitation in case of third party access. /// The created entity. /// The user created. /// The user could not be created. /// The service internal error. [HttpPost(Routes.Register)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status201Created)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Updates a full user by identifier. /// /// The user to update. /// The user identifier. /// The updated entity. /// The user updated. /// The user not found. /// The user could not be updated. /// The service internal error. [HttpPut] [Route(Routes.Id)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Logs in the user. /// /// The User's email. /// A representing /// the asynchronous execution of the service. /// The User found. /// The User not found. /// The service internal error. [HttpPatch(Routes.LogIn)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] public async Task 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}"); } } /// /// Logs out the user. /// /// The User's email. /// A representing /// the asynchronous execution of the service. /// The User updated. /// The service internal error. [HttpPatch(Routes.LogOut)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] public async Task 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}"); } } /// /// Changes the status of the user. /// /// The user identifier. /// The new status of the user. /// The updated entity. /// The user updates. /// The user not found. /// The user could not be deleted. /// The service internal error. [HttpPatch] [Route(Routes.ChangeStatus)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Adds a company to the user's list of companies. /// /// The user identifier. /// The company identifier to add. /// The updated entity. /// The user with the updated companies. /// The user or company not found. /// The service internal error. [HttpPost] [Route(Routes.AddCompany)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Removes a company from the user's list of companies. /// /// The user identifier. /// The company identifier to remove. /// The updated entity. /// The user with the updated companies. /// The user or company not found. /// The service internal error. [HttpDelete] [Route(Routes.RemoveCompany)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Adds a project to the user's list of projects. /// /// The user identifier. /// The project identifier to add. /// The updated entity. /// The user with the updated projects. /// The user or project not found. /// The service internal error. [HttpPost] [Route(Routes.AddProject)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Removes a project from the user's list of projects. /// /// The user identifier. /// The project identifier to remove. /// The updated entity. /// The user with the updated projects. /// The user or project not found. /// The service internal error. [HttpDelete] [Route(Routes.RemoveProject)] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Write")] public async Task 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}"); } } /// /// Gets a token for the user, including roles, permissions, and modules. /// /// The user's email. /// The token adapter with user details, role, permissions, and modules. /// The token adapter with user details. /// The user not found. /// The service internal error. [HttpGet] [Route("{email}/GetTokenAdapter")] [ProducesResponseType(typeof(TokenAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] public async Task 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}"); } } /// /// Get Consent Form PDF. /// /// The found pdf. /// The pdf found. /// The pdf not found error. /// The service internal error. [HttpGet] [Route("GetConsentFormPDF")] [ProducesResponseType(typeof(BlobDownloadUriAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] [Permission("UserManagement.Read")] public async Task GetConsentFormPDFService() { try { var result = await service.GetConsentFormPDFService(); return Ok(result); } catch (Exception ex) { logger.LogError(ex, "Error in GetConsentFormPDFService"); return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}"); } } /// /// Accept user consent form. /// /// A representing /// the asynchronous execution of the service. /// The User found. /// The User not found. /// The service internal error. [HttpPatch("AcceptUserConsentForm")] [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)] [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] public async Task AcceptUserConsentFormAsync() { try { var result = await service.AcceptUserConsentFormService().ConfigureAwait(false); return Ok(result); } catch (Exception ex) { logger.LogError(ex, "Error in AcceptUserConsentFormService"); return StatusCode(500, $"Internal server error, ErrorMessage: {ex.Message}"); } } } }