From c1f222dd6c8084790efea2313f86934270bbc672 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 24 Jan 2020 13:19:40 -0500 Subject: [PATCH] move metadata commands from rpc to their own module --- lib/commands/metadata.js | 113 +++++++++++++++++++++++++++++++++++++ lib/rpc.js | 118 ++------------------------------------- 2 files changed, 119 insertions(+), 112 deletions(-) create mode 100644 lib/commands/metadata.js diff --git a/lib/commands/metadata.js b/lib/commands/metadata.js new file mode 100644 index 000000000..91b08d8cc --- /dev/null +++ b/lib/commands/metadata.js @@ -0,0 +1,113 @@ +/*jshint esversion: 6 */ +const Data = module.exports; + +const Meta = require("../metadata"); +const BatchRead = require("../batch-read"); +const WriteQueue = require("./write-queue"); +const Core = require("./commands/core"); + +const batchMetadata = BatchRead("GET_METADATA"); +Data.getMetadata = function (Env, channel, cb) { + if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } + if (channel.length !== 32) { return cb("INVALID_CHAN_LENGTH"); } + + batchMetadata(channel, cb, function (done) { + var ref = {}; + var lineHandler = Meta.createLineHandler(ref, Env.Log.error); + + return void Env.msgStore.readChannelMetadata(channel, lineHandler, function (err) { + if (err) { + // stream errors? + return void done(err); + } + done(void 0, ref.meta); + }); + }); +}; + +/* setMetadata + - write a new line to the metadata log if a valid command is provided + - data is an object: { + channel: channelId, + command: metadataCommand (string), + value: value + } +*/ +var queueMetadata = WriteQueue(); +Data.setMetadata = function (Env, data, unsafeKey, cb) { + var channel = data.channel; + var command = data.command; + if (!channel || !Core.isValidId(channel)) { return void cb ('INVALID_CHAN'); } + if (!command || typeof (command) !== 'string') { return void cb ('INVALID_COMMAND'); } + if (Meta.commands.indexOf(command) === -1) { return void('UNSUPPORTED_COMMAND'); } + + queueMetadata(channel, function (next) { + Data.getMetadata(Env, channel, function (err, metadata) { + if (err) { + cb(err); + return void next(); + } + if (!Core.hasOwners(metadata)) { + cb('E_NO_OWNERS'); + return void next(); + } + + // if you are a pending owner and not an owner + // you can either ADD_OWNERS, or RM_PENDING_OWNERS + // and you should only be able to add yourself as an owner + // everything else should be rejected + // else if you are not an owner + // you should be rejected + // else write the command + + // Confirm that the channel is owned by the user in question + // or the user is accepting a pending ownership offer + if (Core.hasPendingOwners(metadata) && + Core.isPendingOwner(metadata, unsafeKey) && + !Core.isOwner(metadata, unsafeKey)) { + + // If you are a pending owner, make sure you can only add yourelf as an owner + if ((command !== 'ADD_OWNERS' && command !== 'RM_PENDING_OWNERS') + || !Array.isArray(data.value) + || data.value.length !== 1 + || data.value[0] !== unsafeKey) { + cb('INSUFFICIENT_PERMISSIONS'); + return void next(); + } + // FIXME wacky fallthrough is hard to read + // we could pass this off to a writeMetadataCommand function + // and make the flow easier to follow + } else if (!Core.isOwner(metadata, unsafeKey)) { + cb('INSUFFICIENT_PERMISSIONS'); + return void next(); + } + + // Add the new metadata line + var line = [command, data.value, +new Date()]; + var changed = false; + try { + changed = Meta.handleCommand(metadata, line); + } catch (e) { + cb(e); + return void next(); + } + + // if your command is valid but it didn't result in any change to the metadata, + // call back now and don't write any "useless" line to the log + if (!changed) { + cb(void 0, metadata); + return void next(); + } + Env.msgStore.writeMetadata(channel, JSON.stringify(line), function (e) { + if (e) { + cb(e); + return void next(); + } + cb(void 0, metadata); + next(); + }); + }); + }); +}; + + diff --git a/lib/rpc.js b/lib/rpc.js index 3785b20a1..0ddfdb128 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -1,8 +1,5 @@ /*jshint esversion: 6 */ const nThen = require("nthen"); -const Meta = require("./metadata"); -const WriteQueue = require("./write-queue"); -const BatchRead = require("./batch-read"); const Util = require("./common-util"); const escapeKeyCharacters = Util.escapeKeyCharacters; @@ -13,6 +10,7 @@ const Admin = require("./commands/admin-rpc"); const Pinning = require("./commands/pin-rpc"); const Quota = require("./commands/quota"); const Block = require("./commands/block"); +const Metadata = require("./commands/metadata"); var RPC = module.exports; @@ -31,116 +29,12 @@ var WARN = function (e, output) { } }; -const batchMetadata = BatchRead("GET_METADATA"); -var getMetadata = function (Env, channel, cb) { - if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } - if (channel.length !== 32) { return cb("INVALID_CHAN_LENGTH"); } - - batchMetadata(channel, cb, function (done) { - var ref = {}; - var lineHandler = Meta.createLineHandler(ref, Log.error); - - return void Env.msgStore.readChannelMetadata(channel, lineHandler, function (err) { - if (err) { - // stream errors? - return void done(err); - } - done(void 0, ref.meta); - }); - }); -}; - -/* setMetadata - - write a new line to the metadata log if a valid command is provided - - data is an object: { - channel: channelId, - command: metadataCommand (string), - value: value - } -*/ -var queueMetadata = WriteQueue(); -var setMetadata = function (Env, data, unsafeKey, cb) { - var channel = data.channel; - var command = data.command; - if (!channel || !Core.isValidId(channel)) { return void cb ('INVALID_CHAN'); } - if (!command || typeof (command) !== 'string') { return void cb ('INVALID_COMMAND'); } - if (Meta.commands.indexOf(command) === -1) { return void('UNSUPPORTED_COMMAND'); } - - queueMetadata(channel, function (next) { - getMetadata(Env, channel, function (err, metadata) { - if (err) { - cb(err); - return void next(); - } - if (!Core.hasOwners(metadata)) { - cb('E_NO_OWNERS'); - return void next(); - } - - // if you are a pending owner and not an owner - // you can either ADD_OWNERS, or RM_PENDING_OWNERS - // and you should only be able to add yourself as an owner - // everything else should be rejected - // else if you are not an owner - // you should be rejected - // else write the command - - // Confirm that the channel is owned by the user in question - // or the user is accepting a pending ownership offer - if (Core.hasPendingOwners(metadata) && - Core.isPendingOwner(metadata, unsafeKey) && - !Core.isOwner(metadata, unsafeKey)) { - - // If you are a pending owner, make sure you can only add yourelf as an owner - if ((command !== 'ADD_OWNERS' && command !== 'RM_PENDING_OWNERS') - || !Array.isArray(data.value) - || data.value.length !== 1 - || data.value[0] !== unsafeKey) { - cb('INSUFFICIENT_PERMISSIONS'); - return void next(); - } - // FIXME wacky fallthrough is hard to read - // we could pass this off to a writeMetadataCommand function - // and make the flow easier to follow - } else if (!Core.isOwner(metadata, unsafeKey)) { - cb('INSUFFICIENT_PERMISSIONS'); - return void next(); - } - - // Add the new metadata line - var line = [command, data.value, +new Date()]; - var changed = false; - try { - changed = Meta.handleCommand(metadata, line); - } catch (e) { - cb(e); - return void next(); - } - - // if your command is valid but it didn't result in any change to the metadata, - // call back now and don't write any "useless" line to the log - if (!changed) { - cb(void 0, metadata); - return void next(); - } - Env.msgStore.writeMetadata(channel, JSON.stringify(line), function (e) { - if (e) { - cb(e); - return void next(); - } - cb(void 0, metadata); - next(); - }); - }); - }); -}; - var clearOwnedChannel = function (Env, channelId, unsafeKey, cb) { if (typeof(channelId) !== 'string' || channelId.length !== 32) { return cb('INVALID_ARGUMENTS'); } - getMetadata(Env, channelId, function (err, metadata) { + Metadata.getMetadata(Env, channelId, function (err, metadata) { if (err) { return void cb(err); } if (!Core.hasOwners(metadata)) { return void cb('E_NO_OWNERS'); } // Confirm that the channel is owned by the user in question @@ -199,7 +93,7 @@ var removeOwnedChannel = function (Env, channelId, unsafeKey, cb) { }); } - getMetadata(Env, channelId, function (err, metadata) { + Metadata.getMetadata(Env, channelId, function (err, metadata) { if (err) { return void cb(err); } if (!Core.hasOwners(metadata)) { return void cb('E_NO_OWNERS'); } if (!Core.isOwner(metadata, unsafeKey)) { @@ -219,7 +113,7 @@ var removeOwnedChannel = function (Env, channelId, unsafeKey, cb) { var removeOwnedChannelHistory = function (Env, channelId, unsafeKey, hash, cb) { nThen(function (w) { - getMetadata(Env, channelId, w(function (err, metadata) { + Metadata.getMetadata(Env, channelId, w(function (err, metadata) { if (err) { return void cb(err); } if (!Core.hasOwners(metadata)) { w.abort(); @@ -463,7 +357,7 @@ RPC.create = function (config, cb) { respond(e, [null, size, null]); }); case 'GET_METADATA': - return void getMetadata(Env, msg[1], function (e, data) { + return void Metadata.getMetadata(Env, msg[1], function (e, data) { WARN(e, msg[1]); respond(e, [null, data, null]); }); @@ -718,7 +612,7 @@ RPC.create = function (config, cb) { Respond(void 0, result); }); case 'SET_METADATA': - return void setMetadata(Env, msg[1], publicKey, function (e, data) { + return void Metadata.setMetadata(Env, msg[1], publicKey, function (e, data) { if (e) { WARN(e, data); return void Respond(e);