163 lines
6.1 KiB
C#
163 lines
6.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Dynamic;
|
|
using System.Linq;
|
|
using System.Text.Json;
|
|
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 readonly ValidationService ValidationService;
|
|
|
|
protected BaseApiController(
|
|
AccessTokenCache accessTokenCache,
|
|
ValidationService validationService
|
|
)
|
|
{
|
|
AccessTokenCache = accessTokenCache;
|
|
ValidationService = validationService;
|
|
}
|
|
|
|
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, JsonElement requestBody)
|
|
{
|
|
if (!CheckPermissions.GetResult(AccessTokenCache, Request, guildId, out IActionResult result))
|
|
return result;
|
|
|
|
if (!ValidationService.Validate(requestBody, GetValidationRules(), out string errors))
|
|
return BadRequest(errors);
|
|
|
|
await using ChaosbotContext dbContext = new ChaosbotContext();
|
|
|
|
T databaseObject = SetDefaultFieldsForUpsert(new T(), guildId);
|
|
|
|
foreach (string key in GetValidationRules().Keys)
|
|
{
|
|
Type type = databaseObject?.GetType()?.GetProperty(key)?.PropertyType;
|
|
if (type == null) continue;
|
|
|
|
dynamic value;
|
|
if (type.IsEnum)
|
|
value = Convert.ChangeType(Enum.ToObject(type, JsonElementHelper.GetValueFromRequest(requestBody, key)), type);
|
|
else
|
|
value = Convert.ChangeType(JsonElementHelper.GetValueFromRequest(requestBody, key), type);
|
|
|
|
databaseObject
|
|
.GetType()
|
|
.GetProperty(key)
|
|
?.SetValue(databaseObject, value);
|
|
}
|
|
|
|
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();
|
|
|
|
List<T> toDelete = FilterQueryMultipleForDeletion(GetBasicQuery(dbContext), guildId, deleteParameter);
|
|
toDelete.Add(FilterQueryForDeletion(GetBasicQuery(dbContext), 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);
|
|
protected abstract T SetDefaultFieldsForUpsert(T obj, ulong guildId);
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|