using System.Security.Claims; using iknow_api.DTOs; using iknow_api.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace iknow_api.Controllers { /// /// UC012 subjects, UC013 active semesters, UC014 professor assignments. /// Every action requires the admin role, checked against the validated token. /// [ApiController] [Route("api/[controller]")] [Authorize] public class AdminController : ControllerBase { private readonly IAdminService _adminService; public AdminController(IAdminService adminService) { _adminService = adminService; } // ---------- UC012 ---------- [HttpGet("subjects")] public async Task GetSubjects() => RequireAdmin(out var error) ? Ok(await _adminService.GetSubjectsAsync()) : error; [HttpPost("subjects")] public async Task CreateSubject([FromBody] SubjectWriteDto request) => RequireAdmin(out var error) ? Result(await _adminService.CreateSubjectAsync(request)) : error; [HttpPut("subjects/{id:int}")] public async Task UpdateSubject(int id, [FromBody] SubjectWriteDto request) => RequireAdmin(out var error) ? Result(await _adminService.UpdateSubjectAsync(id, request)) : error; [HttpDelete("subjects/{id:int}")] public async Task DeleteSubject(int id) => RequireAdmin(out var error) ? Result(await _adminService.DeleteSubjectAsync(id)) : error; [HttpPost("subjects/{id:int}/majors")] public async Task LinkMajor(int id, [FromBody] MajorLinkDto request) => RequireAdmin(out var error) ? Result(await _adminService.LinkMajorAsync(id, request)) : error; [HttpDelete("subjects/{id:int}/majors/{majorId:int}")] public async Task UnlinkMajor(int id, int majorId) => RequireAdmin(out var error) ? Result(await _adminService.UnlinkMajorAsync(id, majorId)) : error; [HttpPost("subjects/{id:int}/prerequisites")] public async Task AddPrerequisite(int id, [FromBody] PrerequisiteDto request) => RequireAdmin(out var error) ? Result(await _adminService.AddPrerequisiteAsync(id, request)) : error; [HttpDelete("subjects/{id:int}/prerequisites/{dependencyId:int}")] public async Task RemovePrerequisite(int id, int dependencyId) => RequireAdmin(out var error) ? Result(await _adminService.RemovePrerequisiteAsync(id, dependencyId)) : error; // ---------- UC013 ---------- [HttpGet("semesters")] public async Task GetSemesters() => RequireAdmin(out var error) ? Ok(await _adminService.GetSemestersAsync()) : error; [HttpPost("semesters")] public async Task CreateSemester([FromBody] SemesterWriteDto request) => RequireAdmin(out var error) ? Result(await _adminService.CreateSemesterAsync(request)) : error; // ---------- UC014 ---------- [HttpGet("schedule/{semesterId:int}")] public async Task GetSchedule(int semesterId) { if (!RequireAdmin(out var error)) return error; var schedule = await _adminService.GetScheduleAsync(semesterId); return schedule is null ? NotFound(new AdminResultDto { Ok = false, Message = "Semester not found." }) : Ok(schedule); } [HttpPost("schedule")] public async Task Assign([FromBody] ScheduleWriteDto request) => RequireAdmin(out var error) ? Result(await _adminService.AssignAsync(request)) : error; [HttpDelete("schedule")] public async Task Unassign([FromBody] ScheduleWriteDto request) => RequireAdmin(out var error) ? Result(await _adminService.UnassignAsync(request)) : error; // ---------- shared ---------- [HttpGet("majors")] public async Task GetMajors() => RequireAdmin(out var error) ? Ok(await _adminService.GetMajorsAsync()) : error; private IActionResult Result(AdminResultDto result) => result.Ok ? Ok(result) : BadRequest(result); /// /// The role comes from the validated token, so it cannot be set by the caller. /// private bool RequireAdmin(out IActionResult error) { var role = User.FindFirst(ClaimTypes.Role)?.Value ?? User.FindFirst("role")?.Value; if (!string.Equals(role, nameof(Models.UserRole.Admin), StringComparison.OrdinalIgnoreCase)) { error = StatusCode(403, new AdminResultDto { Ok = false, Message = "This endpoint is for administrators." }); return false; } error = Ok(); return true; } } }