Merge branch 'restricted-registration' into staging

pull/1/head
ansuz 4 years ago
commit 885d6c4dc7

@ -392,7 +392,7 @@ define([
// send an RPC to store the block which you created. // send an RPC to store the block which you created.
console.log("initializing rpc interface"); console.log("initializing rpc interface");
Pinpad.create(RT.network, RT.proxy, waitFor(function (e, _rpc) { Pinpad.create(RT.network, Block.keysToRPCFormat(res.opt.blockKeys), waitFor(function (e, _rpc) {
if (e) { if (e) {
waitFor.abort(); waitFor.abort();
console.error(e); // INVALID_KEYS console.error(e); // INVALID_KEYS
@ -414,7 +414,10 @@ define([
var blockRequest = Block.serialize(JSON.stringify(toPublish), res.opt.blockKeys); var blockRequest = Block.serialize(JSON.stringify(toPublish), res.opt.blockKeys);
rpc.writeLoginBlock(blockRequest, waitFor(function (e) { rpc.writeLoginBlock(blockRequest, waitFor(function (e) {
if (e) { return void console.error(e); } if (e) {
console.error(e);
return void cb(e);
}
console.log("blockInfo available at:", blockHash); console.log("blockInfo available at:", blockHash);
LocalStore.setBlockHash(blockHash); LocalStore.setBlockHash(blockHash);
@ -531,6 +534,9 @@ define([
}); });
}); });
break; break;
case 'E_RESTRICTED':
UI.errorLoadingScreen(Messages.register_registrationIsClosed);
break;
default: // UNHANDLED ERROR default: // UNHANDLED ERROR
hashing = false; hashing = false;
UI.errorLoadingScreen(Messages.login_unhandledError); UI.errorLoadingScreen(Messages.login_unhandledError);

@ -4,7 +4,8 @@ define([
'/customize/application_config.js', '/customize/application_config.js',
'/customize/messages.js', '/customize/messages.js',
'jquery', 'jquery',
], function (h, Language, AppConfig, Msg, $) { '/api/config',
], function (h, Language, AppConfig, Msg, $, ApiConfig) {
var Pages = {}; var Pages = {};
Pages.setHTML = function (e, html) { Pages.setHTML = function (e, html) {
@ -156,10 +157,16 @@ define([
Pages.infopageTopbar = function () { Pages.infopageTopbar = function () {
var rightLinks; var rightLinks;
var username = window.localStorage.getItem('User_name'); var username = window.localStorage.getItem('User_name');
var registerLink;
if (!ApiConfig.restrictRegistration) {
registerLink = h('a.nav-item.nav-link.cp-register-btn', { href: '/register/'}, Msg.login_register);
}
if (username === null) { if (username === null) {
rightLinks = [ rightLinks = [
h('a.nav-item.nav-link.cp-login-btn', { href: '/login/'}, Msg.login_login), h('a.nav-item.nav-link.cp-login-btn', { href: '/login/'}, Msg.login_login),
h('a.nav-item.nav-link.cp-register-btn', { href: '/register/'}, Msg.login_register) registerLink,
]; ];
} else { } else {
rightLinks = h('a.nav-item.nav-link.cp-user-btn', { href: '/drive/' }, [ rightLinks = h('a.nav-item.nav-link.cp-user-btn', { href: '/drive/' }, [

@ -146,7 +146,7 @@ define([
]), ]),
]); ]);
var availableFeatures = var availableFeatures =
(Config.allowSubscriptions && accounts.upgradeURL) ? (Config.allowSubscriptions && accounts.upgradeURL && !Config.restrictRegistration) ?
[anonymousFeatures, registeredFeatures, premiumFeatures] : [anonymousFeatures, registeredFeatures, premiumFeatures] :
[anonymousFeatures, registeredFeatures]; [anonymousFeatures, registeredFeatures];

@ -2,8 +2,9 @@ define([
'/common/hyperscript.js', '/common/hyperscript.js',
'/common/common-interface.js', '/common/common-interface.js',
'/customize/messages.js', '/customize/messages.js',
'/customize/pages.js' '/customize/pages.js',
], function (h, UI, Msg, Pages) { '/api/config',
], function (h, UI, Msg, Pages, Config) {
return function () { return function () {
return [h('div#cp-main', [ return [h('div#cp-main', [
Pages.infopageTopbar(), Pages.infopageTopbar(),
@ -32,7 +33,10 @@ define([
]), ]),
h('div.extra', [ h('div.extra', [
h('button.login', Msg.login_login), h('button.login', Msg.login_login),
h('button#register.cp-secondary', Msg.login_register) (Config.restrictRegistration?
undefined:
h('button#register.cp-secondary', Msg.login_register)
)
]) ])
]), ]),
h('div.col-md-3') h('div.col-md-3')

@ -16,11 +16,30 @@ define([
tabindex: '-1', tabindex: '-1',
}); });
return [h('div#cp-main', [
Pages.infopageTopbar(), var frame = function (content) {
h('div.container.cp-container', [ return [
h('div.row.cp-page-title', h('h1', Msg.register_header)), h('div#cp-main', [
h('div.row.cp-register-det', [ Pages.infopageTopbar(),
h('div.container.cp-container', [
h('div.row.cp-page-title', h('h1', Msg.register_header)),
//h('div.row.cp-register-det', content),
].concat(content)),
]),
Pages.infopageFooter(),
];
};
if (Config.restrictRegistration) {
return frame([
h('div.cp-restricted-registration', [
h('p', Msg.register_registrationIsClosed),
])
]);
}
return frame([
h('div.row.cp-register-det', [
h('div#data.hidden.col-md-6', [ h('div#data.hidden.col-md-6', [
h('h2', Msg.register_notes_title), h('h2', Msg.register_notes_title),
Pages.setHTML(h('div.cp-register-notes'), Msg.register_notes) Pages.setHTML(h('div.cp-register-notes'), Msg.register_notes)
@ -59,11 +78,8 @@ define([
h('button#register', Msg.login_register) h('button#register', Msg.login_register)
]) ])
]), ]),
]), ])
]), ]);
Pages.infopageFooter(),
])];
}; };
}); });

@ -52,6 +52,9 @@
} }
} }
.cp-restricted-registration {
text-align: center !important;
}
.cp-register-det { .cp-register-det {
#data { #data {

@ -50,7 +50,6 @@ $(function () {
} else if (/^\/login\//.test(pathname)) { } else if (/^\/login\//.test(pathname)) {
require([ '/login/main.js' ], function () {}); require([ '/login/main.js' ], function () {});
} else if (/^\/($|^\/index\.html$)/.test(pathname)) { } else if (/^\/($|^\/index\.html$)/.test(pathname)) {
// TODO use different top bar
require([ '/customize/main.js', ], function () {}); require([ '/customize/main.js', ], function () {});
} else { } else {
require([ '/customize/main.js', ], function () {}); require([ '/customize/main.js', ], function () {});

@ -86,47 +86,122 @@ var createLoginBlockPath = function (Env, publicKey) { // FIXME BLOCKS
return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey); return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey);
}; };
Block.writeLoginBlock = function (Env, safeKey, msg, cb) { // FIXME BLOCKS Block.validateAncestorProof = function (Env, proof, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
/* prove that you own an existing block by signing for its publicKey */
try {
var parsed = JSON.parse(proof);
var pub = parsed[0];
var u8_pub = Nacl.util.decodeBase64(pub);
var sig = parsed[1];
var u8_sig = Nacl.util.decodeBase64(sig);
var valid = false;
nThen(function (w) {
valid = Nacl.sign.detached.verify(u8_pub, u8_sig, u8_pub);
if (!valid) {
w.abort();
return void cb('E_INVALID_ANCESTOR_PROOF');
}
// else fall through to next step
}).nThen(function (w) {
var path = createLoginBlockPath(Env, pub);
Fs.access(path, Fs.constants.F_OK, w(function (err) {
if (!err) { return; }
w.abort(); // else
return void cb("E_MISSING_ANCESTOR");
}));
}).nThen(function () {
cb(void 0, pub);
});
} catch (err) {
return void cb(err);
}
};
Block.writeLoginBlock = function (Env, safeKey, msg, _cb) { // FIXME BLOCKS
var cb = Util.once(Util.mkAsync(_cb));
//console.log(msg); //console.log(msg);
var publicKey = msg[0]; var publicKey = msg[0];
var signature = msg[1]; var signature = msg[1];
var block = msg[2]; var block = msg[2];
var registrationProof = msg[3];
validateLoginBlock(Env, publicKey, signature, block, function (e, validatedBlock) { var previousKey;
if (e) { return void cb(e); }
if (!(validatedBlock instanceof Uint8Array)) { return void cb('E_INVALID_BLOCK'); } var validatedBlock, parsed, path;
nThen(function (w) {
// derive the filepath if (Util.escapeKeyCharacters(publicKey) !== safeKey) {
var path = createLoginBlockPath(Env, publicKey); w.abort();
return void cb("INCORRECT_KEY");
// make sure the path is valid
if (typeof(path) !== 'string') {
return void cb('E_INVALID_BLOCK_PATH');
} }
}).nThen(function (w) {
var parsed = Path.parse(path); if (!Env.restrictRegistration) { return; }
if (!parsed || typeof(parsed.dir) !== 'string') { if (!registrationProof) {
return void cb("E_INVALID_BLOCK_PATH_2"); // we allow users with existing blocks to create new ones
// call back with error if registration is restricted and no proof of an existing block was provided
w.abort();
Env.Log.info("BLOCK_REJECTED_REGISTRATION", {
safeKey: safeKey,
publicKey: publicKey,
});
return cb("E_RESTRICTED");
} }
Env.validateAncestorProof(registrationProof, w(function (err, provenKey) {
nThen(function (w) { if (err || !provenKey) { // double check that a key was validated
// make sure the path to the file exists w.abort();
Fse.mkdirp(parsed.dir, w(function (e) { Env.Log.warn('BLOCK_REJECTED_INVALID_ANCESTOR', {
if (e) { error: err,
w.abort(); });
cb(e); return void cb("E_RESTRICTED");
} }
})); previousKey = provenKey;
}).nThen(function () { }));
// actually write the block }).nThen(function (w) {
validateLoginBlock(Env, publicKey, signature, block, w(function (e, _validatedBlock) {
// flow is dumb and I need to guard against this which will never happen if (e) {
/*:: if (typeof(validatedBlock) === 'undefined') { throw new Error('should never happen'); } */ w.abort();
/*:: if (typeof(path) === 'undefined') { throw new Error('should never happen'); } */ return void cb(e);
Fs.writeFile(path, Buffer.from(validatedBlock), { encoding: "binary", }, function (err) { }
if (err) { return void cb(err); } if (!(_validatedBlock instanceof Uint8Array)) {
cb(); w.abort();
return void cb('E_INVALID_BLOCK');
}
validatedBlock = _validatedBlock;
// derive the filepath
path = createLoginBlockPath(Env, publicKey);
// make sure the path is valid
if (typeof(path) !== 'string') {
return void cb('E_INVALID_BLOCK_PATH');
}
parsed = Path.parse(path);
if (!parsed || typeof(parsed.dir) !== 'string') {
w.abort();
return void cb("E_INVALID_BLOCK_PATH_2");
}
}));
}).nThen(function (w) {
// make sure the path to the file exists
Fse.mkdirp(parsed.dir, w(function (e) {
if (e) {
w.abort();
cb(e);
}
}));
}).nThen(function () {
// actually write the block
Fs.writeFile(path, Buffer.from(validatedBlock), { encoding: "binary", }, function (err) {
if (err) { return void cb(err); }
Env.Log.info('BLOCK_WRITE_BY_OWNER', {
safeKey: safeKey,
blockId: publicKey,
isChange: Boolean(registrationProof),
previousKey: previousKey,
path: path,
}); });
cb();
}); });
}); });
}; };
@ -146,26 +221,33 @@ Block.removeLoginBlock = function (Env, safeKey, msg, cb) { // FIXME BLOCKS
var signature = msg[1]; var signature = msg[1];
var block = Nacl.util.decodeUTF8('DELETE_BLOCK'); // clients and the server will have to agree on this constant var block = Nacl.util.decodeUTF8('DELETE_BLOCK'); // clients and the server will have to agree on this constant
validateLoginBlock(Env, publicKey, signature, block, function (e /*::, validatedBlock */) { nThen(function (w) {
if (e) { return void cb(e); } if (Util.escapeKeyCharacters(publicKey) !== safeKey) {
// derive the filepath w.abort();
var path = createLoginBlockPath(Env, publicKey); return void cb("INCORRECT_KEY");
// make sure the path is valid
if (typeof(path) !== 'string') {
return void cb('E_INVALID_BLOCK_PATH');
} }
}).nThen(function () {
validateLoginBlock(Env, publicKey, signature, block, function (e /*::, validatedBlock */) {
if (e) { return void cb(e); }
// derive the filepath
var path = createLoginBlockPath(Env, publicKey);
// make sure the path is valid
if (typeof(path) !== 'string') {
return void cb('E_INVALID_BLOCK_PATH');
}
// FIXME COLDSTORAGE
Fs.unlink(path, function (err) {
Env.Log.info('DELETION_BLOCK_BY_OWNER_RPC', {
publicKey: publicKey,
path: path,
status: err? String(err): 'SUCCESS',
});
// FIXME COLDSTORAGE if (err) { return void cb(err); }
Fs.unlink(path, function (err) { cb();
Env.Log.info('DELETION_BLOCK_BY_OWNER_RPC', {
publicKey: publicKey,
path: path,
status: err? String(err): 'SUCCESS',
}); });
if (err) { return void cb(err); }
cb();
}); });
}); });
}; };

@ -89,6 +89,7 @@ module.exports.create = function (config) {
} }
}, },
restrictRegistration: false,
allowSubscriptions: config.allowSubscriptions === true, allowSubscriptions: config.allowSubscriptions === true,
blockDailyCheck: config.blockDailyCheck === true, blockDailyCheck: config.blockDailyCheck === true,

@ -158,6 +158,7 @@ module.exports.create = function (Env, cb) {
pinPath: Env.paths.pin, pinPath: Env.paths.pin,
filePath: Env.paths.data, filePath: Env.paths.data,
archivePath: Env.paths.archive, archivePath: Env.paths.archive,
blockPath: Env.paths.block,
inactiveTime: Env.inactiveTime, inactiveTime: Env.inactiveTime,
archiveRetentionTime: Env.archiveRetentionTime, archiveRetentionTime: Env.archiveRetentionTime,

@ -295,7 +295,7 @@ var owned_upload_complete = function (Env, safeKey, id, cb) {
// removeBlob // removeBlob
var remove = function (Env, blobId, cb) { var remove = function (Env, blobId, cb) {
var blobPath = makeBlobPath(Env, blobId); var blobPath = makeBlobPath(Env, blobId);
Fs.unlink(blobPath, cb); // TODO COLDSTORAGE Fs.unlink(blobPath, cb);
}; };
// removeProof // removeProof

@ -4,6 +4,7 @@
const HK = require("../hk-util"); const HK = require("../hk-util");
const Store = require("../storage/file"); const Store = require("../storage/file");
const BlobStore = require("../storage/blob"); const BlobStore = require("../storage/blob");
const Block = require("../commands/block");
const Util = require("../common-util"); const Util = require("../common-util");
const nThen = require("nthen"); const nThen = require("nthen");
const Meta = require("../metadata"); const Meta = require("../metadata");
@ -47,6 +48,7 @@ const init = function (config, _cb) {
Env.paths = { Env.paths = {
pin: config.pinPath, pin: config.pinPath,
block: config.blockPath,
}; };
Env.inactiveTime = config.inactiveTime; Env.inactiveTime = config.inactiveTime;
@ -688,6 +690,10 @@ COMMANDS.HASH_CHANNEL_LIST = function (data, cb) {
cb(void 0, hash); cb(void 0, hash);
}; };
COMMANDS.VALIDATE_ANCESTOR_PROOF = function (data, cb) {
Block.validateAncestorProof(Env, data && data.proof, cb);
};
process.on('message', function (data) { process.on('message', function (data) {
if (!data || !data.txid || !data.pid) { if (!data || !data.txid || !data.pid) {
return void process.send({ return void process.send({

@ -444,6 +444,13 @@ Workers.initialize = function (Env, config, _cb) {
}, cb); }, cb);
}; };
Env.validateAncestorProof = function (proof, cb) {
sendCommand({
command: 'VALIDATE_ANCESTOR_PROOF',
proof: proof,
}, cb);
};
cb(void 0); cb(void 0);
}); });
}; };

@ -280,6 +280,7 @@ var serveConfig = makeRouteCache(function (host) {
defaultStorageLimit: Env.defaultStorageLimit, defaultStorageLimit: Env.defaultStorageLimit,
maxUploadSize: Env.maxUploadSize, maxUploadSize: Env.maxUploadSize,
premiumUploadSize: Env.premiumUploadSize, premiumUploadSize: Env.premiumUploadSize,
restrictRegistration: Env.restrictRegistration,
}, null, '\t'), }, null, '\t'),
'obj.httpSafeOrigin = ' + (function () { 'obj.httpSafeOrigin = ' + (function () {
if (config.httpSafeOrigin) { return '"' + config.httpSafeOrigin + '"'; } if (config.httpSafeOrigin) { return '"' + config.httpSafeOrigin + '"'; }

@ -53,7 +53,7 @@ define([
'cp-admin-update-limit', 'cp-admin-update-limit',
'cp-admin-archive', 'cp-admin-archive',
'cp-admin-unarchive', 'cp-admin-unarchive',
// 'cp-admin-registration', 'cp-admin-registration',
], ],
'quota': [ // Msg.admin_cat_quota 'quota': [ // Msg.admin_cat_quota
'cp-admin-defaultlimit', 'cp-admin-defaultlimit',

@ -243,7 +243,7 @@ define([
opt.keys = secret.keys; opt.keys = secret.keys;
opt.channelHex = secret.channel; opt.channelHex = secret.channel;
var RT, rpc, exists; var RT, rpc, exists, restricted;
nThen(function (waitFor) { nThen(function (waitFor) {
Util.fetch(blockUrl, waitFor(function (err) { Util.fetch(blockUrl, waitFor(function (err) {
@ -285,6 +285,12 @@ define([
// Write block // Write block
if (exists) { return; } if (exists) { return; }
rpc.writeLoginBlock(blockRequest, waitFor(function (e) { rpc.writeLoginBlock(blockRequest, waitFor(function (e) {
// we should tolerate restricted registration
// and proceed to clean up after any data we've created
if (e === 'E_RESTRICTED') {
restricted = true;
return void cb(true);
}
if (e) { if (e) {
waitFor.abort(); waitFor.abort();
console.error("Can't write login block", e); console.error("Can't write login block", e);
@ -292,6 +298,7 @@ define([
} }
})); }));
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
if (restricted) { return; }
// Read block // Read block
Util.fetch(blockUrl, waitFor(function (e) { Util.fetch(blockUrl, waitFor(function (e) {
if (e) { if (e) {
@ -303,6 +310,7 @@ define([
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
// Remove block // Remove block
rpc.removeLoginBlock(removeRequest, waitFor(function (e) { rpc.removeLoginBlock(removeRequest, waitFor(function (e) {
if (restricted) { return; } // an ENOENT is expected in the case of restricted registration, but we call this anyway to clean up any mess from previous tests.
if (e) { if (e) {
waitFor.abort(); waitFor.abort();
console.error("Can't remove login block", e); console.error("Can't remove login block", e);

@ -1873,14 +1873,16 @@ define([
Common.setLoginRedirect('login'); Common.setLoginRedirect('login');
}, },
}); });
options.push({ if (!Config.restrictRegistration) {
tag: 'a', options.push({
attributes: {'class': 'cp-toolbar-menu-register fa fa-user-plus'}, tag: 'a',
content: h('span', Messages.login_register), attributes: {'class': 'cp-toolbar-menu-register fa fa-user-plus'},
action: function () { content: h('span', Messages.login_register),
Common.setLoginRedirect('register'); action: function () {
}, Common.setLoginRedirect('register');
}); },
});
}
} }
var $icon = $('<span>', {'class': 'fa fa-user-secret'}); var $icon = $('<span>', {'class': 'fa fa-user-secret'});
//var $userbig = $('<span>', {'class': 'big'}).append($displayedName.clone()); //var $userbig = $('<span>', {'class': 'big'}).append($displayedName.clone());

@ -1735,6 +1735,7 @@ define([
var removeData = obj.Block.remove(blockKeys); var removeData = obj.Block.remove(blockKeys);
postMessage("DELETE_ACCOUNT", { postMessage("DELETE_ACCOUNT", {
keys: Block.keysToRPCFormat(blockKeys),
removeData: removeData removeData: removeData
}, function (obj) { }, function (obj) {
if (obj.state) { if (obj.state) {
@ -1855,9 +1856,16 @@ define([
}; };
var content = Block.serialize(JSON.stringify(temp), blockKeys); var content = Block.serialize(JSON.stringify(temp), blockKeys);
console.error("OLD AND NEW BLOCK KEYS", oldBlockKeys, blockKeys);
content.registrationProof = Block.proveAncestor(oldBlockKeys);
console.log("writing new login block"); console.log("writing new login block");
common.writeLoginBlock(content, waitFor(function (obj) {
var data = {
keys: Block.keysToRPCFormat(blockKeys),
content: content,
};
common.writeLoginBlock(data, waitFor(function (obj) {
if (obj && obj.error) { if (obj && obj.error) {
waitFor.abort(); waitFor.abort();
return void cb(obj); return void cb(obj);
@ -1875,8 +1883,11 @@ define([
// Remove block hash // Remove block hash
if (blockHash) { if (blockHash) {
console.log('removing old login block'); console.log('removing old login block');
var removeData = Block.remove(oldBlockKeys); var data = {
common.removeLoginBlock(removeData, waitFor(function (obj) { keys: Block.keysToRPCFormat(oldBlockKeys), // { edPrivate, edPublic }
content: Block.remove(oldBlockKeys),
};
common.removeLoginBlock(data, waitFor(function (obj) {
if (obj && obj.error) { return void console.error(obj.error); } if (obj && obj.error) { return void console.error(obj.error); }
})); }));
} }

@ -451,19 +451,33 @@ define([
}; };
Store.writeLoginBlock = function (clientId, data, cb) { Store.writeLoginBlock = function (clientId, data, cb) {
store.rpc.writeLoginBlock(data, function (e, res) { Pinpad.create(store.network, data && data.keys, function (err, rpc) {
cb({ if (err) {
error: e, return void cb({
data: res error: err,
});
}
rpc.writeLoginBlock(data && data.content, function (e, res) {
cb({
error: e,
data: res
});
}); });
}); });
}; };
Store.removeLoginBlock = function (clientId, data, cb) { Store.removeLoginBlock = function (clientId, data, cb) {
store.rpc.removeLoginBlock(data, function (e, res) { Pinpad.create(store.network, data && data.keys, function (err, rpc) {
cb({ if (err) {
error: e, return void cb({
data: res error: err,
});
}
rpc.removeLoginBlock(data && data.content, function (e, res) {
cb({
error: e,
data: res
});
}); });
}); });
}; };
@ -815,6 +829,7 @@ define([
Store.deleteAccount = function (clientId, data, cb) { Store.deleteAccount = function (clientId, data, cb) {
var edPublic = store.proxy.edPublic; var edPublic = store.proxy.edPublic;
var removeData = data && data.removeData; var removeData = data && data.removeData;
var rpcKeys = data && data.keys;
Store.anonRpcMsg(clientId, { Store.anonRpcMsg(clientId, {
msg: 'GET_METADATA', msg: 'GET_METADATA',
data: store.driveChannel data: store.driveChannel
@ -845,8 +860,15 @@ define([
}, waitFor()); }, waitFor());
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
if (!removeData) { return; } if (!removeData) { return; }
// Delete the block. Don't abort if it fails, it doesn't leak any data. var done = waitFor();
store.rpc.removeLoginBlock(removeData, waitFor()); Pinpad.create(store.network, rpcKeys, function (err, rpc) {
if (err) {
console.error(err);
return void done();
}
// Delete the block. Don't abort if it fails, it doesn't leak any data.
rpc.removeLoginBlock(removeData, done);
});
}).nThen(function () { }).nThen(function () {
// Log out current worker // Log out current worker
postMessage(clientId, "DELETE_ACCOUNT", token, function () {}); postMessage(clientId, "DELETE_ACCOUNT", token, function () {});

@ -40,6 +40,19 @@ define([
}; };
}; };
Block.keysToRPCFormat = function (keys) {
try {
var sign = keys.sign;
return {
edPrivate: Nacl.util.encodeBase64(sign.secretKey),
edPublic: Nacl.util.encodeBase64(sign.publicKey),
};
} catch (err) {
console.error(err);
return;
}
};
// (UTF8 content, keys object) => Uint8Array block // (UTF8 content, keys object) => Uint8Array block
Block.encrypt = function (version, content, keys) { Block.encrypt = function (version, content, keys) {
var u8 = Nacl.util.decodeUTF8(content); var u8 = Nacl.util.decodeUTF8(content);
@ -86,6 +99,20 @@ define([
}; };
}; };
Block.proveAncestor = function (O /* oldBlockKeys */, N /* newBlockKeys */) {
N = N;
var u8_pub = Util.find(O, ['sign', 'publicKey']);
var u8_secret = Util.find(O, ['sign', 'secretKey']);
try {
// sign your old publicKey with your old privateKey
var u8_sig = Nacl.sign.detached(u8_pub, u8_secret);
// return an array with the sig and the pubkey
return JSON.stringify([u8_pub, u8_sig].map(Nacl.util.encodeBase64));
} catch (err) {
return void console.error(err);
}
};
Block.remove = function (keys) { Block.remove = function (keys) {
// sign the hash of the text 'DELETE_BLOCK' // sign the hash of the text 'DELETE_BLOCK'
var sig = Nacl.sign.detached(Nacl.hash( var sig = Nacl.sign.detached(Nacl.hash(

@ -226,11 +226,15 @@ var factory = function (Util, Rpc) {
console.log(data); console.log(data);
return void cb("MISSING_PARAMETERS"); return void cb("MISSING_PARAMETERS");
} }
if (['string', 'undefined'].indexOf(typeof(data.registrationProof)) === -1) {
return void cb("INVALID_REGISTRATION_PROOF");
}
rpc.send('WRITE_LOGIN_BLOCK', [ rpc.send('WRITE_LOGIN_BLOCK', [
data.publicKey, data.publicKey,
data.signature, data.signature,
data.ciphertext data.ciphertext,
data.registrationProof || undefined,
], function (e) { ], function (e) {
cb(e); cb(e);
}); });

@ -11,21 +11,11 @@ define([
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, Cryptpad, Login, UI, Realtime, Feedback, LocalStore, Test) { ], function ($, Cryptpad, Login, UI, Realtime, Feedback, LocalStore, Test) {
$(function () { $(function () {
var $main = $('#mainBlock');
var $checkImport = $('#import-recent'); var $checkImport = $('#import-recent');
// main block is hidden in case javascript is disabled
$main.removeClass('hidden');
// Make sure we don't display non-translated content (empty button)
$main.find('#data').removeClass('hidden');
if (LocalStore.isLoggedIn()) { if (LocalStore.isLoggedIn()) {
// already logged in, redirect to drive // already logged in, redirect to drive
document.location.href = '/drive/'; document.location.href = '/drive/';
return; return;
} else {
$main.find('#userForm').removeClass('hidden');
} }
/* Log in UI */ /* Log in UI */

@ -15,22 +15,11 @@ define([
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
], function ($, Login, Cryptpad, Test, Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h) { ], function ($, Login, Cryptpad, Test, Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h) {
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
$(function () { $(function () {
var $main = $('#mainBlock');
// main block is hidden in case javascript is disabled
$main.removeClass('hidden');
// Make sure we don't display non-translated content (empty button)
$main.find('#data').removeClass('hidden');
if (LocalStore.isLoggedIn()) { if (LocalStore.isLoggedIn()) {
// already logged in, redirect to drive // already logged in, redirect to drive
document.location.href = '/drive/'; document.location.href = '/drive/';
return; return;
} else {
$main.find('#userForm').removeClass('hidden');
} }
// text and password input fields // text and password input fields

Loading…
Cancel
Save