mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
267 lines
8.3 KiB
JavaScript
267 lines
8.3 KiB
JavaScript
'use strict';
|
|
|
|
var crypto = require('crypto');
|
|
var Storages = require('js-storage');
|
|
|
|
var hashauth = {
|
|
initialized: false
|
|
};
|
|
|
|
hashauth.init = function init (client, $) {
|
|
|
|
hashauth.apisecret = '';
|
|
hashauth.storeapisecret = false;
|
|
hashauth.apisecrethash = null;
|
|
hashauth.authenticated = false;
|
|
hashauth.tokenauthenticated = false;
|
|
hashauth.hasReadPermission = false;
|
|
hashauth.isAdmin = false;
|
|
hashauth.hasWritePermission = false;
|
|
hashauth.permissionlevel = 'NONE';
|
|
|
|
hashauth.verifyAuthentication = function verifyAuthentication (next) {
|
|
hashauth.authenticated = false;
|
|
$.ajax({
|
|
method: 'GET'
|
|
, url: '/api/v1/verifyauth?t=' + Date.now() //cache buster
|
|
, headers: client.headers()
|
|
}).done(function verifysuccess (response) {
|
|
|
|
|
|
var message = response.message;
|
|
|
|
if (message.canRead) { hashauth.hasReadPermission = true; }
|
|
if (message.canWrite) { hashauth.hasWritePermission = true; }
|
|
if (message.isAdmin) { hashauth.isAdmin = true; }
|
|
if (message.permissions) { hashauth.permissionlevel = message.permissions; }
|
|
|
|
if (message.rolefound == 'FOUND') {
|
|
hashauth.tokenauthenticated = true;
|
|
console.log('Token Authentication passed.');
|
|
next(true);
|
|
return;
|
|
}
|
|
|
|
if (response.message === 'OK' || message.message === 'OK') {
|
|
hashauth.authenticated = true;
|
|
console.log('Authentication passed.');
|
|
next(true);
|
|
return;
|
|
}
|
|
|
|
console.log('Authentication failed!', response);
|
|
hashauth.removeAuthentication();
|
|
next(false);
|
|
return;
|
|
|
|
}).fail(function verifyfail (err) {
|
|
console.log('Authentication failure', err);
|
|
hashauth.removeAuthentication();
|
|
next(false);
|
|
});
|
|
};
|
|
|
|
hashauth.injectHtml = function injectHtml () {
|
|
if (!hashauth.injectedHtml) {
|
|
$('#authentication_placeholder').html(hashauth.inlineCode());
|
|
hashauth.injectedHtml = true;
|
|
}
|
|
};
|
|
|
|
hashauth.initAuthentication = function initAuthentication (next) {
|
|
hashauth.apisecrethash = hashauth.apisecrethash || Storages.localStorage.get('apisecrethash') || null;
|
|
hashauth.verifyAuthentication(function() {
|
|
hashauth.injectHtml();
|
|
if (next) { next(hashauth.isAuthenticated()); }
|
|
});
|
|
return hashauth;
|
|
};
|
|
|
|
hashauth.removeAuthentication = function removeAuthentication (event) {
|
|
|
|
Storages.localStorage.remove('apisecrethash');
|
|
|
|
if (hashauth.authenticated || hashauth.tokenauthenticated) {
|
|
client.browserUtils.reload();
|
|
}
|
|
|
|
// clear eveything just in case
|
|
hashauth.apisecret = null;
|
|
hashauth.apisecrethash = null;
|
|
hashauth.authenticated = false;
|
|
|
|
if (event) {
|
|
event.preventDefault();
|
|
}
|
|
return false;
|
|
};
|
|
|
|
hashauth.requestAuthentication = function requestAuthentication (eventOrNext) {
|
|
var translate = client.translate;
|
|
hashauth.injectHtml();
|
|
|
|
var clientWidth = window.innerWidth ||
|
|
document.documentElement.clientWidth ||
|
|
document.body.clientWidth;
|
|
|
|
clientWidth = Math.min(400, clientWidth);
|
|
|
|
$('#requestauthenticationdialog').dialog({
|
|
width: clientWidth
|
|
, height: 270
|
|
, closeText: ''
|
|
, buttons: [
|
|
{
|
|
id: 'requestauthenticationdialog-btn'
|
|
, text: translate('Authenticate')
|
|
, click: function() {
|
|
var dialog = this;
|
|
hashauth.processSecret($('#apisecret').val(), $('#storeapisecret').is(':checked'), function done (close) {
|
|
if (close) {
|
|
if (eventOrNext && eventOrNext.call) {
|
|
eventOrNext(true);
|
|
} else {
|
|
client.afterAuth(true);
|
|
}
|
|
$(dialog).dialog('close');
|
|
} else {
|
|
$('#apisecret').val('').focus();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
]
|
|
, open: function open () {
|
|
$('#apisecret').off('keyup').on('keyup', function pressed (e) {
|
|
if (e.keyCode === $.ui.keyCode.ENTER) {
|
|
$('#requestauthenticationdialog-btn').trigger('click');
|
|
}
|
|
});
|
|
$('#apisecret').val('').focus();
|
|
}
|
|
|
|
});
|
|
|
|
if (eventOrNext && eventOrNext.preventDefault) {
|
|
eventOrNext.preventDefault();
|
|
}
|
|
return false;
|
|
};
|
|
|
|
hashauth.processSecret = function processSecret (apisecret, storeapisecret, callback) {
|
|
var translate = client.translate;
|
|
|
|
hashauth.apisecret = apisecret;
|
|
hashauth.storeapisecret = storeapisecret;
|
|
if (!hashauth.apisecret || hashauth.apisecret.length < 12) {
|
|
window.alert(translate('Too short API secret'));
|
|
if (callback) {
|
|
callback(false);
|
|
}
|
|
} else {
|
|
var shasum = crypto.createHash('sha1');
|
|
shasum.update(hashauth.apisecret);
|
|
hashauth.apisecrethash = shasum.digest('hex');
|
|
|
|
hashauth.verifyAuthentication(function(isok) {
|
|
if (isok) {
|
|
if (hashauth.storeapisecret) {
|
|
Storages.localStorage.set('apisecrethash', hashauth.apisecrethash);
|
|
// TODO show dialog first, then reload
|
|
if (hashauth.tokenauthenticated) client.browserUtils.reload();
|
|
}
|
|
$('#authentication_placeholder').html(hashauth.inlineCode());
|
|
if (callback) {
|
|
callback(true);
|
|
}
|
|
} else {
|
|
alert(translate('Wrong API secret'));
|
|
if (callback) {
|
|
callback(false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
hashauth.inlineCode = function inlineCode () {
|
|
var translate = client.translate;
|
|
|
|
var status = null;
|
|
|
|
if (!hashauth.isAdmin) {
|
|
$('.needsadminaccess').hide();
|
|
} else {
|
|
$('.needsadminaccess').show();
|
|
}
|
|
|
|
if (client.updateAdminMenu) client.updateAdminMenu();
|
|
|
|
if (client.authorized || hashauth.tokenauthenticated) {
|
|
status = translate('Authorized by token');
|
|
if (client.authorized && client.authorized.sub) {
|
|
status += '<br>' + translate('Auth role') + ': ' + client.authorized.sub;
|
|
if (hashauth.hasReadPermission) { status += '<br>' + translate('Data reads enabled'); }
|
|
if (hashauth.hasWritePermission) { status += '<br>' + translate('Data writes enabled'); }
|
|
if (!hashauth.hasWritePermission) { status += '<br>' + translate('Data writes not enabled'); }
|
|
}
|
|
if (hashauth.apisecrethash) {
|
|
status += '<br> <a href="#" onclick="Nightscout.client.hashauth.removeAuthentication(); return false;">(' + translate('Remove stored token') + ')</a>';
|
|
} else {
|
|
status += '<br><a href="/">(' + translate('view without token') + ')</a>';
|
|
}
|
|
|
|
} else if (hashauth.isAuthenticated()) {
|
|
status = translate('Admin authorized') + ' <a href="#" onclick="Nightscout.client.hashauth.removeAuthentication(); return false;">(' + translate('Remove') + ')</a>';
|
|
} else {
|
|
status = translate('Unauthorized') +
|
|
'<br>' +
|
|
translate('Reads enabled in default permissions') +
|
|
'<br>' +
|
|
' <a href="#" onclick="Nightscout.client.hashauth.requestAuthentication(); return false;">(' +
|
|
translate('Authenticate') + ')</a>';
|
|
}
|
|
|
|
var html =
|
|
'<div id="requestauthenticationdialog" style="display:none" title="' + translate('Device authentication') + '">' +
|
|
'<label for="apisecret">' + translate('Your API secret or token') + ': </label>' +
|
|
'<input type="password" id="apisecret" size="20" style="width: 100%;"/>' +
|
|
'<br>' +
|
|
'<input type="checkbox" id="storeapisecret" /> <label for="storeapisecret">' + translate('Remember this device. (Do not enable this on public computers.)') + '</label>' +
|
|
'</div>' +
|
|
'<div id="authorizationstatus">' + status + '</div>';
|
|
|
|
return html;
|
|
};
|
|
|
|
hashauth.updateSocketAuth = function updateSocketAuth () {
|
|
client.socket.emit(
|
|
'authorize'
|
|
, {
|
|
client: 'web'
|
|
, secret: client.authorized && client.authorized.token ? null : client.hashauth.hash()
|
|
, token: client.authorized && client.authorized.token
|
|
}
|
|
, function authCallback (data) {
|
|
if (!data.read && !client.authorized) {
|
|
hashauth.requestAuthentication();
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
hashauth.hash = function hash () {
|
|
return hashauth.apisecrethash;
|
|
};
|
|
|
|
hashauth.isAuthenticated = function isAuthenticated () {
|
|
return hashauth.authenticated || hashauth.tokenauthenticated;
|
|
};
|
|
|
|
hashauth.initialized = true;
|
|
|
|
return hashauth;
|
|
}
|
|
|
|
module.exports = hashauth;
|