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

Last change on this file since 477 was 474, checked in by alloc, 15 months ago

Added locks on AdminTools instead of local to the individual permission systems

File size: 4.3 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 lock (Parent) {
43 ApiToken apiToken = new ApiToken (_name, _secret, _permissionLevel);
44 tokens[_name] = apiToken;
45 Parent.Save ();
46 }
47 }
48
49 public bool RemoveToken (string _name) {
50 lock (Parent) {
51 bool removed = tokens.Remove (_name);
52 if (removed) {
53 Parent.Save ();
54 }
55
56 return removed;
57 }
58 }
59
60 public Dictionary<string, ApiToken> GetTokens () {
61 lock (Parent) {
62 return tokens;
63 }
64 }
65
66#endregion
67
68 public readonly struct ApiToken {
69 public readonly string Name;
70 public readonly string Secret;
71 public readonly int PermissionLevel;
72
73 public ApiToken (string _name, string _secret, int _permissionLevel) {
74 Name = _name;
75 Secret = _secret;
76 PermissionLevel = _permissionLevel;
77 }
78
79 public void ToXml (XmlElement _parent) {
80 _parent.AddXmlElement ("token")
81 .SetAttrib ("name", Name)
82 .SetAttrib ("secret", Secret)
83 .SetAttrib ("permission_level", PermissionLevel.ToString ());
84 }
85
86 public static bool TryParse (XmlElement _element, out ApiToken _result) {
87 _result = default;
88
89
90 if (!_element.TryGetAttribute ("name", out string name)) {
91 Log.Warning ($"[Web] [Perms] Ignoring apitoken-entry because of missing 'name' attribute: {_element.OuterXml}");
92 return false;
93 }
94
95 if (!_element.TryGetAttribute ("secret", out string secret)) {
96 Log.Warning ($"[Web] [Perms] Ignoring apitoken-entry because of missing 'secret' attribute: {_element.OuterXml}");
97 return false;
98 }
99
100 if (!_element.TryGetAttribute ("permission_level", out string permissionLevelString)) {
101 Log.Warning ($"[Web] [Perms] Ignoring apitoken-entry because of missing 'permission_level' attribute: {_element.OuterXml}");
102 return false;
103 }
104
105 if (!int.TryParse (permissionLevelString, out int permissionLevel)) {
106 Log.Warning (
107 $"[Web] [Perms] Ignoring apitoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: {_element.OuterXml}");
108 return false;
109 }
110
111
112 _result = new ApiToken (name, secret, permissionLevel);
113 return true;
114 }
115 }
116
117
118#region Specials
119
120 public int GetPermissionLevel (string _name, string _secret) {
121 lock (Parent) {
122 if (tokens.TryGetValue (_name, out ApiToken apiToken) && apiToken.Secret == _secret) {
123 return apiToken.PermissionLevel;
124 }
125
126 if (IsCommandlineToken (_name, _secret)) {
127 return 0;
128 }
129
130 return int.MaxValue;
131 }
132 }
133
134 private bool commandlineChecked;
135 private string commandlineTokenName;
136 private string commandlineTokenSecret;
137
138 private bool IsCommandlineToken (string _name, string _secret) {
139 if (!commandlineChecked) {
140 commandlineTokenName = GameUtils.GetLaunchArgument ("webapitokenname");
141 commandlineTokenSecret = GameUtils.GetLaunchArgument ("webapitokensecret");
142
143 commandlineChecked = true;
144 }
145
146 if (string.IsNullOrEmpty (commandlineTokenName) || string.IsNullOrEmpty (commandlineTokenSecret)) {
147 return false;
148 }
149
150 return _name == commandlineTokenName && _secret == commandlineTokenSecret;
151 }
152
153#endregion
154 }
155}
Note: See TracBrowser for help on using the repository browser.