diff --git a/Controllers/QuoteController.cs b/Controllers/QuoteController.cs
index 4ab53b0..d743572 100644
--- a/Controllers/QuoteController.cs
+++ b/Controllers/QuoteController.cs
@@ -75,7 +75,7 @@ public class QuotesController : ControllerBase
// GET /api/v1/quotes/{id}
///
- /// [AUTH] Get specified quote summary
+ /// [AUTHED] Get specified quote summary
///
/// The quote id in question
/// A quote: id, quote content and author, imageUrl and categories if successful, otherwise: error message
@@ -221,51 +221,111 @@ public class QuotesController : ControllerBase
return Ok(dto);
}
-
+ // DELETE /api/v1/quotes/{id}
+ ///
+ /// [AUTHED] Delete a quote
+ ///
+ ///
+ /// Deletes a quote, granted it exists.
+ ///
+ ///
+ /// Is this the best practice? Marking the quote as hidden is also an option.
+ /// ~eee4
+ ///
+ /// Json with status
+ /// Quote id which will be deleted
+ /// Returned on valid request
+ /// Returned when no such quote exists
[HttpDelete("{id}")]
- [ProducesResponseType(204)]
- [ProducesResponseType(typeof(ErrorDTO), 404)]
[Authorize]
[EnableCors]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(typeof(ErrorDTO), 404)]
public async Task DeleteQuote(int id)
{
- var quote = await _db.Quotes
- .FirstOrDefaultAsync(q => q.Id == id);
- if(quote==null) return NotFound(new { status = "error", error_msg = "Quote not found" });
+ // (Attempt to) find the quote
+ Quote? quote = await _db.Quotes
+ .FirstOrDefaultAsync(q => q.Id == id);
+ // Failed?
+ if (quote == null)
+ return NotFound(new { status = "error", error_msg = "Quote not found" });
+
+ // If succeded, remove the quote
_db.Quotes.Remove(quote);
await _db.SaveChangesAsync();
- return Ok();
+
+ // ====================================================================== //
+ // Important! //
+ // Is this the best we can do? Won't marking the quote as "hidden" //
+ // be better than explicitly deleting it? ~eee4 //
+ // ====================================================================== //
+
+ // Return ok
+ return Ok(new { Status = "ok" });
}
+ // PATCH /api/v1/quotes/{id}
+ ///
+ /// [AUTHED] Modify an existing quote
+ ///
+ ///
+ /// Modifies an existing quote.
+ ///
+ /// Warning!
+ /// We don't check the user id which created the quote.
+ /// In case of single-user instances, this should not be a problem.
+ /// This might become one, if we want users with non-admin roles;
+ /// that would need some proper ACL checks here (with the help of GUHF).
+ ///
+ /// Important!
+ /// Image handling works the same as with creating new quote.
+ /// This means that images not present in the DB will be added automatically.
+ ///
+ /// Important!
+ /// "categories = null" is not the same as "categories = []"!
+ /// While "categories = null" will not alter the quote's categories,
+ /// "categories = []" will (and in turn, empty each and every present category)!
+ /// Be careful when handling user-provided categories!
+ ///
+ /// Newly modified quote as a DTO
+ /// Quote to be modified
+ /// Updated quote form data
+ /// Returned on valid request
+ /// Returned when request text or author is empty (or whitespace)
+ /// Returned when no such quote exists
[HttpPatch("{id}")]
[Authorize]
[EnableCors]
[ProducesResponseType(typeof(QuoteShortDTO), 200)]
[ProducesResponseType(typeof(ErrorDTO), 400)]
[ProducesResponseType(typeof(ErrorDTO), 404)]
-
public async Task EditQuote(int id, [FromBody] QuoteShortDTO updatedQuote)
{
- var Quote = await _db.Quotes
+ // Try to find the quote in question
+ Quote? quote = await _db.Quotes
.Include(q => q.QuoteCategories)
- // include image?
.FirstOrDefaultAsync(q => q.Id == id);
- if (Quote == null) return NotFound(new { status = "error", error_msg = "Quote not found" });
+ // Failed?
+ if (quote == null)
+ return NotFound(new { status = "error", error_msg = "Quote not found" });
+
+ // Is quote contents or author empty?
if (string.IsNullOrWhiteSpace(updatedQuote.Text) || string.IsNullOrWhiteSpace(updatedQuote.Author))
- {
return BadRequest(new ErrorDTO { Status = "error", Error_msg = "Text and author are required." });
- }
- Quote.Text = updatedQuote.Text;
- Quote.Author = updatedQuote.Author;
- Quote.LastUpdatedAt = DateTime.UtcNow;
+ // Alter the quote's content
+ quote.Text = updatedQuote.Text;
+ quote.Author = updatedQuote.Author;
+ quote.LastUpdatedAt = DateTime.UtcNow;
+ // Try to find the image inside the DB
Image? image = null;
if (!string.IsNullOrEmpty(updatedQuote.ImageUrl))
{
image = await _db.Images.FirstOrDefaultAsync(i => i.Url == updatedQuote.ImageUrl);
+ // Failed? Just insert it yourself
if (image == null)
{
image = new Image { Url = updatedQuote.ImageUrl };
@@ -273,22 +333,29 @@ public class QuotesController : ControllerBase
await _db.SaveChangesAsync();
}
}
- Quote.Image = image;
+ quote.Image = image;
+ // Don't touch categories if they are explicitly null
if (updatedQuote.Categories == null) { }
+ // If they aren't
else if (updatedQuote.Categories.Any())
{
- var categoriesFromDb = await _db.Categories
+ // Get all the categories associated with a quote from DB
+ List categoriesFromDb = await _db.Categories
.Where(c => updatedQuote.Categories.Contains(c.Name))
.ToListAsync();
- // Dodaj nowe kategorie, których nie ma w bazie
- var existingNames = categoriesFromDb
+ // Determine which ones are already present, and which to add
+ IEnumerable existingNames = categoriesFromDb
.Select(c => c.Name);
- var newNames = updatedQuote.Categories.Except(existingNames).ToList();
+ List newNames = updatedQuote.Categories
+ .Except(existingNames)
+ .ToList();
+ // For all the categories not present
foreach (var name in newNames)
{
+ // Add them to the DB
var newCat = new Category {
Name = name,
Description = string.Empty,
@@ -298,25 +365,28 @@ public class QuotesController : ControllerBase
categoriesFromDb.Add(newCat);
}
+ // If any categories were added, save changes
if (newNames.Any())
await _db.SaveChangesAsync();
- // Przypisz cytatowi nowe kategorie
- Quote.QuoteCategories = categoriesFromDb
+ // Assign all the new categories to the quote
+ quote.QuoteCategories = categoriesFromDb
.Select(cat => new QuoteCategory {
CategoryId = cat.Id,
- QuoteId = Quote.Id
+ QuoteId = quote.Id
})
.ToList();
}
else
{
- // Jeśli brak kategorii w dto, czyścić przypisane kategorie?
- Quote.QuoteCategories.Clear();
+ // No categories (empty list) inside DTO?
+ // Clear them all!
+ quote.QuoteCategories.Clear();
}
+ // Save changes, return new quote as a DTO
await _db.SaveChangesAsync();
- return Ok(Quote.ToQuoteShortDTO());
+ return Ok(quote.ToQuoteShortDTO());
}
}