keewebhttp: make it work
This commit is contained in:
parent
ef1312bd24
commit
52ed78cb97
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"manifestVersion": "0.1.0",
|
"manifestVersion": "0.1.0",
|
||||||
"name": "keewebhttp",
|
"name": "keewebhttp",
|
||||||
"description": "KeeWebHttp allows to use browser extensions with KeeWeb",
|
"description": "KeeWebHttp allows to use browser extensions with KeeWeb",
|
||||||
|
@ -11,8 +11,9 @@
|
||||||
"licence": "MIT",
|
"licence": "MIT",
|
||||||
"url": "https://plugins.keeweb.info/plugins/keewebhttp",
|
"url": "https://plugins.keeweb.info/plugins/keewebhttp",
|
||||||
"resources": {
|
"resources": {
|
||||||
"js": "dWXmIa4n78RRR6tiMNIqnejfj54lOsNJrn6mz1eQ3HYpCu4sVKv7E+9ABSGykyHJJVQDjTJAUF+7UcwCfDhIFfbFDttPmeylM3vtg+YAfaJFfU5e0l9/MtuUEuXuiUwjXi3jFg5yAYNq9ZCkHs2YCm4JyE8KXm1flmzIpmTiVi6TkX/ulmO74lLm2wXUD23eP7B8RqXk0wBoc7VcZ1x5uHomJIrQfS+J7vdXrMLBt/EJU4VNlyw8LLxcwP3/UbsBzBotpif3AH0hq+Dcwuh8v8H9Z+756T8EFEXz0JmCLhU0oyFcgOmUt0QwrIiFD18aHt0s80BmuqO600I/3M3+Sg=="
|
"js": "NB8wqvULI7yTqf8FAkJYx2TbyW/BjDo7zpm15MHHHTcYYVIRhYFAeiKx5f9j9UtXLYr1deVc7STdvVLhNsD//tN4LRsSXmOiMt2NnhjIHLhVHwlKxSZTMeK5NrajxjdS0YtBKMg5oDt9vYa15qOvoX0fhmc9E1gD6j5z9sJAxT450JEDRZidXLnUnEnGIZunVH5OCe75eavvcEQ64sZ3pUouTN9iWU66sjC3hG/pk3o5I4+8W4v1MWy2TR7IKaVOLrRiDrzT/rnZoroRg7QLLUb+L185S/OYMEo8MIa7lMu/ULhmbhk0+JT2pukEofPkOZAlF8BIf1EGXGp6gObo4w=="
|
||||||
},
|
},
|
||||||
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0oZB2Kt7AzRFNqf8FuO3C3kepHPAIQYiDPYdQxHcsiaFCwyKVx6K1cE/3vBhb8/2rj+QIIWNfAAuu1Y+2VK90ZBeq6HciukWzQRO/HWhfdy0c7JwDAslmyGI5olj0ZQkNLhkde1MiMxjDPpRhZtdJaryVO5cFJaJESpv3dV6m0qXsaQCluWYOSNfSjP9C8o2zRVjSi3ZQZnZIV5pnk9K2MtlZIPXrN9iJiM5zZ9DTSnqApI6dC9mX4R3LvGN+GTovm9C8Crl+qb106nGRR3LcweicDnPyMtZLa/E0DBpWYxUVLDp6WeLhxoUBr+6+t3Xp9IDnPoANDQXJXD0f1vQxQIDAQAB",
|
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0oZB2Kt7AzRFNqf8FuO3C3kepHPAIQYiDPYdQxHcsiaFCwyKVx6K1cE/3vBhb8/2rj+QIIWNfAAuu1Y+2VK90ZBeq6HciukWzQRO/HWhfdy0c7JwDAslmyGI5olj0ZQkNLhkde1MiMxjDPpRhZtdJaryVO5cFJaJESpv3dV6m0qXsaQCluWYOSNfSjP9C8o2zRVjSi3ZQZnZIV5pnk9K2MtlZIPXrN9iJiM5zZ9DTSnqApI6dC9mX4R3LvGN+GTovm9C8Crl+qb106nGRR3LcweicDnPyMtZLa/E0DBpWYxUVLDp6WeLhxoUBr+6+t3Xp9IDnPoANDQXJXD0f1vQxQIDAQAB",
|
||||||
"desktop": true
|
"desktop": true,
|
||||||
|
"versionMin": "1.5.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,282 +1,311 @@
|
||||||
const nodeRequire = window.require;
|
|
||||||
|
|
||||||
const http = nodeRequire('http');
|
|
||||||
const crypto = nodeRequire('crypto');
|
|
||||||
const fs = nodeRequire('fs');
|
|
||||||
const path = nodeRequire('path');
|
|
||||||
const electron = nodeRequire('electron');
|
|
||||||
|
|
||||||
const AutoType = require('auto-type/index');
|
|
||||||
const AutoTypeFilter = require('auto-type/auto-type-filter');
|
|
||||||
const Logger = require('util/logger');
|
|
||||||
const Alerts = require('comp/alerts');
|
|
||||||
|
|
||||||
// const appModel = ...; TODO: use AppModel.instance
|
|
||||||
|
|
||||||
const Version = '1.8.4.2';
|
|
||||||
const DebugMode = true;
|
|
||||||
|
|
||||||
const keys = {};
|
|
||||||
|
|
||||||
const logger = new Logger('keewebhttp');
|
|
||||||
|
|
||||||
let server;
|
let server;
|
||||||
let uninstalled = false;
|
let uninstalled = false;
|
||||||
|
|
||||||
setTimeout(init, 0);
|
setTimeout(run, 500);
|
||||||
|
|
||||||
function init() {
|
function run() {
|
||||||
if (uninstalled) {
|
const nodeRequire = window.require;
|
||||||
return;
|
|
||||||
}
|
const http = nodeRequire('http');
|
||||||
server = http.createServer((req, res) => {
|
const crypto = nodeRequire('crypto');
|
||||||
if (req.method === 'POST') {
|
const fs = nodeRequire('fs');
|
||||||
const body = [];
|
const path = nodeRequire('path');
|
||||||
req.on('data', data => body.push(data));
|
const electron = nodeRequire('electron');
|
||||||
req.on('end', () => {
|
|
||||||
const postData = Buffer.concat(body).toString();
|
const AppModel = require('models/app-model');
|
||||||
if (DebugMode) {
|
const AutoTypeFilter = require('auto-type/auto-type-filter');
|
||||||
logger.debug('< ' + postData);
|
const Logger = require('util/logger');
|
||||||
}
|
const Alerts = require('comp/alerts');
|
||||||
new RequestContext(postData)
|
const Generator = require('util/password-generator');
|
||||||
.handle()
|
const GeneratorPresets = require('comp/generator-presets');
|
||||||
.then(response => {
|
|
||||||
if (DebugMode) {
|
const Version = '1.8.4.2';
|
||||||
logger.debug('> ' + response);
|
const DebugMode = true;
|
||||||
}
|
|
||||||
res.statusCode = 200;
|
const keys = {};
|
||||||
res.setHeader('Content-Type', 'application/json');
|
const logger = new Logger('keewebhttp');
|
||||||
res.end(response);
|
|
||||||
});
|
startServer();
|
||||||
});
|
|
||||||
} else {
|
function startServer() {
|
||||||
res.statusCode = 200;
|
|
||||||
res.setHeader('Content-Type', 'text/plain');
|
|
||||||
res.end('Hey dude, you should POST here!');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const port = 19455;
|
|
||||||
const hostname = '127.0.0.1';
|
|
||||||
server.listen(port, hostname, () => {
|
|
||||||
if (uninstalled) {
|
if (uninstalled) {
|
||||||
server.close();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.debug(`Server running at http://${hostname}:${port}/`);
|
server = http.createServer((req, res) => {
|
||||||
});
|
if (req.method === 'POST') {
|
||||||
server.on('connection', function(conn) {
|
const body = [];
|
||||||
const key = conn.remoteAddress + ':' + conn.remotePort;
|
req.on('data', data => body.push(data));
|
||||||
server.conn[key] = conn;
|
req.on('end', () => {
|
||||||
conn.on('close', () => {
|
const postData = Buffer.concat(body).toString();
|
||||||
if (server) {
|
if (DebugMode) {
|
||||||
delete server.conn[key];
|
logger.debug('< ' + postData);
|
||||||
}
|
}
|
||||||
});
|
new RequestContext(postData)
|
||||||
});
|
.handle()
|
||||||
server.conn = {};
|
.then(response => {
|
||||||
}
|
if (DebugMode) {
|
||||||
|
logger.debug('> ' + response);
|
||||||
class RequestContext {
|
}
|
||||||
constructor(postData) {
|
res.statusCode = 200;
|
||||||
this.postData = postData;
|
res.setHeader('Content-Type', 'application/json');
|
||||||
}
|
res.end(response);
|
||||||
|
});
|
||||||
handle() {
|
|
||||||
let result;
|
|
||||||
try {
|
|
||||||
this.req = JSON.parse(this.postData);
|
|
||||||
const response = this.execute() || this.resp;
|
|
||||||
if (response instanceof Promise) {
|
|
||||||
result = response.catch(e => {
|
|
||||||
return this.makeError(e);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
result = Promise.resolve(response);
|
res.statusCode = 200;
|
||||||
|
res.setHeader('Content-Type', 'text/plain');
|
||||||
|
res.end('Hey dude, you should POST here!');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
result = Promise.resolve(this.makeError(e));
|
|
||||||
}
|
|
||||||
return result.then(res => JSON.stringify(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
execute() {
|
|
||||||
switch (this.req.RequestType) {
|
|
||||||
case 'test-associate':
|
|
||||||
return this.testAssociate();
|
|
||||||
case 'associate':
|
|
||||||
return this.associate();
|
|
||||||
case 'get-logins':
|
|
||||||
return this.getLogins({});
|
|
||||||
case 'get-logins-count':
|
|
||||||
return this.getLogins({ onlyCount: true });
|
|
||||||
case 'get-all-logins':
|
|
||||||
return this.getLogins({ all: true });
|
|
||||||
case 'set-login':
|
|
||||||
return this.setLogin();
|
|
||||||
case 'generate-password':
|
|
||||||
return this.generatePassword();
|
|
||||||
default:
|
|
||||||
throw 'Not implemented';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
makeError(e) {
|
|
||||||
logger.error('handleRequest error', e);
|
|
||||||
return {
|
|
||||||
Error: e ? e.toString() : '',
|
|
||||||
Success: false,
|
|
||||||
RequestType: this.req ? this.req.RequestType : '',
|
|
||||||
Version: Version
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt(value) {
|
|
||||||
if (!this.aesKey) {
|
|
||||||
throw 'No key';
|
|
||||||
}
|
|
||||||
if (!this.req.Nonce) {
|
|
||||||
throw 'No nonce';
|
|
||||||
}
|
|
||||||
const key = Buffer.from(this.aesKey, 'base64');
|
|
||||||
const nonce = Buffer.from(this.req.Nonce, 'base64');
|
|
||||||
const decipher = crypto.createDecipheriv('aes-256-cbc', key, nonce);
|
|
||||||
return Buffer.concat([decipher.update(value, 'base64'), decipher.final()]).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
encrypt(value) {
|
|
||||||
if (!this.aesKey) {
|
|
||||||
throw 'No key';
|
|
||||||
}
|
|
||||||
if (!this.resp || !this.resp.Nonce) {
|
|
||||||
throw 'No nonce';
|
|
||||||
}
|
|
||||||
const key = Buffer.from(this.aesKey, 'base64');
|
|
||||||
const nonce = Buffer.from(this.resp.Nonce, 'base64');
|
|
||||||
const cipher = crypto.createCipheriv('aes-256-cbc', key, nonce);
|
|
||||||
return Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]).toString('base64');
|
|
||||||
}
|
|
||||||
|
|
||||||
getKeyById() {
|
|
||||||
return keys[this.req.Id];
|
|
||||||
}
|
|
||||||
|
|
||||||
saveKeyWithId() {
|
|
||||||
keys[this.req.Id] = this.req.Key;
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyRequest() {
|
|
||||||
if (!this.req.Verifier) {
|
|
||||||
throw 'No verifier';
|
|
||||||
}
|
|
||||||
if (!this.aesKey) {
|
|
||||||
this.aesKey = this.getKeyById();
|
|
||||||
}
|
|
||||||
const decrypted = this.decrypt(this.req.Verifier);
|
|
||||||
if (decrypted !== this.req.Nonce) {
|
|
||||||
throw 'Bad signature';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createResponse() {
|
|
||||||
const resp = {
|
|
||||||
Success: true,
|
|
||||||
Nonce: '',
|
|
||||||
Verifier: '',
|
|
||||||
Version: Version,
|
|
||||||
RequestType: this.req.RequestType
|
|
||||||
};
|
|
||||||
if (this.req.Id && keys[this.req.Id]) {
|
|
||||||
const key = Buffer.from(keys[this.req.Id], 'base64');
|
|
||||||
const nonce = crypto.randomBytes(16);
|
|
||||||
const cipher = crypto.createCipheriv('aes-256-cbc', key, nonce);
|
|
||||||
const encrypted = Buffer.concat([cipher.update(nonce.toString('base64'), 'utf8'), cipher.final()]).toString('base64');
|
|
||||||
resp.Id = this.req.Id;
|
|
||||||
resp.Nonce = nonce.toString('base64');
|
|
||||||
resp.Verifier = encrypted;
|
|
||||||
}
|
|
||||||
this.resp = resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
testAssociate() {
|
|
||||||
if (!this.req.Id) {
|
|
||||||
return this.makeError('');
|
|
||||||
}
|
|
||||||
this.verifyRequest();
|
|
||||||
this.createResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
associate() {
|
|
||||||
if (this.req.Id) {
|
|
||||||
throw 'Id not expected';
|
|
||||||
}
|
|
||||||
if (!this.req.Key) {
|
|
||||||
throw 'No key';
|
|
||||||
}
|
|
||||||
this.aesKey = this.req.Key;
|
|
||||||
this.verifyRequest();
|
|
||||||
electron.remote.app.getMainWindow().focus();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
Alerts.yesno({
|
|
||||||
header: 'External Connection',
|
|
||||||
body: 'Some app is trying to connect to KeeWeb. If you are setting up your plugin, please allow the connection. Otherwise, click No.',
|
|
||||||
success: () => { resolve(); },
|
|
||||||
cancel: () => { reject('Rejected by user'); }
|
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
this.req.Id = 'KeeWeb_' + new Date().toISOString() + '_' + crypto.randomBytes(16).toString('hex');
|
|
||||||
this.saveKeyWithId();
|
|
||||||
this.createResponse();
|
|
||||||
return this.resp;
|
|
||||||
});
|
});
|
||||||
|
const port = 19455;
|
||||||
|
const hostname = '127.0.0.1';
|
||||||
|
server.listen(port, hostname, () => {
|
||||||
|
if (uninstalled) {
|
||||||
|
server.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.debug(`Server running at http://${hostname}:${port}/`);
|
||||||
|
});
|
||||||
|
server.on('connection', function (conn) {
|
||||||
|
const key = conn.remoteAddress + ':' + conn.remotePort;
|
||||||
|
server.conn[key] = conn;
|
||||||
|
conn.on('close', () => {
|
||||||
|
if (server) {
|
||||||
|
delete server.conn[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
server.conn = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
getLogins(config) {
|
class RequestContext {
|
||||||
this.verifyRequest();
|
constructor(postData) {
|
||||||
if (!this.req.Url) {
|
this.postData = postData;
|
||||||
throw 'No url';
|
|
||||||
}
|
}
|
||||||
const url = this.decrypt(this.req.Url);
|
|
||||||
logger.debug('get-logins', url);
|
handle() {
|
||||||
this.createResponse();
|
let result;
|
||||||
const filter = new AutoTypeFilter({ url }, AutoType.appModel);
|
try {
|
||||||
const entries = filter.getEntries();
|
this.req = JSON.parse(this.postData);
|
||||||
this.resp.Count = entries.length;
|
const response = this.execute() || this.resp;
|
||||||
if (!config.onlyCount) {
|
if (response instanceof Promise) {
|
||||||
this.resp.Entries = entries.map(entry => ({
|
result = response.catch(e => {
|
||||||
Login: entry.user ? this.encrypt(entry.user) : '',
|
return this.makeError(e);
|
||||||
Name: entry.title ? this.encrypt(entry.title) : '',
|
});
|
||||||
Password: entry.password ? this.encrypt(entry.password.getText()) : '',
|
} else {
|
||||||
|
result = Promise.resolve(response);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
result = Promise.resolve(this.makeError(e));
|
||||||
|
}
|
||||||
|
return result.then(res => JSON.stringify(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
execute() {
|
||||||
|
switch (this.req.RequestType) {
|
||||||
|
case 'test-associate':
|
||||||
|
return this.testAssociate();
|
||||||
|
case 'associate':
|
||||||
|
return this.associate();
|
||||||
|
case 'get-logins':
|
||||||
|
return this.getLogins({});
|
||||||
|
case 'get-logins-count':
|
||||||
|
return this.getLogins({onlyCount: true});
|
||||||
|
case 'get-all-logins':
|
||||||
|
return this.getLogins({all: true});
|
||||||
|
case 'set-login':
|
||||||
|
return this.setLogin();
|
||||||
|
case 'generate-password':
|
||||||
|
return this.generatePassword();
|
||||||
|
default:
|
||||||
|
throw 'Not implemented';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeError(e, skipLog) {
|
||||||
|
if (!skipLog) {
|
||||||
|
logger.error('handleRequest error', e);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
Error: e ? e.toString() : '',
|
||||||
|
Success: false,
|
||||||
|
RequestType: this.req ? this.req.RequestType : '',
|
||||||
|
Version: Version
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypt(value) {
|
||||||
|
if (!this.aesKey) {
|
||||||
|
throw 'No key';
|
||||||
|
}
|
||||||
|
if (!this.req.Nonce) {
|
||||||
|
throw 'No nonce';
|
||||||
|
}
|
||||||
|
const key = Buffer.from(this.aesKey, 'base64');
|
||||||
|
const nonce = Buffer.from(this.req.Nonce, 'base64');
|
||||||
|
const decipher = crypto.createDecipheriv('aes-256-cbc', key, nonce);
|
||||||
|
return Buffer.concat([decipher.update(value, 'base64'), decipher.final()]).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt(value) {
|
||||||
|
if (!this.aesKey) {
|
||||||
|
throw 'No aes key';
|
||||||
|
}
|
||||||
|
if (!this.resp || !this.resp.Nonce) {
|
||||||
|
throw 'No nonce';
|
||||||
|
}
|
||||||
|
const key = Buffer.from(this.aesKey, 'base64');
|
||||||
|
const nonce = Buffer.from(this.resp.Nonce, 'base64');
|
||||||
|
const cipher = crypto.createCipheriv('aes-256-cbc', key, nonce);
|
||||||
|
let data;
|
||||||
|
if (value.isProtected) {
|
||||||
|
const binaryData = value.getBinary();
|
||||||
|
data = Buffer.from(binaryData);
|
||||||
|
binaryData.fill(0);
|
||||||
|
} else {
|
||||||
|
data = Buffer.from(value, 'utf8');
|
||||||
|
}
|
||||||
|
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]).toString('base64');
|
||||||
|
data.fill(0);
|
||||||
|
return encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
getKeyById() {
|
||||||
|
// TODO
|
||||||
|
return keys[this.req.Id];
|
||||||
|
}
|
||||||
|
|
||||||
|
saveKeyWithId() {
|
||||||
|
keys[this.req.Id] = this.req.Key;
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyRequest() {
|
||||||
|
if (!this.req.Verifier) {
|
||||||
|
throw 'No verifier';
|
||||||
|
}
|
||||||
|
if (!this.aesKey) {
|
||||||
|
this.aesKey = this.getKeyById();
|
||||||
|
}
|
||||||
|
const decrypted = this.decrypt(this.req.Verifier);
|
||||||
|
if (decrypted !== this.req.Nonce) {
|
||||||
|
throw 'Bad signature';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createResponse() {
|
||||||
|
const resp = {
|
||||||
|
Success: true,
|
||||||
|
Nonce: '',
|
||||||
|
Verifier: '',
|
||||||
|
Version: Version,
|
||||||
|
RequestType: this.req.RequestType
|
||||||
|
};
|
||||||
|
if (this.req.Id && keys[this.req.Id]) {
|
||||||
|
const key = Buffer.from(keys[this.req.Id], 'base64');
|
||||||
|
const nonce = crypto.randomBytes(16);
|
||||||
|
const cipher = crypto.createCipheriv('aes-256-cbc', key, nonce);
|
||||||
|
const encrypted = Buffer.concat([cipher.update(nonce.toString('base64'), 'utf8'), cipher.final()]).toString('base64');
|
||||||
|
resp.Id = this.req.Id;
|
||||||
|
resp.Nonce = nonce.toString('base64');
|
||||||
|
resp.Verifier = encrypted;
|
||||||
|
}
|
||||||
|
this.resp = resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
testAssociate() {
|
||||||
|
if (!this.req.Id) {
|
||||||
|
return this.makeError('', true);
|
||||||
|
}
|
||||||
|
if (!this.getKeyById(this.req.Id)) {
|
||||||
|
return this.makeError('Unknown Id', true);
|
||||||
|
}
|
||||||
|
this.verifyRequest();
|
||||||
|
this.createResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
associate() {
|
||||||
|
if (this.req.Id) {
|
||||||
|
throw 'Id not expected';
|
||||||
|
}
|
||||||
|
if (!this.req.Key) {
|
||||||
|
throw 'No request key';
|
||||||
|
}
|
||||||
|
this.aesKey = this.req.Key;
|
||||||
|
this.verifyRequest();
|
||||||
|
electron.remote.app.getMainWindow().focus();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Alerts.yesno({
|
||||||
|
header: 'External Connection',
|
||||||
|
body: 'Some app is trying to connect to KeeWeb. If you are setting up your plugin, please allow the connection. Otherwise, click No.',
|
||||||
|
success: () => {
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
cancel: () => {
|
||||||
|
reject('Rejected by user');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
this.req.Id = 'KeeWeb_' + new Date().toISOString() + '_' + crypto.randomBytes(16).toString('hex');
|
||||||
|
logger.info('associate: ', this.req.Id);
|
||||||
|
this.saveKeyWithId();
|
||||||
|
this.createResponse();
|
||||||
|
return this.resp;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getLogins(config) {
|
||||||
|
this.verifyRequest();
|
||||||
|
if (!this.req.Url && !config.all) {
|
||||||
|
throw 'No url';
|
||||||
|
}
|
||||||
|
const url = this.req.Url ? this.decrypt(this.req.Url) : '';
|
||||||
|
this.createResponse();
|
||||||
|
const filter = new AutoTypeFilter({url}, AppModel.instance);
|
||||||
|
if (config.all) {
|
||||||
|
filter.ignoreWindowInfo = true;
|
||||||
|
}
|
||||||
|
const entries = filter.getEntries();
|
||||||
|
this.resp.Count = entries.length;
|
||||||
|
logger.info(`getLogins(${url}): ${this.resp.Count}`);
|
||||||
|
if (!config.onlyCount) {
|
||||||
|
this.resp.Entries = entries.map(entry => ({
|
||||||
|
Login: entry.user ? this.encrypt(entry.user) : '',
|
||||||
|
Name: entry.title ? this.encrypt(entry.title) : '',
|
||||||
|
Password: entry.password ? this.encrypt(entry.password) : '',
|
||||||
|
StringFields: null,
|
||||||
|
Uuid: this.encrypt(entry.id)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLogin() {
|
||||||
|
this.verifyRequest();
|
||||||
|
if (!this.req.Url || !this.req.Login || !this.req.Password) {
|
||||||
|
throw 'Invalid request';
|
||||||
|
}
|
||||||
|
const url = this.decrypt(this.req.Url);
|
||||||
|
const login = this.decrypt(this.req.Login);
|
||||||
|
const password = this.decrypt(this.req.Password);
|
||||||
|
logger.info('setLogin', url, login, password);
|
||||||
|
this.createResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
generatePassword() {
|
||||||
|
this.verifyRequest();
|
||||||
|
this.createResponse();
|
||||||
|
const preset = GeneratorPresets.all.filter(p => p.default)[0] || GeneratorPresets.defaultPreset;
|
||||||
|
const password = Generator.generate(preset);
|
||||||
|
this.resp.Count = 1;
|
||||||
|
this.resp.Entries = [{
|
||||||
|
Login: '',
|
||||||
|
Name: '',
|
||||||
|
Password: this.encrypt(password),
|
||||||
StringFields: null,
|
StringFields: null,
|
||||||
Uuid: this.encrypt(entry.id)
|
Uuid: ''
|
||||||
}));
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLogin() {
|
|
||||||
this.verifyRequest();
|
|
||||||
if (!this.req.Url || !this.req.Login || !this.req.Password) {
|
|
||||||
throw 'Invalid request';
|
|
||||||
}
|
|
||||||
const url = this.decrypt(this.req.Url);
|
|
||||||
const login = this.decrypt(this.req.Login);
|
|
||||||
const password = this.decrypt(this.req.Password);
|
|
||||||
logger.debug('set-login', url, login, password);
|
|
||||||
this.createResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
generatePassword() {
|
|
||||||
this.verifyRequest();
|
|
||||||
this.createResponse();
|
|
||||||
this.resp.Count = 1;
|
|
||||||
this.resp.Entries = [{
|
|
||||||
Login: '',
|
|
||||||
Name: '',
|
|
||||||
Password: this.encrypt('I am generated password: ' + new Date()),
|
|
||||||
StringFields: null,
|
|
||||||
Uuid: ''
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.uninstall = function() {
|
module.exports.uninstall = function() {
|
||||||
|
|
Loading…
Reference in New Issue