source: binary-improvements2/WebServer/src/UrlHandlers/ApiHandler.cs@ 414

Last change on this file since 414 was 404, checked in by alloc, 22 months ago

Latest state including reworking to the permissions system

File size: 3.3 KB
RevLine 
[391]1using System;
2using System.Collections.Generic;
3using System.Net;
4using System.Reflection;
[404]5using Webserver.Permissions;
[391]6using Webserver.WebAPI;
7
8namespace Webserver.UrlHandlers {
9 public class ApiHandler : AbsHandler {
10 private readonly Dictionary<string, AbsWebAPI> apis = new CaseInsensitiveStringDictionary<AbsWebAPI> ();
11
12 public ApiHandler () : base (null) {
13 }
[404]14
15 private static readonly Type[] apiWithParentCtorTypes = { typeof (Web) };
16 private static readonly object[] apiWithParentCtorArgs = new object[1];
17 private static readonly Type[] apiEmptyCtorTypes = { };
18 private static readonly object[] apiEmptyCtorArgs = { };
[391]19
20 public override void SetBasePathAndParent (Web _parent, string _relativePath) {
21 base.SetBasePathAndParent (_parent, _relativePath);
22
[404]23 apiWithParentCtorArgs[0] = _parent;
[391]24
[404]25 ReflectionHelpers.FindTypesImplementingBase (typeof (AbsWebAPI), apiFoundCallback);
[391]26
27 // Permissions that don't map to a real API
28 addApi (new Null ("viewallclaims"));
29 addApi (new Null ("viewallplayers"));
30 }
31
[404]32 private void apiFoundCallback (Type _type) {
33 ConstructorInfo ctor = _type.GetConstructor (apiWithParentCtorTypes);
34 if (ctor != null) {
35 AbsWebAPI apiInstance = (AbsWebAPI)ctor.Invoke (apiWithParentCtorArgs);
36 addApi (apiInstance);
37 return;
38 }
39
40 ctor = _type.GetConstructor (apiEmptyCtorTypes);
41 if (ctor != null) {
42 AbsWebAPI apiInstance = (AbsWebAPI)ctor.Invoke (apiEmptyCtorArgs);
43 addApi (apiInstance);
44 }
45 }
46
[391]47 private void addApi (AbsWebAPI _api) {
48 apis.Add (_api.Name, _api);
[404]49 AdminWebModules.Instance.AddKnownModule ($"webapi.{_api.Name}", _api.DefaultPermissionLevel ());
[391]50 }
51
52 private static readonly UnityEngine.Profiling.CustomSampler apiHandlerSampler = UnityEngine.Profiling.CustomSampler.Create ("API_Handler");
53
54 public override void HandleRequest (RequestContext _context) {
55
56 string apiName;
57 string subPath = null;
58
59 int pathSeparatorIndex = _context.RequestPath.IndexOf ('/', urlBasePath.Length);
60 if (pathSeparatorIndex >= 0) {
61 apiName = _context.RequestPath.Substring (urlBasePath.Length, pathSeparatorIndex - urlBasePath.Length);
62 subPath = _context.RequestPath.Substring (pathSeparatorIndex + 1);
63 } else {
64 apiName = _context.RequestPath.Substring (urlBasePath.Length);
65 }
66
67 if (!apis.TryGetValue (apiName, out AbsWebAPI api)) {
[399]68 Log.Warning ($"[Web] In {nameof(ApiHandler)}.HandleRequest(): No handler found for API \"{apiName}\"");
[391]69 _context.Response.StatusCode = (int) HttpStatusCode.NotFound;
70 return;
71 }
72
73 if (!IsAuthorizedForApi (apiName, _context.PermissionLevel)) {
74 _context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
75 if (_context.Connection != null) {
76 //Log.Out ($"{nameof(ApiHandler)}: user '{user.SteamID}' not allowed to execute '{apiName}'");
77 }
78
79 return;
80 }
81
82 _context.RequestPath = subPath;
83
84 try {
85 apiHandlerSampler.Begin ();
86 api.HandleRequest (_context);
87 apiHandlerSampler.End ();
88 } catch (Exception e) {
[399]89 Log.Error ($"[Web] In {nameof(ApiHandler)}.HandleRequest(): Handler {api.Name} threw an exception:");
[391]90 Log.Exception (e);
91 _context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
92 }
93 }
94
95 private bool IsAuthorizedForApi (string _apiName, int _permissionLevel) {
[404]96 return AdminWebModules.Instance.ModuleAllowedWithLevel ($"webapi.{_apiName}", _permissionLevel);
[391]97 }
98 }
99}
Note: See TracBrowser for help on using the repository browser.