using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Moonlight.Api.Database; using Moonlight.Api.Database.Entities; using Moonlight.Api.Mappers; using Moonlight.Shared; using Moonlight.Shared.Http.Requests; using Moonlight.Shared.Http.Requests.Admin.Roles; using Moonlight.Shared.Http.Responses; using Moonlight.Shared.Http.Responses.Admin; namespace Moonlight.Api.Http.Controllers.Admin; [ApiController] [Route("api/admin/roles")] public class RolesController : Controller { private readonly DatabaseRepository RoleRepository; public RolesController(DatabaseRepository roleRepository) { RoleRepository = roleRepository; } [HttpGet] [Authorize(Policy = Permissions.Roles.View)] public async Task>> GetAsync( [FromQuery] int startIndex, [FromQuery] int length, [FromQuery] FilterOptions? filterOptions ) { // Validation if (startIndex < 0) return Problem("Invalid start index specified", statusCode: 400); if (length is < 1 or > 100) return Problem("Invalid length specified"); // Query building var query = RoleRepository .Query(); // Filters if (filterOptions != null) { foreach (var filterOption in filterOptions.Filters) { query = filterOption.Key switch { nameof(Role.Name) => query.Where(role => EF.Functions.ILike(role.Name, $"%{filterOption.Value}%")), _ => query }; } } // Pagination var data = await query .OrderBy(x => x.Id) .ProjectToDto() .Skip(startIndex) .Take(length) .ToArrayAsync(); var total = await query.CountAsync(); return new PagedData(data, total); } [HttpGet("{id:int}")] [Authorize(Policy = Permissions.Roles.View)] public async Task> GetAsync([FromRoute] int id) { var role = await RoleRepository .Query() .FirstOrDefaultAsync(x => x.Id == id); if (role == null) return Problem("No role with this id found", statusCode: 404); return RoleMapper.ToDto(role); } [HttpPost] [Authorize(Policy = Permissions.Roles.Create)] public async Task> CreateAsync([FromBody] CreateRoleDto request) { var role = RoleMapper.ToEntity(request); var finalRole = await RoleRepository.AddAsync(role); return RoleMapper.ToDto(finalRole); } [HttpPatch("{id:int}")] [Authorize(Policy = Permissions.Roles.Edit)] public async Task> UpdateAsync([FromRoute] int id, [FromBody] UpdateRoleDto request) { var role = await RoleRepository .Query() .FirstOrDefaultAsync(x => x.Id == id); if (role == null) return Problem("No role with this id found", statusCode: 404); RoleMapper.Merge(role, request); await RoleRepository.UpdateAsync(role); return RoleMapper.ToDto(role); } [HttpDelete("{id:int}")] [Authorize(Policy = Permissions.Roles.Delete)] public async Task DeleteAsync([FromRoute] int id) { var role = await RoleRepository .Query() .FirstOrDefaultAsync(x => x.Id == id); if (role == null) return Problem("No role with this id found", statusCode: 404); await RoleRepository.RemoveAsync(role); return NoContent(); } }