Merge branch 'leolivier-master'

This commit is contained in:
antelle 2018-03-25 13:55:25 +02:00
commit c73895e237
3 changed files with 55 additions and 55 deletions

View File

@ -9,7 +9,8 @@
"url": "https://github.com/leolivier"
},
"resources": {
"js": "v4ywb0IknjyQB86IYbnI11S3kVHSb6Te7KuPlLz1SkRxeKQua4G2mWYU1DW0A36oep9suCMQ9pENFyh1UaT8AtzGyhX1DPa7paJdfODUvEdX0Zy7TdMRbvZOqmrmYBovsRGfiZenA3oEqJnHlW2EJpBud1MdYyKSdlEOAMPhON0moppON9oqRjb+MMnIPaTJcwya7OntfcEVSgvnwk7jj0eDJtsnjNHub+1DWg4IFaDUA0SIQ9qP0MtexwKYlQJhzfSSReQ3kgK7v09QcZZgEvl0VnjrZJtgTZGaWAYA3Sy6hooCIkeXDzADl6DPCCN6EK0PA2WBIzmcARbJ3Z38dg=="
"js": "W19SmYNJkAkejgHnjLZ1APMXN6B5PJCNR4ygpZ1p0J/i/44GpnJ9N/0xzkAy/XH3EDlQP8qAnfjIoYgdS665G2bQzU7cmudu8Wb/ZzX2yDsRlP+gkvFNrt3XQs62aDNcdY6r4PHElS7Y6W8F6IQILng3Ep5/m+D811QnT1DP32A+K/wyX02DrveDRFYy9UKIJN06KAEWrXaci1FY90ZbFOOB9xXPHFtWw7HeyaBfpMXlZxgqP9XJwlbeZR9MGLEpne/53DQ/Y9KDfoV8eziknYotJcSbV+P8++7NZaD854k+tr51G3KmDBaaBE3A6PUL0mIHvUuJkMkM9u2ok2kFlA==",
"css": "SjqcXv4URjI8bGAnkmzSncSAcoUEwlVwhN9T/k5APlwaxu6MOqIObmmBclUoxblDJ5p/ZG5eZljyHdfrLKhbuFFOWR/78InuDr8Ybn9LH6El5G3uuQlowt+wn0QtIaznPoWTzNemtev3q+3ttaZFCf88Qw5rni6JEdaxJ1VZkx3nZM+zQjbHlgmeCE6UgSWEhqo6n334KSB1sJieKw9Aht4W/ZjuBdrlf3S4navns1KA1dJut8/H9fWmHyksMzkVgzGYwgc7UPrp9Pgh5eUdD2BGFDNJBXxMhs3V/Vam/9idzD7xzcRUApRx5JEwCPoCUlGLINzQJBz7TnHJDd14AA=="
},
"url": "https://plugins.keeweb.info/plugins/haveibeenpwned",
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0oZB2Kt7AzRFNqf8FuO3C3kepHPAIQYiDPYdQxHcsiaFCwyKVx6K1cE/3vBhb8/2rj+QIIWNfAAuu1Y+2VK90ZBeq6HciukWzQRO/HWhfdy0c7JwDAslmyGI5olj0ZQkNLhkde1MiMxjDPpRhZtdJaryVO5cFJaJESpv3dV6m0qXsaQCluWYOSNfSjP9C8o2zRVjSi3ZQZnZIV5pnk9K2MtlZIPXrN9iJiM5zZ9DTSnqApI6dC9mX4R3LvGN+GTovm9C8Crl+qb106nGRR3LcweicDnPyMtZLa/E0DBpWYxUVLDp6WeLhxoUBr+6+t3Xp9IDnPoANDQXJXD0f1vQxQIDAQAB",

View File

@ -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); }
}

View File

@ -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.
const LogLevel = Logger.Level.Info;
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',
@ -221,26 +213,13 @@ module.exports.getSettings = function () {
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 () {