More work on login tokens.
Ylian Saint-Hilaire committed
Apr 15, 2021 at 20:51 UTC
0f99e9bf380b801f064be35ca61dde3edef13595
2 files changed
+56
-13
meshuser.js
+9
-5
@@ -4961,7 +4961,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4961
const doc = docs[i];
4962
if (doc.expireTime < now) {
4963
// This share is expired.
4964
- parent.db.Remove(doc._id, function () { }); delete docs[i]; removed = true;
4964
+ parent.db.Remove(doc._id, function () { }); removed = true;
4965
} else {
4966
// This share is ok, remove extra data we don't need to send.
4967
delete doc._id; delete doc.domain; delete doc.nodeid; delete doc.type;
@@ -5611,14 +5611,19 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5611
break;
5612
}
5613
case 'loginTokens': { // Respond with the list of currently valid login tokens
5614
+ if ((typeof domain.passwordrequirements != 'object') && (domain.passwordrequirements.logintokens == false)) break; // Login tokens are not supported on this server
5615
+
5616
+ // If remove is an array or strings, we are going to be removing these and returning the results.
5617
+ if (common.validateStrArray(command.remove, 1) == false) { delete command.remove; }
5618
+
5619
parent.db.GetAllTypeNodeFiltered(['logintoken-' + user._id], domain.id, 'logintoken', null, function (err, docs) {
5620
if (err != null) return;
5621
var now = Date.now(), removed = 0, okDocs = [];
5622
for (var i = 0; i < docs.length; i++) {
5623
const doc = docs[i];
5619
- if (doc.expireTime < now) {
5624
+ if (((doc.expire != 0) && (doc.expire < now)) || (doc.tokenUser == null) || ((command.remove != null) && (command.remove.indexOf(doc.tokenUser) >= 0))) {
5625
// This share is expired.
5621
- parent.db.Remove(doc._id, function () { }); delete docs[i]; removed++;
5626
+ parent.db.Remove(doc._id, function () { }); removed++;
5627
} else {
5628
// This share is ok, remove extra data we don't need to send.
5629
delete doc._id; delete doc.domain; delete doc.nodeid; delete doc.type; delete doc.userid; delete doc.salt; delete doc.hash;
@@ -5668,10 +5673,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5673
// Dispatch the new event
5674
var targets = ['*', 'server-users', user._id];
5675
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
5671
- var event = { etype: 'user', userid: user._id, username: user.name, action: 'loginTokenAdded', msgid: 115, msg: "Added login token", domain: domain.id };
5676
+ var event = { etype: 'user', userid: user._id, username: user.name, action: 'loginTokenAdded', msgid: 115, msg: "Added login token", domain: domain.id, newToken: { name: command.name, tokenUser: tokenUser, created: created, expire: expire } };
5677
parent.parent.DispatchEvent(targets, obj, event);
5678
});
5674
-
5679
break;
5680
}
5681
case 'getDeviceDetails': {
views/default.handlebars
+47
-8
@@ -385,8 +385,9 @@
385
</p>
386
<br style=clear:both />
387
</div>
388
+ <div id=p2logintokens></div>
389
<strong>Device Groups</strong>
389
- <span id="p2createMeshLink1">( <a href=# onclick="return account_createMesh()" class="newMeshBtn"> New</a> )</span>
390
+ <span id="p2createMeshLink1"> - <a href=# onclick="return account_createMesh()" class="newMeshBtn"> New</a></span>
391
<br /><br />
392
<div id=p2meshes></div>
393
<div id=p2noMeshFound style="display:none">No device groups.<span id="p2createMeshLink2"> <a href=# onclick="return account_createMesh()"><strong>Get started here!</strong></a></span></div>
@@ -2004,6 +2005,7 @@
2005
if (updateNaggleFlags & 8192) { updateUserGroups(); }
2006
if (updateNaggleFlags & 16384) { updateUsers(); }
2007
if (updateNaggleFlags & 32768) { updateRecordings(); }
2008
+ if (updateNaggleFlags & 65536) { updateLoginTokens(); }
2009
updateNaggleTimer = null;
2010
updateNaggleFlags = 0;
2011
gotoStartViewPage();
@@ -3169,11 +3171,17 @@
3171
if ((Q('DevFilterSelect').value == 2) || (Q('DevFilterSelect').value == 6)) { mainUpdate(1); }
3172
break;
3173
}
3172
- case 'loginTokenChanged': {
3174
+ case 'loginTokenChanged': { // Login tokens have changed
3175
if (message.event.userid != userinfo._id) return;
3176
loginTokens = message.event.loginTokens;
3175
- // TODO: Update
3176
- console.log('t1', loginTokens);
3177
+ mainUpdate(65536);
3178
+ break;
3179
+ }
3180
+ case 'loginTokenAdded': { // A login token was added
3181
+ if (message.event.userid != userinfo._id) return;
3182
+ if (loginTokens == null) { loginTokens = []; }
3183
+ loginTokens.push(message.event.newToken);
3184
+ mainUpdate(65536);
3185
break;
3186
}
3187
case 'stopped': { // Server is stopping.
@@ -3342,7 +3350,7 @@
3350
saveAs(new Blob([message.data], { type: 'application/octet-stream' }), "devicelist" + '.' + message.type);
3351
break;
3352
}
3345
- case 'createLoginToken': {
3353
+ case 'createLoginToken': { // A new login token was created
3354
if (xxdialogMode) return;
3355
var x = "Take note of this username and password, the password cannot be shown again." + '<br /><br />';
3356
x += addHtmlValue("Name", EscapeHtml(message.name))
@@ -3352,10 +3360,9 @@
3360
setDialogMode(2, "Create Login Token", 1, null, x);
3361
break;
3362
}
3355
- case 'loginTokens': {
3363
+ case 'loginTokens': { // Reveiced the list of login tokens
3364
loginTokens = message.loginTokens;
3357
- // TODO: Update
3358
- console.log('t2', loginTokens);
3365
+ mainUpdate(65536);
3366
break;
3367
}
3368
default:
@@ -10437,6 +10444,38 @@
10444
QV('p2noMeshFound', count == 0);
10445
}
10446
10447
+
10448
+ function updateLoginTokens() {
10449
+ var x = '', count = 1;
10450
+ if ((loginTokens != null) && (loginTokens.length > 0)) {
10451
+ x += '<p><strong>' + "Active Login Tokens" + '</strong> - <span id="p2createMeshLink1"> <a href=# onclick="return account_createLoginToken()" class="newMeshBtn"> ' + "New" + '</a></span></p><div style=margin-left:40px><table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Name" + '</th><th scope=col style=text-align:left>' + "Username" + '</th></tr>';
10452
+ for (var i = 0; i < loginTokens.length; i++) {
10453
+ var ltoken = loginTokens[i];
10454
+ var trash = '<a href=# onclick=\'return p2removeLoginToken(event,"' + encodeURIComponentEx(ltoken.tokenUser) + '")\' title="' + "Remove login token" + '" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10455
+ var details = '';
10456
+ if (ltoken.expire != 0) { details = EscapeHtml(format("Expires {0}", printDateTime(new Date(ltoken.expire)))) + ' '; }
10457
+ x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div class=m' + 2 + '></div><div> ' + EscapeHtml(ltoken.name) + '<div></div></div></td><td style=width:70%><div style=float:right>' + details + trash + '</div><div>' + EscapeHtml(ltoken.tokenUser) + '</div></td></tr>';
10458
+ }
10459
+ x += '</tbody></table></div><br />';
10460
+ QV('accountCreateLoginTokenSpan', false);
10461
+ } else {
10462
+ QV('accountCreateLoginTokenSpan', features2 & 0x00000080);
10463
+ }
10464
+ QH('p2logintokens', x);
10465
+ }
10466
+
10467
+ function p2removeLoginToken(e, tokenUser) {
10468
+ tokenUser = decodeURIComponent(tokenUser);
10469
+ if (loginTokens == null) return;
10470
+ var token = null;
10471
+ for (var i = 0; i < loginTokens.length; i++) { if (loginTokens[i].tokenUser == tokenUser) { token = loginTokens[i]; } }
10472
+ if (token == null) return;
10473
+ var x = "Confirm removal of this login token?" + '<br /><br />';
10474
+ x += addHtmlValue("Name", EscapeHtml(token.name));
10475
+ x += addHtmlValue("Username", EscapeHtml(token.tokenUser));
10476
+ setDialogMode(2, "Remove Login Token", 3, function(b, tokenUser) { meshserver.send({ action: 'loginTokens', remove: [ tokenUser ] }); }, x, tokenUser);
10477
+ }
10478
+
10479
function gotoMesh(meshid) {
10480
currentMesh = meshes[meshid];
10481
p20updateMesh();