blockstack
Version:
The Blockstack Javascript library for authentication, identity, and storage.
1,041 lines (878 loc) • 44.1 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
exports.runStorageTests = runStorageTests;
var _tape = require('tape');
var _tape2 = _interopRequireDefault(_tape);
var _fetchMock = require('fetch-mock');
var _fetchMock2 = _interopRequireDefault(_fetchMock);
var _proxyquire18 = require('proxyquire');
var _proxyquire19 = _interopRequireDefault(_proxyquire18);
var _sinon = require('sinon');
var _sinon2 = _interopRequireDefault(_sinon);
var _jsontokens = require('jsontokens');
var _hub = require('../../../lib/storage/hub');
var _storage = require('../../../lib/storage');
var _keys = require('../../../lib/keys');
var _lib = require('../../../lib');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// class LocalStorage {
// constructor() {
// this.data = {}
// }
//
// setItem(k, v) {
// this.data[k] = v
// }
//
// removeItem(k) {
// delete this.data[k]
// }
//
// getItem(k) {
// return this.data[k]
// }
// }
// const localStorage = new LocalStorage()
// global.localStorage = localStorage
// global.window = {}
// global.window.localStorage = localStorage
// global.window.location = {}
// global.window.location.origin = 'https://myApp.blockstack.org'
function runStorageTests() {
(0, _tape2.default)('getFile unencrypted, unsigned', function (t) {
t.plan(2);
var path = 'file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json';
var fileContent = { test: 'test' };
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var getFullReadUrl = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var _proxyquire = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl: getFullReadUrl }
}),
getFileImpl = _proxyquire.getFileImpl;
_fetchMock2.default.get(fullReadUrl, fileContent);
var options = { decrypt: false };
getFileImpl(blockstack, path, options).then(function (file) {
t.ok(file, 'Returns file content');
t.same(JSON.parse(file), fileContent);
});
});
(0, _tape2.default)('getFile unencrypted, unsigned - multi-reader', function (t) {
t.plan(6);
var path = 'file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:8080');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json';
var fileContent = { test: 'test' };
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var getFullReadUrl2 = _sinon2.default.stub().resolves(fullReadUrl);
var _proxyquire2 = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl2: getFullReadUrl2 }
}),
getFileImpl = _proxyquire2.getFileImpl;
_fetchMock2.default.get(fullReadUrl, fileContent);
var nameLookupUrl = 'https://core.blockstack.org/v1/names/yukan.id';
var nameRecord = {
status: 'registered',
zonefile: '$ORIGIN yukan.id\n$TTL 3600\n_http._tcp URI 10 1 "https://gaia.blockstack.org/hub/16zVUoP7f15nfTiHw2UNiX8NT5SWYqwNv3/0/profile.json"\n',
expire_block: 581432,
blockchain: 'bitcoin',
last_txid: 'f7fa811518566b1914a098c3bd61a810aee56390815bd608490b0860ac1b5b4d',
address: '16zVUoP7f15nfTiHw2UNiX8NT5SWYqwNv3',
zonefile_hash: '98f42e11026d42d394b3424d4d7f0cccd6f376e2'
};
var nameRecordContent = JSON.stringify(nameRecord);
_fetchMock2.default.get(nameLookupUrl, nameRecordContent);
var profileUrl = 'https://gaia.blockstack.org/hub/16zVUoP7f15nfTiHw2UNiX8NT5SWYqwNv3/0/profile.json';
/* eslint-disable */
var profileContent = [{
'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiJjNDhmOTQ0OC1hMGZlLTRiOWUtOWQ2YS1mYzA5MzhjOGUyNzAiLCJpYXQiOiIyMDE4LTAxLTA4VDE4OjIyOjI0Ljc5NloiLCJleHAiOiIyMDE5LTAxLTA4VDE4OjIyOjI0Ljc5NloiLCJzdWJqZWN0Ijp7InB1YmxpY0tleSI6IjAyNDg3YTkxY2Q5NjZmYWVjZWUyYWVmM2ZkZTM3MjgwOWI0NmEzNmVlMTkyNDhjMDFmNzJiNjQ1ZjQ0Y2VmMmUyYyJ9LCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDI0ODdhOTFjZDk2NmZhZWNlZTJhZWYzZmRlMzcyODA5YjQ2YTM2ZWUxOTI0OGMwMWY3MmI2NDVmNDRjZWYyZTJjIn0sImNsYWltIjp7IkB0eXBlIjoiUGVyc29uIiwiQGNvbnRleHQiOiJodHRwOi8vc2NoZW1hLm9yZyIsImltYWdlIjpbeyJAdHlwZSI6IkltYWdlT2JqZWN0IiwibmFtZSI6ImF2YXRhciIsImNvbnRlbnRVcmwiOiJodHRwczovL3d3dy5kcm9wYm94LmNvbS9zL2oxaDBrdHMwbTdhYWRpcC9hdmF0YXItMD9kbD0xIn1dLCJnaXZlbk5hbWUiOiIiLCJmYW1pbHlOYW1lIjoiIiwiZGVzY3JpcHRpb24iOiIiLCJhY2NvdW50IjpbeyJAdHlwZSI6IkFjY291bnQiLCJwbGFjZWhvbGRlciI6ZmFsc2UsInNlcnZpY2UiOiJoYWNrZXJOZXdzIiwiaWRlbnRpZmllciI6Inl1a2FubCIsInByb29mVHlwZSI6Imh0dHAiLCJwcm9vZlVybCI6Imh0dHBzOi8vbmV3cy55Y29tYmluYXRvci5jb20vdXNlcj9pZD15dWthbmwifSx7IkB0eXBlIjoiQWNjb3VudCIsInBsYWNlaG9sZGVyIjpmYWxzZSwic2VydmljZSI6ImdpdGh1YiIsImlkZW50aWZpZXIiOiJ5a25sIiwicHJvb2ZUeXBlIjoiaHR0cCIsInByb29mVXJsIjoiaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20veWtubC8xZjcwMThiOThmNzE2ZjAxNWE2Y2Y0NGZkYTA4MDZkNyJ9LHsiQHR5cGUiOiJBY2NvdW50IiwicGxhY2Vob2xkZXIiOmZhbHNlLCJzZXJ2aWNlIjoidHdpdHRlciIsImlkZW50aWZpZXIiOiJ5dWthbmwiLCJwcm9vZlR5cGUiOiJodHRwIiwicHJvb2ZVcmwiOiJodHRwczovL3R3aXR0ZXIuY29tL3l1a2FuTC9zdGF0dXMvOTE2NzQwNzQ5MjM2MTAxMTIwIn1dLCJuYW1lIjoiS2VuIExpYW8iLCJhcHBzIjp7Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCI6Imh0dHBzOi8vZ2FpYS5ibG9ja3N0YWNrLm9yZy9odWIvMUREVXFmS3RRZ1lOdDcyMnd1QjRaMmZQQzdhaU5HUWE1Ui8ifX19.UyQNZ02kBFHEovbwiGaS-VQd57w9kcwn1Nt3QbW3afEMArg1OndmeplB7lzjMuRCLAi-88lkpQLkFw7LwKZ31Q',
'decodedToken': {
'header': {
'typ': 'JWT',
'alg': 'ES256K'
},
'payload': {
'jti': 'c48f9448-a0fe-4b9e-9d6a-fc0938c8e270',
'iat': '2018-01-08T18:22:24.796Z',
'exp': '2019-01-08T18:22:24.796Z',
'subject': {
'publicKey': '02487a91cd966faecee2aef3fde372809b46a36ee19248c01f72b645f44cef2e2c'
},
'issuer': {
'publicKey': '02487a91cd966faecee2aef3fde372809b46a36ee19248c01f72b645f44cef2e2c'
},
'claim': {
'@type': 'Person',
'@context': 'http://schema.org',
'image': [{
'@type': 'ImageObject',
'name': 'avatar',
'contentUrl': 'https://www.dropbox.com/s/j1h0kts0m7aadip/avatar-0?dl=1'
}],
'givenName': '',
'familyName': '',
'description': '',
'account': [{
'@type': 'Account',
'placeholder': false,
'service': 'hackerNews',
'identifier': 'yukanl',
'proofType': 'http',
'proofUrl': 'https://news.ycombinator.com/user?id=yukanl'
}, {
'@type': 'Account',
'placeholder': false,
'service': 'github',
'identifier': 'yknl',
'proofType': 'http',
'proofUrl': 'https://gist.github.com/yknl/1f7018b98f716f015a6cf44fda0806d7'
}, {
'@type': 'Account',
'placeholder': false,
'service': 'twitter',
'identifier': 'yukanl',
'proofType': 'http',
'proofUrl': 'https://twitter.com/yukanL/status/916740749236101120'
}],
'name': 'Ken Liao',
'apps': {
'http://localhost:8080': 'https://gaia.blockstack.org/hub/1DDUqfKtQgYNt722wuB4Z2fPC7aiNGQa5R/'
}
}
},
'signature': 'UyQNZ02kBFHEovbwiGaS-VQd57w9kcwn1Nt3QbW3afEMArg1OndmeplB7lzjMuRCLAi-88lkpQLkFw7LwKZ31Q'
}
}];
/* eslint-enable */
_fetchMock2.default.get(profileUrl, profileContent);
var fileUrl = 'https://gaia.blockstack.org/hub/1DDUqfKtQgYNt722wuB4Z2fPC7aiNGQa5R/file.json';
var fileContents = JSON.stringify({ key: 'value' });
_fetchMock2.default.get(fileUrl, fileContents);
var options = {
username: 'yukan.id',
app: 'http://localhost:8080',
decrypt: false
};
getFileImpl(blockstack, path, options).then(function (file) {
t.ok(file, 'Returns file content');
t.same(JSON.parse(file), JSON.parse(fileContents));
});
var optionsNameLookupUrl = {
username: 'yukan.id',
app: 'http://localhost:8080',
zoneFileLookupURL: 'https://potato/v1/names',
decrypt: false
};
_fetchMock2.default.get('https://potato/v1/names/yukan.id', nameRecordContent);
getFileImpl(blockstack, path, optionsNameLookupUrl).then(function (file) {
t.ok(file, 'Returns file content');
t.same(JSON.parse(file), JSON.parse(fileContents));
});
var optionsNoApp = {
username: 'yukan.id',
decrypt: false
};
getFileImpl(blockstack, path, optionsNoApp).then(function (file) {
t.ok(file, 'Returns file content');
t.same(JSON.parse(file), JSON.parse(fileContents));
});
});
(0, _tape2.default)('encrypt & decrypt content', function (t) {
t.plan(2);
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set private key for testing
};var content = 'yellowsubmarine';
var ciphertext = blockstack.encryptContent(content);
t.ok(ciphertext);
var deciphered = blockstack.decryptContent(ciphertext);
t.equal(content, deciphered);
});
(0, _tape2.default)('encrypt & decrypt content -- specify key', function (t) {
t.plan(2);
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var privateKey = '896adae13a1bf88db0b2ec94339b62382ec6f34cd7e2ff8abae7ec271e05f9d8';
var publicKey = (0, _keys.getPublicKeyFromPrivate)(privateKey);
var content = 'we-all-live-in-a-yellow-submarine';
var ciphertext = blockstack.encryptContent(content, { publicKey: publicKey });
t.ok(ciphertext);
var deciphered = blockstack.decryptContent(ciphertext, { privateKey: privateKey });
t.equal(content, deciphered);
});
(0, _tape2.default)('putFile unencrypted, not signed', function (t) {
t.plan(1);
var path = 'file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json';
var fileContent = { test: 'test' };
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var uploadToGaiaHub = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var _proxyquire3 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, uploadToGaiaHub: uploadToGaiaHub }
}),
putFileImpl = _proxyquire3.putFileImpl;
var options = { encrypt: false };
putFileImpl(blockstack, path, fileContent, options).then(function (publicURL) {
t.ok(publicURL, fullReadUrl);
});
});
(0, _tape2.default)('putFile & getFile unencrypted, not signed, with contentType', function (t) {
t.plan(3);
var path = 'file.html';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.html';
var fileContent = '<!DOCTYPE html><html><head><title>Title</title></head><body>Blockstack</body></html>';
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var uploadToGaiaHub = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var getFullReadUrl = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var _proxyquire4 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, uploadToGaiaHub: uploadToGaiaHub }
}),
putFileImpl = _proxyquire4.putFileImpl;
var _proxyquire5 = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl: getFullReadUrl }
}),
getFileImpl = _proxyquire5.getFileImpl;
var config = {
status: 200,
body: fileContent,
headers: { 'Content-Type': 'text/html' }
};
_fetchMock2.default.get(fullReadUrl, config);
var options = { encrypt: false, contentType: 'text/html' };
putFileImpl(blockstack, path, fileContent, options).then(function (publicURL) {
t.ok(publicURL, fullReadUrl);
}).then(function () {
var decryptOptions = { decrypt: false };
getFileImpl(blockstack, path, decryptOptions).then(function (readContent) {
t.equal(readContent, fileContent);
t.ok(typeof readContent === 'string');
});
});
});
(0, _tape2.default)('putFile & getFile encrypted, not signed', function (t) {
t.plan(2);
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set private key for testing
};var path = 'file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8A/file.json';
var fileContent = JSON.stringify({ test: 'test' });
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var uploadToGaiaHub = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var getFullReadUrl = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var _proxyquire6 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, uploadToGaiaHub: uploadToGaiaHub }
}),
putFileImpl = _proxyquire6.putFileImpl;
var _proxyquire7 = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl: getFullReadUrl }
}),
getFileImpl = _proxyquire7.getFileImpl;
_fetchMock2.default.get(fullReadUrl, (0, _storage.encryptContentImpl)(blockstack, fileContent));
var encryptOptions = { encrypt: true };
var decryptOptions = { decrypt: true
// put and encrypt the file
};putFileImpl(blockstack, path, fileContent, encryptOptions).then(function (publicURL) {
t.ok(publicURL, fullReadUrl);
}).then(function () {
// read and decrypt the file
getFileImpl(blockstack, path, decryptOptions).then(function (readContent) {
t.equal(readContent, fileContent);
// put back whatever was inside before
});
});
});
(0, _tape2.default)('putFile encrypt/no-sign using specifying public key & getFile decrypt', function (t) {
t.plan(2);
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var publicKey = (0, _keys.getPublicKeyFromPrivate)(privateKey);
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set private key for testing
};var path = 'file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8A/file.json';
var fileContent = JSON.stringify({ test: 'test' });
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var uploadToGaiaHub = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var getFullReadUrl = _sinon2.default.stub().resolves(fullReadUrl); // eslint-disable-line no-shadow
var _proxyquire8 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, uploadToGaiaHub: uploadToGaiaHub }
}),
putFileImpl = _proxyquire8.putFileImpl;
var _proxyquire9 = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl: getFullReadUrl }
}),
getFileImpl = _proxyquire9.getFileImpl;
_fetchMock2.default.get(fullReadUrl, (0, _storage.encryptContentImpl)(blockstack, fileContent));
var encryptOptions = { encrypt: publicKey };
var decryptOptions = { decrypt: true
// put and encrypt the file
};putFileImpl(blockstack, path, fileContent, encryptOptions).then(function (publicURL) {
t.ok(publicURL, fullReadUrl);
}).then(function () {
// read and decrypt the file
getFileImpl(blockstack, path, decryptOptions).then(function (readContent) {
t.equal(readContent, fileContent);
});
});
});
(0, _tape2.default)('putFile & getFile encrypted, signed', function (t) {
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set private key for testing
};var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack2.org/hub/'
};
var readPrefix = 'https://gaia.testblockstack8.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U';
var fullReadUrl = readPrefix + '/file.json';
var urlBadPK = readPrefix + '/badPK.json';
var urlBadSig = readPrefix + '/badSig.json';
var fileContent = JSON.stringify({ test: 'test' });
var badPK = '0288580b020800f421d746f738b221d384f098e911b81939d8c94df89e74cba776';
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var putFiledContents = '';
var uploadToGaiaHub = _sinon2.default.stub().callsFake( // eslint-disable-line no-shadow
function (fname, contents) {
putFiledContents = contents;
return Promise.resolve(readPrefix + '/' + fname);
});
var getFullReadUrl = _sinon2.default.stub().callsFake( // eslint-disable-line no-shadow
function (path) {
return Promise.resolve(readPrefix + '/' + path);
});
var lookupProfile = _sinon2.default.stub().callsFake(function (username) {
t.equal(username, 'applejacks.id', 'Unexpected user lookup request');
return Promise.resolve({ apps: { origin: readPrefix } });
});
var _proxyquire10 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, uploadToGaiaHub: uploadToGaiaHub }
}),
putFileImpl = _proxyquire10.putFileImpl;
var _proxyquire11 = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl: getFullReadUrl },
'../profiles': { lookupProfile: lookupProfile }
}),
getFileImpl = _proxyquire11.getFileImpl;
var encryptOptions = { encrypt: true, sign: true };
var decryptOptions = { decrypt: true, verify: true
// put and encrypt the file
};putFileImpl(blockstack, 'doesnt-matter.json', fileContent, encryptOptions).then(function (publicURL) {
t.ok(publicURL, fullReadUrl);
_fetchMock2.default.get(fullReadUrl, putFiledContents);
var contentsObj = JSON.parse(putFiledContents);
_fetchMock2.default.get(urlBadPK, JSON.stringify({
signature: contentsObj.signature,
publicKey: badPK,
cipherText: contentsObj.cipherText
}));
_fetchMock2.default.get(urlBadSig, JSON.stringify({
signature: contentsObj.signature,
publicKey: contentsObj.publicKey,
cipherText: 'potato potato potato'
}));
}).then(function () {
return getFileImpl(blockstack, 'file.json', decryptOptions).then(function (readContent) {
t.equal(readContent, fileContent);
});
}).then(function () {
return getFileImpl(blockstack, 'file.json', {
decrypt: true,
verify: true,
username: 'applejacks.id',
app: 'origin'
}).then(function (readContent) {
t.equal(readContent, fileContent);
});
}).then(function () {
return getFileImpl(blockstack, 'badPK.json', decryptOptions).then(function () {
return t.true(false, 'Should not successfully decrypt file');
}).catch(function (err) {
return t.ok(err.message.indexOf('doesn\'t match gaia address') >= 0, 'Should fail with complaint about mismatch PK: ' + err.message);
});
}).then(function () {
return getFileImpl(blockstack, 'badPK.json', {
decrypt: true,
verify: true,
username: 'applejacks.id',
app: 'origin'
}).then(function () {
return t.true(false, 'Should not successfully decrypt file');
}).catch(function (err) {
return t.ok(err.message.indexOf('doesn\'t match gaia address') >= 0, 'Should fail with complaint about mismatch PK: ' + err.message);
});
}).then(function () {
return getFileImpl(blockstack, 'badSig.json', decryptOptions).then(function () {
return t.true(false, 'Should not successfully decrypt file');
}).catch(function (err) {
return t.ok(err.message.indexOf('do not match ECDSA') >= 0, 'Should fail with complaint about bad signature');
});
}).catch(function (err) {
return console.log(err.stack);
}).then(function () {
t.end();
});
});
(0, _tape2.default)('putFile & getFile unencrypted, signed', function (t) {
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set private key for testing
};var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack2.org/hub/'
};
var readPrefix = 'https://gaia.testblockstack4.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U';
var goodPath = 'file.json';
var badPKPath = 'badPK.json';
var badSigPath = 'badSig.json';
var noSigPath = 'noSig.json';
var fileContent = JSON.stringify({ test: 'test' });
var badPK = '0288580b020800f421d746f738b221d384f098e911b81939d8c94df89e74cba776';
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var putFiledContents = [];
var pathToReadUrl = function pathToReadUrl(fname) {
return readPrefix + '/' + fname;
};
var uploadToGaiaHub = _sinon2.default.stub().callsFake( // eslint-disable-line no-shadow
function (fname, contents) {
putFiledContents.push([fname, contents]);
if (!fname.endsWith('.sig')) {
t.equal(contents, fileContent);
}
return Promise.resolve(pathToReadUrl(fname));
});
var getFullReadUrl = _sinon2.default.stub().callsFake( // eslint-disable-line no-shadow
function (path) {
return Promise.resolve(pathToReadUrl(path));
});
var lookupProfile = _sinon2.default.stub().callsFake(function (username) {
t.equal(username, 'applejacks.id', 'Unexpected user lookup request');
return Promise.resolve({ apps: { origin: readPrefix } });
});
var _proxyquire12 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, uploadToGaiaHub: uploadToGaiaHub }
}),
putFileImpl = _proxyquire12.putFileImpl;
var _proxyquire13 = (0, _proxyquire19.default)('../../../lib/storage', { // eslint-disable-line no-shadow
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection, getFullReadUrl: getFullReadUrl },
'../profiles': { lookupProfile: lookupProfile }
}),
getFileImpl = _proxyquire13.getFileImpl;
var encryptOptions = { encrypt: false, sign: true };
var decryptOptions = { decrypt: false, verify: true };
var multiplayerDecryptOptions = {
username: 'applejacks.id',
decrypt: false,
verify: true,
app: 'origin'
// put and encrypt the file
};putFileImpl(blockstack, goodPath, fileContent, encryptOptions).then(function (publicURL) {
t.equal(publicURL, pathToReadUrl(goodPath));
t.equal(putFiledContents.length, 2);
var sigContents = '';
// good path mocks
putFiledContents.forEach(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
path = _ref2[0],
contents = _ref2[1];
_fetchMock2.default.get(pathToReadUrl(path), contents);
if (path.endsWith('.sig')) {
sigContents = contents;
}
});
var sigObject = JSON.parse(sigContents);
// bad sig mocks
_fetchMock2.default.get(pathToReadUrl(badSigPath), 'hello world, this is inauthentic.');
_fetchMock2.default.get(pathToReadUrl(badSigPath + '.sig'), sigContents);
// no sig mocks
_fetchMock2.default.get(pathToReadUrl(noSigPath), 'hello world, this is inauthentic.');
_fetchMock2.default.get(pathToReadUrl(noSigPath + '.sig'), { status: 404, body: 'nopers.' });
// bad pk mocks
_fetchMock2.default.get(pathToReadUrl(badPKPath), fileContent);
_fetchMock2.default.get(pathToReadUrl(badPKPath + '.sig'), JSON.stringify({
signature: sigObject.signature,
publicKey: badPK
}));
}).then(function () {
return getFileImpl(blockstack, goodPath, decryptOptions).then(function (readContent) {
t.equal(readContent, fileContent, 'should read the file');
});
}).then(function () {
return getFileImpl(blockstack, badSigPath, decryptOptions).then(function () {
return t.fail('Should have failed to read file.');
}).catch(function (err) {
return t.ok(err.message.indexOf('do not match ECDSA') >= 0, 'Should fail with complaint about bad signature');
});
}).then(function () {
return getFileImpl(blockstack, noSigPath, decryptOptions).then(function () {
return t.fail('Should have failed to read file.');
}).catch(function (err) {
return t.ok(err.message.indexOf('obtain signature for file') >= 0, 'Should fail with complaint about missing signature');
});
}).then(function () {
return getFileImpl(blockstack, badPKPath, decryptOptions).then(function () {
return t.fail('Should have failed to read file.');
}).catch(function (err) {
return t.ok(err.message.indexOf('match gaia address') >= 0, 'Should fail with complaint about matching addresses');
});
}).then(function () {
return getFileImpl(blockstack, goodPath, multiplayerDecryptOptions).then(function (readContent) {
t.equal(readContent, fileContent, 'should read the file');
});
}).then(function () {
return getFileImpl(blockstack, badSigPath, multiplayerDecryptOptions).then(function () {
return t.fail('Should have failed to read file.');
}).catch(function (err) {
return t.ok(err.message.indexOf('do not match ECDSA') >= 0, 'Should fail with complaint about bad signature');
});
}).then(function () {
return getFileImpl(blockstack, noSigPath, multiplayerDecryptOptions).then(function () {
return t.fail('Should have failed to read file.');
}).catch(function (err) {
return t.ok(err.message.indexOf('obtain signature for file') >= 0, 'Should fail with complaint about missing signature');
});
}).then(function () {
return getFileImpl(blockstack, badPKPath, multiplayerDecryptOptions).then(function () {
return t.fail('Should have failed to read file.');
}).catch(function (err) {
return t.ok(err.message.indexOf('match gaia address') >= 0, 'Should fail with complaint about matching addresses');
});
}).catch(function (err) {
console.log(err.stack);
t.fail('Unexpected error!');
}).then(function () {
t.end();
});
});
(0, _tape2.default)('promises reject', function (t) {
t.plan(2);
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var path = 'file.json';
var fullReadUrl = 'https://hub.testblockstack.org/store/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.testblockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var setLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var _proxyquire14 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': {
getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection,
setLocalGaiaHubConnection: setLocalGaiaHubConnection
}
}),
putFileImpl = _proxyquire14.putFileImpl;
_fetchMock2.default.post('' + fullReadUrl, { status: 404, body: 'Not found.' });
putFileImpl(blockstack, path, 'hello world', { encrypt: false }).then(function () {
return t.ok(false, 'Should not have returned');
}).catch(function () {
return t.ok(true, 'Should have rejected promise');
});
var gaiaHubUrl = 'https://potato.hub.farm';
var signer = '01010101';
_fetchMock2.default.get('https://potato.hub.farm/hub_info', { status: 421, body: 'Nope.' });
(0, _hub.connectToGaiaHub)(gaiaHubUrl, signer).then(function () {
return t.ok(false, 'Should not have returned');
}).catch(function () {
return t.ok(true, 'Should have rejected promise');
});
});
(0, _tape2.default)('putFile gets a new gaia config and tries again', function (t) {
t.plan(3);
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
var path = 'file.json';
var fullWriteUrl = 'https://hub.testblockstack.org/store/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc/file.json';
var invalidHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc',
server: 'https://hub.testblockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var validHubConfig = Object.assign({}, invalidHubConfig, {
token: 'valid'
});
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(invalidHubConfig);
var setLocalGaiaHubConnection = _sinon2.default.stub().resolves(validHubConfig);
var _proxyquire15 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': {
getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection,
setLocalGaiaHubConnection: setLocalGaiaHubConnection
}
}),
putFileImpl = _proxyquire15.putFileImpl;
_fetchMock2.default.post(fullWriteUrl, function (url, _ref3) {
var headers = _ref3.headers;
console.log(url, headers);
if (headers.Authorization === 'bearer ') {
t.ok(true, 'tries with invalid token');
return 401;
} else if (headers.Authorization === 'bearer valid') {
t.ok(true, 'Tries with valid hub config');
return {
status: 200,
body: JSON.stringify({ publicURL: 'readURL' })
};
}
return 401;
});
putFileImpl(blockstack, path, 'hello world', { encrypt: false }).then(function () {
return t.ok(true, 'Request should pass');
});
});
(0, _tape2.default)('fetch404null', function (t) {
t.plan(2);
var config = {
address: '19MoWG8u88L6t766j7Vne21Mg4wHsCQ7vk',
url_prefix: 'gaia.testblockstack.org/hub/',
token: '',
server: 'hub.testblockstack.org'
};
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey,
gaiaHubConfig: config // manually set for testing
};_fetchMock2.default.get('' + config.url_prefix + config.address + '/foo.json', { status: 404 });
var optionsNoDecrypt = { decrypt: false };
(0, _storage.getFileImpl)(blockstack, 'foo.json', optionsNoDecrypt).then(function (x) {
return t.equal(x, null, '404 should return null');
});
var optionsDecrypt = { decrypt: true };
(0, _storage.getFileImpl)(blockstack, 'foo.json', optionsDecrypt).then(function (x) {
return t.equal(x, null, '404 should return null, even if we try to decrypt');
});
});
(0, _tape2.default)('uploadToGaiaHub', function (t) {
t.plan(2);
var config = {
address: '19MoWG8u88L6t766j7Vne21Mg4wHsCQ7vk',
url_prefix: 'gaia.testblockstack.org',
token: '',
server: 'hub.testblockstack.org'
};
_fetchMock2.default.post(config.server + '/store/' + config.address + '/foo.json', JSON.stringify({ publicURL: config.url_prefix + '/' + config.address + '/foo.json' }));
(0, _hub.uploadToGaiaHub)('foo.json', 'foo the bar', config).then(function (url) {
t.ok(url, 'URL returned');
t.equal(url, config.url_prefix + '/' + config.address + '/foo.json');
});
});
(0, _tape2.default)('getFullReadUrl', function (t) {
t.plan(1);
var config = {
address: '19MoWG8u88L6t766j7Vne21Mg4wHsCQ7vk',
url_prefix: 'gaia.testblockstack.org',
token: '',
server: 'hub.testblockstack.org'
};
var outUrl = (0, _hub.getFullReadUrl)('foo.json', config);
t.equal('' + config.url_prefix + config.address + '/foo.json', outUrl);
});
(0, _tape2.default)('connectToGaiaHub', function (t) {
t.plan(6);
var hubServer = 'hub.testblockstack.org';
var hubInfo = {
read_url_prefix: 'gaia.testblockstack.org',
challenge_text: 'please-sign',
latest_auth_version: 'v1'
};
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var address = '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U';
var publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69';
_fetchMock2.default.get(hubServer + '/hub_info', JSON.stringify(hubInfo));
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set for testing
};(0, _hub.connectToGaiaHub)(hubServer, privateKey).then(function (config) {
t.ok(config, 'Config returned by connectToGaiaHub()');
t.equal(hubInfo.read_url_prefix, config.url_prefix);
t.equal(address, config.address);
t.equal(hubServer, config.server);
var jsonTokenPart = config.token.slice('v1:'.length);
var verified = new _jsontokens.TokenVerifier('ES256K', publicKey).verify(jsonTokenPart);
t.ok(verified, 'Verified token');
t.equal(hubServer, (0, _jsontokens.decodeToken)(jsonTokenPart).payload.hubUrl, 'Intended hubUrl');
});
});
(0, _tape2.default)('connectToGaiaHub with an association token', function (t) {
t.plan(7);
var hubServer = 'hub.testblockstack.org';
var hubInfo = {
read_url_prefix: 'gaia.testblockstack.org',
challenge_text: 'please-sign',
latest_auth_version: 'v1'
};
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var address = '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U';
var publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69';
var identityPrivateKey = '4dea04fe440d760664d96f1fd219e7a73324fc8faa28c7babd1a7813d05970aa01';
var identityPublicKey = '0234f3c7aec9fe13190aede94d1eaa0a7d2b48d18fd86b9651fc3996a5f467fc73';
var FOUR_MONTH_SECONDS = 60 * 60 * 24 * 31 * 4;
var salt = '00000000000000000000000000000';
var associationTokenClaim = {
childToAssociate: publicKey,
iss: identityPublicKey,
exp: FOUR_MONTH_SECONDS + new Date() / 1000,
salt: salt
};
var gaiaAssociationToken = new _jsontokens.TokenSigner('ES256K', identityPrivateKey).sign(associationTokenClaim);
_fetchMock2.default.get(hubServer + '/hub_info', JSON.stringify(hubInfo));
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey // manually set for testing
};(0, _hub.connectToGaiaHub)(hubServer, privateKey, gaiaAssociationToken).then(function (config) {
t.ok(config, 'Config returned by connectToGaiaHub()');
t.equal(hubInfo.read_url_prefix, config.url_prefix);
t.equal(address, config.address);
t.equal(hubServer, config.server);
var jsonTokenPart = config.token.slice('v1:'.length);
var verified = new _jsontokens.TokenVerifier('ES256K', publicKey).verify(jsonTokenPart);
t.ok(verified, 'Verified token');
t.equal(hubServer, (0, _jsontokens.decodeToken)(jsonTokenPart).payload.hubUrl, 'Intended hubUrl');
t.equal(gaiaAssociationToken, (0, _jsontokens.decodeToken)(jsonTokenPart).payload.associationToken, 'Intended association token');
});
});
(0, _tape2.default)('getBucketUrl', function (t) {
t.plan(2);
var hubServer = 'hub2.testblockstack.org';
var hubInfo = {
read_url_prefix: 'https://gaia.testblockstack.org/hub/',
challenge_text: 'please-sign',
latest_auth_version: 'v1'
};
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var address = '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U';
_fetchMock2.default.get(hubServer + '/hub_info', JSON.stringify(hubInfo));
(0, _hub.getBucketUrl)(hubServer, privateKey).then(function (bucketUrl) {
t.ok(bucketUrl, 'App index file URL returned by getBucketUrl');
t.equal(bucketUrl, '' + hubInfo.read_url_prefix + address + '/');
});
});
(0, _tape2.default)('getUserAppFileUrl', function (t) {
t.plan(2);
var path = 'file.json';
var name = 'test.id';
var appOrigin = 'testblockstack.org';
var profile = {
apps: {
'testblockstack.org': 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/'
}
};
var fileUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json';
var lookupProfile = _sinon2.default.stub().resolves(profile);
var _proxyquire16 = (0, _proxyquire19.default)('../../../lib/storage', {
'../profiles': { lookupProfile: lookupProfile }
}),
getUserAppFileUrl = _proxyquire16.getUserAppFileUrl;
getUserAppFileUrl(path, name, appOrigin).then(function (url) {
t.ok(url, 'Returns user app file url');
t.equals(url, fileUrl);
});
});
(0, _tape2.default)('listFiles', function (t) {
t.plan(3);
var path = 'file.json';
var gaiaHubConfig = {
address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U',
server: 'https://hub.blockstack.org',
token: '',
url_prefix: 'gaia.testblockstack.org/hub/'
};
var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229';
var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000');
var blockstack = new _lib.UserSession({ appConfig: appConfig });
blockstack.store.getSessionData().userData = {
appPrivateKey: privateKey,
gaiaHubConfig: gaiaHubConfig // manually set for testing
};var callCount = 0;
_fetchMock2.default.post(gaiaHubConfig.server + '/list-files/' + gaiaHubConfig.address, function () {
callCount += 1;
if (callCount === 1) {
return { entries: [path], page: callCount };
} else if (callCount === 2) {
return { entries: [], page: callCount };
} else {
throw new Error('Called too many times');
}
});
var getOrSetLocalGaiaHubConnection = _sinon2.default.stub().resolves(gaiaHubConfig);
var _proxyquire17 = (0, _proxyquire19.default)('../../../lib/storage', {
'./hub': { getOrSetLocalGaiaHubConnection: getOrSetLocalGaiaHubConnection }
}),
listFilesImpl = _proxyquire17.listFilesImpl;
var files = [];
listFilesImpl(blockstack, function (name) {
files.push(name);
return true;
}).then(function (count) {
t.equal(files.length, 1, 'Got one file back');
t.equal(files[0], 'file.json', 'Got the right file back');
t.equal(count, 1, 'Count matches number of files');
});
});
}