mirror of
https://github.com/QuotifyTeam/QuotifyBE.git
synced 2025-12-16 22:20:08 +01:00
chore: (WIP) group controllers, slightly annotate code
This commit is contained in:
@@ -22,6 +22,7 @@ public class AuthController : ControllerBase
|
|||||||
_appsettings = appsettings;
|
_appsettings = appsettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST /api/v1/auth/login
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
public async Task<IActionResult> Login([FromBody] UserLoginDTO formUser, GeneralUseHelpers guhf)
|
public async Task<IActionResult> Login([FromBody] UserLoginDTO formUser, GeneralUseHelpers guhf)
|
||||||
{
|
{
|
||||||
@@ -48,6 +49,7 @@ public class AuthController : ControllerBase
|
|||||||
} else return Unauthorized(new {status = "error", error_msg = "Unknown pair of email and password"});
|
} else return Unauthorized(new {status = "error", error_msg = "Unknown pair of email and password"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/auth/some_values
|
||||||
[HttpGet("some_values")]
|
[HttpGet("some_values")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public IActionResult GetValues()
|
public IActionResult GetValues()
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using QuotifyBE.Data;
|
|
||||||
using QuotifyBE.Entities;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace QuotifyBE.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[Route("controller")]
|
|
||||||
|
|
||||||
public class QuotesController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _db;
|
|
||||||
|
|
||||||
public QuotesController(ApplicationDbContext db)
|
|
||||||
{
|
|
||||||
_db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public async Task<IActionResult> CreateQuote([FromBody] CreateQuoteRequest request)
|
|
||||||
{
|
|
||||||
// Get user ID from claims
|
|
||||||
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
if (userIdClaim == null || !int.TryParse(userIdClaim, out int userId))
|
|
||||||
return Unauthorized("Invalid user ID");
|
|
||||||
|
|
||||||
// Find or create image
|
|
||||||
Image? image = null;
|
|
||||||
if (!string.IsNullOrEmpty(request.ImageUrl))
|
|
||||||
{
|
|
||||||
image = await _db.Images.FirstOrDefaultAsync(i => i.Url == request.ImageUrl);
|
|
||||||
if (image == null)
|
|
||||||
{
|
|
||||||
image = new Image { Url = request.ImageUrl };
|
|
||||||
_db.Images.Add(image);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create quote
|
|
||||||
var quote = new Quote
|
|
||||||
{
|
|
||||||
Text = request.Text,
|
|
||||||
Author = request.Author,
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
LastUpdatedAt = DateTime.UtcNow,
|
|
||||||
ImageId = image?.Id ?? 0,
|
|
||||||
UserId = userId,
|
|
||||||
QuoteCategories = new List<QuoteCategory>()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attach categories
|
|
||||||
foreach (var categoryId in request.CategoryIds)
|
|
||||||
{
|
|
||||||
var categoryExists = await _db.Categories.AnyAsync(c => c.Id == categoryId);
|
|
||||||
if (!categoryExists)
|
|
||||||
return BadRequest($"Category ID {categoryId} not found");
|
|
||||||
|
|
||||||
quote.QuoteCategories.Add(new QuoteCategory
|
|
||||||
{
|
|
||||||
CategoryId = categoryId,
|
|
||||||
Quote = quote
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_db.Quotes.Add(quote);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return CreatedAtAction(nameof(GetQuoteById), new { id = quote.Id }, quote);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
|
||||||
public async Task<IActionResult> GetQuoteById(int id)
|
|
||||||
{
|
|
||||||
var quote = await _db.Quotes
|
|
||||||
.Include(q => q.QuoteCategories)
|
|
||||||
.ThenInclude(qc => qc.Category)
|
|
||||||
.Include(q => q.User)
|
|
||||||
.Include(q => q.ImageId)
|
|
||||||
.FirstOrDefaultAsync(q => q.Id == id);
|
|
||||||
|
|
||||||
if (quote == null)
|
|
||||||
return NotFound();
|
|
||||||
|
|
||||||
return Ok(quote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
153
Controllers/QuoteController.cs
Normal file
153
Controllers/QuoteController.cs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using QuotifyBE.Data;
|
||||||
|
using QuotifyBE.Entities;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace QuotifyBE.Controllers;
|
||||||
|
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/v1/quotes")]
|
||||||
|
public class QuotesController : ControllerBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ApplicationDbContext _db;
|
||||||
|
|
||||||
|
public QuotesController(ApplicationDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/quotes
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetQuoteByRange()
|
||||||
|
{
|
||||||
|
// TODO...
|
||||||
|
|
||||||
|
return NotFound(new { status = "error", error_msg = "Not implemented" });
|
||||||
|
|
||||||
|
// TODO: Consider turning the quote into a DTO
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/quotes/{id}
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<IActionResult> GetQuoteById(int id)
|
||||||
|
{
|
||||||
|
// FIXME: The expression 'q.QuoteCategories' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'.
|
||||||
|
var quote = await _db.Quotes
|
||||||
|
.Include(q => q.QuoteCategories!)
|
||||||
|
.ThenInclude(qc => qc.Category)
|
||||||
|
.Include(q => q.User)
|
||||||
|
.Include(q => q.ImageId)
|
||||||
|
.FirstOrDefaultAsync(q => q.Id == id);
|
||||||
|
|
||||||
|
if (quote == null)
|
||||||
|
return NotFound(new { status = "error", error_msg = "Quote not found" });
|
||||||
|
|
||||||
|
// TODO: Consider turning the quote into a DTO
|
||||||
|
|
||||||
|
return Ok(quote);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /api/v1/quotes/new
|
||||||
|
[HttpPost("new")]
|
||||||
|
[Authorize]
|
||||||
|
public async Task<IActionResult> CreateQuote([FromBody] CreateQuoteDTO request)
|
||||||
|
{
|
||||||
|
// Get user ID from claims
|
||||||
|
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||||
|
if (userIdClaim == null || !int.TryParse(userIdClaim, out int userId))
|
||||||
|
return Unauthorized(new {status = "error", error_msg = "Invalid user ID"});
|
||||||
|
|
||||||
|
// Find or create image
|
||||||
|
Image? image = null;
|
||||||
|
if (!string.IsNullOrEmpty(request.ImageUrl))
|
||||||
|
{
|
||||||
|
image = await _db.Images.FirstOrDefaultAsync(i => i.Url == request.ImageUrl);
|
||||||
|
if (image == null)
|
||||||
|
{
|
||||||
|
image = new Image { Url = request.ImageUrl };
|
||||||
|
_db.Images.Add(image);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create quote
|
||||||
|
var quote = new Quote
|
||||||
|
{
|
||||||
|
Text = request.Text,
|
||||||
|
Author = request.Author,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
LastUpdatedAt = DateTime.UtcNow,
|
||||||
|
ImageId = image?.Id ?? 0,
|
||||||
|
UserId = userId,
|
||||||
|
QuoteCategories = new List<QuoteCategory>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Attach categories
|
||||||
|
foreach (var categoryId in request.CategoryIds)
|
||||||
|
{
|
||||||
|
var categoryExists = await _db.Categories.AnyAsync(c => c.Id == categoryId);
|
||||||
|
if (!categoryExists)
|
||||||
|
return BadRequest(new {status = "error", error_msg = $"Category ID {categoryId} not found"});
|
||||||
|
|
||||||
|
quote.QuoteCategories.Add(new QuoteCategory
|
||||||
|
{
|
||||||
|
CategoryId = categoryId,
|
||||||
|
Quote = quote
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_db.Quotes.Add(quote);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return CreatedAtAction(nameof(GetQuoteById), new { id = quote.Id }, quote);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/quotes/random
|
||||||
|
[HttpGet("random")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> GetRandomQuote()
|
||||||
|
{
|
||||||
|
var totalQuotes = await _db.Quotes.CountAsync();
|
||||||
|
if (totalQuotes == 0)
|
||||||
|
return NotFound(new { status = "error", error_msg = "No quotes to choose from" });
|
||||||
|
|
||||||
|
var random = new Random();
|
||||||
|
var skip = random.Next(0, totalQuotes);
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
var quote = await _db.Quotes
|
||||||
|
.Include(q => q.QuoteCategories!)
|
||||||
|
.ThenInclude(qc => qc.Category)
|
||||||
|
.Skip(skip)
|
||||||
|
.Take(1)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (quote == null)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
Image? image = null;
|
||||||
|
if (quote.ImageId != 0)
|
||||||
|
{
|
||||||
|
image = await _db.Images.FirstOrDefaultAsync(i => i.Id == quote.ImageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dto = new RandomQuote
|
||||||
|
{
|
||||||
|
Text = quote.Text,
|
||||||
|
Author = quote.Author,
|
||||||
|
ImageUrl = image?.Url,
|
||||||
|
Categories = quote.QuoteCategories?
|
||||||
|
.Select(qc => qc.Category?.Name ?? "")
|
||||||
|
.Where(name => !string.IsNullOrEmpty(name))
|
||||||
|
.ToList() ?? new List<string>()
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(dto);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using QuotifyBE.Data;
|
|
||||||
using QuotifyBE.Entities;
|
|
||||||
namespace QuotifyBE.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[Route("controller")]
|
|
||||||
public class QuotesController_2 : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _db;
|
|
||||||
|
|
||||||
public QuotesController_2(ApplicationDbContext db)
|
|
||||||
{
|
|
||||||
_db = db;
|
|
||||||
}
|
|
||||||
[HttpGet]
|
|
||||||
[AllowAnonymous]
|
|
||||||
|
|
||||||
public async Task<IActionResult> GetRandomQuote()
|
|
||||||
{
|
|
||||||
var totalQuotes = await _db.Quotes.CountAsync();
|
|
||||||
if (totalQuotes == 0)
|
|
||||||
return NotFound(new { status = "error", error_msg = "brak cytatow" });
|
|
||||||
|
|
||||||
var random = new Random();
|
|
||||||
var skip = random.Next(0, totalQuotes);
|
|
||||||
|
|
||||||
var quote = await _db.Quotes
|
|
||||||
.Include(q => q.QuoteCategories)
|
|
||||||
.ThenInclude(qc => qc.Category)
|
|
||||||
.Skip(skip)
|
|
||||||
.Take(1)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (quote == null)
|
|
||||||
return NotFound();
|
|
||||||
|
|
||||||
Image? image = null;
|
|
||||||
if (quote.ImageId != 0)
|
|
||||||
{
|
|
||||||
image = await _db.Images.FirstOrDefaultAsync(i => i.Id == quote.ImageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dto = new RandomQuote
|
|
||||||
{
|
|
||||||
Text = quote.Text,
|
|
||||||
Author = quote.Author,
|
|
||||||
ImageUrl = image?.Url,
|
|
||||||
Categories = quote.QuoteCategories?
|
|
||||||
.Select(qc => qc.Category?.Name ?? "")
|
|
||||||
.Where(name => !string.IsNullOrEmpty(name))
|
|
||||||
.ToList() ?? new List<string>()
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(dto);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
public record class CreateQuoteRequest
|
public record class CreateQuoteDTO
|
||||||
{
|
{
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
public string Author { get; set; }
|
public string Author { get; set; }
|
||||||
public List<int> CategoryIds { get; set; }
|
public List<int> CategoryIds { get; set; }
|
||||||
public string? ImageUrl { get; set; }
|
public string? ImageUrl { get; set; }
|
||||||
};
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
public record class RandomQuote
|
public record class RandomQuote
|
||||||
{
|
{
|
||||||
public string Text { get; set; } = string.Empty;
|
public string Text { get; set; } = string.Empty;
|
||||||
public string Author { get; set; } = string.Empty;
|
public string Author { get; set; } = string.Empty;
|
||||||
public string? ImageUrl { get; set; }
|
public string? ImageUrl { get; set; }
|
||||||
public List<string> Categories { get; set; } = new();
|
public List<string> Categories { get; set; } = new();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// using Microsoft.AspNetCore.Identity;
|
// using Microsoft.AspNetCore.Identity;
|
||||||
// using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
// using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -17,6 +17,7 @@ namespace QuotifyBE.Data
|
|||||||
public DbSet<Quote> Quotes => Set<Quote>();
|
public DbSet<Quote> Quotes => Set<Quote>();
|
||||||
public DbSet<Category> Categories => Set<Category>();
|
public DbSet<Category> Categories => Set<Category>();
|
||||||
public DbSet<Image> Images => Set<Image>();
|
public DbSet<Image> Images => Set<Image>();
|
||||||
|
public DbSet<QuoteCategory> QuoteCategories => Set<QuoteCategory>();
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
@@ -26,4 +27,4 @@ namespace QuotifyBE.Data
|
|||||||
.HasKey(vs => new { vs.QuoteId, vs.CategoryId });
|
.HasKey(vs => new { vs.QuoteId, vs.CategoryId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace QuotifyBE.Entities
|
namespace QuotifyBE.Entities
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user