@ -10,6 +10,7 @@ var Fs = require("fs");
var Path = require ( "path" ) ;
var Path = require ( "path" ) ;
var Https = require ( "https" ) ;
var Https = require ( "https" ) ;
const Package = require ( './package.json' ) ;
const Package = require ( './package.json' ) ;
const Pinned = require ( './pinned' ) ;
var RPC = module . exports ;
var RPC = module . exports ;
@ -212,7 +213,6 @@ var checkSignature = function (signedMsg, signature, publicKey) {
} ;
} ;
var loadUserPins = function ( Env , publicKey , cb ) {
var loadUserPins = function ( Env , publicKey , cb ) {
var pinStore = Env . pinStore ;
var session = beginSession ( Env . Sessions , publicKey ) ;
var session = beginSession ( Env . Sessions , publicKey ) ;
if ( session . channels ) {
if ( session . channels ) {
@ -230,7 +230,7 @@ var loadUserPins = function (Env, publicKey, cb) {
pins [ channel ] = false ;
pins [ channel ] = false ;
} ;
} ;
pinStore. getMessages ( publicKey , function ( msg ) {
Env. pinStore. getMessages ( publicKey , function ( msg ) {
// handle messages...
// handle messages...
var parsed ;
var parsed ;
try {
try {
@ -325,9 +325,8 @@ var getFileSize = function (Env, channel, cb) {
} ;
} ;
var getMultipleFileSize = function ( Env , channels , cb ) {
var getMultipleFileSize = function ( Env , channels , cb ) {
var msgStore = Env . msgStore ;
if ( ! Array . isArray ( channels ) ) { return cb ( 'INVALID_PIN_LIST' ) ; }
if ( ! Array . isArray ( channels ) ) { return cb ( 'INVALID_PIN_LIST' ) ; }
if ( typeof ( msgStore. getChannelSize ) !== 'function' ) {
if ( typeof ( Env. msgStore. getChannelSize ) !== 'function' ) {
return cb ( 'GET_CHANNEL_SIZE_UNSUPPORTED' ) ;
return cb ( 'GET_CHANNEL_SIZE_UNSUPPORTED' ) ;
}
}
@ -428,6 +427,28 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
"Content-Length" : Buffer . byteLength ( body )
"Content-Length" : Buffer . byteLength ( body )
}
}
} ;
} ;
// read custom limits from the config
var customLimits = ( function ( custom ) {
var limits = { } ;
Object . keys ( custom ) . forEach ( function ( k ) {
k . replace ( /\/([^\/]+)$/ , function ( all , safeKey ) {
var id = unescapeKeyCharacters ( safeKey || '' ) ;
limits [ id ] = custom [ k ] ;
return '' ;
} ) ;
} ) ;
return limits ;
} ( config . customLimits || { } ) ) ;
var isLimit = function ( o ) {
var valid = o && typeof ( o ) === 'object' &&
typeof ( o . limit ) === 'number' &&
typeof ( o . plan ) === 'string' &&
typeof ( o . note ) === 'string' ;
return valid ;
} ;
var req = Https . request ( options , function ( response ) {
var req = Https . request ( options , function ( response ) {
if ( ! ( '' + response . statusCode ) . match ( /^2\d\d$/ ) ) {
if ( ! ( '' + response . statusCode ) . match ( /^2\d\d$/ ) ) {
return void cb ( 'SERVER ERROR ' + response . statusCode ) ;
return void cb ( 'SERVER ERROR ' + response . statusCode ) ;
@ -442,6 +463,11 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
try {
try {
var json = JSON . parse ( str ) ;
var json = JSON . parse ( str ) ;
limits = json ;
limits = json ;
Object . keys ( customLimits ) . forEach ( function ( k ) {
if ( ! isLimit ( customLimits [ k ] ) ) { return ; }
limits [ k ] = customLimits [ k ] ;
} ) ;
var l ;
var l ;
if ( userId ) {
if ( userId ) {
var limit = limits [ userId ] ;
var limit = limits [ userId ] ;
@ -499,6 +525,54 @@ var sumChannelSizes = function (sizes) {
. reduce ( function ( a , b ) { return a + b ; } , 0 ) ;
. reduce ( function ( a , b ) { return a + b ; } , 0 ) ;
} ;
} ;
// inform that the
var loadChannelPins = function ( Env ) {
Pinned . load ( function ( data ) {
Env . pinnedPads = data ;
Env . evPinnedPadsReady . fire ( ) ;
} ) ;
} ;
var addPinned = function (
Env ,
publicKey /*:string*/ ,
channelList /*Array<string>*/ ,
cb /*:()=>void*/ )
{
Env . evPinnedPadsReady . reg ( ( ) => {
channelList . forEach ( ( c ) => {
const x = Env . pinnedPads [ c ] ;
if ( ! x ) { return ; }
delete x [ publicKey ] ;
} ) ;
cb ( ) ;
} ) ;
} ;
var removePinned = function (
Env ,
publicKey /*:string*/ ,
channelList /*Array<string>*/ ,
cb /*:()=>void*/ )
{
Env . evPinnedPadsReady . reg ( ( ) => {
channelList . forEach ( ( c ) => {
const x = Env . pinnedPads [ c ] ;
if ( ! x ) { return ; }
delete x [ publicKey ] ;
} ) ;
cb ( ) ;
} ) ;
} ;
var isChannelPinned = function ( Env , channel , cb ) {
Env . evPinnedPadsReady . reg ( ( ) => {
if ( Env . pinnedPads [ channel ] && Object . keys ( Env . pinnedPads [ channel ] ) . length ) {
cb ( true ) ;
} else {
delete Env . pinnedPads [ channel ] ;
cb ( false ) ;
}
} ) ;
} ;
var pinChannel = function ( Env , publicKey , channels , cb ) {
var pinChannel = function ( Env , publicKey , channels , cb ) {
if ( ! channels && channels . filter ) {
if ( ! channels && channels . filter ) {
return void cb ( 'INVALID_PIN_LIST' ) ;
return void cb ( 'INVALID_PIN_LIST' ) ;
@ -534,6 +608,7 @@ var pinChannel = function (Env, publicKey, channels, cb) {
toStore . forEach ( function ( channel ) {
toStore . forEach ( function ( channel ) {
session . channels [ channel ] = true ;
session . channels [ channel ] = true ;
} ) ;
} ) ;
addPinned ( Env , publicKey , toStore , ( ) => { } ) ;
getHash ( Env , publicKey , cb ) ;
getHash ( Env , publicKey , cb ) ;
} ) ;
} ) ;
} ) ;
} ) ;
@ -542,7 +617,6 @@ var pinChannel = function (Env, publicKey, channels, cb) {
} ;
} ;
var unpinChannel = function ( Env , publicKey , channels , cb ) {
var unpinChannel = function ( Env , publicKey , channels , cb ) {
var pinStore = Env . pinStore ;
if ( ! channels && channels . filter ) {
if ( ! channels && channels . filter ) {
// expected array
// expected array
return void cb ( 'INVALID_PIN_LIST' ) ;
return void cb ( 'INVALID_PIN_LIST' ) ;
@ -560,13 +634,13 @@ var unpinChannel = function (Env, publicKey, channels, cb) {
return void getHash ( Env , publicKey , cb ) ;
return void getHash ( Env , publicKey , cb ) ;
}
}
pinStore. message ( publicKey , JSON . stringify ( [ 'UNPIN' , toStore ] ) ,
Env. pinStore. message ( publicKey , JSON . stringify ( [ 'UNPIN' , toStore ] ) ,
function ( e ) {
function ( e ) {
if ( e ) { return void cb ( e ) ; }
if ( e ) { return void cb ( e ) ; }
toStore . forEach ( function ( channel ) {
toStore . forEach ( function ( channel ) {
delete session . channels [ channel ] ;
delete session . channels [ channel ] ;
} ) ;
} ) ;
removePinned ( Env , publicKey , toStore , ( ) => { } ) ;
getHash ( Env , publicKey , cb ) ;
getHash ( Env , publicKey , cb ) ;
} ) ;
} ) ;
} ) ;
} ) ;
@ -574,7 +648,6 @@ var unpinChannel = function (Env, publicKey, channels, cb) {
var resetUserPins = function ( Env , publicKey , channelList , cb ) {
var resetUserPins = function ( Env , publicKey , channelList , cb ) {
if ( ! Array . isArray ( channelList ) ) { return void cb ( 'INVALID_PIN_LIST' ) ; }
if ( ! Array . isArray ( channelList ) ) { return void cb ( 'INVALID_PIN_LIST' ) ; }
var pinStore = Env . pinStore ;
var session = beginSession ( Env . Sessions , publicKey ) ;
var session = beginSession ( Env . Sessions , publicKey ) ;
if ( ! channelList . length ) {
if ( ! channelList . length ) {
@ -605,13 +678,18 @@ var resetUserPins = function (Env, publicKey, channelList, cb) {
They will not be able to pin additional pads until they upgrade
They will not be able to pin additional pads until they upgrade
or delete enough files to go back under their limit . * /
or delete enough files to go back under their limit . * /
if ( pinSize > limit [ 0 ] && session . hasPinned ) { return void ( cb ( 'E_OVER_LIMIT' ) ) ; }
if ( pinSize > limit [ 0 ] && session . hasPinned ) { return void ( cb ( 'E_OVER_LIMIT' ) ) ; }
pinStore. message ( publicKey , JSON . stringify ( [ 'RESET' , channelList ] ) ,
Env. pinStore. message ( publicKey , JSON . stringify ( [ 'RESET' , channelList ] ) ,
function ( e ) {
function ( e ) {
if ( e ) { return void cb ( e ) ; }
if ( e ) { return void cb ( e ) ; }
channelList . forEach ( function ( channel ) {
channelList . forEach ( function ( channel ) {
pins [ channel ] = true ;
pins [ channel ] = true ;
} ) ;
} ) ;
var oldChannels = Object . keys ( session . channels ) ;
removePinned ( Env , publicKey , oldChannels , ( ) => {
addPinned ( Env , publicKey , channelList , ( ) => { } ) ;
} ) ;
// update in-memory cache IFF the reset was allowed.
// update in-memory cache IFF the reset was allowed.
session . channels = pins ;
session . channels = pins ;
getHash ( Env , publicKey , function ( e , hash ) {
getHash ( Env , publicKey , function ( e , hash ) {
@ -879,6 +957,7 @@ var isUnauthenticatedCall = function (call) {
return [
return [
'GET_FILE_SIZE' ,
'GET_FILE_SIZE' ,
'GET_MULTIPLE_FILE_SIZE' ,
'GET_MULTIPLE_FILE_SIZE' ,
'IS_CHANNEL_PINNED' ,
] . indexOf ( call ) !== - 1 ;
] . indexOf ( call ) !== - 1 ;
} ;
} ;
@ -894,10 +973,31 @@ var isAuthenticatedCall = function (call) {
'GET_LIMIT' ,
'GET_LIMIT' ,
'UPLOAD_COMPLETE' ,
'UPLOAD_COMPLETE' ,
'UPLOAD_CANCEL' ,
'UPLOAD_CANCEL' ,
'EXPIRE_SESSION' ,
'EXPIRE_SESSION'
] . indexOf ( call ) !== - 1 ;
] . indexOf ( call ) !== - 1 ;
} ;
} ;
const mkEvent = function ( once ) {
var handlers = [ ] ;
var fired = false ;
return {
reg : function ( cb ) {
if ( once && fired ) { return void setTimeout ( cb ) ; }
handlers . push ( cb ) ;
} ,
unreg : function ( cb ) {
if ( handlers . indexOf ( cb ) === - 1 ) { throw new Error ( "Not registered" ) ; }
handlers . splice ( handlers . indexOf ( cb ) , 1 ) ;
} ,
fire : function ( ) {
if ( once && fired ) { return ; }
fired = true ;
var args = Array . prototype . slice . call ( arguments ) ;
handlers . forEach ( function ( h ) { h . apply ( null , args ) ; } ) ;
}
} ;
} ;
/*::const ConfigType = require('./config.example.js');*/
/*::const ConfigType = require('./config.example.js');*/
RPC . create = function ( config /*:typeof(ConfigType)*/ , cb /*:(?Error, ?Function)=>void*/ ) {
RPC . create = function ( config /*:typeof(ConfigType)*/ , cb /*:(?Error, ?Function)=>void*/ ) {
// load pin-store...
// load pin-store...
@ -909,14 +1009,19 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
return typeof ( config [ key ] ) === 'string' ? config [ key ] : def ;
return typeof ( config [ key ] ) === 'string' ? config [ key ] : def ;
} ;
} ;
var Env = { } ;
var Env = {
Env . defaultStorageLimit = config . defaultStorageLimit ;
defaultStorageLimit : config . defaultStorageLimit ,
maxUploadSize : config . maxUploadSize || ( 20 * 1024 * 1024 ) ,
Env . maxUploadSize = config . maxUploadSize || ( 20 * 1024 * 1024 ) ;
Sessions : { } ,
paths : { } ,
var Sessions = Env . Sessions = { } ;
msgStore : ( undefined /*:any*/ ) ,
pinStore : ( undefined /*:any*/ ) ,
pinnedPads : { } ,
evPinnedPadsReady : mkEvent ( true )
} ;
var paths = Env . paths = { } ;
var Sessions = Env . Sessions ;
var paths = Env . paths ;
var pinPath = paths . pin = keyOrDefaultString ( 'pinPath' , './pins' ) ;
var pinPath = paths . pin = keyOrDefaultString ( 'pinPath' , './pins' ) ;
var blobPath = paths . blob = keyOrDefaultString ( 'blobPath' , './blob' ) ;
var blobPath = paths . blob = keyOrDefaultString ( 'blobPath' , './blob' ) ;
var blobStagingPath = paths . staging = keyOrDefaultString ( 'blobStagingPath' , './blobstage' ) ;
var blobStagingPath = paths . staging = keyOrDefaultString ( 'blobStagingPath' , './blobstage' ) ;
@ -943,6 +1048,10 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
}
}
respond ( e , [ null , dict , null ] ) ;
respond ( e , [ null , dict , null ] ) ;
} ) ;
} ) ;
case 'IS_CHANNEL_PINNED' :
return void isChannelPinned ( Env , msg [ 1 ] , function ( isPinned ) {
respond ( null , [ null , isPinned , null ] ) ;
} ) ;
default :
default :
console . error ( "unsupported!" ) ;
console . error ( "unsupported!" ) ;
return respond ( 'UNSUPPORTED_RPC_CALL' , msg ) ;
return respond ( 'UNSUPPORTED_RPC_CALL' , msg ) ;
@ -1174,6 +1283,8 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
updateLimitDaily ( ) ;
updateLimitDaily ( ) ;
setInterval ( updateLimitDaily , 24 * 3600 * 1000 ) ;
setInterval ( updateLimitDaily , 24 * 3600 * 1000 ) ;
loadChannelPins ( Env ) ;
Store . create ( {
Store . create ( {
filePath : pinPath ,
filePath : pinPath ,
} , function ( s ) {
} , function ( s ) {