Class: StraightServer::GatewayOnDB

Inherits:
Object
  • Object
show all
Includes:
Straight::GatewayModule, GatewayModule
Defined in:
lib/straight-server/gateway.rb

Overview

Uses database to load and save attributes

Constant Summary

Constants included from GatewayModule

StraightServer::GatewayModule::CALLBACK_URL_ATTEMPT_TIMEFRAME

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from GatewayModule

#add_websocket_for_order, #create_order, #fetch_transactions_for, #find_reusable_order, #get_next_last_keychain_id, #get_order_counter, #increment_order_counter!, #initialize_blockchain_adapters, #initialize_callbacks, #initialize_exchange_rate_adapters, #initialize_network, #initialize_status_check_schedule, #order_counters, #order_status_changed, #send_order_to_websocket_client, #sign_with_secret, #update_last_keychain_id, #websockets

Instance Attribute Details

#update_secretObject

This virtual attribute is important because it’s difficult to detect whether secret was actually updated or not. Sequel’s #changed_columns may mistakenly say :secret attr was changed, while it hasn’t. Thus we provide a manual way of ensuring this. It’s also better and works as safety switch: we don’t want somebody accidentally updating a secret.



374
375
376
# File 'lib/straight-server/gateway.rb', line 374

def update_secret
  @update_secret
end

Class Method Details

.find_by_hashed_id(s) ⇒ Object



366
367
368
# File 'lib/straight-server/gateway.rb', line 366

def self.find_by_hashed_id(s)
  self.where(hashed_id: s).first
end

.find_by_id(id) ⇒ Object



421
422
423
# File 'lib/straight-server/gateway.rb', line 421

def self.find_by_id(id)
  self[id]
end

Instance Method Details

#address_providerObject



450
451
452
# File 'lib/straight-server/gateway.rb', line 450

def address_provider
  Kernel.const_get("Straight::AddressProvider::#{address_provider_type}").new(self)
end

#address_provider_typeObject



446
447
448
# File 'lib/straight-server/gateway.rb', line 446

def address_provider_type
  self[:address_provider] ? self[:address_provider].to_sym : :Bip32
end

#after_createObject



389
390
391
392
# File 'lib/straight-server/gateway.rb', line 389

def after_create
  @@websockets[self.id] = {}
  update(hashed_id: OpenSSL::HMAC.digest('sha256', Config.server_secret, self.id.to_s).unpack("H*").first)
end

#after_initializeObject



394
395
396
397
398
399
400
401
402
# File 'lib/straight-server/gateway.rb', line 394

def after_initialize
  @status_check_schedule = Straight::GatewayModule::DEFAULT_STATUS_CHECK_SCHEDULE
  @@websockets[self.id] ||= {} if self.id
  initialize_callbacks
  initialize_exchange_rate_adapters
  initialize_blockchain_adapters
  initialize_status_check_schedule
  initialize_network
end

#before_createObject



376
377
378
379
380
381
# File 'lib/straight-server/gateway.rb', line 376

def before_create
  super
  encrypt_secret
  self.test_mode ||= false
  self.test_last_keychain_id ||= 0
end

#before_updateObject



383
384
385
386
387
# File 'lib/straight-server/gateway.rb', line 383

def before_update
  encrypt_secret if @update_secret
  @update_secret = false
  super
end

#disable_test_mode!Object



454
455
456
457
# File 'lib/straight-server/gateway.rb', line 454

def disable_test_mode!
  self[:test_mode] = false
  save(columns: 'test_mode')
end

#enable_test_mode!Object



459
460
461
462
# File 'lib/straight-server/gateway.rb', line 459

def enable_test_mode!
  self[:test_mode] = true
  save(columns: 'test_mode')
end

#encrypt_secretObject



425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/straight-server/gateway.rb', line 425

def encrypt_secret
  cipher           = OpenSSL::Cipher::AES.new(128, :CBC)
  cipher.encrypt
  cipher.key       = OpenSSL::HMAC.digest('sha256', 'nonce', Config.server_secret).unpack("H*").first[0,16]

  cipher.iv        = iv = OpenSSL::HMAC.digest('sha256', 'nonce', "#{self.class.max(:id)}#{Config.server_secret}").unpack("H*").first[0,16]
  raise "cipher.iv cannot be nil" unless iv

  encrypted        = cipher.update(self[:secret]) << cipher.final()
  base64_encrypted = Base64.strict_encode64(encrypted).encode('utf-8')
  result           = "#{iv}:#{base64_encrypted}"

  # Check whether we can decrypt. It should not be possible to encrypt the
  # gateway secret unless we are sure we can decrypt it.
  if decrypt_secret(result) == self[:secret]
    self.secret = result
  else
    raise "Decrypted and original secrets don't match! Cannot proceed with writing the encrypted gateway secret."
  end
end

#secretObject

We cannot allow to store gateway secret in a DB plaintext, this would be completetly unsecure. Althougth we use symmetrical encryption here and store the encryption key in the server’s in a special file (~/.straight/server_secret), which in turn can also be stolen, this is still marginally better than doing nothing.

Also, server admnistrators now have the freedom of developing their own strategy of storing that secret - it doesn’t have to be stored on the same machine.



417
418
419
# File 'lib/straight-server/gateway.rb', line 417

def secret
  decrypt_secret
end

#validateObject



404
405
406
407
408
# File 'lib/straight-server/gateway.rb', line 404

def validate
  super
  errors.add(:pubkey, "Please provide public key") if pubkey_missing?
  errors.add(:test_pubkey, "Please provide test public key if you activate test mode") if test_pubkey_missing?
end