using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using WinStudentGoalTracker.Models; using WinStudentGoalTracker.BaseClasses; using WinStudentGoalTracker.DataAccess; using WinStudentGoalTracker.Services; namespace WinStudentGoalTracker.Controllers; [ApiController] [Route("api/[controller]")] public class StudentController : BaseController { private readonly StudentRepository _studentRepository = new(); [HttpGet("my")] [Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")] [ProducesResponseType(typeof(ResponseResult>), StatusCodes.Status200OK)] public async Task>>> GetMyStudents() { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); if (error is not null) { return error; } var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role); return Ok(new ResponseResult> { Success = true, Message = "Students retrieved successfully.", Data = students }); } // TODO refactor with database changes to ensure // users who are a district admin are actually associated with a district, and // then this endpoint should validate that the requested program is part of the district // Once that is in place, then district admins will be allowed to call this function. [HttpGet("program/{idProgram:guid}")] [Authorize(Roles = $"{UserRoles.SuperAdmin}")] [ProducesResponseType(typeof(ResponseResult>), StatusCodes.Status200OK)] public async Task>>> GetStudentsForProgram(Guid idProgram) { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); if (error is not null) { return error; } var students = await _studentRepository.GetMyStudentsAsync(userId, idProgram, role); return Ok(new ResponseResult> { Success = true, Message = "Students retrieved successfully.", Data = students }); } [HttpGet("{idStudent:guid}")] [Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status404NotFound)] public async Task>> GetById(Guid idStudent) { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); if (error is not null) { return error; } var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role); if (!students.Select(s => s.StudentId).Contains(idStudent)) { return NotFound(new ResponseResult { Success = false, Message = "Student not found." }); } var student = students.Single(s => s.StudentId == idStudent); return Ok(new ResponseResult { Success = true, Message = "Student retrieved successfully.", Data = student }); } [HttpPost] [Authorize(Roles = $"{UserRoles.Teacher}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status201Created)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status400BadRequest)] public async Task>> Create([FromBody] CreateStudentDto newStudentData) { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); if (error is not null) { return error; } if (!PermissionService.IsAllowed(role, EntityType.Student, PermissionAction.Create)) { return BadRequest(new ResponseResult { Success = false, Message = "Unable to create student." }); } var newStudentId = Guid.NewGuid(); var created = await _studentRepository.InsertAsync(newStudentData, newStudentId, programId, userId); if (created is null) { return BadRequest(new ResponseResult { Success = false, Message = "Unable to create student." }); } return CreatedAtAction(nameof(GetById), new { idStudent = created.StudentId }, new ResponseResult { Success = true, Message = "Student created successfully.", Data = created }); } [HttpPut("{idStudent:guid}")] [Authorize(Roles = $"{UserRoles.Teacher}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status404NotFound)] public async Task>> Update(Guid idStudent, [FromBody] UpdateStudentDto request) { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); if (error is not null) { return error; } var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role); if (!students.Select(s => s.StudentId).Contains(idStudent)) { return NotFound(new ResponseResult { Success = false, Message = "Student not found." }); } var updated = await _studentRepository.UpdateAsync(idStudent, request); var refreshed = await _studentRepository.GetByIdAsync(idStudent); if (refreshed is null) { return NotFound(new ResponseResult { Success = false, Message = "Student not found after update." }); } return Ok(new ResponseResult { Success = true, Message = updated ? "Changes applied successfully." : "No changes were applied.", Data = refreshed }); } [HttpDelete("{idStudent:guid}")] [Authorize(Roles = $"{UserRoles.Teacher}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status404NotFound)] public async Task>> Delete(Guid idStudent) { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); if (error is not null) { return error; } var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role); if (!students.Select(s => s.StudentId).Contains(idStudent)) { return NotFound(new ResponseResult { Success = false, Message = "Student not found." }); } var deleted = await _studentRepository.DeleteAsync(idStudent); if (!deleted) { return NotFound(new ResponseResult { Success = false, Message = "Student not found." }); } return Ok(new ResponseResult { Success = true, Message = "Student deleted." }); } }