source: TFP-WebServer/WebServer/src/Permissions/AdminWebUsers.cs@ 498

Last change on this file since 498 was 487, checked in by alloc, 5 months ago

1.1.0.1 Release for V 1.0

File size: 5.1 KB
RevLine 
[404]1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Xml;
5
6namespace Webserver.Permissions {
7 public class AdminWebUsers : AdminSectionAbs {
8 public static AdminWebUsers Instance { get; private set; }
9
10 public AdminWebUsers (AdminTools _parent) : base (_parent, "webusers") {
11 Instance = this;
12 }
13
14 private readonly Dictionary<string, WebUser> users = new CaseInsensitiveStringDictionary<WebUser> ();
15
16
17#region IO
18
19 public override void Clear () {
20 users.Clear ();
21 }
22
[487]23 public override void ParseElement (XmlElement _childElement) {
[404]24 if (WebUser.TryParse (_childElement, out WebUser webUser)) {
25 users [webUser.Name] = webUser;
26 }
27 }
28
29 public override void Save (XmlElement _root) {
30 XmlElement usersElement = _root.AddXmlElement (SectionTypeName);
31 // modulesElement.AddXmlComment (" <module name=\"adminuser1\" secret=\"supersecrettoken\" permission_level=\"0\" /> ");
32
33 foreach ((string _, WebUser module) in users) {
34 module.ToXml (usersElement);
35 }
36 }
37
38#endregion
39
40
41#region Runtime interaction
42
43
44 public void AddUser (string _name, string _password, PlatformUserIdentifierAbs _userIdentifier, PlatformUserIdentifierAbs _crossPlatformIdentifier) {
[474]45 lock (Parent) {
46 WebUser p = new WebUser (_name, _password, _userIdentifier, _crossPlatformIdentifier);
47
48 // TODO: Check if another name exists with the same (crossplatform)identifier, remove that
49 users[_name] = p;
50
51 Parent.Save ();
52 }
[404]53 }
54
55 public bool RemoveUser (string _name) {
[474]56 lock (Parent) {
57 bool removed = users.Remove (_name);
58 if (removed) {
59 Parent.Save ();
60 }
61
62 return removed;
[404]63 }
64 }
65
66 public Dictionary<string, WebUser> GetUsers () {
[474]67 lock (Parent) {
68 return users;
69 }
[404]70 }
71
72#endregion
73
74 public readonly struct WebUser {
75 public readonly string Name;
76 public readonly byte[] PasswordHash;
77 public readonly PlatformUserIdentifierAbs PlatformUser;
78 public readonly PlatformUserIdentifierAbs CrossPlatformUser;
79
80 public WebUser (string _name, byte[] _passwordHash, PlatformUserIdentifierAbs _platformUser, PlatformUserIdentifierAbs _crossPlatformUser) {
81 Name = _name;
82 PasswordHash = _passwordHash;
83 PlatformUser = _platformUser;
84 CrossPlatformUser = _crossPlatformUser;
85 }
86
87 public WebUser (string _name, string _password, PlatformUserIdentifierAbs _platformUser, PlatformUserIdentifierAbs _crossPlatformUser) {
88 Name = _name;
89 PasswordHash = Hash (_password);
90 PlatformUser = _platformUser;
91 CrossPlatformUser = _crossPlatformUser;
92 }
93
94 public void ToXml (XmlElement _parent) {
95 XmlElement elem = _parent.AddXmlElement ("user");
96 elem.SetAttrib ("name", Name)
97 .SetAttrib ("pass", Convert.ToBase64String(PasswordHash));
98 PlatformUser.ToXml (elem);
99 CrossPlatformUser?.ToXml (elem, "cross");
100 }
101
102 public static bool TryParse (XmlElement _element, out WebUser _result) {
103 _result = default;
104
105 if (!_element.TryGetAttribute ("name", out string name)) {
106 Log.Warning ($"[Web] [Perms] Ignoring user-entry because of missing 'name' attribute: {_element.OuterXml}");
107 return false;
108 }
109
110 if (!_element.TryGetAttribute ("pass", out string passHashString)) {
111 Log.Warning ($"[Web] [Perms] Ignoring user-entry because of missing 'pass' attribute: {_element.OuterXml}");
112 return false;
113 }
114
115 PlatformUserIdentifierAbs userIdentifier = PlatformUserIdentifierAbs.FromXml (_element, false);
116 if (userIdentifier == null) {
117 Log.Warning ($"[Web] [Perms] Ignoring user-entry because of missing 'platform' or 'userid' attribute: {_element.OuterXml}");
118 return false;
119 }
120
121 PlatformUserIdentifierAbs crossIdentifier = PlatformUserIdentifierAbs.FromXml (_element, false, "cross");
122
123 byte[] passHash = Convert.FromBase64String (passHashString);
124
125 _result = new WebUser (name, passHash, userIdentifier, crossIdentifier);
126 return true;
127 }
128
129 public bool ValidatePassword (string _password) {
130 byte[] input = Hash (_password);
131 return Utils.ArrayEquals (input, PasswordHash);
132 }
133 }
134
135 private static byte[] Hash (string _input) {
136 System.Security.Cryptography.MD5Cng hasherMD5 = new System.Security.Cryptography.MD5Cng();
137
138 return hasherMD5.ComputeHash (Encoding.UTF8.GetBytes (_input));
139 }
140
[433]141 public bool TryGetUser (string _name, string _password, out WebUser _result) {
[474]142 lock (Parent) {
143 if (users.TryGetValue (_name, out _result) && _result.ValidatePassword (_password)) {
144 return true;
145 }
146
147 _result = default;
148 return false;
[404]149 }
150 }
151
[433]152 public bool HasUser (PlatformUserIdentifierAbs _platformUser, PlatformUserIdentifierAbs _crossPlatformUser, out WebUser _result) {
[474]153 lock (Parent) {
154 _result = default;
155
156 foreach ((string _, WebUser webUser) in users) {
[485]157 if (!Equals (webUser.PlatformUser, _platformUser) ||
158 !Equals (webUser.CrossPlatformUser, _crossPlatformUser)) {
[474]159 continue;
160 }
161
162 _result = webUser;
163 return true;
[433]164 }
[404]165
[474]166 return false;
[433]167 }
168 }
169
[404]170 }
171}
Note: See TracBrowser for help on using the repository browser.