mirror of
https://github.com/QuotifyTeam/QuotifyBE.git
synced 2025-12-16 08:10:07 +01:00
257 lines
8.8 KiB
C#
257 lines
8.8 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using QuotifyBE.Data;
|
|
using QuotifyBE.Entities;
|
|
using QuotifyBE.DTOs;
|
|
using System.Threading.Tasks;
|
|
using QuotifyBE.Mapping;
|
|
using Microsoft.AspNetCore.Cors;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace QuotifyBE.Controllers;
|
|
|
|
|
|
[ApiController]
|
|
[EnableCors]
|
|
[Route("api/v1/categories")]
|
|
[Produces("application/json")]
|
|
public class CategoryController : ControllerBase
|
|
{
|
|
|
|
private readonly ApplicationDbContext _db;
|
|
private readonly GeneralUseHelpers guhf;
|
|
|
|
public CategoryController(ApplicationDbContext db, GeneralUseHelpers GUHF)
|
|
{
|
|
_db = db;
|
|
guhf = GUHF;
|
|
}
|
|
|
|
// GET /api/v1/categories/page/1
|
|
/// <summary>
|
|
/// Get a category page
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Can (and will) return an empty list if no categories are found in DB. <br/>
|
|
/// Has CORS set.
|
|
/// </remarks>
|
|
/// <param name="page_no">The page number</param>
|
|
/// <response code="200">Returned on valid request</response>
|
|
/// <response code="404">Returned when requested page is invalid (page_no <= 0)</response>
|
|
[HttpGet("page/{page_no}")]
|
|
[EnableCors]
|
|
[ProducesResponseType(typeof(List<CategoryShortDTO>), 200)]
|
|
[ProducesResponseType(typeof(ErrorDTO), 404)]
|
|
public async Task<IActionResult> GetCategoryPage(int page_no = 1)
|
|
{
|
|
// The following seems to be a bad idea, so I leave it as is. ~eee4
|
|
//
|
|
// int totalCategories = await _db.Categories.CountAsync();
|
|
//
|
|
// if (totalCategories <= 0)
|
|
// {
|
|
// return NoContent(new ErrorDTO { Status = "error", Error_msg = "No categories to list" });
|
|
// }
|
|
|
|
const int PageSize = 10;
|
|
|
|
if (page_no <= 0)
|
|
{
|
|
return NotFound(new ErrorDTO { Status = "error", Error_msg = "Numer strony musi być większy niż 0" });
|
|
}
|
|
|
|
// Get all the categories
|
|
//List<Category> categories = await _db.Categories
|
|
// .ToListAsync();
|
|
List<Category> categories = await _db.Categories
|
|
.Skip((page_no - 1) * PageSize)
|
|
.Take(PageSize)
|
|
.ToListAsync();
|
|
|
|
// Convert them to a list of DTO
|
|
List<CategoryShortDTO> result = categories
|
|
.Select(c => c.ToCategoryShortDTO())
|
|
.ToList();
|
|
|
|
// Return to user
|
|
return Ok(result);
|
|
|
|
}
|
|
|
|
// GET /api/v1/categories
|
|
/// <summary>
|
|
/// [AUTHED] Get every category
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Can (and will) return an empty list if no categories are found in DB. <br/>
|
|
/// Unlike GET /api/v1/categories/page/..., requires authorization with a JWT.
|
|
/// Has CORS set.
|
|
/// </remarks>
|
|
/// <response code="200">Returned on valid request</response>
|
|
// /// <response code="404">Returned when there are no categories to list</response>
|
|
[HttpGet]
|
|
[Authorize]
|
|
[EnableCors]
|
|
[ProducesResponseType(typeof(List<CategoryShortDTO>), 200)]
|
|
public async Task<IActionResult> GetQuotePage()
|
|
{
|
|
// The following seems to be a bad idea, so I leave it as is. ~eee4
|
|
//
|
|
// int totalCategories = await _db.Categories.CountAsync();
|
|
//
|
|
// if (totalCategories <= 0)
|
|
// {
|
|
// return NotFound(new ErrorDTO { Status = "error", Error_msg = "No categories to list" });
|
|
// }
|
|
|
|
// Get all the categories
|
|
List<Category> categories = await _db.Categories
|
|
.ToListAsync();
|
|
|
|
// Convert them to a list of DTO
|
|
List<CategoryShortDTO> result = categories
|
|
.Select(c => c.ToCategoryShortDTO())
|
|
.ToList();
|
|
|
|
// Return to user
|
|
return Ok(result);
|
|
|
|
}
|
|
|
|
|
|
// POST /api/v1/categories
|
|
/// <summary>
|
|
/// [AUTHED] Create a new category
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Allows authorized users to create categories.
|
|
/// <br/><br/>
|
|
/// <b>Important!</b>
|
|
/// Category names are case insensitive. <br/>
|
|
/// Has CORS set.
|
|
/// </remarks>
|
|
/// <response code="200">Returned on valid request</response>
|
|
/// <response code="406">Returned when such category already exists (case insensitive)</response>
|
|
[HttpPost]
|
|
[Authorize]
|
|
[EnableCors]
|
|
[ProducesResponseType(typeof(CategoryShortDTO), 200)]
|
|
[ProducesResponseType(typeof(ErrorDTO), 406)]
|
|
public async Task<IActionResult> PostNewCategory([FromBody] NewCategoryDTO formCategory)
|
|
{
|
|
// Check if such category doesn't already exist
|
|
Category? cat = await _db.Categories.FirstOrDefaultAsync(c => c.Name.ToLower() == formCategory.Name.ToLower());
|
|
if (cat != null)
|
|
{
|
|
return StatusCode(406, new ErrorDTO { Status = "error", Error_msg = "This category already exists" });
|
|
}
|
|
|
|
// Create new category
|
|
cat = new Category
|
|
{
|
|
Name = formCategory.Name,
|
|
Description = formCategory.Description,
|
|
CreatedAt = DateTime.UtcNow
|
|
};
|
|
|
|
// Add to DB
|
|
await _db.Categories.AddAsync(cat);
|
|
await _db.SaveChangesAsync();
|
|
|
|
// And send back to the user as DTO
|
|
return Ok(cat.ToCategoryShortDTO());
|
|
|
|
}
|
|
|
|
// DELETE /api/v1/categories
|
|
/// <summary>
|
|
/// [AUTHED] Delete a category
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Allows authorized users to delete categories.
|
|
/// <br/><br/>
|
|
/// Has CORS set.
|
|
/// </remarks>
|
|
/// <param name="id">Id of the category which shall be deleted</param>
|
|
/// <response code="200">Returned on valid request</response>
|
|
/// <response code="404">Returned when no such category exists</response>
|
|
[HttpDelete("{id}")]
|
|
[Authorize]
|
|
[EnableCors]
|
|
[ProducesResponseType(200)]
|
|
[ProducesResponseType(typeof(ErrorDTO), 404)]
|
|
public async Task<IActionResult> DeleteCategory(int id)
|
|
{
|
|
// (Attempt to) find the category
|
|
Category? cat = await _db.Categories
|
|
.FirstOrDefaultAsync(c => c.Id == id);
|
|
// Failed?
|
|
if (cat == null)
|
|
return NotFound(new { status = "error", error_msg = "Category not found" });
|
|
|
|
// Find all the QuoteId <-> CategoryId pairs for provided id
|
|
List<QuoteCategory> quoteLinks = await _db.QuoteCategories
|
|
.Where(qc => qc.CategoryId == id)
|
|
.ToListAsync();
|
|
|
|
// For each of the dependent quotes
|
|
foreach (var link in quoteLinks) {
|
|
// Remove all the associative pairs
|
|
_db.QuoteCategories.Remove(link);
|
|
}
|
|
|
|
// Finally, remove the category
|
|
_db.Categories.Remove(cat);
|
|
await _db.SaveChangesAsync();
|
|
|
|
// Return ok
|
|
return Ok(new { Status = "ok" });
|
|
}
|
|
|
|
// PATCH /api/v1/categories/1
|
|
/// <summary>
|
|
/// [AUTHED] Modify an existing category
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Allows authorized users to modify categories.
|
|
/// <br/><br/>
|
|
/// Has CORS set.
|
|
/// </remarks>
|
|
/// <param name="id">Id of the category which shall be modified</param>
|
|
/// <param name="updatedCategory">DTO with new name and description. Id and creation date are ignored.</param>
|
|
/// <response code="200">Returned on valid request</response>
|
|
/// <response code="400">Returned when category name is empty or null</response>
|
|
/// <response code="404">Returned when no such category exists</response>
|
|
[HttpPatch("{id}")]
|
|
[Authorize]
|
|
[EnableCors]
|
|
[ProducesResponseType(typeof(CategoryShortDTO), 200)]
|
|
[ProducesResponseType(typeof(ErrorDTO), 400)]
|
|
[ProducesResponseType(typeof(ErrorDTO), 404)]
|
|
public async Task<IActionResult> EditCategory(int id, [FromBody] CategoryShortDTO updatedCategory)
|
|
{
|
|
// Find the category to modify
|
|
Category? cat = await _db.Categories.FirstOrDefaultAsync(c => c.Id == id);
|
|
|
|
// Failed?
|
|
if (cat == null)
|
|
return NotFound(new { status = "error", error_msg = "Category not found" });
|
|
|
|
// Otherwise, ensure the category name is not empty or null
|
|
if (string.IsNullOrWhiteSpace(updatedCategory.Name))
|
|
return BadRequest(new ErrorDTO { Status = "error", Error_msg = "Category name cannot be empty." });
|
|
|
|
// Update the fields
|
|
cat.Name = updatedCategory.Name;
|
|
cat.Description = updatedCategory.Description;
|
|
// Note the user cannot modify the createdAt field,
|
|
// and we do not store last modification date.
|
|
await _db.SaveChangesAsync();
|
|
|
|
// Return the modified category to user
|
|
return Ok(cat.ToCategoryShortDTO());
|
|
}
|
|
|
|
}
|
|
|