@ -10,6 +10,7 @@ var Fs = require("fs");
var Path = require ( "path" ) ;
var Https = require ( "https" ) ;
const Package = require ( './package.json' ) ;
const Pinned = require ( './pinned' ) ;
var RPC = module . exports ;
@ -212,7 +213,6 @@ var checkSignature = function (signedMsg, signature, publicKey) {
} ;
var loadUserPins = function ( Env , publicKey , cb ) {
var pinStore = Env . pinStore ;
var session = beginSession ( Env . Sessions , publicKey ) ;
if ( session . channels ) {
@ -230,7 +230,7 @@ var loadUserPins = function (Env, publicKey, cb) {
pins [ channel ] = false ;
} ;
pinStore. getMessages ( publicKey , function ( msg ) {
Env. pinStore. getMessages ( publicKey , function ( msg ) {
// handle messages...
var parsed ;
try {
@ -325,9 +325,8 @@ var getFileSize = function (Env, channel, cb) {
} ;
var getMultipleFileSize = function ( Env , channels , cb ) {
var msgStore = Env . msgStore ;
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' ) ;
}
@ -428,6 +427,28 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
"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 ) {
if ( ! ( '' + response . statusCode ) . match ( /^2\d\d$/ ) ) {
return void cb ( 'SERVER ERROR ' + response . statusCode ) ;
@ -442,6 +463,11 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
try {
var json = JSON . parse ( str ) ;
limits = json ;
Object . keys ( customLimits ) . forEach ( function ( k ) {
if ( ! isLimit ( customLimits [ k ] ) ) { return ; }
limits [ k ] = customLimits [ k ] ;
} ) ;
var l ;
if ( userId ) {
var limit = limits [ userId ] ;
@ -499,6 +525,54 @@ var sumChannelSizes = function (sizes) {
. 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 ) {
if ( ! channels && channels . filter ) {
return void cb ( 'INVALID_PIN_LIST' ) ;
@ -534,6 +608,7 @@ var pinChannel = function (Env, publicKey, channels, cb) {
toStore . forEach ( function ( channel ) {
session . channels [ channel ] = true ;
} ) ;
addPinned ( Env , publicKey , toStore , ( ) => { } ) ;
getHash ( Env , publicKey , cb ) ;
} ) ;
} ) ;
@ -542,7 +617,6 @@ var pinChannel = function (Env, publicKey, channels, cb) {
} ;
var unpinChannel = function ( Env , publicKey , channels , cb ) {
var pinStore = Env . pinStore ;
if ( ! channels && channels . filter ) {
// expected array
return void cb ( 'INVALID_PIN_LIST' ) ;
@ -560,13 +634,13 @@ var unpinChannel = function (Env, publicKey, channels, cb) {
return void getHash ( Env , publicKey , cb ) ;
}
pinStore. message ( publicKey , JSON . stringify ( [ 'UNPIN' , toStore ] ) ,
Env. pinStore. message ( publicKey , JSON . stringify ( [ 'UNPIN' , toStore ] ) ,
function ( e ) {
if ( e ) { return void cb ( e ) ; }
toStore . forEach ( function ( channel ) {
delete session . channels [ channel ] ;
} ) ;
removePinned ( Env , publicKey , toStore , ( ) => { } ) ;
getHash ( Env , publicKey , cb ) ;
} ) ;
} ) ;
@ -574,7 +648,6 @@ var unpinChannel = function (Env, publicKey, channels, cb) {
var resetUserPins = function ( Env , publicKey , channelList , cb ) {
if ( ! Array . isArray ( channelList ) ) { return void cb ( 'INVALID_PIN_LIST' ) ; }
var pinStore = Env . pinStore ;
var session = beginSession ( Env . Sessions , publicKey ) ;
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
or delete enough files to go back under their 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 ) {
if ( e ) { return void cb ( e ) ; }
channelList . forEach ( function ( channel ) {
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.
session . channels = pins ;
getHash ( Env , publicKey , function ( e , hash ) {
@ -879,6 +957,7 @@ var isUnauthenticatedCall = function (call) {
return [
'GET_FILE_SIZE' ,
'GET_MULTIPLE_FILE_SIZE' ,
'IS_CHANNEL_PINNED' ,
] . indexOf ( call ) !== - 1 ;
} ;
@ -894,10 +973,31 @@ var isAuthenticatedCall = function (call) {
'GET_LIMIT' ,
'UPLOAD_COMPLETE' ,
'UPLOAD_CANCEL' ,
'EXPIRE_SESSION' ,
'EXPIRE_SESSION'
] . 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');*/
RPC . create = function ( config /*:typeof(ConfigType)*/ , cb /*:(?Error, ?Function)=>void*/ ) {
// load pin-store...
@ -909,14 +1009,19 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
return typeof ( config [ key ] ) === 'string' ? config [ key ] : def ;
} ;
var Env = { } ;
Env . defaultStorageLimit = config . defaultStorageLimit ;
Env . maxUploadSize = config . maxUploadSize || ( 20 * 1024 * 1024 ) ;
var Sessions = Env . Sessions = { } ;
var Env = {
defaultStorageLimit : config . defaultStorageLimit ,
maxUploadSize : config . maxUploadSize || ( 20 * 1024 * 1024 ) ,
Sessions : { } ,
paths : { } ,
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 blobPath = paths . blob = keyOrDefaultString ( 'blobPath' , './blob' ) ;
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 ] ) ;
} ) ;
case 'IS_CHANNEL_PINNED' :
return void isChannelPinned ( Env , msg [ 1 ] , function ( isPinned ) {
respond ( null , [ null , isPinned , null ] ) ;
} ) ;
default :
console . error ( "unsupported!" ) ;
return respond ( 'UNSUPPORTED_RPC_CALL' , msg ) ;
@ -1174,6 +1283,8 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
updateLimitDaily ( ) ;
setInterval ( updateLimitDaily , 24 * 3600 * 1000 ) ;
loadChannelPins ( Env ) ;
Store . create ( {
filePath : pinPath ,
} , function ( s ) {