diff --git a/.env.copy b/.env.copy deleted file mode 100644 index 50b97e0d..00000000 --- a/.env.copy +++ /dev/null @@ -1,17 +0,0 @@ -DB_USERNAME= -DB_PASSWORD= -DB_NAME= -DB_HOST= -CW_PORT=31310 -DATALAYER_URL=https://localhost:8562 -WALLET_URL=https://localhost:9256 -USE_SIMULATOR=false -TESTNET_PICKLIST_URL=https://climate-warehouse.s3.us-west-2.amazonaws.com/public/picklists.json -TESTNET_DEFAULT_ORGANIZATIONS=https://climate-warehouse.s3.us-west-2.amazonaws.com/public/cw-organizations-testnet.json -READ_ONLY=false -IS_GOVERNANCE_BODY=false -API_KEY= -GOVERANCE_BODY_ID=8790c347e96eda4266fa5805a16b4baeecf8018433995782555a7b6883fdd868 -GOVERNANCE_BODY_IP=35.82.228.204 -GOVERNANCE_BODY_PORT=8000 -CHIA_NETWORK=mainnet \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 0fcb8628..b70715a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,6 @@ FROM node:16 WORKDIR /usr/src/app RUN npm install -g json COPY package*.json ./ -COPY .env.copy ./.env RUN json -I -f package.json -e "this.type=\"commonjs\"" RUN npm set-script prepare "" RUN npm set-script requirements-check "" diff --git a/package-lock.json b/package-lock.json index 45b1dac4..501742d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "express-fileupload": "^1.2.1", "express-joi-validation": "^5.0.0", "joi": "^17.5.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", "log-update": "^4.0.0", "mysql2": "^2.3.3", @@ -3783,8 +3784,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/args-js": { "version": "0.10.12", @@ -10729,7 +10729,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -18949,8 +18948,7 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "args-js": { "version": "0.10.12", @@ -24170,7 +24168,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "requires": { "argparse": "^2.0.1" } diff --git a/package.json b/package.json index 211ebf61..52dc4bdf 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "prepare": "husky install", "build": "babel src --keep-file-extension --out-dir build --copy-files", "build-migrations": "babel migrations --keep-file-extension --out-dir dist/migrations --copy-files", - "prepare-binary": "rm -rf dist && mkdir dist && cp .env.copy dist/.env", + "prepare-binary": "rm -rf dist && mkdir dist", "create-win-x64-dist": "npm run build && npm run prepare-binary && pkg package.json -t node16-win-x64 --out-path dist", "create-mac-x64-dist": "npm run build && npm run prepare-binary && pkg package.json -t node16-macos-x64 --out-path dist", "create-linux-x64-dist": "npm run build && npm run prepare-binary && pkg package.json -t node16-linux-x64 --out-path dist" @@ -37,6 +37,7 @@ "express-fileupload": "^1.2.1", "express-joi-validation": "^5.0.0", "joi": "^17.5.0", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", "log-update": "^4.0.0", "mysql2": "^2.3.3", diff --git a/src/config/config.cjs b/src/config/config.cjs index 91fcfa47..ba64bfa1 100644 --- a/src/config/config.cjs +++ b/src/config/config.cjs @@ -1,10 +1,51 @@ require('dotenv').config(); +const _ = require('lodash'); +const yaml = require('js-yaml'); +const fs = require('fs'); const os = require('os'); +const path = require('path'); const homeDir = os.homedir(); +const defaultConfig = require('../utils/defaultConfig.json'); const persistanceFolder = `${homeDir}/.chia/climate-warehouse`; +// Adding this duplicate function here because im having trouble +// importing it in from utils folder +const getConfig = _.memoize(() => { + const configFile = path.resolve( + `${homeDir}/.chia/climate-warehouse/config.yaml`, + ); + + // First write it to chia home + if (!fs.existsSync(configFile)) { + try { + fs.writeFileSync(configFile, yaml.dump(defaultConfig), 'utf8'); + } catch (err) { + // if it still doesnt exist that means we are in an env without write permissions + // so just load the default en + if (typeof process.env.USE_SIMULATOR === 'string') { + defaultConfig.APP.USE_SIMULATOR = process.env.USE_SIMULATOR === 'true'; + } + + console.log('Cant write config file, falling back to defaults'); + return yaml.load(yaml.dump(defaultConfig)); + } + } + + try { + const yml = yaml.load(fs.readFileSync(configFile, 'utf8')); + + if (typeof process.env.USE_SIMULATOR === 'string') { + yml.APP.USE_SIMULATOR = process.env.USE_SIMULATOR === 'true'; + } + + return yml; + } catch (e) { + console.log(e, `Config file not found at ${configFile}`); + } +}); + module.exports = { local: { dialect: 'sqlite', @@ -27,10 +68,10 @@ module.exports = { logging: false, }, mirror: { - username: process.env.DB_USERNAME || '', - password: process.env.DB_PASSWORD || '', - database: process.env.DB_NAME || '', - host: process.env.DB_HOST || '', + username: getConfig().MIRROR_DB.DB_USERNAME || '', + password: getConfig().MIRROR_DB.DB_PASSWORD || '', + database: getConfig().MIRROR_DB.DB_NAME || '', + host: getConfig().MIRROR_DB.DB_HOST || '', dialect: 'mysql', logging: false, }, diff --git a/src/database/index.js b/src/database/index.js index 8b86b13d..0ce223f8 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -4,6 +4,7 @@ import Debug from 'debug'; Debug.enable('climate-warehouse:mirror-database'); const log = Debug('climate-warehouse:mirror-database'); import mysql from 'mysql2/promise'; +import { getConfig } from '../utils/config-loader'; import { migrations } from './migrations'; import { seeders } from './seeders'; @@ -26,7 +27,10 @@ export const safeMirrorDbHandler = (callback) => { callback(); }) .catch(() => { - if (process.env.DB_HOST && process.env.DB_HOST !== '') { + if ( + getConfig().MIRROR_DB.DB_HOST && + getConfig().MIRROR_DB.DB_HOST !== '' + ) { log('Mirror DB not connected'); } }); @@ -99,18 +103,18 @@ export const prepareDb = async () => { if ( mirrorConfig == 'mirror' && - process.env.DB_HOST && - process.env.DB_HOST !== '' + getConfig().MIRROR_DB.DB_HOST && + getConfig().MIRROR_DB.DB_HOST !== '' ) { const connection = await mysql.createConnection({ - host: process.env.DB_HOST, + host: getConfig().MIRROR_DB.DB_HOST, port: 3306, - user: process.env.DB_USERNAME, - password: process.env.DB_PASSWORD, + user: getConfig().MIRROR_DB.DB_USERNAME, + password: getConfig().MIRROR_DB.DB_PASSWORD, }); await connection.query( - `CREATE DATABASE IF NOT EXISTS \`${process.env.DB_NAME}\`;`, + `CREATE DATABASE IF NOT EXISTS \`${getConfig().MIRROR_DB.DB_NAME}\`;`, ); const db = new Sequelize(config[mirrorConfig]); diff --git a/src/datalayer/persistance.js b/src/datalayer/persistance.js index 8b3221bd..b5205e2a 100644 --- a/src/datalayer/persistance.js +++ b/src/datalayer/persistance.js @@ -4,6 +4,7 @@ import fs from 'fs'; import path from 'path'; import request from 'request-promise'; import os from 'os'; +import { getConfig } from '../utils/config-loader'; import Debug from 'debug'; Debug.enable('climate-warehouse:datalayer:persistance'); @@ -12,7 +13,7 @@ const log = Debug('climate-warehouse:datalayer:persistance'); process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; -const rpcUrl = process.env.DATALAYER_URL; +const rpcUrl = getConfig().APP.DATALAYER_URL; const getBaseOptions = () => { const homeDir = os.homedir(); diff --git a/src/datalayer/syncService.js b/src/datalayer/syncService.js index 577928b1..1bdb8b72 100644 --- a/src/datalayer/syncService.js +++ b/src/datalayer/syncService.js @@ -2,6 +2,7 @@ import _ from 'lodash'; import { decodeHex, decodeDataLayerResponse } from '../utils/datalayer-utils'; import { Organization, Staging, ModelKeys } from '../models'; +import { getConfig } from '../utils/config-loader'; import * as dataLayer from './persistance'; import * as simulator from './simulator'; @@ -10,6 +11,8 @@ import Debug from 'debug'; Debug.enable('climate-warehouse:datalayer:syncService'); const log = Debug('climate-warehouse:datalayer:syncService'); +const { USE_SIMULATOR } = getConfig().APP; + const POLLING_INTERVAL = 5000; const frames = ['-', '\\', '|', '/']; @@ -36,7 +39,7 @@ const startDataLayerUpdatePolling = async () => { const syncDataLayerStoreToClimateWarehouse = async (storeId, rootHash) => { let storeData; - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { storeData = await simulator.getStoreData(storeId, rootHash); } else { storeData = await dataLayer.getStoreData(storeId, rootHash); @@ -119,7 +122,7 @@ const dataLayerWasUpdated = async () => { } let rootResponse; - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { rootResponse = await simulator.getRoots(subscribedOrgIds); } else { rootResponse = await dataLayer.getRoots(subscribedOrgIds); @@ -160,7 +163,7 @@ const dataLayerWasUpdated = async () => { }; const subscribeToStoreOnDataLayer = async (storeId, ip, port) => { - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { return simulator.subscribeToStoreOnDataLayer(storeId, ip, port); } else { return dataLayer.subscribeToStoreOnDataLayer(storeId, ip, port); @@ -192,7 +195,7 @@ const getSubscribedStoreData = async ( } } - if (process.env.USE_SIMULATOR !== 'true') { + if (!USE_SIMULATOR) { const storeExistAndIsConfirmed = await dataLayer.getRoot(storeId, true); if (!storeExistAndIsConfirmed) { log(`Retrying...`, retry + 1); @@ -205,7 +208,7 @@ const getSubscribedStoreData = async ( } let encodedData; - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { encodedData = await simulator.getStoreData(storeId); } else { encodedData = await dataLayer.getStoreData(storeId); @@ -231,13 +234,13 @@ const getSubscribedStoreData = async ( }; const getRootHistory = (storeId) => { - if (process.env.USE_SIMULATOR !== 'true') { + if (!USE_SIMULATOR) { return dataLayer.getRootHistory(storeId); } }; const getRootDiff = (storeId, root1, root2) => { - if (process.env.USE_SIMULATOR !== 'true') { + if (!USE_SIMULATOR) { return dataLayer.getRootDiff(storeId, root1, root2); } }; diff --git a/src/datalayer/wallet.js b/src/datalayer/wallet.js index a38c50c6..4c39e39d 100644 --- a/src/datalayer/wallet.js +++ b/src/datalayer/wallet.js @@ -2,10 +2,11 @@ import fs from 'fs'; import path from 'path'; import request from 'request-promise'; import os from 'os'; +import { getConfig } from '../utils/config-loader'; process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; -const rpcUrl = process.env.WALLET_URL; +const rpcUrl = getConfig().APP.WALLET_URL; const getBaseOptions = () => { const homeDir = os.homedir(); @@ -81,7 +82,7 @@ const hasUnconfirmedTransactions = async () => { }; const getPublicAddress = async () => { - if (process.env.USE_SIMULATOR === 'true') { + if (getConfig().APP.USE_SIMULATOR) { return Promise.resolve('xch33300ddsje98f33hkkdf9dfuSIMULATED_ADDRESS'); } diff --git a/src/datalayer/writeService.js b/src/datalayer/writeService.js index de13109f..f8410689 100644 --- a/src/datalayer/writeService.js +++ b/src/datalayer/writeService.js @@ -4,14 +4,17 @@ import * as dataLayer from './persistance'; import wallet from './wallet'; import * as simulator from './simulator'; import { encodeHex } from '../utils/datalayer-utils'; +import { getConfig } from '../utils/config-loader'; import Debug from 'debug'; Debug.enable('climate-warehouse:datalayer:writeService'); const log = Debug('climate-warehouse:datalayer:writeService'); +const { USE_SIMULATOR } = getConfig().APP; + const createDataLayerStore = async () => { let storeId; - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { storeId = await simulator.createDataLayerStore(); } else { storeId = await dataLayer.createDataLayerStore(); @@ -58,7 +61,7 @@ const pushChangesWhenStoreIsAvailable = async ( failedCallback = _.noop, retryAttempts = 0, ) => { - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { return simulator.pushChangeListToDataLayer(storeId, changeList); } else { const hasUnconfirmedTransactions = @@ -87,7 +90,8 @@ const pushDataLayerChangeList = (storeId, changeList, failedCallback) => { }; const dataLayerAvailable = async () => { - if (process.env.USE_SIMULATOR === 'true') { + console.log('!!!!!!!!!!!!!!!!', USE_SIMULATOR, typeof USE_SIMULATOR); + if (USE_SIMULATOR) { return simulator.dataLayerAvailable(); } else { return dataLayer.dataLayerAvailable(); diff --git a/src/models/governance/governance.model.js b/src/models/governance/governance.model.js index 3c0b9b38..4eafe877 100644 --- a/src/models/governance/governance.model.js +++ b/src/models/governance/governance.model.js @@ -6,6 +6,10 @@ import { sequelize } from '../../database'; import { Meta } from '../../models'; import datalayer from '../../datalayer'; import { keyValueToChangeList } from '../../utils/datalayer-utils'; +import { getConfig } from '../../utils/config-loader'; + +const { GOVERANCE_BODY_ID, GOVERNANCE_BODY_IP, GOVERNANCE_BODY_PORT } = + getConfig().GOVERNANCE; import ModelTypes from './governance.modeltypes.cjs'; @@ -13,7 +17,7 @@ class Governance extends Model { static async createGoveranceBody() { const goveranceBodyId = await datalayer.createDataLayerStore(); - if (process.env.GOVERANCE_BODY_ID && process.env.GOVERANCE_BODY_ID !== '') { + if (GOVERANCE_BODY_ID && GOVERANCE_BODY_ID !== '') { throw new Error( 'You are already listening to another governance body. Please clear GOVERANCE_BODY_ID from your env and try again', ); @@ -28,9 +32,6 @@ class Governance extends Model { } static async sync() { - const { GOVERANCE_BODY_ID, GOVERNANCE_BODY_IP, GOVERNANCE_BODY_PORT } = - process.env; - if (!GOVERANCE_BODY_ID || !GOVERNANCE_BODY_IP || !GOVERNANCE_BODY_PORT) { throw new Error('Missing information in env to sync Governance data'); } diff --git a/src/models/organizations/organizations.model.js b/src/models/organizations/organizations.model.js index 7aba7999..09ccf00b 100644 --- a/src/models/organizations/organizations.model.js +++ b/src/models/organizations/organizations.model.js @@ -11,6 +11,9 @@ import { serverAvailable, } from '../../utils/data-loaders'; +import { getConfig } from '../../utils/config-loader'; +const { USE_SIMULATOR } = getConfig().APP; + import Debug from 'debug'; Debug.enable('climate-warehouse:organizations'); const log = Debug('climate-warehouse:organizations'); @@ -60,10 +63,9 @@ class Organization extends Model { return myOrganization.orgUid; } - const newOrganizationId = - process.env.USE_SIMULATOR === 'true' - ? 'f1c54511-865e-4611-976c-7c3c1f704662' - : await datalayer.createDataLayerStore(); + const newOrganizationId = USE_SIMULATOR + ? 'f1c54511-865e-4611-976c-7c3c1f704662' + : await datalayer.createDataLayerStore(); const newRegistryId = await datalayer.createDataLayerStore(); const registryVersionId = await datalayer.createDataLayerStore(); @@ -97,7 +99,7 @@ class Organization extends Model { orgUid: newOrganizationId, registryId: registryVersionId, isHome: true, - subscribed: process.env.USE_SIMULATOR === 'true', + subscribed: USE_SIMULATOR, name, icon, }); @@ -112,7 +114,7 @@ class Organization extends Model { ); }; - if (process.env.USE_SIMULATOR !== 'true') { + if (!USE_SIMULATOR) { log('Waiting for New Organization to be confirmed'); datalayer.getStoreData( newRegistryId, diff --git a/src/routes/index.js b/src/routes/index.js index 39a240c8..e85d193c 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -10,7 +10,9 @@ import { prepareDb } from '../database'; import scheduler from '../tasks'; import { V1Router } from './v1'; import { sequelize } from '../database'; +import { getConfig } from '../utils/config-loader'; +const { API_KEY, READ_ONLY } = getConfig().APP; const app = express(); app.use(cors()); @@ -20,9 +22,9 @@ app.use(fileUpload()); // Add optional API key if set in .env file app.use(function (req, res, next) { - if (process.env.API_KEY && process.env.API_KEY !== '') { + if (API_KEY && API_KEY !== '') { const apikey = req.header('x-api-key'); - if (process.env.API_KEY === apikey) { + if (API_KEY === apikey) { next(); } else { res.status(403).json({ message: 'API key not found' }); @@ -35,8 +37,8 @@ app.use(function (req, res, next) { // Add readonly header if set in .env file app.use(function (req, res, next) { res.setHeader('Access-Control-Expose-Headers', 'cw-read-only'); - if (process.env.READ_ONLY) { - res.setHeader('cw-read-only', process.env.READ_ONLY); + if (READ_ONLY) { + res.setHeader('cw-read-only', READ_ONLY); } else { res.setHeader('cw-read-only', false); } diff --git a/src/server.js b/src/server.js index 12881307..594522a9 100644 --- a/src/server.js +++ b/src/server.js @@ -6,6 +6,7 @@ import http from 'http'; import { Server } from 'socket.io'; import Debug from 'debug'; import { connection } from './websocket'; +import { getConfig } from './utils/config-loader'; import dotenv from 'dotenv'; @@ -14,7 +15,7 @@ Debug.enable('climate-warehouse:*'); const debug = Debug('climate-warehouse:server'); -const port = process.env.CW_PORT || 3030; +const port = getConfig().APP.CW_PORT || 3030; const server = http.createServer(rootRouter); server.on('error', onError); diff --git a/src/tasks/sync-audit-table.js b/src/tasks/sync-audit-table.js index c132c7f9..9dc5d80d 100644 --- a/src/tasks/sync-audit-table.js +++ b/src/tasks/sync-audit-table.js @@ -7,14 +7,15 @@ import { decodeHex } from '../utils/datalayer-utils'; import dotenv from 'dotenv'; import Debug from 'debug'; Debug.enable('climate-warehouse:task:audit'); - const log = Debug('climate-warehouse:datalayer:persistance'); - dotenv.config(); +import { getConfig } from '../utils/config-loader'; + +const { USE_SIMULATOR } = getConfig().APP; const task = new Task('sync-audit', async () => { log('Syncing Audit Information'); - if (process.env.USE_SIMULATOR === 'false') { + if (!USE_SIMULATOR) { const organizations = await Organization.findAll({ where: { subscribed: true }, raw: true, diff --git a/src/tasks/sync-default-organizations.js b/src/tasks/sync-default-organizations.js index 45f72369..7e988a80 100644 --- a/src/tasks/sync-default-organizations.js +++ b/src/tasks/sync-default-organizations.js @@ -1,5 +1,8 @@ import { SimpleIntervalJob, Task } from 'toad-scheduler'; import { Organization } from '../models'; +import { getConfig } from '../utils/config-loader'; +const { USE_SIMULATOR } = getConfig().APP; + import dotenv from 'dotenv'; dotenv.config(); @@ -10,7 +13,7 @@ const log = Debug('climate-warehouse:task:organizations'); const task = new Task('sync-default-organizations', () => { log('Subscribing to default organizations'); - if (process.env.USE_SIMULATOR === 'false') { + if (!USE_SIMULATOR) { Organization.subscribeToDefaultOrganizations(); } }); diff --git a/src/tasks/sync-governance-body.js b/src/tasks/sync-governance-body.js index 3a6e95a4..b9f08d74 100644 --- a/src/tasks/sync-governance-body.js +++ b/src/tasks/sync-governance-body.js @@ -1,5 +1,9 @@ import { SimpleIntervalJob, Task } from 'toad-scheduler'; import { Governance } from '../models'; +import { getConfig } from '../utils/config-loader'; +const { GOVERANCE_BODY_ID, GOVERNANCE_BODY_IP, GOVERNANCE_BODY_PORT } = + getConfig().GOVERNANCE; + import dotenv from 'dotenv'; dotenv.config(); @@ -10,11 +14,7 @@ const log = Debug('climate-warehouse:task:governance'); const task = new Task('sync-governance-meta', () => { log('Syncing governance data'); - if ( - process.env.GOVERANCE_BODY_ID && - process.env.GOVERNANCE_BODY_IP && - process.env.GOVERNANCE_BODY_PORT - ) { + if (GOVERANCE_BODY_ID && GOVERNANCE_BODY_IP && GOVERNANCE_BODY_PORT) { Governance.sync(); } }); diff --git a/src/tasks/sync-organization-meta.js b/src/tasks/sync-organization-meta.js index 8d034899..3f9a554d 100644 --- a/src/tasks/sync-organization-meta.js +++ b/src/tasks/sync-organization-meta.js @@ -1,5 +1,8 @@ import { SimpleIntervalJob, Task } from 'toad-scheduler'; import { Organization } from '../models'; +import { getConfig } from '../utils/config-loader'; +const { USE_SIMULATOR } = getConfig().APP; + import dotenv from 'dotenv'; dotenv.config(); @@ -10,7 +13,7 @@ const log = Debug('climate-warehouse:task:organizations'); const task = new Task('sync-organization-meta', () => { log('Syncing subscribed organizations'); - if (process.env.USE_SIMULATOR === 'false') { + if (!USE_SIMULATOR) { Organization.syncOrganizationMeta(); } }); diff --git a/src/utils/config-loader.js b/src/utils/config-loader.js new file mode 100644 index 00000000..b7d2694e --- /dev/null +++ b/src/utils/config-loader.js @@ -0,0 +1,37 @@ +import _ from 'lodash'; +import yaml from 'js-yaml'; +import fs from 'fs'; +import os from 'os'; +import path from 'path'; + +import defaultConfig from './defaultConfig.json'; + +export const getConfig = _.memoize(() => { + const homeDir = os.homedir(); + const configFile = path.resolve( + `${homeDir}/.chia/climate-warehouse/config.yaml`, + ); + + try { + if (!fs.existsSync(configFile)) { + try { + fs.writeFileSync(configFile, yaml.dump(defaultConfig), 'utf8'); + } catch (err) { + // if it still doesnt exist that means we are in an env without write permissions + // so just load the default env + console.log('$$$$$$$$$$$$$$$', process.env.USE_SIMULATOR); + if (process.env.USE_SIMULATOR) { + console.log('################', _.get(process, 'env.USE_SIMULATOR')); + defaultConfig.APP.USE_SIMULATOR = + _.get(process, 'env.USE_SIMULATOR', 'false') === 'true'; + } + + return yaml.load(yaml.dump(defaultConfig)); + } + } + + return yaml.load(fs.readFileSync(configFile, 'utf8')); + } catch (e) { + console.log(`Config file not found at ${configFile}`); + } +}); diff --git a/src/utils/data-assertions.js b/src/utils/data-assertions.js index bda8ba94..07c9f624 100644 --- a/src/utils/data-assertions.js +++ b/src/utils/data-assertions.js @@ -6,9 +6,12 @@ import { Organization, Unit, Project, Staging, Meta } from '../models'; import { transformSerialNumberBlock } from '../utils/helpers'; import datalayer from '../datalayer'; import { formatModelAssociationName } from './model-utils.js'; +import { getConfig } from '../utils/config-loader'; + +const { IS_GOVERNANCE_BODY, READ_ONLY, USE_SIMULATOR } = getConfig().APP; export const assertCanBeGovernanceBody = async () => { - if (process.env.IS_GOVERNANCE_BODY !== 'true') { + if (IS_GOVERNANCE_BODY !== 'true') { throw new Error( 'You are not an governance body and can not use this functionality', ); @@ -36,13 +39,13 @@ export const assertDataLayerAvailable = async () => { }; export const assertIfReadOnlyMode = async () => { - if (process.env.READ_ONLY === 'true') { + if (READ_ONLY) { throw new Error('You can not use this API in read-only mode'); } }; export const assertNoPendingCommits = async () => { - if (process.env.USE_SIMULATOR === 'true') { + if (USE_SIMULATOR) { const pendingCommits = await Staging.findAll({ where: { commited: true, failedCommit: false }, raw: true, @@ -63,7 +66,7 @@ export const assertNoPendingCommits = async () => { }; export const assertWalletIsSynced = async () => { - if (process.env.USE_SIMULATOR === 'false') { + if (!USE_SIMULATOR) { if (!(await datalayer.walletIsSynced())) { throw new Error( 'Your wallet is syncing, please wait for it to sync and try again', @@ -73,7 +76,7 @@ export const assertWalletIsSynced = async () => { }; export const assertWalletIsAvailable = async () => { - if (process.env.USE_SIMULATOR === 'false') { + if (!USE_SIMULATOR) { if (!(await datalayer.walletIsAvailable())) { throw new Error( 'Your wallet is not available, please turn it on to continue using climate warehouse', diff --git a/src/utils/data-loaders.js b/src/utils/data-loaders.js index 48bc2225..3039e01f 100644 --- a/src/utils/data-loaders.js +++ b/src/utils/data-loaders.js @@ -4,15 +4,16 @@ import request from 'request-promise'; import { Governance } from '../models'; import PickListStub from '../models/governance/governance.stub.json'; +import { getConfig } from '../utils/config-loader'; + +const { USE_SIMULATOR, CHIA_NETWORK } = getConfig().APP; +const { TESTNET_DEFAULT_ORGANIZATIONS } = getConfig().TESTNET; let downloadedPickList = {}; export const getPicklistValues = () => downloadedPickList; export const pullPickListValues = async () => { - if ( - process.env.USE_SIMULATOR === 'true' || - process.env.CHIA_NETWORK === 'testnet' - ) { + if (USE_SIMULATOR || CHIA_NETWORK === 'testnet') { downloadedPickList = PickListStub; } else { const goveranceData = await Governance.findOne({ @@ -27,13 +28,10 @@ export const pullPickListValues = async () => { }; export const getDefaultOrganizationList = async () => { - if ( - process.env.USE_SIMULATOR === 'true' || - process.env.CHIA_NETWORK === 'testnet' - ) { + if (USE_SIMULATOR || CHIA_NETWORK === 'testnet') { const options = { method: 'GET', - url: process.env.TESTNET_DEFAULT_ORGANIZATIONS, + url: TESTNET_DEFAULT_ORGANIZATIONS, }; return JSON.parse(await request(Object.assign({}, options))); diff --git a/src/utils/defaultConfig.json b/src/utils/defaultConfig.json new file mode 100644 index 00000000..f78b9cc6 --- /dev/null +++ b/src/utils/defaultConfig.json @@ -0,0 +1,27 @@ +{ + "MIRROR_DB": { + "DB_USERNAME": null, + "DB_PASSWORD": null, + "DB_NAME": null, + "DB_HOST": null + }, + "APP": { + "CW_PORT": 31310, + "DATALAYER_URL": "https://localhost:8562", + "WALLET_URL": "https://localhost:9256", + "USE_SIMULATOR": false, + "READ_ONLY": false, + "API_KEY": null, + "CHIA_NETWORK": "mainnet", + "IS_GOVERNANCE_BODY": false + }, + "TESTNET": { + "TESTNET_PICKLIST_URL": "https://climate-warehouse.s3.us-west-2.amazonaws.com/public/picklists.json", + "TESTNET_DEFAULT_ORGANIZATIONS": "https://climate-warehouse.s3.us-west-2.amazonaws.com/public/cw-organizations-testnet.json" + }, + "GOVERNANCE": { + "GOVERANCE_BODY_ID": "9234ee8a1db6e81e91abbc65961a3c4d2dd97b5404872d9336d60f4ae3057c3d", + "GOVERNANCE_BODY_IP": "71.244.129.72", + "GOVERNANCE_BODY_PORT": 8575 + } +}