Changed alerts by animated icon + tip and trimmed logs
This commit is contained in:
parent
0573744d2e
commit
92422ad81c
|
@ -9,7 +9,8 @@
|
|||
"url": "https://github.com/leolivier"
|
||||
},
|
||||
"resources": {
|
||||
"js": "BeXlCVvW20aFD4PXy65b/sMxTl44rMy6yvFgTGIHJGlnLxIyQIvp4wPcDyf6sSXZqn5IthrxSDvRvsAW/gOcbeOAt/cwsafazJXU1El1xjKJ5FGcE6oJLZfcBYDSoAk5+OBQi1Casyw5F1PflBxtk4J64ASADnNNZbEi+kpnZcIho6e//qwfXMpqMftCZVqWgqVQX0N9OFa7qWxLv2x4acLx2B7cHu7/No97ChjwNNh8vqjo2BQG40rjiCtx0P6lh2r54K5c1QC3k15OJM2atSA+mG6d3HhHqhJMhjOCp3BwwyVfJ1jZ6/xg6GBDTaDmaIuegAfXd+gpZ+8DG5iPPg=="
|
||||
"js": "cndRTfuwDPqQiIkLIdjEQEh273d0ykOa+nkexFbaunc4yBaCLQvD2bA6t17Y0goIREfFP22vyc6+qohHEgxvb43+agVGpM0IwdtPsqLg8I+4x5lXlBjXZso+eKLS4wfq0r3h2cRHpk+z8+B1WB5LksiuWJdeSZY4Zch1KYYdzTh40qOulQFtQVcW2KjSEGnEMnm1vuQs433WeRD8yXPP5S8hpO8ytJl/Wg3Xm7Va/K6vijXfc54PeIxs7/jUbk13J9h/3/TVVOxuzVQeT2LxKZ8yjYF3AsX62HmqDnhjOQghoERbuW71tjYdcExPsbkgznGXieJoAvSyM0nUO/5Iqg==",
|
||||
"css": "SjqcXv4URjI8bGAnkmzSncSAcoUEwlVwhN9T/k5APlwaxu6MOqIObmmBclUoxblDJ5p/ZG5eZljyHdfrLKhbuFFOWR/78InuDr8Ybn9LH6El5G3uuQlowt+wn0QtIaznPoWTzNemtev3q+3ttaZFCf88Qw5rni6JEdaxJ1VZkx3nZM+zQjbHlgmeCE6UgSWEhqo6n334KSB1sJieKw9Aht4W/ZjuBdrlf3S4navns1KA1dJut8/H9fWmHyksMzkVgzGYwgc7UPrp9Pgh5eUdD2BGFDNJBXxMhs3V/Vam/9idzD7xzcRUApRx5JEwCPoCUlGLINzQJBz7TnHJDd14AA=="
|
||||
},
|
||||
"url": "https://plugins.keeweb.info/plugins/haveibeenpwned",
|
||||
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp9Cay/z7whBsHcf9klDjlA4qylWT7a/igTJ2nvUq2XuQrx98PTOexzzzg5oflk8nPEaMIsaFIf90V/rvQjJ1z9DR4zuQKDb4/GZVzxoylECAwNk80LvSPc1G0+6mwXIFp48wc6Advd4iYQCMkzWDCJXEm/1E+q85ty+H6EaLleKcJI0vlW96bbA9vFCmOsM5PYZfoGnVFRBLVthyUcGneilMvsxu5J7DKggQKPs04/WQZ5oHbUG83mxkxTdYDC3glpvV4BiaAD6z+2usO+fA97bXb+rY3O2iHJgWsa7jH0ybO0Nif6txE4d2+LJOLmfoImv7kdyu/eN3A78KejCOhwIDAQAB",
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
.hibp-pwned:after{
|
||||
content: "';--";
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
background-color: white;
|
||||
background-size:cover;
|
||||
position: relative;;
|
||||
width:20px;
|
||||
height:20px;
|
||||
animation: hibp-spin 1s linear 0s infinite;
|
||||
transform-origin: center center;
|
||||
}
|
||||
@keyframes hibp-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
25% { transform: rotate(10deg); color: rgb(226, 0, 0); }
|
||||
50% { transform: rotate(0deg); }
|
||||
75% { transform: rotate(-10deg); color: rgb(126, 0, 0); }
|
||||
100% { transform: rotate(0deg); }
|
||||
}
|
||||
|
|
@ -4,21 +4,19 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
const DetailsView = require('views/details/details-view');
|
||||
const Alerts = require('comp/alerts');
|
||||
const Logger = require('util/logger');
|
||||
// change log level here. See issue #893 on keeweb: I need to set Debug for seing Infos...
|
||||
const LogLevel = Logger.Level.Debug;
|
||||
|
||||
const DetailsView = require('views/details/details-view');
|
||||
// const Alerts = require('comp/alerts');
|
||||
const InputFx = require('util/input-fx');
|
||||
const Kdbxweb = require('kdbxweb');
|
||||
const _ = require('_');
|
||||
|
||||
// const Menu = require()
|
||||
const Tip = require('util/tip');
|
||||
const detailsViewFieldChanged = DetailsView.prototype.fieldChanged;
|
||||
|
||||
DetailsView.prototype.checkPwnedOnSettingsChanged = function (changes) {
|
||||
// if (changes['CheckPwnedPwd'] || changes['CheckPwnedName'] || changes['BlockPwnedPwd'] || changes['BlockPwnedName']) {
|
||||
// info('Full HaveIBeenPwned check not yet implemented. Checks are done one by one when you change a name or a password.');
|
||||
// }
|
||||
};
|
||||
|
||||
let _seen = [];
|
||||
class HIBPUtils {
|
||||
constructor() {
|
||||
|
@ -28,6 +26,7 @@ class HIBPUtils {
|
|||
this.blockPwnedPwd = false;
|
||||
this.blockPwnedName = false;
|
||||
this.logger = new Logger('HaveIBeenPwned');
|
||||
this.logger.setLevel(LogLevel);
|
||||
};
|
||||
replacer(key, value) {
|
||||
if (value != null && typeof value === 'object') {
|
||||
|
@ -57,7 +56,10 @@ class HIBPUtils {
|
|||
}
|
||||
});
|
||||
xhr.addEventListener('error', () => {
|
||||
return config.error && config.error('network error', xhr);
|
||||
const err = xhr.response && xhr.response.error || new Error('Network error');
|
||||
this.logger.error('HaveIBeenPwned API error', 'GET', xhr.status, err);
|
||||
err.status = xhr.status;
|
||||
return err;
|
||||
});
|
||||
xhr.addEventListener('timeout', () => {
|
||||
return config.error && config.error('timeout', xhr);
|
||||
|
@ -87,7 +89,6 @@ class HIBPUtils {
|
|||
return hexCodes.join('');
|
||||
};
|
||||
digest(algo, str) {
|
||||
// We transform the string into an arraybuffer.
|
||||
const buffer = Kdbxweb.ByteUtils.stringToBytes(str);
|
||||
const subtle = window.crypto.subtle || window.crypto.webkitSubtle;
|
||||
const _self = this;
|
||||
|
@ -101,9 +102,19 @@ class HIBPUtils {
|
|||
sha256(str) {
|
||||
return this.digest('SHA-256', str);
|
||||
};
|
||||
alert (msg) {
|
||||
Alerts.info({ body: msg, title: 'HaveIBeenPwned' });
|
||||
alert (el, msg) {
|
||||
// Alerts.info({ body: msg, title: 'HaveIBeenPwned' });
|
||||
el.focus();
|
||||
el.addClass('input--error');
|
||||
el.addClass('hibp-pwned');
|
||||
Tip.createTip(el, { title: msg, placement: 'bottom' });
|
||||
InputFx.shake(el);
|
||||
};
|
||||
passed(el, msg) {
|
||||
hibp.logger.info(msg);
|
||||
el.removeClass('input--error');
|
||||
el.removeClass('hibp-pwned');
|
||||
}
|
||||
}
|
||||
|
||||
const hibp = new HIBPUtils();
|
||||
|
@ -112,7 +123,7 @@ DetailsView.prototype.checkNamePwned = function (name) {
|
|||
hibp.logger.info('check hibp name ' + name);
|
||||
name = encodeURIComponent(name);
|
||||
const url = `https://haveibeenpwned.com/api/v2/breachedaccount/${name}?truncateResponse=true`;
|
||||
hibp.logger.info('url ' + url);
|
||||
hibp.logger.debug('url ' + url);
|
||||
hibp.xhrcall({
|
||||
url: url,
|
||||
method: 'GET',
|
||||
|
@ -121,24 +132,14 @@ DetailsView.prototype.checkNamePwned = function (name) {
|
|||
data: null,
|
||||
statuses: [200, 404],
|
||||
success: (data, xhr) => {
|
||||
hibp.logger.info('xhr ' + JSON.stringify(xhr));
|
||||
if (data && data.length > 0) {
|
||||
hibp.logger.info('found breaches ' + JSON.stringify(data));
|
||||
hibp.logger.debug('found breaches ' + JSON.stringify(data));
|
||||
let breaches = '';
|
||||
data.forEach(breach => { breaches += '<li>' + _.escape(breach.Name) + '</li>\n'; });
|
||||
hibp.alert(`WARNING! This account has been pawned in the following breaches<br/>\n<ul>\n${breaches}\n</ul>\n<p>Please check on <a href='https://haveibeenpwned.com'>https://haveibeenpwned.com</a>\n`);
|
||||
this.userEditView.$el.focus();
|
||||
this.userEditView.$el.addClass('input--error');
|
||||
InputFx.shake(this.userEditView.$el);
|
||||
hibp.alert(this.userEditView.$el, `WARNING! This account has been pawned in the following breaches<br/>\n<ul>\n${breaches}\n</ul>\n<p>Please check on <a href='https://haveibeenpwned.com'>https://haveibeenpwned.com</a>\n`);
|
||||
} else {
|
||||
hibp.logger.info('check pwnd name passed...');
|
||||
this.userEditView.$el.removeClass('input--error');
|
||||
hibp.passed(this.userEditView.$el, 'check pwned user name passed...');
|
||||
}
|
||||
},
|
||||
error: (e, xhr) => {
|
||||
const err = xhr.response && xhr.response.error || new Error('Network error');
|
||||
hibp.logger.error('Pwned Password API error', 'GET', xhr.status, err);
|
||||
err.status = xhr.status;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -155,27 +156,18 @@ DetailsView.prototype.checkPwdPwned = function (passwordHash) {
|
|||
statuses: [200, 404],
|
||||
success: data => {
|
||||
if (data) {
|
||||
hibp.logger.info('found breaches ' + JSON.stringify(data));
|
||||
hibp.logger.debug('found breaches ' + JSON.stringify(data));
|
||||
data.split('\r\n').forEach(line => {
|
||||
const h = line.split(':');
|
||||
const suffix = h[0];
|
||||
if (prefix + suffix === passwordHash) {
|
||||
const nb = _.escape(h[1]);
|
||||
hibp.alert(`WARNING: This password is referenced as pawned ${nb} times on <a href='https://haveibeenpwned.com'>https://haveibeenpwned.com</a>!\n`);
|
||||
this.passEditView.$el.focus();
|
||||
this.passEditView.$el.addClass('input--error');
|
||||
InputFx.shake(this.passEditView.$el);
|
||||
hibp.alert(this.passEditView.$el, `WARNING: This password is referenced as pawned ${nb} times on <a href='https://haveibeenpwned.com'>https://haveibeenpwned.com</a>!\n`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
hibp.logger.info('check pwnd passwd passed...');
|
||||
this.passEditView.$el.removeClass('input--error');
|
||||
hibp.passed(this.userEditView.$el, 'check pwned password passed...');
|
||||
}
|
||||
},
|
||||
error: (e, xhr) => {
|
||||
const err = xhr.response && xhr.response.error || new Error('Network error');
|
||||
hibp.logger.error('Pwned Password API error', 'GET', xhr.status, err);
|
||||
err.status = xhr.status;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -183,7 +175,7 @@ DetailsView.prototype.checkPwdPwned = function (passwordHash) {
|
|||
DetailsView.prototype.fieldChanged = function (e) {
|
||||
detailsViewFieldChanged.apply(this, arguments);
|
||||
if (e.field) {
|
||||
// hibp.logger.info('field changed ' + hibp.stringify(e));
|
||||
hibp.logger.debug('field changed ' + hibp.stringify(e));
|
||||
if (e.field === '$Password' && hibp.checkPwnedPwd) {
|
||||
if (this.passEditView.value) {
|
||||
const pwd = this.passEditView.value.getText();
|
||||
|
@ -200,7 +192,7 @@ DetailsView.prototype.fieldChanged = function (e) {
|
|||
};
|
||||
|
||||
module.exports.getSettings = function () {
|
||||
const ret = [{
|
||||
return [{
|
||||
name: 'checkPwnedPwd',
|
||||
label: 'Check passwords against HaveIBeenPwned list',
|
||||
type: 'checkbox',
|
||||
|
@ -220,28 +212,14 @@ module.exports.getSettings = function () {
|
|||
label: 'Block pwned names if they are in HaveIBeenPwned list',
|
||||
type: 'checkbox',
|
||||
value: hibp.blockPwnedName
|
||||
}
|
||||
];
|
||||
hibp.logger.info(hibp.stringify(ret));
|
||||
return ret;
|
||||
}];
|
||||
};
|
||||
|
||||
module.exports.setSettings = function (changes) {
|
||||
// apply changed settings in plugin logic
|
||||
// this method will be called:
|
||||
// 1. when any of settings fields is modified by user
|
||||
// 2. after plugin startup, with saved values
|
||||
// only changed settings will be passed
|
||||
|
||||
// example: { MyText: 'value', MySel: 'selected-value', MyCheckbox: true }
|
||||
// info(JSON.stringify(changes));
|
||||
|
||||
for (const field in changes) {
|
||||
const ccfield = field.substr(0, 1).toLowerCase() + field.substring(1);
|
||||
hibp[ccfield] = changes[field];
|
||||
}
|
||||
DetailsView.prototype.checkPwnedOnSettingsChanged.apply(changes);
|
||||
// hibp.logger.info(hibp.stringify(hibp));
|
||||
};
|
||||
|
||||
module.exports.uninstall = function () {
|
||||
|
|
Loading…
Reference in New Issue