Start refactoring to base api controller

This commit is contained in:
Daniel_I_Am 2020-10-13 00:04:36 +02:00
parent 7f47fa6753
commit e78c0d8746
No known key found for this signature in database
GPG Key ID: 80C428FCC9743E84
3 changed files with 234 additions and 93 deletions

View File

@ -0,0 +1,145 @@
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Threading.Tasks;
using ChaosBot.Models;
using ChaosBot.WebServer.Services;
using FlexLabs.EntityFrameworkCore.Upsert;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
namespace ChaosBot.WebServer.App.ApiControllers
{
public abstract class BaseApiController<T, TDeleteParameter> : Controller where T : class, new()
{
protected readonly AccessTokenCache AccessTokenCache;
protected BaseApiController(
AccessTokenCache accessTokenCache
)
{
AccessTokenCache = accessTokenCache;
}
public async Task<IActionResult> Index(ulong guildId)
{
if (!CheckPermissions.GetResult(AccessTokenCache, Request, guildId, out IActionResult result))
return result;
await using ChaosbotContext dbContext = new ChaosbotContext();
IQueryable<T> query = GetBasicQuery(dbContext);
List<T> list = ApplyFilterForCurrentGuild(query, guildId).ToList();
LoggingFacade.Info("Received request");
List<dynamic> response = list.Select(element =>
{
Dictionary<string, object> responseDict = new Dictionary<string, object>();
foreach (string field in GetIndexFields())
{
responseDict.Add(field, element.GetType().GetProperty(field)?.GetValue(element, null));
}
dynamic dynamicResponseElement = new DynamicResponse(responseDict);
return dynamicResponseElement;
}).ToList();
return Content(JsonConvert.SerializeObject(response), new MediaTypeHeaderValue("application/json"));
}
public async Task<IActionResult> Upsert(ulong guildId, dynamic requestBody)
{
if (!CheckPermissions.GetResult(AccessTokenCache, Request, guildId, out IActionResult result))
return result;
await using ChaosbotContext dbContext = new ChaosbotContext();
T databaseObject = new T();
foreach (string key in GetValidationRules().Keys)
{
databaseObject
.GetType()
.GetProperty(key)
?.SetValue(databaseObject, requestBody.GetType().GetProperty(key)?.GetValue(requestBody, null));
}
await ApplyFilterForUpsert(GetBasicQuery(dbContext).Upsert(databaseObject)).RunAsync();
await dbContext.SaveChangesAsync();
return NoContent();
}
public async Task<IActionResult> Delete(ulong guildId, TDeleteParameter deleteParameter)
{
if (!CheckPermissions.GetResult(AccessTokenCache, Request, guildId, out IActionResult result))
return result;
await using ChaosbotContext dbContext = new ChaosbotContext();
IQueryable<T> query = GetBasicQuery(dbContext);
List<T> toDelete = FilterQueryMultipleForDeletion(query, guildId, deleteParameter);
toDelete.Add(FilterQueryForDeletion(query, guildId, deleteParameter));
if (toDelete.Count == 0)
return NotFound();
foreach (T obj in toDelete)
{
GetBasicQuery(dbContext).Remove(obj);
}
await dbContext.SaveChangesAsync();
return NoContent();
}
protected abstract DbSet<T> GetBasicQuery(ChaosbotContext context);
protected abstract IQueryable<T> ApplyFilterForCurrentGuild(IQueryable<T> query, ulong guildId);
protected abstract List<string> GetIndexFields();
protected abstract Dictionary<string, List<string>> GetValidationRules();
protected abstract UpsertCommandBuilder<T> ApplyFilterForUpsert(UpsertCommandBuilder<T> builder);
protected abstract T FilterQueryForDeletion(IQueryable<T> query, ulong guildId, TDeleteParameter deleteParameter);
protected abstract List<T> FilterQueryMultipleForDeletion(IQueryable<T> query, ulong guildId, TDeleteParameter deleteParameter);
private class DynamicResponse : DynamicObject
{
private readonly Dictionary<string, object> _properties;
public DynamicResponse(Dictionary<string, object> properties)
{
_properties = properties;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _properties.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_properties.ContainsKey(binder.Name))
{
result = _properties[binder.Name];
return true;
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_properties.ContainsKey(binder.Name))
{
_properties[binder.Name] = value;
return true;
}
return false;
}
}
}
}

View File

@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ChaosBot.Models;
using ChaosBot.WebServer.Models;
using ChaosBot.WebServer.Services;
using FlexLabs.EntityFrameworkCore.Upsert;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace ChaosBot.WebServer.App.ApiControllers
{
[ApiController]
[Route("/api/custom-commands")]
public class CustomCommandController : BaseApiController<CustomCommand, string>
{
public CustomCommandController(
AccessTokenCache accessTokenCache
) : base(
accessTokenCache
) {}
[HttpGet]
[Route("{guildId}")]
public async Task<IActionResult> IndexAction(ulong guildId)
{
return await Index(guildId);
}
[HttpPost]
[Route("{guildId}")]
public async Task<IActionResult> UpsertAction(
[FromRoute] ulong guildId,
[FromBody] dynamic requestBody)
{
return await Upsert(guildId, requestBody);
}
[HttpDelete]
[Route("{guildId}/{command}")]
public async Task<IActionResult> DeleteAction([FromRoute]ulong guildId, [FromRoute]string command)
{
return await Delete(guildId, command);
}
protected override DbSet<CustomCommand> GetBasicQuery(ChaosbotContext context)
{
return context.CustomCommands;
}
protected override IQueryable<CustomCommand> ApplyFilterForCurrentGuild(IQueryable<CustomCommand> query, ulong guildId)
{
return query.Where(e => e.DiscordGuildId == guildId);
}
protected override List<string> GetIndexFields() {
return new List<string>
{
"Command",
"Type",
"Content"
};
}
protected override Dictionary<string, List<string>> GetValidationRules()
{
return new Dictionary<string, List<string>>();
}
protected override UpsertCommandBuilder<CustomCommand> ApplyFilterForUpsert(
UpsertCommandBuilder<CustomCommand> builder)
{
return builder.On(cc => new {cc.DiscordGuildId, cc.Command});
}
protected override CustomCommand FilterQueryForDeletion(IQueryable<CustomCommand> query, ulong guildId, string deleteParameter)
{
return query
.Where(cc => cc.DiscordGuildId == guildId)
.First(cc => cc.Command == deleteParameter)
;
}
protected override List<CustomCommand> FilterQueryMultipleForDeletion(IQueryable<CustomCommand> query, ulong guildId, string deleteParameter)
{
return new List<CustomCommand>();
}
}
}

View File

@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ChaosBot.Discord;
using ChaosBot.Models;
using ChaosBot.WebServer.Models;
using ChaosBot.WebServer.Services;
using Discord.WebSocket;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace ChaosBot.WebServer.App
{
[ApiController]
[Route("/api/custom-commands")]
public class CustomCommandController : Controller
{
private readonly AccessTokenCache _accessTokenCache;
public CustomCommandController(
AccessTokenCache accessTokenCache
)
{
_accessTokenCache = accessTokenCache;
}
[HttpGet]
[Route("{guildId}")]
public async Task<IActionResult> GetCustomCommands([FromRoute]ulong guildId)
{
if (!CheckPermissions.GetResult(_accessTokenCache, Request, guildId, out IActionResult result))
return result;
await using ChaosbotContext dbContext = new ChaosbotContext();
IQueryable<CustomCommand> customCommandsQuery = dbContext.CustomCommands;
List<CustomCommand> customCommands = customCommandsQuery
.Where(cc => cc.DiscordGuildId == guildId)
.ToList();
List<CustomCommandResponse> response = customCommands.Select(e => new CustomCommandResponse(e)).ToList();
return Json(response);
}
[HttpPost]
[Route("{guildId}")]
public async Task<IActionResult> UpsertCustomCommands([FromRoute]ulong guildId, [FromBody]CustomCommandRequest customCommandRequest)
{
if (!CheckPermissions.GetResult(_accessTokenCache, Request, guildId, out IActionResult result))
return result;
await using ChaosbotContext dbContext = new ChaosbotContext();
CustomCommand customCommand = new CustomCommand
{
DiscordGuildId = guildId,
Command = customCommandRequest.Command,
Type = customCommandRequest.Type,
Content = customCommandRequest.Content
};
await dbContext.CustomCommands.Upsert(customCommand)
.On(cc => new {cc.DiscordGuildId, cc.Command}).RunAsync();
await dbContext.SaveChangesAsync();
return NoContent();
}
[HttpDelete]
[Route("{guildId}/{command}")]
public async Task<IActionResult> DeleteCustomCommands([FromRoute]ulong guildId, [FromRoute]string command)
{
if (!CheckPermissions.GetResult(_accessTokenCache, Request, guildId, out IActionResult result))
return result;
await using ChaosbotContext dbContext = new ChaosbotContext();
IQueryable<CustomCommand> customCommandQuery = dbContext.CustomCommands;
CustomCommand customCommand = customCommandQuery
.Where(cc => cc.DiscordGuildId == guildId)
.First(cc => cc.Command == command);
if (customCommand == null)
return NotFound();
dbContext.CustomCommands.Remove(customCommand);
await dbContext.SaveChangesAsync();
return NoContent();
}
}
}