feat: decouple l-s entrypoint

This commit is contained in:
Sérgio Salgado 2022-03-29 15:00:52 +01:00
parent 2a2c1fccc8
commit f4d6b5e454
48 changed files with 411 additions and 232 deletions

1
.env
View file

@ -1 +0,0 @@
LAMASSU_DB=DEV

59
.sample.env Normal file
View file

@ -0,0 +1,59 @@
## Database variables
# Used to describe which database to use. Possible values include: DEV, RELEASE, STRESS_TEST
LAMASSU_DB=
# Postgres related environment variables
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_HOST=
POSTGRES_PORT=
POSTGRES_DB=
## File paths
# Certificate-related variables
LAMASSU_CA_PATH=
CA_PATH=
CERT_PATH=
KEY_PATH=
# Full path to where the wallet's mnemonic is stored
MNEMONIC_PATH=
MIGRATE_STATE_PATH=
## Directories
BLOCKCHAIN_DIR=
OFAC_DATA_DIR=
ID_PHOTO_CARD_DIR=
FRONT_CAMERA_DIR=
OPERATOR_DATA_DIR=
## URLs
STRIKE_BASE_URL=
COIN_ATM_RADAR_URL=
## OFAC Sources variables
# These variables map to each other, similar to a zip HOF. Entries are separated by commas
# Example:
# OFAC_SOURCES_NAMES=name1,name2
# OFAC_SOURCES_URLS=url1,url2
OFAC_SOURCES_NAMES=
OFAC_SOURCES_URLS=
## Misc
HOSTNAME=
LOG_LEVEL=
LIGHTNING_NETWORK_DAEMON=
## Deprecated or in deprecation
HTTP=
DEV_MODE=
## Uncategorized variables

View file

@ -1,9 +1,13 @@
#!/usr/bin/env node
var pgp = require('pg-promise')()
var psqlUrl = require('../lib/options').postgresql
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
var db = pgp(psqlUrl)
var pgp = require('pg-promise')()
const { PSQL_URL } = require('../lib/constants')
var db = pgp(PSQL_URL)
db.manyOrNone(`select * from transactions where incoming=false
and stage='final_request' and authority='machine'`)

View file

@ -2,11 +2,11 @@
'use strict'
const fs = require('fs')
const options = require('../lib/options-loader')()
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
if (!options.opts.frontCameraDir) {
options.opts.frontCameraDir = '/opt/lamassu-server/frontcamera'
const setEnvVariable = require('../tools/set-env-var')
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
if (!process.env.FRONT_CAMERA_DIR) {
setEnvVariable('FRONT_CAMERA_DIR', '/opt/lamassu-server/frontcamera')
}

View file

@ -1,5 +1,7 @@
#!/usr/bin/env node
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const hdkey = require('ethereumjs-wallet/hdkey')
const hkdf = require('futoin-hkdf')
const db = require('../lib/db')
@ -9,14 +11,14 @@ const mnemonicHelpers = require('../lib/mnemonic-helpers')
const pify = require('pify')
const fs = pify(require('fs'))
const options = require('../lib/options')
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
const defaultPrefixPath = "m/44'/60'/1'/0'"
const paymentPrefixPath = "m/44'/60'/0'/0'"
const address = process.argv[2]
if (!options || !options.mnemonicPath) {
if (!MNEMONIC_PATH) {
console.error(`Unable to fetch mnemonic from your account!`)
process.exit(1)
}
@ -47,7 +49,7 @@ function searchForHdIndex (address) {
}
function fetchMnemonic () {
return fs.readFile(options.mnemonicPath, 'utf8')
return fs.readFile(MNEMONIC_PATH, 'utf8')
.then(mnemonic => computeSeed(mnemonic))
}

View file

@ -1,10 +1,16 @@
#!/usr/bin/env node
const FileStore = require('migrate/lib/file-store')
const _ = require('lodash/fp')
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const db = require('../lib/db')
const migrate = require('../lib/migrate')
const options = require('../lib/options')
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
const MIGRATE_STATE_PATH = process.env.MIGRATE_STATE_PATH
const createMigration = `CREATE TABLE IF NOT EXISTS migrations (
id serial PRIMARY KEY,
data json NOT NULL
@ -14,7 +20,7 @@ const select = 'select * from migrations limit 1'
const getMigrateFile = () => {
return new Promise((resolve, reject) => {
new FileStore(options.migrateStatePath).load((err, store) => {
new FileStore(MIGRATE_STATE_PATH).load((err, store) => {
if (err) return reject(err)
return resolve(store)
})
@ -26,7 +32,7 @@ asyncLocalStorage.run(store, () => {
db.none(createMigration)
.then(() => Promise.all([db.oneOrNone(select), getMigrateFile()]))
.then(([qResult, migrateFile]) => {
process.env.SKIP_SERVER_LOGS = !(qResult && qResult.data.migrations.find(({ title }) => title === '1572524820075-server-support-logs.js'))
process.env.SKIP_SERVER_LOGS = !(qResult && _.find(({ title }) => title === '1572524820075-server-support-logs.js', qResult.data.migrations ?? []))
if (!qResult && migrateFile) {
return db.none('insert into migrations (id, data) values (1, $1)', [migrateFile])
}

View file

@ -1,8 +1,10 @@
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const options = require('../lib/options')
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
const mnemonic = fs.readFileSync(options.mnemonicPath, 'utf8').trim()
const mnemonic = fs.readFileSync(MNEMONIC_PATH, 'utf8').trim()
console.log(mnemonic)

View file

@ -2,22 +2,12 @@
'use strict'
const fs = require('fs')
const setEnvVariable = require('../tools/set-env-var')
const ofacSources = [
{
name: 'sdn_advanced',
url: 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml'
},
{
name: 'cons_advanced',
url: 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml'
}
]
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const options = require('../lib/options-loader')()
if (!options.opts.ofacSources) {
options.opts.ofacSources = ofacSources
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, ' '), 'utf8')
if (!process.env.OFAC_SOURCES_NAMES && !process.env.OFAC_SOURCES_URLS) {
setEnvVariable('OFAC_SOURCES_NAMES', 'sdn_advanced,cons_advanced')
setEnvVariable('OFAC_SOURCES_URLS', 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml')
}

View file

@ -3,10 +3,14 @@
const fs = require('fs')
const hkdf = require('futoin-hkdf')
const options = require('../lib/options')
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const mnemonicHelpers = require('../lib/mnemonic-helpers')
const mnemonic = fs.readFileSync(options.mnemonicPath, 'utf8').trim()
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
const mnemonic = fs.readFileSync(MNEMONIC_PATH, 'utf8').trim()
const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
console.log(hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex'))

View file

@ -1,16 +1,17 @@
#!/usr/bin/env node
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
const userManagement = require('../lib/new-admin/graphql/modules/userManagement')
const authErrors = require('../lib/new-admin/graphql/errors/authentication')
const options = require('../lib/options')
const name = process.argv[2]
const role = process.argv[3]
const domain = options.hostname
const domain = process.env.HOSTNAME
if (!domain) {
console.error('No hostname configured in lamassu.json')
console.error('No hostname configured in the environment')
process.exit(1)
}

View file

@ -6,25 +6,26 @@ const fs = require('fs')
const path = require('path')
const os = require('os')
const mnemonicHelpers = require('../lib/mnemonic-helpers')
const options = require('../lib/options-loader')()
const setEnvVariable = require('../tools/set-env-var')
if (!options.opts.mnemonicPath && options.opts.seedPath) {
const seed = fs.readFileSync(options.opts.seedPath, 'utf8').trim()
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
if (!process.env.MNEMONIC_PATH && process.env.SEED_PATH) {
const seed = fs.readFileSync(process.env.SEED_PATH, 'utf8').trim()
const mnemonic = mnemonicHelpers.fromSeed(seed)
if (process.argv[2] === '--prod') {
options.opts.mnemonicPath = path.resolve('/etc', 'lamassu', 'mnemonics', 'mnemonic.txt')
setEnvVariable('MNEMONIC_PATH', path.resolve('/etc', 'lamassu', 'mnemonics', 'mnemonic.txt'))
} else {
options.opts.mnemonicPath = path.resolve(os.homedir(), '.lamassu', 'mnemonics', 'mnemonic.txt')
setEnvVariable('MNEMONIC_PATH', path.resolve(os.homedir(), '.lamassu', 'mnemonics', 'mnemonic.txt'))
}
if (!fs.existsSync(path.dirname(options.opts.mnemonicPath))) {
fs.mkdirSync(path.dirname(options.opts.mnemonicPath))
if (!fs.existsSync(path.dirname(process.env.MNEMONIC_PATH))) {
fs.mkdirSync(path.dirname(process.env.MNEMONIC_PATH))
}
if (!fs.existsSync(options.opts.mnemonicPath)) {
fs.writeFileSync(options.opts.mnemonicPath, mnemonic, 'utf8')
if (!fs.existsSync(process.env.MNEMONIC_PATH)) {
fs.writeFileSync(process.env.MNEMONIC_PATH, mnemonic, 'utf8')
}
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
}

View file

@ -3,9 +3,13 @@
'use strict'
const pgp = require('pg-promise')()
const psqlUrl = require('../lib/options').postgresql
const db = pgp(psqlUrl)
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const { PSQL_URL } = require('../lib/constants')
const db = pgp(PSQL_URL)
db.many('select data from user_config', 'exchanges')
.then(rows => {

View file

@ -1,13 +1,15 @@
#!/usr/bin/env node
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const login = require('../lib/admin/login')
const options = require('../lib/options')
const name = process.argv[2]
const domain = options.hostname
const domain = process.env.HOSTNAME
if (!domain) {
console.error('No hostname configured in lamassu.json')
console.error('No hostname configured in the environment')
process.exit(1)
}

View file

@ -2,7 +2,7 @@ require('es6-promise').polyfill()
var notifier = require('../lib/notifier')
var db = require('../lib/postgresql_interface')
var psqlUrl = require('../lib/options').postgres
const { PSQL_URL } = require('../lib/constants')
function getBalances () {
return [
@ -11,7 +11,7 @@ function getBalances () {
]
}
db.init(psqlUrl)
db.init(PSQL_URL)
notifier.init(db, getBalances, {lowBalanceThreshold: 10})
console.log('DEBUG0')
notifier.checkStatus()

View file

@ -6,21 +6,21 @@ const fs = require('fs')
const path = require('path')
const os = require('os')
const bip39 = require('bip39')
const options = require('../lib/options-loader')()
const setEnvVariable = require('../tools/set-env-var')
if (options.opts.mnemonicPath && !options.opts.seedPath) {
const mnemonic = fs.readFileSync(options.opts.mnemonicPath, 'utf8')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
if (process.env.MNEMONIC_PATH && !process.env.SEED_PATH) {
const mnemonic = fs.readFileSync(process.env.MNEMONIC_PATH, 'utf8')
const seed = bip39.mnemonicToEntropy(mnemonic.split('\n').join(' ').trim()).toString('hex')
options.opts.seedPath = path.resolve(os.homedir(), '.lamassu', 'seeds', 'seed.txt')
setEnvVariable('SEED_PATH', path.resolve(os.homedir(), '.lamassu', 'seeds', 'seed.txt'))
if (!fs.existsSync(path.dirname(options.opts.seedPath))) {
fs.mkdirSync(path.dirname(options.opts.seedPath))
if (!fs.existsSync(path.dirname(process.env.SEED_PATH))) {
fs.mkdirSync(path.dirname(process.env.SEED_PATH))
}
if (!fs.existsSync(options.opts.seedPath)) {
fs.writeFileSync(options.opts.seedPath, seed, 'utf8')
if (!fs.existsSync(process.env.SEED_PATH)) {
fs.writeFileSync(process.env.SEED_PATH, seed, 'utf8')
}
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
}

View file

@ -20,7 +20,6 @@ const _ = require('lodash/fp')
const machineLoader = require('../machine-loader')
const T = require('../time')
const logger = require('../logger')
const options = require('../options')
const accounts = require('./accounts')
const config = require('./config')
@ -35,18 +34,20 @@ const supportServer = require('./admin-support')
const NEVER = new Date(Date.now() + 100 * T.years)
const REAUTHENTICATE_INTERVAL = T.minute
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
const frontCameraBasedir = _.get('frontCameraDir', options)
const operatorDataBasedir = _.get('operatorDataDir', options)
const HOSTNAME = process.env.HOSTNAME
const KEY_PATH = process.env.KEY_PATH
const CERT_PATH = process.env.CERT_PATH
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
const devMode = argv.dev
const version = require('../../package.json').version
logger.info('Version: %s', version)
const hostname = options.hostname
if (!hostname) {
if (!HOSTNAME) {
logger.error('no hostname specified.')
process.exit(1)
}
@ -82,7 +83,7 @@ app.get('/api/totem', (req, res) => {
if (!name) return res.status(400).send('Name is required')
return pairing.totem(hostname, name)
return pairing.totem(HOSTNAME, name)
.then(totem => res.send(totem))
})
@ -222,27 +223,27 @@ app.use((err, req, res, next) => {
})
const certOptions = {
key: fs.readFileSync(options.keyPath),
cert: fs.readFileSync(options.certPath)
key: fs.readFileSync(KEY_PATH),
cert: fs.readFileSync(CERT_PATH)
}
app.use(serveStatic(path.resolve(__dirname, 'public')))
if (!fs.existsSync(idPhotoCardBasedir)) {
makeDir.sync(idPhotoCardBasedir)
if (!fs.existsSync(ID_PHOTO_CARD_DIR)) {
makeDir.sync(ID_PHOTO_CARD_DIR)
}
if (!fs.existsSync(frontCameraBasedir)) {
makeDir.sync(frontCameraBasedir)
if (!fs.existsSync(FRONT_CAMERA_DIR)) {
makeDir.sync(FRONT_CAMERA_DIR)
}
if (!fs.existsSync(operatorDataBasedir)) {
makeDir.sync(operatorDataBasedir)
if (!fs.existsSync(OPERATOR_DATA_DIR)) {
makeDir.sync(OPERATOR_DATA_DIR)
}
app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, {index: false}))
app.use('/front-camera-photo', serveStatic(frontCameraBasedir, {index: false}))
app.use('/operator-data', serveStatic(operatorDataBasedir, {index: false}))
app.use('/id-card-photo', serveStatic(ID_PHOTO_CARD_DIR, {index: false}))
app.use('/front-camera-photo', serveStatic(FRONT_CAMERA_DIR, {index: false}))
app.use('/operator-data', serveStatic(OPERATOR_DATA_DIR, {index: false}))
function register (req, res, next) {
const otp = req.query.otp
@ -259,7 +260,7 @@ function register (req, res, next) {
const cookieOpts = {
httpOnly: true,
secure: true,
domain: hostname,
domain: HOSTNAME,
sameSite: true,
expires: NEVER
}

View file

@ -9,7 +9,9 @@ const _ = require('lodash/fp')
const serveStatic = require('serve-static')
const path = require('path')
const options = require('../options')
const KEY_PATH = process.env.KEY_PATH
const CERT_PATH = process.env.CERT_PATH
const LAMASSU_CA_PATH = process.env.LAMASSU_CA_PATH
app.use(morgan('dev'))
app.use(helmet({noCache: true}))
@ -20,9 +22,9 @@ app.use(serveStatic(path.resolve(__dirname, '..', '..', 'public'), {
}))
const certOptions = {
key: fs.readFileSync(options.keyPath),
cert: fs.readFileSync(options.certPath),
ca: [fs.readFileSync(options.lamassuCaPath)],
key: fs.readFileSync(KEY_PATH),
cert: fs.readFileSync(CERT_PATH),
ca: [fs.readFileSync(LAMASSU_CA_PATH)],
requestCert: true,
rejectUnauthorized: true
}

View file

@ -4,19 +4,18 @@ const readFile = pify(fs.readFile)
const crypto = require('crypto')
const baseX = require('base-x')
const options = require('../options')
const db = require('../db')
const pairing = require('../pairing')
const ALPHA_BASE = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'
const bsAlpha = baseX(ALPHA_BASE)
const CA_PATH = process.env.CA_PATH
const unpair = pairing.unpair
function totem (hostname, name) {
const caPath = options.caPath
return readFile(caPath)
return readFile(CA_PATH)
.then(data => {
const caHash = crypto.createHash('sha256').update(data).digest()
const token = crypto.randomBytes(32)

View file

@ -1,8 +1,11 @@
const fs = require('fs')
const path = require('path')
const http = require('http')
const https = require('https')
const argv = require('minimist')(process.argv.slice(2))
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const { asyncLocalStorage, defaultStore } = require('./async-storage')
const routes = require('./routes')
const logger = require('./logger')
@ -10,11 +13,13 @@ const poller = require('./poller')
const settingsLoader = require('./new-settings-loader')
const configManager = require('./new-config-manager')
const complianceTriggers = require('./compliance-triggers')
const options = require('./options')
const ofac = require('./ofac/index')
const ofacUpdate = require('./ofac/update')
const devMode = argv.dev || options.http
const KEY_PATH = process.env.KEY_PATH
const CERT_PATH = process.env.CERT_PATH
const devMode = argv.dev || process.env.HTTP
const version = require('../package.json').version
logger.info('Version: %s', version)
@ -66,8 +71,8 @@ function startServer (settings) {
.then(() => {
poller.setup(['public'])
const httpsServerOptions = {
key: fs.readFileSync(options.keyPath),
cert: fs.readFileSync(options.certPath),
key: fs.readFileSync(KEY_PATH),
cert: fs.readFileSync(CERT_PATH),
requestCert: true,
rejectUnauthorized: false
}
@ -80,7 +85,7 @@ function startServer (settings) {
const localPort = 3030
const localServer = http.createServer(routes.localApp)
if (options.devMode) logger.info('In dev mode')
if (devMode) logger.info('In dev mode')
server.listen(port, () => {
logger.info('lamassu-server listening on port ' +

View file

@ -1,10 +1,10 @@
const fs = require('fs')
const options = require('../options')
const common = require('./common')
const MOUNT_POINT = options.blockchainDir
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
const MOUNT_POINT = BLOCKCHAIN_DIR
module.exports = {prepareVolume}

View file

@ -8,7 +8,6 @@ const inquirer = require('inquirer')
const _ = require('lodash/fp')
const { utils: coinUtils } = require('@lamassu/coins')
const options = require('../options')
const settingsLoader = require('../new-settings-loader')
const wallet = require('../wallet')
@ -29,10 +28,12 @@ const PLUGINS = {
ZEC: require('./zcash.js')
}
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
module.exports = {run}
function installedVolumeFilePath (crypto) {
return path.resolve(coinUtils.cryptoDir(crypto, options.blockchainDir), '.installed')
return path.resolve(coinUtils.cryptoDir(crypto, BLOCKCHAIN_DIR), '.installed')
}
function isInstalledVolume (crypto) {
@ -63,7 +64,7 @@ function processCryptos (codes) {
common.es('sudo supervisorctl reread')
common.es('sudo supervisorctl update')
const blockchainDir = options.blockchainDir
const blockchainDir = BLOCKCHAIN_DIR
const backupDir = path.resolve(os.homedir(), 'backups')
const rsyncCmd = `( \
(crontab -l 2>/dev/null || echo -n "") | grep -v "@daily rsync ".*"wallet.dat"; \
@ -83,7 +84,7 @@ function processCryptos (codes) {
function setupCrypto (crypto) {
logger.info(`Installing ${crypto.display}...`)
const cryptoDir = coinUtils.cryptoDir(crypto, options.blockchainDir)
const cryptoDir = coinUtils.cryptoDir(crypto, BLOCKCHAIN_DIR)
makeDir.sync(cryptoDir)
const cryptoPlugin = plugin(crypto)
const oldDir = process.cwd()

View file

@ -1,13 +1,9 @@
const axios = require('axios')
const _ = require('lodash/fp')
const pify = require('pify')
const fs = pify(require('fs'))
const db = require('../db')
const configManager = require('../new-config-manager')
const complianceTriggers = require('../compliance-triggers')
const options = require('../options')
const logger = require('../logger')
const plugins = require('../plugins')
const { getOperatorId } = require('../operator')
@ -15,6 +11,8 @@ const { getOperatorId } = require('../operator')
const TIMEOUT = 10000
const MAX_CONTENT_LENGTH = 2000
const COIN_ATM_RADAR_URL = process.env.COIN_ATM_RADAR_URL
// How long a machine can be down before it's considered offline
const STALE_INTERVAL = '2 minutes'
@ -112,7 +110,7 @@ function getMachines (rates, settings) {
}
function sendRadar (data) {
const url = _.get(['coinAtmRadar', 'url'], options)
const url = COIN_ATM_RADAR_URL
if (_.isEmpty(url)) {
return Promise.reject(new Error('Missing coinAtmRadar url!'))

View file

@ -1,5 +1,13 @@
const T = require('./time')
const POSTGRES_USER = process.env.POSTGRES_USER
const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD
const POSTGRES_HOST = process.env.POSTGRES_HOST
const POSTGRES_PORT = process.env.POSTGRES_PORT
const POSTGRES_DB = process.env.POSTGRES_DB
const PSQL_URL = `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}`
const anonymousCustomer = {
uuid: '47ac1184-8102-11e7-9079-8f13a7117867',
name: 'anonymous'
@ -39,5 +47,6 @@ module.exports = {
CASH_OUT_MINIMUM_AMOUNT_OF_CASSETTES,
CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES,
WALLET_SCORE_THRESHOLD,
RECEIPT
RECEIPT,
PSQL_URL
}

View file

@ -13,20 +13,20 @@ const BN = require('./bn')
const anonymous = require('../lib/constants').anonymousCustomer
const complianceOverrides = require('./compliance_overrides')
const users = require('./users')
const options = require('./options')
const writeFile = util.promisify(fs.writeFile)
const notifierQueries = require('./notifier/queries')
const notifierUtils = require('./notifier/utils')
const NUM_RESULTS = 1000
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
const frontCameraBaseDir = _.get('frontCameraDir', options)
const operatorDataDir = _.get('operatorDataDir', options)
const sms = require('./sms')
const settingsLoader = require('./new-settings-loader')
const logger = require('./logger')
const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel']
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
/**
* Add new customer
*
@ -673,7 +673,7 @@ function updatePhotoCard (id, patch) {
const rpath = _.join(path.sep, _.map(_.wrap(_.join, ''), _.take(3, _.chunk(2, _.split('', hash)))))
// i.e. ../<lamassu-server-home>/idphotocard/24/0e/85
const dirname = path.join(idPhotoCardBasedir, rpath)
const dirname = path.join(ID_PHOTO_CARD_DIR, rpath)
// create the directory tree if needed
_.attempt(() => makeDir.sync(dirname))
@ -736,7 +736,7 @@ function updatePhotos (imagesData, id, dir) {
function updateIdCardData (patch, id) {
/* TODO: fetch operator id */
const operatorId = 'id-operator'
const directory = `${operatorDataDir}/${operatorId}/${id}/`
const directory = `${OPERATOR_DATA_DIR}/${operatorId}/${id}/`
return Promise.resolve(patch)
.then(patch => {
@ -755,7 +755,7 @@ function updateTxCustomerPhoto (imageData) {
return Promise.resolve(imageData)
.then(imageData => {
const newPatch = {}
const directory = `${operatorDataDir}/customersphotos`
const directory = `${OPERATOR_DATA_DIR}/customersphotos`
if (_.isEmpty(imageData)) {
return
@ -826,7 +826,7 @@ function updateFrontCamera (id, patch) {
const rpath = _.join(path.sep, _.map(_.wrap(_.join, ''), _.take(3, _.chunk(2, _.split('', hash)))))
// i.e. ../<lamassu-server-home>/idphotocard/24/0e/85
const dirname = path.join(frontCameraBaseDir, rpath)
const dirname = path.join(FRONT_CAMERA_DIR, rpath)
// create the directory tree if needed
_.attempt(() => makeDir.sync(dirname))

View file

@ -2,7 +2,7 @@ const Pgp = require('pg-promise')
const uuid = require('uuid')
const _ = require('lodash/fp')
const psqlUrl = require('../lib/options').postgresql
const { PSQL_URL } = require('./constants')
const logger = require('./logger')
const eventBus = require('./event-bus')
const { asyncLocalStorage, defaultStore } = require('./async-storage')
@ -87,7 +87,7 @@ const pgp = Pgp({
}
})
const db = stripDefaultDbFuncs(pgp(psqlUrl))
const db = stripDefaultDbFuncs(pgp(PSQL_URL))
eventBus.subscribe('log', args => {
if (process.env.SKIP_SERVER_LOGS) return

View file

@ -1,9 +1,11 @@
const winston = require('winston')
const Postgres = require('./pg-transport')
const options = require('./options')
const { PSQL_URL } = require('./constants')
const LOG_LEVEL = process.env.LOG_LEVEL
const logger = new winston.Logger({
level: options.logLevel,
level: LOG_LEVEL,
transports: [
new (winston.transports.Console)({
timestamp: true,
@ -12,7 +14,7 @@ const logger = new winston.Logger({
humanReadableUnhandledException: true
}),
new Postgres({
connectionString: options.postgresql,
connectionString: PSQL_URL,
tableName: 'server_logs',
handleExceptions: true,
humanReadableUnhandledException: true

View file

@ -8,13 +8,13 @@ const cors = require('cors')
const helmet = require('helmet')
const nocache = require('nocache')
const cookieParser = require('cookie-parser')
const { ApolloServer, AuthenticationError } = require('apollo-server-express')
const { graphqlUploadExpress } = require('graphql-upload')
const { ApolloServer } = require('apollo-server-express')
const _ = require('lodash/fp')
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') })
const { asyncLocalStorage, defaultStore } = require('../async-storage')
const options = require('../options')
const users = require('../users')
const logger = require('../logger')
const { AuthDirective } = require('./graphql/directives')
@ -25,13 +25,16 @@ const { USER_SESSIONS_CLEAR_INTERVAL } = require('../constants')
const { session, cleanUserSessions, buildApolloContext } = require('./middlewares')
const devMode = require('minimist')(process.argv.slice(2)).dev
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
const frontCameraBasedir = _.get('frontCameraDir', options)
const operatorDataBasedir = _.get('operatorDataDir', options)
const hostname = options.hostname
if (!hostname) {
logger.error('no hostname specified.')
const HOSTNAME = process.env.HOSTNAME
const KEY_PATH = process.env.KEY_PATH
const CERT_PATH = process.env.CERT_PATH
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
if (!HOSTNAME) {
logger.error('No hostname specified.')
process.exit(1)
}
@ -77,16 +80,16 @@ apolloServer.applyMiddleware({
// cors on app for /api/register endpoint.
app.use(cors({ credentials: true, origin: devMode && 'https://localhost:3001' }))
app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, { index: false }))
app.use('/front-camera-photo', serveStatic(frontCameraBasedir, { index: false }))
app.use('/operator-data', serveStatic(operatorDataBasedir, { index: false }))
app.use('/id-card-photo', serveStatic(ID_PHOTO_CARD_DIR, { index: false }))
app.use('/front-camera-photo', serveStatic(FRONT_CAMERA_DIR, { index: false }))
app.use('/operator-data', serveStatic(OPERATOR_DATA_DIR, { index: false }))
// Everything not on graphql or api/register is redirected to the front-end
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, '..', '..', 'public', 'index.html')))
const certOptions = {
key: fs.readFileSync(options.keyPath),
cert: fs.readFileSync(options.certPath)
key: fs.readFileSync(KEY_PATH),
cert: fs.readFileSync(CERT_PATH)
}
function run () {

View file

@ -1,6 +1,9 @@
const express = require('express')
const path = require('path')
const { ApolloServer } = require('apollo-server-express')
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') })
const { typeDefs, resolvers } = require('./graphql/schema')
const logger = require('../logger')

View file

@ -3,12 +3,9 @@ const router = express.Router()
const session = require('express-session')
const PgSession = require('connect-pg-simple')(session)
const db = require('../../db')
const options = require('../../options')
const { USER_SESSIONS_TABLE_NAME } = require('../../constants')
const { getOperatorId } = require('../../operator')
const hostname = options.hostname
router.use('*', async (req, res, next) => getOperatorId('authentication').then(({ operatorId }) => session({
store: new PgSession({
pgPromise: db,

View file

@ -5,24 +5,25 @@ const crypto = require('crypto')
const baseX = require('base-x')
const { parse, NIL } = require('uuid')
const options = require('../../options')
const db = require('../../db')
const pairing = require('../../pairing')
const ALPHA_BASE = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'
const bsAlpha = baseX(ALPHA_BASE)
const CA_PATH = process.env.CA_PATH
const HOSTNAME = process.env.HOSTNAME
const unpair = pairing.unpair
function totem (name) {
const caPath = options.caPath
return readFile(caPath)
return readFile(CA_PATH)
.then(data => {
const caHash = crypto.createHash('sha256').update(data).digest()
const token = crypto.randomBytes(32)
const hexToken = token.toString('hex')
const caHexToken = crypto.createHash('sha256').update(hexToken).digest('hex')
const buf = Buffer.concat([caHash, token, Buffer.from(options.hostname)])
const buf = Buffer.concat([caHash, token, Buffer.from(HOSTNAME)])
const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)'
return db.none(sql, [hexToken, caHexToken, name])

View file

@ -4,23 +4,24 @@ const util = require('util')
const loader = require('./loading')
const matcher = require('./matching')
const nameUtils = require('./name-utils')
const options = require('../options')
const _ = require('lodash/fp')
const logger = require('../logger')
const debugLog = require('../pp')(__filename) // KOSTIS TODO: remove
const OFAC_DATA_DIR = process.env.OFAC_DATA_DIR
let structs = null
const readdir = util.promisify(fs.readdir)
function load () {
if (!options.ofacDataDir) {
const message = 'The ofacDataDir option has not been set in lamassu.json'
if (!OFAC_DATA_DIR) {
const message = 'The ofacDataDir option has not been set in the environment'
return Promise.reject(new Error(message))
}
const ofacSourcesDir = path.join(options.ofacDataDir, 'sources')
const ofacSourcesDir = path.join(OFAC_DATA_DIR, 'sources')
return readdir(ofacSourcesDir)
.then(_.flow(

View file

@ -4,12 +4,23 @@ const url = require('url')
const fs = require('fs')
const path = require('path')
const util = require('util')
const options = require('../options')
const _ = require('lodash/fp')
const logger = require('../logger')
const DOWNLOAD_DIR = path.resolve('/tmp')
const OFAC_DATA_DIR = process.env.OFAC_DATA_DIR
const OFAC_SOURCES_NAMES = process.env.OFAC_SOURCES_NAMES.split(',')
const OFAC_SOURCES_URLS = process.env.OFAC_SOURCES_URLS.split(',')
const ofacSources = _.map(
it => ({
name: it[0],
url: it[1]
}),
_.zip(OFAC_SOURCES_NAMES, OFAC_SOURCES_URLS)
)
function mkdir (path) {
return new Promise((resolve, reject) => {
fs.mkdir(path, err => {
@ -97,14 +108,12 @@ const moveToSourcesDir = (srcFile, ofacSourcesDir) => {
}
function update () {
const OFAC_DATA_DIR = options.ofacDataDir
if (!OFAC_DATA_DIR) {
throw new Error('ofacDataDir must be defined in lamassu.json')
throw new Error('ofacDataDir must be defined in the environment')
}
if (!options.ofacSources) {
logger.error('ofacSources must be defined in lamassu.json')
if (!ofacSources) {
logger.error('ofacSources must be defined in the environment')
}
const OFAC_SOURCES_DIR = path.join(OFAC_DATA_DIR, 'sources')
@ -125,7 +134,7 @@ function update () {
return {}
})
const promiseNewEtags = Promise.resolve(options.ofacSources || [])
const promiseNewEtags = Promise.resolve(ofacSources || [])
.then(sources => Promise.all(_.map(promiseGetEtag, sources))
.then(etags => _.map(
([source, etag]) => ({...source, etag}),

View file

@ -4,11 +4,12 @@ const os = require('os')
const argv = require('minimist')(process.argv.slice(2))
const _ = require('lodash/fp')
require('dotenv').config()
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const DATABASE = process.env.LAMASSU_DB ?? 'PROD'
const dbMapping = psqlConf => ({
STRESS_TEST: _.replace('lamassu', 'lamassu_stress', psqlConf),
PAZUZ: _.replace('lamassu', 'lamassu_pazuz', psqlConf),
RELEASE: _.replace('lamassu', 'lamassu_release', psqlConf),
DEV: _.replace('lamassu', 'lamassu', psqlConf),
PROD: _.replace('lamassu', 'lamassu', psqlConf)

View file

@ -2,10 +2,11 @@ const fs = require('fs')
const pify = require('pify')
const readFile = pify(fs.readFile)
const db = require('./db')
const options = require('./options')
const logger = require('./logger')
const uuid = require('uuid')
const CA_PATH = process.env.CA_PATH
// A machine on an older version (no multicassette code) could be paired with a server with multicassette code.
// This makes sure that the server stores a default value
const DEFAULT_NUMBER_OF_CASSETTES = 2
@ -58,8 +59,7 @@ function authorizeCaDownload (caToken) {
.then(r => {
if (r.expired) throw new Error('Expired')
const caPath = options.caPath
return readFile(caPath, {encoding: 'utf8'})
return readFile(CA_PATH, {encoding: 'utf8'})
})
}

View file

@ -6,9 +6,7 @@ const _ = require('lodash/fp')
const request = require('request-promise')
const { utils: coinUtils } = require('@lamassu/coins')
const options = require('../../options')
const blockchainDir = options.blockchainDir
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
module.exports = {
fetch, fetchDigest, parseConf, rpcConfig
@ -108,7 +106,7 @@ function parseConf (confPath) {
function rpcConfig (cryptoRec) {
try {
const configPath = coinUtils.configPath(cryptoRec, blockchainDir)
const configPath = coinUtils.configPath(cryptoRec, BLOCKCHAIN_DIR)
const config = parseConf(configPath)
return {
username: config.rpcuser,

View file

@ -1,7 +1,7 @@
const axios = require('axios')
const _ = require('lodash/fp')
const options = require('../../../options')
const STRIKE_BASE_URL = process.env.STRIKE_BASE_URL
module.exports = {
newAddress,
@ -9,7 +9,7 @@ module.exports = {
cryptoNetwork
}
axios.defaults.baseURL = _.get('strike.baseUrl', options)
axios.defaults.baseURL = STRIKE_BASE_URL
if (_.isEmpty(axios.defaults.baseURL)) {
throw new Error('Missing Strike baseUrl!')
}

View file

@ -3,13 +3,14 @@ const lnd = require('lnd-async')
const BN = require('../../../bn')
const E = require('../../../error')
const { utils: coinUtils } = require('@lamassu/coins')
const options = require('../../../options')
const _ = require('lodash/fp')
const cryptoRec = coinUtils.getCryptoCurrency('BTC')
const unitScale = cryptoRec.unitScale
const LND = process.env.LIGHTNING_NETWORK_DAEMON
module.exports = {
balance,
sendCoins,
@ -20,7 +21,7 @@ module.exports = {
}
function connect () {
return lnd.connect(options.lnd || {})
return lnd.connect(LND || {})
}
function cryptoNetwork (account, cryptoCode, settings, operatorId) {

View file

@ -7,14 +7,13 @@ const { default: PQueue } = require('p-queue')
const BN = require('../../../bn')
const E = require('../../../error')
const { logger } = require('../../../blockchain/common')
const options = require('../../../options')
const jsonRpc = require('../../common/json-rpc')
const blockchainDir = options.blockchainDir
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
const cryptoRec = utils.getCryptoCurrency(COINS.XMR)
const configPath = utils.configPath(cryptoRec, blockchainDir)
const walletDir = path.resolve(utils.cryptoDir(cryptoRec, blockchainDir), 'wallets')
const configPath = utils.configPath(cryptoRec, BLOCKCHAIN_DIR)
const walletDir = path.resolve(utils.cryptoDir(cryptoRec, BLOCKCHAIN_DIR), 'wallets')
const DIGEST_QUEUE = new PQueue({
concurrency: 1,

View file

@ -4,11 +4,11 @@ const E = require('../../../error')
const _ = require('lodash/fp')
const ENV = process.env.NODE_ENV === undefined || process.env.NODE_ENV === 'development' ? 'development' : 'production'
const SUPPORTED_COINS = ['BTC', 'ZEC', 'LTC', 'BCH', 'DASH', 'ETH']
const SUPPORTED_COINS = ['BTC']
const axios = require('axios').create({
// TODO: get rejectUnauthorized true to work
baseURL: ENV === 'development' ? 'https://localhost:5555/api/' : process.env.PAZUZ_API_WALLET_URL,
baseURL: `${process.env.WALLET_URL}/api`,
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
@ -22,9 +22,8 @@ function balance (account, cryptoCode, settings, operatorId) {
return checkCryptoCode(cryptoCode)
.then(() => {
return axios.post('/balance', {
account,
cryptoCode,
settings,
config: settings.config,
operatorId
})
})
@ -39,9 +38,8 @@ function sendCoins (account, tx, settings, operatorId) {
return checkCryptoCode(cryptoCode)
.then(() => {
return axios.post('/sendCoins', {
account,
tx,
settings,
config: settings.config,
operatorId
})
})
@ -57,10 +55,9 @@ function sendCoins (account, tx, settings, operatorId) {
function newAddress (account, info, tx, settings, operatorId) {
return checkCryptoCode(info.cryptoCode)
.then(() => axios.post('/newAddress', {
account,
info,
tx,
settings,
config: settings.config,
operatorId
}))
.then(({ data }) => {

View file

@ -6,7 +6,6 @@ const morgan = require('morgan')
const nocache = require('nocache')
const logger = require('./logger')
const options = require('./options')
const authorize = require('./middlewares/authorize')
const errorHandler = require('./middlewares/errorHandler')
@ -41,7 +40,7 @@ const configRequiredRoutes = [
'/tx',
'/verify_promo_code'
]
const devMode = argv.dev || options.http
const devMode = argv.dev || process.env.HTTP
// middleware setup
app.use(compression({ threshold: 500 }))

View file

@ -7,7 +7,6 @@ const pify = require('pify')
const fs = pify(require('fs'))
const mnemonicHelpers = require('./mnemonic-helpers')
const options = require('./options')
const ph = require('./plugin-helper')
const layer2 = require('./layer2')
const httpError = require('./route-helpers').httpError
@ -20,6 +19,8 @@ const INSUFFICIENT_FUNDS_CODE = 570
const INSUFFICIENT_FUNDS_NAME = 'InsufficientFunds'
const ZERO_CONF_EXPIRATION = 60000
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
function computeSeed (masterSeed) {
return hkdf(masterSeed, 32, { salt: 'lamassu-server-salt', info: 'wallet-seed' })
}
@ -29,7 +30,7 @@ function computeOperatorId (masterSeed) {
}
function fetchWallet (settings, cryptoCode) {
return fs.readFile(options.mnemonicPath, 'utf8')
return fs.readFile(MNEMONIC_PATH, 'utf8')
.then(mnemonic => {
const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
const plugin = configManager.getWalletSettings(cryptoCode, settings.config).wallet

View file

@ -5,7 +5,6 @@ const hkdf = require('futoin-hkdf')
const state = require('../lib/middlewares/state')
const mnemonicHelpers = require('../lib/mnemonic-helpers')
const options = require('../lib/options')
function computeOperatorId (masterSeed) {
return hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex')
@ -13,7 +12,7 @@ function computeOperatorId (masterSeed) {
function getMnemonic () {
if (state.mnemonic) return Promise.resolve(state.mnemonic)
return fs.readFile(options.mnemonicPath, 'utf8').then(mnemonic => {
return fs.readFile(process.env.MNEMONIC_PATH, 'utf8').then(mnemonic => {
state.mnemonic = mnemonic
return mnemonic
})

View file

@ -2,4 +2,4 @@ SKIP_PREFLIGHT_CHECK=true
HTTPS=true
REACT_APP_TYPE_CHECK_SANCTUARY=false
PORT=3001
REACT_APP_BUILD_TARGET=LAMASSU
REACT_APP_BUILD_TARGET=PAZUZ

View file

@ -170,22 +170,26 @@ const Accounting = () => {
]
return (
<>
<TitleSection title="Accounting" />
<Assets
balance={operatorData.fiatBalances[operatorData.preferredFiatCurrency]}
hedgingReserve={operatorData.hedgingReserve ?? 0}
currency={operatorData.preferredFiatCurrency}
/>
<H4 className={classes.tableTitle}>Fiat balance history</H4>
<DataTable
loading={loading}
emptyText="No transactions so far"
elements={elements}
data={operatorData.fundings ?? []}
rowSize="sm"
/>
</>
!loading && (
<>
<TitleSection title="Accounting" />
<Assets
balance={
operatorData.fiatBalances[operatorData.preferredFiatCurrency]
}
hedgingReserve={operatorData.hedgingReserve ?? 0}
currency={operatorData.preferredFiatCurrency}
/>
<H4 className={classes.tableTitle}>Fiat balance history</H4>
<DataTable
loading={loading}
emptyText="No transactions so far"
elements={elements}
data={operatorData.fundings ?? []}
rowSize="sm"
/>
</>
)
)
}

32
tools/build-dev-env.js Normal file
View file

@ -0,0 +1,32 @@
const fs = require('fs')
const os = require('os')
const path = require('path')
const setEnvVariable = require('./set-env-var')
fs.copyFileSync(path.resolve(__dirname, '../.sample.env'), path.resolve(__dirname, '../.env'))
setEnvVariable('LAMASSU_DB', 'DEV')
setEnvVariable('POSTGRES_USER', 'postgres')
setEnvVariable('POSTGRES_PASSWORD', 'postgres123')
setEnvVariable('POSTGRES_HOST', 'localhost')
setEnvVariable('POSTGRES_PORT', '5432')
setEnvVariable('POSTGRES_DB', 'lamassu')
setEnvVariable('CA_PATH', `${process.env.PWD}/certs/Lamassu_OP_Root_CA.pem`)
setEnvVariable('CERT_PATH', `${process.env.PWD}/certs/Lamassu_OP.pem`)
setEnvVariable('KEY_PATH', `${process.env.PWD}/certs/Lamassu_OP.key`)
setEnvVariable('MNEMONIC_PATH', `${process.env.HOME}/.lamassu/mnemonics/mnemonic.txt`)
setEnvVariable('MIGRATE_STATE_PATH', `${process.env.HOME}/.lamassu/.migrate`)
setEnvVariable('OFAC_DATA_DIR', `${process.env.HOME}/.lamassu/ofac`)
setEnvVariable('ID_PHOTO_CARD_DIR', `${process.env.HOME}/.lamassu/idphotocard`)
setEnvVariable('FRONT_CAMERA_DIR', `${process.env.HOME}/.lamassu/frontcamera`)
setEnvVariable('OPERATOR_DATA_DIR', `${process.env.HOME}/.lamassu/operatordata`)
setEnvVariable('OFAC_SOURCES_NAMES', 'sdn_advanced,cons_advanced')
setEnvVariable('OFAC_SOURCES_URLS', 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml')
setEnvVariable('HOSTNAME', 'localhost')
setEnvVariable('LOG_LEVEL', 'debug')

45
tools/build-prod-env.js Normal file
View file

@ -0,0 +1,45 @@
const fs = require('fs')
const os = require('os')
const path = require('path')
const argv = require('minimist')(process.argv.slice(2))
const _ = require('lodash/fp')
const setEnvVariable = require('./set-env-var')
const requiredParams = ['db-password', 'hostname']
if (!_.isEqual(_.intersection(_.keys(argv), requiredParams), requiredParams)) {
console.error('Usage: node tools/build-prod-env.js --db-password <DB_PASSWORD> --hostname <IP>')
process.exit(2)
}
fs.copyFileSync(path.resolve(__dirname, '../.sample.env'), path.resolve(__dirname, '../.env'))
setEnvVariable('POSTGRES_USER', 'lamassu_pg')
setEnvVariable('POSTGRES_PASSWORD', `${argv['db-password']}`)
setEnvVariable('POSTGRES_HOST', 'localhost')
setEnvVariable('POSTGRES_PORT', '5432')
setEnvVariable('POSTGRES_DB', 'lamassu')
setEnvVariable('LAMASSU_CA_PATH', `/etc/ssl/certs/Lamassu_CA.pem`)
setEnvVariable('CA_PATH', `/etc/ssl/certs/Lamassu_OP_Root_CA.pem`)
setEnvVariable('CERT_PATH', `/etc/ssl/certs/Lamassu_OP.pem`)
setEnvVariable('KEY_PATH', `/etc/ssl/certs/Lamassu_OP.key`)
setEnvVariable('MNEMONIC_PATH', `/etc/lamassu/mnemonics/mnemonic.txt`)
setEnvVariable('MIGRATE_STATE_PATH', `/etc/lamassu/.migrate`)
setEnvVariable('BLOCKCHAIN_DIR', `/mnt/blockchains`)
setEnvVariable('OFAC_DATA_DIR', `/var/lamassu/ofac`)
setEnvVariable('ID_PHOTO_CARD_DIR', `/opt/lamassu-server/idphotocard`)
setEnvVariable('FRONT_CAMERA_DIR', `/opt/lamassu-server/frontcamera`)
setEnvVariable('OPERATOR_DATA_DIR', `/opt/lamassu-server/operatordata`)
setEnvVariable('STRIKE_BASE_URL', `https://api.strike.acinq.co/api/`)
setEnvVariable('COIN_ATM_RADAR_URL', `https://coinatmradar.info/api/lamassu/`)
setEnvVariable('OFAC_SOURCES_NAMES', 'sdn_advanced,cons_advanced')
setEnvVariable('OFAC_SOURCES_URLS', 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml')
setEnvVariable('HOSTNAME', `${argv.hostname}`)
setEnvVariable('LOG_LEVEL', 'info')

View file

@ -91,32 +91,6 @@ rm /tmp/Lamassu_OP.csr.pem
mkdir -p $OFAC_DATA_DIR/sources
touch $OFAC_DATA_DIR/etags.json
cat <<EOF > $CONFIG_DIR/lamassu.json
{
"postgresql": "psql://postgres:$POSTGRES_PASS@localhost/lamassu",
"mnemonicPath": "$MNEMONIC_FILE",
"caPath": "$CA_PATH",
"certPath": "$SERVER_CERT_PATH",
"keyPath": "$SERVER_KEY_PATH",
"hostname": "$DOMAIN",
"logLevel": "debug",
"lamassuCaPath": "$LAMASSU_CA_PATH",
"migrateStatePath": "$MIGRATE_STATE_PATH",
"ofacDataDir": "$OFAC_DATA_DIR",
"ofacSources": [
{
"name": "sdn_advanced",
"url": "https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml"
},
{
"name": "cons_advanced",
"url": "https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml"
}
],
"idPhotoCardDir": "$IDPHOTOCARD_DIR",
"frontCameraDir": "$FRONTCAMERA_DIR",
"operatorDataDir": "$OPERATOR_DIR"
}
EOF
node tools/build-dev-env.js
echo "Done."

24
tools/set-env-var.js Normal file
View file

@ -0,0 +1,24 @@
const fs = require('fs')
const os = require('os')
const path = require('path')
const setEnvVariable = (key, value) => {
const ENV_VARIABLES = fs.readFileSync(path.resolve(__dirname, '../.env'), 'utf-8').split(os.EOL)
const target = ENV_VARIABLES.indexOf(ENV_VARIABLES.find(line => line.match(new RegExp(`^${key}=`))))
if (target < 0) {
// The variable doesn't exist, add it
ENV_VARIABLES.push(`${key}=${value}`)
} else {
// .env already has that variable set, or at least has the definition of its key
//
// This is currently circumventing a possible bug on dotenv
// where the variables on this script were showing up as undefined on the first run despite the key existing,
// while on a second run they'd appear as empty string, as intended
ENV_VARIABLES.splice(target, 1, `${key}=${value}`)
}
fs.writeFileSync(path.resolve(__dirname, '../.env'), ENV_VARIABLES.join(os.EOL))
}
module.exports = setEnvVariable