using System.Security.Claims;
using iknow_api.DTOs;
using iknow_api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace iknow_api.Controllers
{
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class ProfController : ControllerBase
{
private readonly IProfService _profService;
public ProfController(IProfService profService)
{
_profService = profService;
}
///
/// The subjects this professor teaches, each with the students enrolled
/// in it and their grade so far.
///
[HttpGet("students")]
public async Task GetStudents()
{
if (!TryGetProfessorId(out var professorId, out var error))
{
return error;
}
return Ok(await _profService.GetStudentsBySubjectAsync(professorId));
}
[HttpPost("grade/add")]
public Task AddGrade([FromBody] GradeRequestDto request) =>
SetGrade(request, GradeAction.Add);
[HttpPost("grade/edit")]
public Task EditGrade([FromBody] GradeRequestDto request) =>
SetGrade(request, GradeAction.Edit);
[HttpPost("grade/remove")]
public Task RemoveGrade([FromBody] GradeRequestDto request) =>
SetGrade(request, GradeAction.Remove);
private async Task SetGrade(GradeRequestDto request, GradeAction action)
{
if (!TryGetProfessorId(out var professorId, out var error))
{
return error;
}
var result = await _profService.SetGradeAsync(professorId, request, action);
return result.Ok ? Ok(result) : BadRequest(result);
}
///
/// Reads the caller from the validated token and requires the professor
/// role, so one professor can never act on another one's subjects.
///
private bool TryGetProfessorId(out int professorId, out IActionResult error)
{
professorId = 0;
error = Forbid();
var role = User.FindFirst(ClaimTypes.Role)?.Value ?? User.FindFirst("role")?.Value;
if (!string.Equals(role, nameof(Models.UserRole.Professor), StringComparison.OrdinalIgnoreCase))
{
error = StatusCode(403, new GradeResultDto
{
Ok = false,
Message = "This endpoint is for professors."
});
return false;
}
var idClaim = User.FindFirst("id")?.Value;
if (!int.TryParse(idClaim, out professorId))
{
error = Unauthorized(new GradeResultDto
{
Ok = false,
Message = "Token has no usable user id."
});
return false;
}
return true;
}
}
}