using System; using System.Collections.Generic; using System.Net; using System.Reflection; using AllocsFixes.NetConnections.Servers.Web.API; namespace AllocsFixes.NetConnections.Servers.Web.Handlers { public class ApiHandler : AbsHandler { private readonly Dictionary apis = new CaseInsensitiveStringDictionary (); public ApiHandler () : base (null) { } public override void SetBasePathAndParent (Web _parent, string _relativePath) { base.SetBasePathAndParent (_parent, _relativePath); Type[] apiWithParentCtorTypes = { typeof (Web) }; Object[] apiWithParentCtorArgs = { _parent }; Type[] apiEmptyCtorTypes = { }; Object[] apiEmptyCtorArgs = { }; foreach (Type t in Assembly.GetExecutingAssembly ().GetTypes ()) { if (!t.IsAbstract && t.IsSubclassOf (typeof (AbsWebAPI))) { ConstructorInfo ctor = t.GetConstructor (apiWithParentCtorTypes); if (ctor != null) { AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiWithParentCtorArgs); addApi (apiInstance); continue; } ctor = t.GetConstructor (apiEmptyCtorTypes); if (ctor != null) { AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiEmptyCtorArgs); addApi (apiInstance); } } } // Permissions that don't map to a real API addApi (new Null ("viewallclaims")); addApi (new Null ("viewallplayers")); } private void addApi (AbsWebAPI _api) { apis.Add (_api.Name, _api); WebPermissions.Instance.AddKnownModule ("webapi." + _api.Name, _api.DefaultPermissionLevel ()); } #if ENABLE_PROFILER private static readonly UnityEngine.Profiling.CustomSampler apiHandlerSampler = UnityEngine.Profiling.CustomSampler.Create ("API_Handler"); #endif public override void HandleRequest (RequestContext _context) { string apiName; string subPath = null; int pathSeparatorIndex = _context.RequestPath.IndexOf ('/', urlBasePath.Length); if (pathSeparatorIndex >= 0) { apiName = _context.RequestPath.Substring (urlBasePath.Length, pathSeparatorIndex - urlBasePath.Length); subPath = _context.RequestPath.Substring (pathSeparatorIndex + 1); } else { apiName = _context.RequestPath.Substring (urlBasePath.Length); } if (!apis.TryGetValue (apiName, out AbsWebAPI api)) { Log.Out ($"Error in {nameof(ApiHandler)}.HandleRequest(): No handler found for API \"{apiName}\""); _context.Response.StatusCode = (int) HttpStatusCode.NotFound; return; } if (!AuthorizeForApi (apiName, _context.PermissionLevel)) { _context.Response.StatusCode = (int) HttpStatusCode.Forbidden; if (_context.Connection != null) { //Log.Out ($"{nameof(ApiHandler)}: user '{user.SteamID}' not allowed to execute '{apiName}'"); } return; } _context.RequestPath = subPath; try { #if ENABLE_PROFILER apiHandlerSampler.Begin (); #endif api.HandleRequest (_context); #if ENABLE_PROFILER apiHandlerSampler.End (); #endif } catch (Exception e) { Log.Error ($"Error in {nameof(ApiHandler)}.HandleRequest(): Handler {api.Name} threw an exception:"); Log.Exception (e); _context.Response.StatusCode = (int) HttpStatusCode.InternalServerError; } } private bool AuthorizeForApi (string _apiName, int _permissionLevel) { return WebPermissions.Instance.ModuleAllowedWithLevel ("webapi." + _apiName, _permissionLevel); } } }