source: TFP-WebServer/WebServer/src/Permissions/AdminApiTokens.cs@ 461

Last change on this file since 461 was 440, checked in by alloc, 18 months ago

*Added: Allow specifying a single level 0 API token on the command line

File size: 4.1 KB
Line 
1using System.Collections.Generic;
2using System.Xml;
3
4namespace Webserver.Permissions {
5 public class AdminApiTokens : AdminSectionAbs {
6 public static AdminApiTokens Instance { get; private set; }
7
8 public AdminApiTokens (AdminTools _parent) : base (_parent, "apitokens") {
9 Instance = this;
10 }
11
12 private readonly Dictionary<string, ApiToken> tokens = new CaseInsensitiveStringDictionary<ApiToken> ();
13
14
15#region IO
16
17 public override void Clear () {
18 tokens.Clear ();
19 }
20
21 protected override void ParseElement (XmlElement _childElement) {
22 if (ApiToken.TryParse (_childElement, out ApiToken apiToken)) {
23 tokens [apiToken.Name] = apiToken;
24 }
25 }
26
27 public override void Save (XmlElement _root) {
28 XmlElement adminTokensElem = _root.AddXmlElement (SectionTypeName);
29 adminTokensElem.AddXmlComment (" <token name=\"adminuser1\" secret=\"supersecrettoken\" permission_level=\"0\" /> ");
30
31 foreach ((string _, ApiToken apiToken) in tokens) {
32 apiToken.ToXml (adminTokensElem);
33 }
34 }
35
36#endregion
37
38
39#region Runtime interaction
40
41 public void AddToken (string _name, string _secret, int _permissionLevel) {
42 ApiToken apiToken = new ApiToken (_name, _secret, _permissionLevel);
43 tokens [_name] = apiToken;
44 Parent.Save ();
45 }
46
47 public bool RemoveToken (string _name) {
48 bool removed = tokens.Remove (_name);
49 if (removed) {
50 Parent.Save ();
51 }
52
53 return removed;
54 }
55
56 public Dictionary<string, ApiToken> GetTokens () {
57 return tokens;
58 }
59
60#endregion
61
62 public readonly struct ApiToken {
63 public readonly string Name;
64 public readonly string Secret;
65 public readonly int PermissionLevel;
66
67 public ApiToken (string _name, string _secret, int _permissionLevel) {
68 Name = _name;
69 Secret = _secret;
70 PermissionLevel = _permissionLevel;
71 }
72
73 public void ToXml (XmlElement _parent) {
74 _parent.AddXmlElement ("token")
75 .SetAttrib ("name", Name)
76 .SetAttrib ("secret", Secret)
77 .SetAttrib ("permission_level", PermissionLevel.ToString ());
78 }
79
80 public static bool TryParse (XmlElement _element, out ApiToken _result) {
81 _result = default;
82
83
84 if (!_element.TryGetAttribute ("name", out string name)) {
85 Log.Warning ($"[Web] [Perms] Ignoring apitoken-entry because of missing 'name' attribute: {_element.OuterXml}");
86 return false;
87 }
88
89 if (!_element.TryGetAttribute ("secret", out string secret)) {
90 Log.Warning ($"[Web] [Perms] Ignoring apitoken-entry because of missing 'secret' attribute: {_element.OuterXml}");
91 return false;
92 }
93
94 if (!_element.TryGetAttribute ("permission_level", out string permissionLevelString)) {
95 Log.Warning ($"[Web] [Perms] Ignoring apitoken-entry because of missing 'permission_level' attribute: {_element.OuterXml}");
96 return false;
97 }
98
99 if (!int.TryParse (permissionLevelString, out int permissionLevel)) {
100 Log.Warning (
101 $"[Web] [Perms] Ignoring apitoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: {_element.OuterXml}");
102 return false;
103 }
104
105
106 _result = new ApiToken (name, secret, permissionLevel);
107 return true;
108 }
109 }
110
111
112#region Specials
113
114 public int GetPermissionLevel (string _name, string _secret) {
115 if (tokens.TryGetValue (_name, out ApiToken apiToken) && apiToken.Secret == _secret) {
116 return apiToken.PermissionLevel;
117 }
118
119 if (IsCommandlineToken (_name, _secret)) {
120 return 0;
121 }
122
123 return int.MaxValue;
124 }
125
126 private bool commandlineChecked;
127 private string commandlineTokenName;
128 private string commandlineTokenSecret;
129
130 private bool IsCommandlineToken (string _name, string _secret) {
131 if (!commandlineChecked) {
132 commandlineTokenName = GameUtils.GetLaunchArgument ("webapitokenname");
133 commandlineTokenSecret = GameUtils.GetLaunchArgument ("webapitokensecret");
134
135 commandlineChecked = true;
136 }
137
138 if (string.IsNullOrEmpty (commandlineTokenName) || string.IsNullOrEmpty (commandlineTokenSecret)) {
139 return false;
140 }
141
142 return _name == commandlineTokenName && _secret == commandlineTokenSecret;
143 }
144
145#endregion
146 }
147}
Note: See TracBrowser for help on using the repository browser.