Updated AuthController and CvController to return exception messages in 500 responses and enhanced logging. MailService now throws descriptive exceptions on email send failures, allowing upstream error reporting and preserving failed messages.
271 lines
12 KiB
C#
271 lines
12 KiB
C#
using Asp.Versioning;
|
|
using AutoMapper;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using PortBlog.API.Models;
|
|
using PortBlog.API.Repositories.Contracts;
|
|
using PortBlog.API.Services.Contracts;
|
|
|
|
namespace PortBlog.API.Controllers
|
|
{
|
|
[ApiController]
|
|
[ApiVersion("1.0")]
|
|
[Route("api/v{version:apiVersion}/cv")]
|
|
public class CvController : ControllerBase
|
|
{
|
|
private readonly ILogger<CvController> _logger;
|
|
private readonly ICandidateRepository _candidateRepository;
|
|
private readonly IResumeRepository _resumeRepository;
|
|
private readonly IMailRepository _mailRepository;
|
|
private readonly IMailService _mailService;
|
|
private readonly IMapper _mapper;
|
|
|
|
public CvController(ILogger<CvController> logger, ICandidateRepository candidateRepository, IResumeRepository resumeRepository, IMailService mailService, IMapper mapper, IMailRepository mailRepository)
|
|
{
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
_candidateRepository = candidateRepository ?? throw new ArgumentNullException(nameof(candidateRepository));
|
|
_resumeRepository = resumeRepository ?? throw new ArgumentNullException(nameof(resumeRepository));
|
|
_mailRepository = mailRepository;
|
|
_mailService = mailService;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get CV details of the candidate by candidateid.
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate whose cv to get</param>
|
|
/// <returns>CV details of the candidate</returns>
|
|
/// <response code="200">Returns the requested cv of the candidate</response>
|
|
[HttpGet("{candidateId}")]
|
|
[Obsolete]
|
|
[ApiVersion("0.1", Deprecated = true)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<CvDto>> Get(int candidateId)
|
|
{
|
|
try
|
|
{
|
|
if (!await _candidateRepository.CandidateExistAsync(candidateId))
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when accessing cv details.");
|
|
return NotFound();
|
|
}
|
|
|
|
var latestResumeForCandidate = await _resumeRepository.GetLatestResumeForCandidateAsync(candidateId, true);
|
|
|
|
return Ok(_mapper.Map<CvDto>(latestResumeForCandidate));
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical($"Exception while getting Cv details for the candidate with id {candidateId}.", ex);
|
|
return StatusCode(500, "A problem happened while handling your request.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get hobbies of the candidate by candidateid
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate whose hobbies to get</param>
|
|
/// <returns>Hobbies of the candidate</returns>
|
|
/// <response code="200">Returns the requested hobbies of the candidate</response>
|
|
[HttpGet("GetHobbies/{candidateId}")]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<AboutDto>> GetHobbies(int candidateId)
|
|
{
|
|
try
|
|
{
|
|
if (!await _candidateRepository.CandidateExistAsync(candidateId))
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching about details.");
|
|
return NotFound();
|
|
}
|
|
|
|
var aboutDetails = await _resumeRepository.GetHobbiesAsync(candidateId);
|
|
|
|
return Ok(_mapper.Map<AboutDto>(aboutDetails));
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical($"Exception while getting about details for the candidate with id {candidateId}.", ex);
|
|
return StatusCode(500, "A problem happened while handling your request.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Candidate details with social links by candidateid
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate whose detials to get with social links</param>
|
|
/// <returns>Candidate details with sociallinks</returns>
|
|
/// <response code="200">Returns the requested candidate details with social links</response>
|
|
[HttpGet("GetCandidateWithSocialLinks/{candidateId}")]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<CandidateSocialLinksDto>> GetContact(int candidateId)
|
|
{
|
|
try
|
|
{
|
|
if (!await _candidateRepository.CandidateExistAsync(candidateId))
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching candidate with social links.");
|
|
return NotFound();
|
|
}
|
|
|
|
var contact = await _resumeRepository.GetCandidateWithSocialLinksAsync(candidateId);
|
|
|
|
return Ok(_mapper.Map<CandidateSocialLinksDto>(contact));
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical($"Exception while getting contact for the candidate with social links with id {candidateId}.", ex);
|
|
return StatusCode(500, "A problem happened while handling your request.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Candidate resume by candidateid
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate whose resume to get</param>
|
|
/// <returns>Candidate resume</returns>
|
|
/// <response code="200">Returns the requested candidate resume</response>
|
|
[HttpGet("GetResume/{candidateId}")]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<ResumeDto>> GetResume(int candidateId)
|
|
{
|
|
try
|
|
{
|
|
if (!await _candidateRepository.CandidateExistAsync(candidateId))
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching resume.");
|
|
return NotFound();
|
|
}
|
|
|
|
var resume = await _resumeRepository.GetResumeAsync(candidateId);
|
|
|
|
return Ok(_mapper.Map<ResumeDto>(resume));
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical($"Exception while getting resume for the candidate with id {candidateId}.", ex);
|
|
return StatusCode(500, "A problem happened while handling your request.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Candidate projects by candidateid
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate whose projects to get</param>
|
|
/// <returns>Candidate projects</returns>
|
|
/// <response code="200">Returns the requested candidate projects</response>
|
|
[HttpGet("GetProjects/{candidateId}")]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<ProjectsDto>> GetProjects(int candidateId)
|
|
{
|
|
try
|
|
{
|
|
if (!await _candidateRepository.CandidateExistAsync(candidateId))
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching projects.");
|
|
return NotFound();
|
|
}
|
|
|
|
var projects = await _resumeRepository.GetProjectsAsync(candidateId);
|
|
|
|
return Ok(_mapper.Map<ProjectsDto>(projects));
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical($"Exception while getting projects for the candidate with id {candidateId}.", ex);
|
|
return StatusCode(500, "A problem happened while handling your request.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Candidate blog with posts by candidateid
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate whose blog with posts to get</param>
|
|
/// <returns>Candidate blog with posts</returns>
|
|
/// <response code="200">Returns the requested candidate blog with posts</response>
|
|
[HttpGet("GetBlog/{candidateId}")]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<BlogDto>> GetBlog(int candidateId)
|
|
{
|
|
try
|
|
{
|
|
if (!await _candidateRepository.CandidateExistAsync(candidateId))
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching projects.");
|
|
return NotFound();
|
|
}
|
|
|
|
var blog = await _resumeRepository.GetBlogAsync(candidateId);
|
|
|
|
return Ok(_mapper.Map<BlogDto>(blog));
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical($"Exception while getting projects for the candidate with id {candidateId}.", ex);
|
|
return StatusCode(500, "A problem happened while handling your request.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Send Message through email
|
|
/// </summary>
|
|
/// <param name="candidateId">The id of the candidate to whom the message should be sent</param>
|
|
/// <param name="message">Details of the Message to send to the candidate</param>
|
|
/// <returns>Returns the status code</returns>
|
|
/// <response code="204">Returns nothing</response>
|
|
[HttpPost("SendMessage/{candidateId}")]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
public async Task<ActionResult<bool>> SendMessage(int candidateId, [FromBody] MessageDto message)
|
|
{
|
|
try
|
|
{
|
|
var candidate = await _candidateRepository.GetCandidateAsync(candidateId);
|
|
if (candidate == null)
|
|
{
|
|
_logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching projects.");
|
|
return NotFound();
|
|
}
|
|
|
|
var candidateDto = _mapper.Map<CandidateDto>(candidate);
|
|
var messageSendDto = _mapper.Map<MessageSendDto>(message);
|
|
messageSendDto.ToEmail = candidateDto.Email;
|
|
messageSendDto.Name = candidateDto.DisplayName;
|
|
messageSendDto.CandidateId = candidateDto.CandidateId;
|
|
await _mailService.SendAsync(messageSendDto);
|
|
return Ok(true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogCritical(ex, "Exception while sending message from {Name}.", message.Name);
|
|
return StatusCode(500, ex.Message);
|
|
}
|
|
}
|
|
}
|
|
}
|