112 lines
3.5 KiB
C#
112 lines
3.5 KiB
C#
using BCards.Web.Areas.Tutoriais.Models;
|
|
using BCards.Web.Areas.Tutoriais.Services;
|
|
using BCards.Web.Repositories;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace BCards.Web.Areas.Tutoriais.Controllers;
|
|
|
|
[Area("Tutoriais")]
|
|
public class TutoriaisController : Controller
|
|
{
|
|
private readonly IMarkdownService _markdownService;
|
|
private readonly ICategoryRepository _categoryRepository;
|
|
private readonly ILogger<TutoriaisController> _logger;
|
|
|
|
public TutoriaisController(
|
|
IMarkdownService markdownService,
|
|
ICategoryRepository categoryRepository,
|
|
ILogger<TutoriaisController> logger)
|
|
{
|
|
_markdownService = markdownService;
|
|
_categoryRepository = categoryRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
// GET /tutoriais
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
var categories = await _categoryRepository.GetAllActiveAsync();
|
|
var tutoriaisPorCategoria = new Dictionary<string, List<ArticleMetadata>>();
|
|
|
|
foreach (var category in categories)
|
|
{
|
|
var artigos = await _markdownService
|
|
.GetArticlesByCategoryAsync(category.Slug, "pt-BR");
|
|
|
|
if (artigos.Any())
|
|
{
|
|
tutoriaisPorCategoria[category.Slug] = artigos;
|
|
}
|
|
}
|
|
|
|
ViewBag.Categories = categories;
|
|
return View(tutoriaisPorCategoria);
|
|
}
|
|
|
|
// GET /tutoriais/{categoria}
|
|
public async Task<IActionResult> Category(string categoria)
|
|
{
|
|
// Validar categoria existe
|
|
var category = await _categoryRepository.GetBySlugAsync(categoria);
|
|
if (category == null)
|
|
{
|
|
_logger.LogWarning("Categoria não encontrada: {Categoria}", categoria);
|
|
return NotFound();
|
|
}
|
|
|
|
var artigos = await _markdownService
|
|
.GetArticlesByCategoryAsync(categoria, "pt-BR");
|
|
|
|
ViewBag.Category = category;
|
|
return View(artigos);
|
|
}
|
|
|
|
// GET /tutoriais/{categoria}/{slug}
|
|
public async Task<IActionResult> Article(string categoria, string slug)
|
|
{
|
|
// Sanitização (segurança contra path traversal)
|
|
categoria = categoria.Replace("..", "").Replace("/", "").Replace("\\", "");
|
|
slug = slug.Replace("..", "").Replace("/", "").Replace("\\", "");
|
|
|
|
// Validar categoria existe
|
|
var category = await _categoryRepository.GetBySlugAsync(categoria);
|
|
if (category == null)
|
|
{
|
|
_logger.LogWarning("Categoria não encontrada: {Categoria}", categoria);
|
|
return NotFound();
|
|
}
|
|
|
|
try
|
|
{
|
|
var article = await _markdownService.GetArticleAsync(
|
|
$"Tutoriais/{categoria}/{slug}",
|
|
"pt-BR"
|
|
);
|
|
|
|
if (article == null)
|
|
{
|
|
_logger.LogWarning("Artigo não encontrado: {Categoria}/{Slug}", categoria, slug);
|
|
return NotFound();
|
|
}
|
|
|
|
// Buscar artigos relacionados da mesma categoria
|
|
article.RelatedArticles = await _markdownService
|
|
.GetArticlesByCategoryAsync(categoria, "pt-BR");
|
|
|
|
// Remover o artigo atual dos relacionados
|
|
article.RelatedArticles = article.RelatedArticles
|
|
.Where(a => a.Slug != slug)
|
|
.Take(3)
|
|
.ToList();
|
|
|
|
ViewBag.Category = category;
|
|
return View(article);
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
_logger.LogWarning("Arquivo markdown não encontrado: {Categoria}/{Slug}", categoria, slug);
|
|
return NotFound();
|
|
}
|
|
}
|
|
}
|