Fix database escaping problem in device groups.

Ylian Saint-Hilaire committed Dec 30, 2020 at 18:52 UTC 5a4fdd3d8dc14c0865bbf492b4964fefbc80a5d4
1 file changed +100 -47
db.js
+100 -47
@@ -97,64 +97,116 @@ module.exports.CreateDB = function (parent, func) {
97 obj.file.remove({ type: 'smbios' }, { multi: true });
98 }
99
100 - // Remove all objects that have a "meshid" that no longer points to a valid mesh.
101 - obj.GetAllType('mesh', function (err, docs) {
102 - if (err != null) { parent.debug('db', 'ERROR (GetAll mesh): ' + err); }
103 - var meshlist = [];
104 - if ((err == null) && (docs.length > 0)) { for (var i in docs) { meshlist.push(docs[i]._id); } }
105 - if ((obj.databaseType == 4) || (obj.databaseType == 5)) {
106 - // MariaDB
107 - sqlDbQuery('DELETE FROM MeshCentral.Main WHERE (extra LIKE ("mesh/%") AND (extra NOT IN ?)', [meshlist], func);
108 - } else if (obj.databaseType == 3) {
109 - // MongoDB
110 - obj.file.deleteMany({ meshid: { $exists: true, $nin: meshlist } }, { multi: true });
111 - } else {
112 - // NeDB or MongoJS
113 - obj.file.remove({ meshid: { $exists: true, $nin: meshlist } }, { multi: true });
114 - }
100 + // List of valid identifiers
101 + var validIdentifiers = {}
102 +
103 + // Load all user groups
104 + obj.GetAllType('ugrp', function (err, docs) {
105 + if (err != null) { parent.debug('db', 'ERROR (GetAll user): ' + err); }
106 + if ((err == null) && (docs.length > 0)) {
107 + for (var i in docs) {
108 + // Add this as a valid user identifier
109 + validIdentifiers[docs[i]._id] = 1;
110 + }
111
116 - // Fix all of the creating & login to ticks by seconds, not milliseconds.
117 - obj.GetAllType('user', function (err, docs) {
118 - if (err != null) { parent.debug('db', 'ERROR (GetAll user): ' + err); }
119 - if ((err == null) && (docs.length > 0)) {
120 - for (var i in docs) {
121 - var fixed = false;
112 + // Fix all of the creating & login to ticks by seconds, not milliseconds.
113 + obj.GetAllType('user', function (err, docs) {
114 + if (err != null) { parent.debug('db', 'ERROR (GetAll user): ' + err); }
115 + if ((err == null) && (docs.length > 0)) {
116 + for (var i in docs) {
117 + var fixed = false;
118
123 - // Fix email address capitalization
124 - if (docs[i].email && (docs[i].email != docs[i].email.toLowerCase())) {
125 - docs[i].email = docs[i].email.toLowerCase(); fixed = true;
126 - }
119 + // Add this as a valid user identifier
120 + validIdentifiers[docs[i]._id] = 1;
121
128 - // Fix account creation
129 - if (docs[i].creation) {
130 - if (docs[i].creation > 1300000000000) { docs[i].creation = Math.floor(docs[i].creation / 1000); fixed = true; }
131 - if ((docs[i].creation % 1) != 0) { docs[i].creation = Math.floor(docs[i].creation); fixed = true; }
132 - }
122 + // Fix email address capitalization
123 + if (docs[i].email && (docs[i].email != docs[i].email.toLowerCase())) {
124 + docs[i].email = docs[i].email.toLowerCase(); fixed = true;
125 + }
126
134 - // Fix last account login
135 - if (docs[i].login) {
136 - if (docs[i].login > 1300000000000) { docs[i].login = Math.floor(docs[i].login / 1000); fixed = true; }
137 - if ((docs[i].login % 1) != 0) { docs[i].login = Math.floor(docs[i].login); fixed = true; }
138 - }
127 + // Fix account creation
128 + if (docs[i].creation) {
129 + if (docs[i].creation > 1300000000000) { docs[i].creation = Math.floor(docs[i].creation / 1000); fixed = true; }
130 + if ((docs[i].creation % 1) != 0) { docs[i].creation = Math.floor(docs[i].creation); fixed = true; }
131 + }
132 +
133 + // Fix last account login
134 + if (docs[i].login) {
135 + if (docs[i].login > 1300000000000) { docs[i].login = Math.floor(docs[i].login / 1000); fixed = true; }
136 + if ((docs[i].login % 1) != 0) { docs[i].login = Math.floor(docs[i].login); fixed = true; }
137 + }
138 +
139 + // Fix last password change
140 + if (docs[i].passchange) {
141 + if (docs[i].passchange > 1300000000000) { docs[i].passchange = Math.floor(docs[i].passchange / 1000); fixed = true; }
142 + if ((docs[i].passchange % 1) != 0) { docs[i].passchange = Math.floor(docs[i].passchange); fixed = true; }
143 + }
144
140 - // Fix last password change
141 - if (docs[i].passchange) {
142 - if (docs[i].passchange > 1300000000000) { docs[i].passchange = Math.floor(docs[i].passchange / 1000); fixed = true; }
143 - if ((docs[i].passchange % 1) != 0) { docs[i].passchange = Math.floor(docs[i].passchange); fixed = true; }
145 + // Fix subscriptions
146 + if (docs[i].subscriptions != null) { delete docs[i].subscriptions; fixed = true; }
147 +
148 + // Save the user if needed
149 + if (fixed) { obj.Set(docs[i]); }
150 }
151
146 - // Fix subscriptions
147 - if (docs[i].subscriptions != null) { delete docs[i].subscriptions; fixed = true; }
152 + // Remove all objects that have a "meshid" that no longer points to a valid mesh.
153 + // Fix any incorrectly escaped user identifiers
154 + obj.GetAllType('mesh', function (err, docs) {
155 + if (err != null) { parent.debug('db', 'ERROR (GetAll mesh): ' + err); }
156 + var meshlist = [];
157 + if ((err == null) && (docs.length > 0)) {
158 + for (var i in docs) {
159 + var meshChange = false;
160 + docs[i] = common.unEscapeLinksFieldName(docs[i]);
161 + meshlist.push(docs[i]._id);
162 +
163 + // Make sure all mesh types are number type, if not, fix it.
164 + if (typeof docs[i].mtype == 'string') { docs[i].mtype = parseInt(docs[i].mtype); meshChange = true; }
165 +
166 + // Take a look at the links
167 + if (docs[i].links != null) {
168 + for (var j in docs[i].links) {
169 + if (validIdentifiers[j] == null) {
170 + // This identifier is not known, let see if we can fix it.
171 + var xid = j, xid2 = common.unEscapeFieldName(xid);
172 + while ((xid != xid2) && (validIdentifiers[xid2] == null)) { xid = xid2; xid2 = common.unEscapeFieldName(xid2); }
173 + if (validIdentifiers[xid2] == 1) {
174 + //console.log('Fixing id: ' + j + ' to ' + common.escapeFieldName(xid2));
175 + docs[i].links[xid2] = docs[i].links[j];
176 + delete docs[i].links[j];
177 + meshChange = true;
178 + } else {
179 + // TODO: here, we may want to clean up links to users and user groups that do not exist anymore.
180 + //console.log('Unknown id: ' + j);
181 + }
182 + }
183 + }
184 + }
185
149 - // Save the user if needed
150 - if (fixed) { obj.Set(docs[i]); }
186 + // Save the updated device group if needed
187 + if (meshChange) { obj.Set(docs[i]); }
188 + }
189 + }
190 + if ((obj.databaseType == 4) || (obj.databaseType == 5)) {
191 + // MariaDB
192 + sqlDbQuery('DELETE FROM MeshCentral.Main WHERE (extra LIKE ("mesh/%") AND (extra NOT IN ?)', [meshlist], func);
193 + } else if (obj.databaseType == 3) {
194 + // MongoDB
195 + obj.file.deleteMany({ meshid: { $exists: true, $nin: meshlist } }, { multi: true });
196 + } else {
197 + // NeDB or MongoJS
198 + obj.file.remove({ meshid: { $exists: true, $nin: meshlist } }, { multi: true });
199 + }
200
152 - // We are done
153 - if (func) { func(); }
201 + // We are done
202 + validIdentifiers = null;
203 + if (func) { func(); }
204 + });
205 }
155 - }
156 - });
206 + });
207 + }
208 });
209 +
210 };
211
212 // Get encryption key
@@ -1331,6 +1383,7 @@ module.exports.CreateDB = function (parent, func) {
1383
1384 // Check that the server is capable of performing a backup
1385 obj.checkBackupCapability = function (func) {
1386 + if ((parent.config.settings.autobackup == null) || (parent.config.settings.autobackup == false)) { func(); }
1387 if ((obj.databaseType == 2) || (obj.databaseType == 3)) {
1388 // Check that we have access to MongoDump
1389 var backupPath = parent.backuppath;