You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bantflags/BantFlags/Controllers/FlagsController.cs

135 lines
5.1 KiB

using BantFlags.Data;
using BantFlags.Data.Database;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
namespace BantFlags.Controllers
{
[ApiController]
[Route("api")]
public class FlagsController : Controller
{
private DatabaseService Database { get; }
private string FlagList { get; set; }
private HashSet<string> DatabaseFlags { get; set; }
public FlagsController(DatabaseService db)
{
Database = db;
// During initialisation we get the current list of flags for resolving supported flags and preventing duplicate flags from being created
var flags = Database.GetFlags().Result; // If this fails the program should exit anyway.
FlagList = string.Join("\n", flags);
DatabaseFlags = flags.ToHashSet();
}
[HttpPost]
[Route("get")]
[Consumes("application/x-www-form-urlencoded")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Get([FromForm]string post_nrs, [FromForm]string board, [FromForm]string version)
{ // TODO: version can be an int?.
// int ver = verson ?? 0
try
{
int ver = int.TryParse(version, out int x) ? x : 0;
if (ver > 1)
{
// Improved flag sending, see Docs/GetPosts
return Json(await Database.GetPosts_V2(post_nrs));
}
else
{
return Json(await Database.GetPosts_V1(post_nrs));
}
}
catch (Exception e)
{
return Problem(ErrorMessage(e), statusCode: StatusCodes.Status400BadRequest);
}
}
/// <summary>
/// Posts flags in the database.
/// </summary>
/// <param name="post_nr">The post number to associate the flags to.</param>
/// <param name="board">/bant/.</param>
/// <param name="regions">List of flags to associate with the post. Split by "||" in API V1 and "," in V2.</param>
[HttpPost]
[Route("post")]
[Consumes("application/x-www-form-urlencoded")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Post([FromForm]string post_nr, [FromForm]string board, [FromForm]string regions, [FromForm]int? version)
{ // Should we rename regions? It'd be more idomatic for it to be flags or something but then we have to introduce a new variable that does the same thing.
try // We only care if the post if valid.
{
string[] flags;
int ver = version ?? 0;
if (ver > 1)
{
flags = regions.Split(",");
}
else
{
flags = regions.Split("||");
}
// TODO: Currently we skip over invalid flags. Should we error instead?
var validFlags = flags.Where(x => DatabaseFlags.Contains(x));
var numberOfFlags = validFlags.Count();
if (numberOfFlags <= 0 || numberOfFlags > 25)
{
throw new ArgumentException("Your post didn't include any flags, or your flags were invalid.");
}
FlagModel post = new FlagModel
{
PostNumber = int.TryParse(post_nr, out int temp) ? temp : throw new ArgumentException("Invalid post number."),
Board = board == "bant" ? "bant" : throw new ArgumentException("Board parameter wasn't formatted correctly."),
Flags = validFlags
};
await Database.InsertPost(post);
return Ok(post);
}
catch (Exception e)
{
return Problem(detail: ErrorMessage(e), statusCode: StatusCodes.Status400BadRequest);
}
}
[HttpGet]
[Route("flags")]
[ProducesResponseType(StatusCodes.Status200OK)]
public IActionResult Flags() => Ok(FlagList);
/// <summary>
/// Creates an error mesage to send in case of 400 bad request, without giving away too much information.
/// </summary>
/// <param name="exception">Raw exception to be filtered.</param>
private string ErrorMessage(Exception exception) =>
exception switch
{
NullReferenceException _ => "Some data wasn't initialised. Are you sending everything?",
DbException _ => "Internal database error.",
ArgumentNullException _ => "No regions sent",
ArgumentException e => e.Message,
Exception e => e.Message, // Don't do this.
_ => "how in the hell"
}; // This needs more testing.
}
}