// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.Json.Serialization;
using EpicGames.Core;
using HordeServer.Utilities;
using Microsoft.AspNetCore.Mvc;
namespace HordeServer.Server
{
///
/// Controller for the /api/v1/schema endpoint
///
[ApiController]
[Route("[controller]")]
public class SchemaController : ControllerBase
{
class CatalogItem
{
public string? Name { get; set; }
public string? Description { get; set; }
public string[]? FileMatch { get; set; }
public Uri? Url { get; set; }
}
class CatalogRoot
{
[JsonPropertyName("$schema")]
public string Schema { get; set; } = "https://json.schemastore.org/schema-catalog.json";
public int Version { get; set; } = 1;
public List Schemas { get; set; } = new List();
}
///
/// Array of types included in the schema
///
public static Type[] ConfigSchemas { get; } = FindSchemaTypes();
readonly JsonSchemaCache _schemaCache;
///
/// Constructor
///
public SchemaController(JsonSchemaCache schemaCache)
{
_schemaCache = schemaCache;
}
static Type[] FindSchemaTypes()
{
List schemaTypes = new List();
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
if (type.GetCustomAttribute() != null)
{
schemaTypes.Add(type);
}
}
}
return schemaTypes.ToArray();
}
///
/// Get the catalog for config schema
///
/// Information about all the schedules
[HttpGet]
[Route("/api/v1/schema/catalog.json")]
public ActionResult GetCatalog()
{
CatalogRoot root = new CatalogRoot();
foreach (Type schemaType in ConfigSchemas)
{
JsonSchemaAttribute? schemaAttribute = schemaType.GetCustomAttribute();
if (schemaAttribute != null)
{
JsonSchemaCatalogAttribute? catalogAttribute = schemaType.GetCustomAttribute();
if (catalogAttribute != null)
{
Uri url = new Uri($"{Request.Scheme}://{Request.Host}/api/v1/schema/types/{schemaType.Name}.json");
root.Schemas.Add(new CatalogItem { Name = catalogAttribute.Name, Description = catalogAttribute.Description, FileMatch = catalogAttribute.FileMatch, Url = url });
}
}
}
return Ok(root);
}
///
/// Gets a specific schema
///
/// The type name
///
[HttpGet]
[Route("/api/v1/schema/types/{typeName}.json")]
public ActionResult GetSchema(string typeName)
{
foreach (Type schemaType in ConfigSchemas)
{
if (schemaType.Name.Equals(typeName, StringComparison.OrdinalIgnoreCase))
{
JsonSchema schema = _schemaCache.CreateSchema(schemaType);
using MemoryStream stream = new MemoryStream();
schema.Write(stream);
return new FileContentResult(stream.ToArray(), "application/json");
}
}
return NotFound();
}
}
}