|
|
|
@ -86,52 +86,89 @@ var createLoginBlockPath = function (Env, publicKey) { // FIXME BLOCKS
|
|
|
|
|
return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var validateAncestorProof = function (Env, proof, newPubKey, cb) {
|
|
|
|
|
/* prove that you own an existing block by signing for its publicKey
|
|
|
|
|
|
|
|
|
|
we will need:
|
|
|
|
|
|
|
|
|
|
1. the publicKey
|
|
|
|
|
2. for the old key's block to exist
|
|
|
|
|
* path = createLoginBlockPath(Env, oldPublicKey)
|
|
|
|
|
* path && FS.readFile(path, err => { !err })
|
|
|
|
|
3. a message signed with that publicKey
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
cb("E_RESTRICTED");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Block.writeLoginBlock = function (Env, safeKey, msg, _cb) { // FIXME BLOCKS
|
|
|
|
|
var cb = Util.once(Util.mkAsync(_cb));
|
|
|
|
|
//console.log(msg);
|
|
|
|
|
var publicKey = msg[0];
|
|
|
|
|
var signature = msg[1];
|
|
|
|
|
var block = msg[2];
|
|
|
|
|
|
|
|
|
|
if (Env.restrictRegistration /* && notAlreadyRegistered */) { // XXX restricted-registration
|
|
|
|
|
return void cb("E_RESTRICTED");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
validateLoginBlock(Env, publicKey, signature, block, function (e, validatedBlock) {
|
|
|
|
|
if (e) { return void cb(e); }
|
|
|
|
|
if (!(validatedBlock instanceof Uint8Array)) { return void cb('E_INVALID_BLOCK'); }
|
|
|
|
|
|
|
|
|
|
// 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');
|
|
|
|
|
var registrationProof = msg[3];
|
|
|
|
|
|
|
|
|
|
var validatedBlock, parsed, path;
|
|
|
|
|
nThen(function (w) {
|
|
|
|
|
if (!Env.restrictRegistration) { return; }
|
|
|
|
|
if (!registrationProof) {
|
|
|
|
|
// 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();
|
|
|
|
|
return cb("E_RESTRICTED");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var parsed = Path.parse(path);
|
|
|
|
|
if (!parsed || typeof(parsed.dir) !== 'string') {
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
// flow is dumb and I need to guard against this which will never happen
|
|
|
|
|
/*:: if (typeof(validatedBlock) === 'undefined') { throw new Error('should never happen'); } */
|
|
|
|
|
/*:: if (typeof(path) === 'undefined') { throw new Error('should never happen'); } */
|
|
|
|
|
Fs.writeFile(path, Buffer.from(validatedBlock), { encoding: "binary", }, function (err) {
|
|
|
|
|
if (err) { return void cb(err); }
|
|
|
|
|
cb();
|
|
|
|
|
});
|
|
|
|
|
// TODO check that the provided proof was valid
|
|
|
|
|
// XXX restricted-registration check whether proof of an existing block was provided
|
|
|
|
|
validateAncestorProof(Env, void 0, w(function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
w.abort();
|
|
|
|
|
cb(err);
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}).nThen(function (w) {
|
|
|
|
|
validateLoginBlock(Env, publicKey, signature, block, w(function (e, _validatedBlock) {
|
|
|
|
|
if (e) {
|
|
|
|
|
w.abort();
|
|
|
|
|
return void cb(e);
|
|
|
|
|
}
|
|
|
|
|
if (!(_validatedBlock instanceof Uint8Array)) {
|
|
|
|
|
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); }
|
|
|
|
|
// XXX log the safeKey to map publicKey <=> block
|
|
|
|
|
cb();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|