feat(API): Adds TagController class
This commit is contained in:
119
Lactose/Controllers/TagController.cs
Normal file
119
Lactose/Controllers/TagController.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Lactose.Mapper;
|
||||
using Lactose.Models;
|
||||
using Lactose.Repositories;
|
||||
using Lactose.Services;
|
||||
using Lactose.Types;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Extensions;
|
||||
|
||||
namespace Lactose.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class TagController(
|
||||
ILogger<TagController> logger,
|
||||
LactoseAuthService authService,
|
||||
ITagRepository tagRepository
|
||||
) : ControllerBase {
|
||||
[HttpGet("id")]
|
||||
public ActionResult<TagDto> Get(Guid id, bool children = false, bool ancestors = false) {
|
||||
Tag? tag = tagRepository.Find(id);
|
||||
|
||||
if (tag == null) { return NotFound(); }
|
||||
var tagDto = TagsMapper.ToTagDto(tag);
|
||||
tagDto.Parent = tag.Parent == null ? null : TagsMapper.ToTagDto(tag.Parent);
|
||||
|
||||
if (children) {
|
||||
tagDto.Children = [];
|
||||
tagRepository.GetChildren(tag.Id).ForEach(t => tagDto.Children.Add(TagsMapper.ToTagDto(t)));
|
||||
}
|
||||
|
||||
//TODO: Protect from overflow
|
||||
if (ancestors) {
|
||||
Tag? index = tag.Parent;
|
||||
TagDto? indexDto = tagDto;
|
||||
List<Tag> ancestorsTags = [];
|
||||
|
||||
// This is redundant, because circular references shouldn't be present
|
||||
while (index != null && !ancestorsTags.Contains(tag)) {
|
||||
ancestorsTags.Add(index);
|
||||
indexDto.Parent = TagsMapper.ToTagDto(index);
|
||||
index = index.Parent;
|
||||
indexDto = indexDto.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
return tagDto;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<List<TagDto>> GetAll(string? search, uint? page, uint? pageSize) {
|
||||
search ??= string.Empty;
|
||||
List<Tag> tags = tagRepository.Search(search, page, pageSize);
|
||||
List<TagDto> tagsDto = [];
|
||||
|
||||
tags.ForEach(
|
||||
t => {
|
||||
var tagDto = TagsMapper.ToTagDto(t);
|
||||
tagDto.Parent = t.Parent == null ? null : TagsMapper.ToTagDto(t.Parent);
|
||||
tagsDto.Add(tagDto);
|
||||
}
|
||||
);
|
||||
|
||||
return tagsDto;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Update([FromBody] TagUpdateDto tagDto) {
|
||||
LactoseAuthenticatedUser? user = authService.GetUserData(User);
|
||||
|
||||
if (user == null) {
|
||||
logger.LogWarning(@"Anonymous User hasn't enough permissions to create a Tag. it shouldn't be here");
|
||||
return Unauthorized("Unauthorized");
|
||||
}
|
||||
|
||||
if (user.AccessLevel != EAccessLevel.Admin && user.AccessLevel != EAccessLevel.Curator) {
|
||||
return Unauthorized("Unauthorized");
|
||||
}
|
||||
|
||||
Tag? tag = tagRepository.Find(tagDto.Id);
|
||||
|
||||
if (tag == null) { return NotFound(); }
|
||||
|
||||
if (!tagDto.Name.IsNullOrEmpty()) { tag.Name = tagDto.Name!; }
|
||||
|
||||
if (tagDto.Parent != null) {
|
||||
if (tagDto.Parent.Equals(Guid.Empty)) { tag.Parent = null; }
|
||||
|
||||
Tag? parent = tagRepository.Find(tagDto.Parent.Value);
|
||||
|
||||
if (parent != null) { tag.Parent = parent; } else { return NotFound("Parent tag was not found"); }
|
||||
}
|
||||
|
||||
tagRepository.Save();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpDelete]
|
||||
[Route("{id}")]
|
||||
public ActionResult Delete(Guid id) {
|
||||
throw new NotImplementedException("Tag:Delete is not implemented yet");
|
||||
}
|
||||
}
|
||||
|
||||
public class TagDto {
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public TagDto? Parent { get; set; }
|
||||
public List<TagDto>? Children { get; set; }
|
||||
}
|
||||
|
||||
public class TagUpdateDto {
|
||||
public Guid Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public Guid? Parent { get; set; }
|
||||
}
|
||||
14
Lactose/Mapper/TagsMapper.cs
Normal file
14
Lactose/Mapper/TagsMapper.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Lactose.Controllers;
|
||||
using Lactose.Models;
|
||||
|
||||
namespace Lactose.Mapper;
|
||||
|
||||
public static class TagsMapper {
|
||||
public static TagDto ToTagDto(Tag tag) {
|
||||
return new TagDto() {
|
||||
Id = tag.Id,
|
||||
Name = tag.Name,
|
||||
Parent = null
|
||||
};
|
||||
}
|
||||
}
|
||||
36
Lactose/Repositories/ITagRepository.cs
Normal file
36
Lactose/Repositories/ITagRepository.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Lactose.Models;
|
||||
|
||||
namespace Lactose.Repositories;
|
||||
|
||||
public interface ITagRepository : IDisposable {
|
||||
/// <summary>
|
||||
/// Search for tags that are like the given <paramref name="searchQuery"/>
|
||||
/// </summary>
|
||||
/// <param name="searchQuery">the search query</param>
|
||||
/// <param name="page"> the number of the page for the given query</param>
|
||||
/// <param name="pageSize">the size of the page</param>
|
||||
/// <returns>list of tags of type <see cref="Tag"/> with the size <paramref name="pageSize"/></returns>
|
||||
List<Tag> Search(string searchQuery, uint? page, uint? pageSize);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all the tags
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<Tag> GetAll();
|
||||
|
||||
/// <summary>
|
||||
/// Find a specific Tag given the id
|
||||
/// </summary>
|
||||
/// <param name="id">identifier of the tag</param>
|
||||
/// <returns>the <see cref="Tag"/> or null</returns>
|
||||
Tag? Find(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Return the list of the children of the given tag
|
||||
/// </summary>
|
||||
/// <param name="id">identifier of the tag</param>
|
||||
/// <returns>the list of <see cref="Tag"/>, could be empty</returns>
|
||||
List<Tag> GetChildren(Guid id);
|
||||
|
||||
void Save();
|
||||
}
|
||||
Reference in New Issue
Block a user