@@ -72,13 +72,13 @@ const logger = require('morgan');
72
72
const cookieParser = require ( 'cookie-parser' ) ;
73
73
const bodyParser = require ( 'body-parser' ) ;
74
74
const session = require ( "express-session" ) ;
75
- const csurf = require ( "csurf" ) ;
75
+ const MemoryStore = require ( 'memorystore' ) ( session ) ;
76
+ const csrfApi = require ( "csurf" ) ;
76
77
const config = require ( "./app/config.js" ) ;
77
78
const simpleGit = require ( 'simple-git' ) ;
78
79
const utils = require ( "./app/utils.js" ) ;
79
80
const moment = require ( "moment" ) ;
80
81
const Decimal = require ( 'decimal.js' ) ;
81
- const bitcoinCore = require ( "btc-rpc-client" ) ;
82
82
const pug = require ( "pug" ) ;
83
83
const momentDurationFormat = require ( "moment-duration-format" ) ;
84
84
const coreApi = require ( "./app/api/coreApi.js" ) ;
@@ -95,14 +95,15 @@ const auth = require('./app/auth.js');
95
95
const sso = require ( './app/sso.js' ) ;
96
96
const markdown = require ( "markdown-it" ) ( ) ;
97
97
const v8 = require ( "v8" ) ;
98
- var compression = require ( "compression" ) ;
98
+ const compression = require ( "compression" ) ;
99
+ const jayson = require ( 'jayson/promise' ) ;
99
100
100
101
const appUtils = require ( "@janoside/app-utils" ) ;
101
102
const s3Utils = appUtils . s3Utils ;
102
103
103
104
let cdnS3Bucket = null ;
104
105
if ( config . cdn . active ) {
105
- cdnS3Bucket = s3Utils . createBucket ( config . cdn . s3Bucket , config . cdn . s3BucketPath ) ;
106
+ cdnS3Bucket = s3Utils . createBucket ( config . cdn . s3Bucket , config . cdn . s3BucketRegion , config . cdn . s3BucketPath ) ;
106
107
}
107
108
108
109
require ( "./app/currencies.js" ) ;
@@ -203,11 +204,31 @@ if (process.env.BTCEXP_BASIC_AUTH_PASSWORD) {
203
204
//expressApp.use(logger('dev'));
204
205
expressApp . use ( bodyParser . json ( ) ) ;
205
206
expressApp . use ( bodyParser . urlencoded ( { extended : false } ) ) ;
206
- expressApp . use ( session ( {
207
+
208
+
209
+ const sessionConfig = {
207
210
secret : config . cookieSecret ,
208
211
resave : false ,
209
- saveUninitialized : false
210
- } ) ) ;
212
+ saveUninitialized : true ,
213
+ cookie : {
214
+ secure : config . secureSite
215
+ }
216
+ } ;
217
+
218
+ if ( config . secureSite ) {
219
+ expressApp . set ( 'trust proxy' , 1 ) ;
220
+ }
221
+
222
+ // Helpful reference for production: nginx HTTPS proxy:
223
+ // https://gist.github.com/nikmartin/5902176
224
+ debugLog ( `Session config: ${ JSON . stringify ( utils . obfuscateProperties ( sessionConfig , [ "secret" ] ) ) } ` ) ;
225
+
226
+ sessionConfig . store = new MemoryStore ( {
227
+ checkPeriod : 86400000 // prune expired entries every 24h
228
+ } ) ;
229
+
230
+
231
+ expressApp . use ( session ( sessionConfig ) ) ;
211
232
212
233
expressApp . use ( compression ( ) ) ;
213
234
@@ -729,6 +750,8 @@ expressApp.onStartup = async () => {
729
750
global . coinConfig = coins [ config . coin ] ;
730
751
global . coinConfigs = coins ;
731
752
753
+ global . SATS_PER_BTC = global . coinConfig . baseCurrencyUnit . multiplier ;
754
+
732
755
global . specialTransactions = { } ;
733
756
global . specialBlocks = { } ;
734
757
global . specialAddresses = { } ;
@@ -852,29 +875,67 @@ expressApp.onStartup = async () => {
852
875
}
853
876
}
854
877
855
- expressApp . continueStartup = function ( ) {
856
- var rpcCred = config . credentials . rpc ;
857
- debugLog ( `Connecting to RPC node at ${ rpcCred . host } :${ rpcCred . port } ` ) ;
878
+ function connectToRpcServer ( ) {
879
+ // reload credentials, the main "config.credentials.rpc" can be stale
880
+ // since the username/password can be sourced from the auth cookie
881
+ // which changes each startup of bitcoind
882
+ let credentialsForRpcConnect = config . credentials . loadFreshRpcCredentials ( ) ;
883
+
884
+ debugLog ( `RPC Credentials: ${ JSON . stringify ( utils . obfuscateProperties ( credentialsForRpcConnect , [ "password" ] ) , null , 4 ) } ` ) ;
885
+
886
+ let rpcCred = credentialsForRpcConnect ;
887
+ debugLog ( `Connecting to RPC node at [${ rpcCred . host } ]:${ rpcCred . port } ` ) ;
858
888
859
- var rpcClientProperties = {
889
+ let usernamePassword = `${ rpcCred . username } :${ rpcCred . password } ` ;
890
+ let authorizationHeader = `Basic ${ btoa ( usernamePassword ) } ` ; // basic auth header format (base64 of "username:password")
891
+
892
+ let rpcClientProperties = {
860
893
host : rpcCred . host ,
861
894
port : rpcCred . port ,
862
895
username : rpcCred . username ,
863
896
password : rpcCred . password ,
864
897
timeout : rpcCred . timeout
865
898
} ;
866
899
867
- global . rpcClient = new bitcoinCore ( rpcClientProperties ) ;
900
+ debugLog ( `RPC Connection properties: ${ JSON . stringify ( utils . obfuscateProperties ( rpcClientProperties , [ "password" ] ) , null , 4 ) } ` ) ;
901
+
902
+ // add after logging to avoid logging base64'd credentials
903
+ rpcClientProperties . headers = {
904
+ "Authorization" : authorizationHeader
905
+ } ;
906
+
907
+ // main RPC client
908
+ global . rpcClient = jayson . Client . http ( rpcClientProperties ) ;
868
909
869
- var rpcClientNoTimeoutProperties = {
910
+ let rpcClientNoTimeoutProperties = {
870
911
host : rpcCred . host ,
871
912
port : rpcCred . port ,
872
913
username : rpcCred . username ,
873
914
password : rpcCred . password ,
874
- timeout : 0
915
+ timeout : 0 ,
916
+ headers : {
917
+ "Authorization" : authorizationHeader
918
+ }
875
919
} ;
876
920
877
- global . rpcClientNoTimeout = new bitcoinCore ( rpcClientNoTimeoutProperties ) ;
921
+ // no timeout RPC client, for long-running commands
922
+ global . rpcClientNoTimeout = jayson . Client . http ( rpcClientNoTimeoutProperties ) ;
923
+ }
924
+
925
+ expressApp . continueStartup = function ( ) {
926
+ connectToRpcServer ( ) ;
927
+
928
+ // if using cookie auth, watch for changes to the file and reconnect
929
+ if ( config . credentials . rpc . authType == "cookie" ) {
930
+ debugLog ( `RPC authentication is cookie based; watching for changes to the auth cookie file...` ) ;
931
+
932
+ fs . watchFile ( config . credentials . rpc . authCookieFilepath , ( curr , prev ) => {
933
+ debugLog ( `RPC auth cookie change detected; attempting reconnect...` ) ;
934
+
935
+ connectToRpcServer ( ) ;
936
+ } ) ;
937
+ }
938
+
878
939
879
940
// default values - after we connect via RPC, we update these
880
941
global . txindexAvailable = false ;
@@ -889,7 +950,7 @@ expressApp.continueStartup = function() {
889
950
890
951
891
952
if ( config . addressApi ) {
892
- var supportedAddressApis = addressApi . getSupportedAddressApis ( ) ;
953
+ let supportedAddressApis = addressApi . getSupportedAddressApis ( ) ;
893
954
if ( ! supportedAddressApis . includes ( config . addressApi ) ) {
894
955
utils . logError ( "32907ghsd0ge" , `Unrecognized value for BTCEXP_ADDRESS_API: '${ config . addressApi } '. Valid options are: ${ supportedAddressApis } ` ) ;
895
956
}
@@ -1033,7 +1094,8 @@ expressApp.use(function(req, res, next) {
1033
1094
next ( ) ;
1034
1095
} ) ;
1035
1096
1036
- expressApp . use ( csurf ( ) , ( req , res , next ) => {
1097
+ const csrfProtection = csrfApi ( ) ;
1098
+ expressApp . use ( csrfProtection , ( req , res , next ) => {
1037
1099
res . locals . csrfToken = req . csrfToken ( ) ;
1038
1100
1039
1101
next ( ) ;
0 commit comments