From 4ae05410c4f8aba36a9d318ed99791c79aeceafc Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Tue, 30 May 2023 13:17:12 -0700 Subject: [PATCH 01/11] ci: auto-update code for dev dependencies --- .github/workflows/auto-release.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index ccbb6252..e3a7f613 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -39,8 +39,20 @@ jobs: git add CHANGELOG.md git config --global user.name 'ChiaAutomation' git config --global user.email 'automation@chia.net' - git commit -m "Updating changelog for $version" + git commit -m "chore: Updating changelog for $version" git tag $version git push origin $version git push origin main fi + + - name: Auto-update dev dependencies + run: | + echo "Updating the package.json file now..." + npx --yes npm-check-updates --dep dev -u + echo "Applying updates to the lock file..." + npm update -D + echo "Committing updates to the main branch" + git config --global user.name 'ChiaAutomation' + git config --global user.email 'automation@chia.net' + git commit -m "chore: Updating npm dev dependencies" + git push origin main From 1cd73f3e3a5f64d07ed050efee369964fb69f901 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Tue, 30 May 2023 17:45:03 -0400 Subject: [PATCH 02/11] feat: set bind address to server --- package.json | 1 + src/server.js | 5 ++++- src/utils/defaultConfig.js | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1cfcf742..bde99c42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "cadt", "version": "1.6.0", + "_comment": "DONT CHANGE MAJOR UNLESS DATAMODEL CHANGES: The major version corresponds to the datamodel version your using, so 2.0.0 means it'll use datamodel v2", "private": true, "bin": "build/server.js", "type": "module", diff --git a/src/server.js b/src/server.js index 63c8e81b..4276aa7d 100644 --- a/src/server.js +++ b/src/server.js @@ -15,12 +15,15 @@ dotenv.config(); logger.info('CADT:server'); const port = getConfig().APP.CW_PORT || 3030; +const bindAddress = getConfig().APP.BIND_ADDRESS || 'localhost'; const server = http.createServer(rootRouter); server.on('error', onError); server.on('listening', onListening); -server.listen(port); +server.listen(port, bindAddress, () => { + console.log(`Server listening at http://${bindAddress}:${port}`); +}); const io = new Server(server); io.of('/v1/ws').on('connection', connection); diff --git a/src/utils/defaultConfig.js b/src/utils/defaultConfig.js index 43472f22..cfb73f29 100644 --- a/src/utils/defaultConfig.js +++ b/src/utils/defaultConfig.js @@ -7,6 +7,7 @@ export const defaultConfig = { }, APP: { CW_PORT: 31310, + BIND_ADDRESS: 'localhost', DATALAYER_URL: 'https://localhost:8562', WALLET_URL: 'https://localhost:9256', USE_SIMULATOR: false, From 810a81ff1bdb880816327778c57b0bc8cd5e2829 Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Tue, 30 May 2023 14:57:08 -0700 Subject: [PATCH 03/11] ci: only commit if updates have been made --- .github/workflows/auto-release.yml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index e3a7f613..e4532b60 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -47,12 +47,17 @@ jobs: - name: Auto-update dev dependencies run: | - echo "Updating the package.json file now..." - npx --yes npm-check-updates --dep dev -u - echo "Applying updates to the lock file..." - npm update -D - echo "Committing updates to the main branch" - git config --global user.name 'ChiaAutomation' - git config --global user.email 'automation@chia.net' - git commit -m "chore: Updating npm dev dependencies" - git push origin main + echo "Checking and updating the package.json file now..." + if $(npx --yes npm-check-updates --dep dev -u | grep -q "All dependencies match the latest package versions") + then + echo "No updates found - exiting" + exit 0 + else + echo "Applying updates to the lock file..." + npm update -D + echo "Committing updates to the main branch" + git config --global user.name 'ChiaAutomation' + git config --global user.email 'automation@chia.net' + git commit -m "chore: Updating npm dev dependencies" + git push origin main + fi From 4b9610d1b38b09283df13eccc91812ddc1ca3a25 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Wed, 31 May 2023 14:52:53 -0400 Subject: [PATCH 04/11] fix: superagent cert handling --- src/database/index.js | 8 +- src/datalayer/persistance.js | 149 ++++++++++++++++++----------------- src/datalayer/wallet.js | 46 +++++++---- 3 files changed, 112 insertions(+), 91 deletions(-) diff --git a/src/database/index.js b/src/database/index.js index 68f6db7f..8a5e5f56 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -1,3 +1,4 @@ +import _ from 'lodash'; import { Sequelize } from 'sequelize'; import config from '../config/config.js'; import { logger } from '../config/logger.cjs'; @@ -19,6 +20,11 @@ export const sequelizeMirror = new Sequelize(config[mirrorConfig]); logger.info('CADT:mirror-database'); +const logDebounce = _.debounce(() => { + console.log('Mirror DB not connected'); + logger.info('Mirror DB not connected'); +}, 120000); + export const safeMirrorDbHandler = (callback) => { try { sequelizeMirror @@ -31,7 +37,7 @@ export const safeMirrorDbHandler = (callback) => { } }) .catch(() => { - logger.info('Mirror DB not connected'); + logDebounce(); }); } catch (error) { logger.error( diff --git a/src/datalayer/persistance.js b/src/datalayer/persistance.js index f0b15a6e..5811d489 100644 --- a/src/datalayer/persistance.js +++ b/src/datalayer/persistance.js @@ -26,8 +26,8 @@ const getBaseOptions = () => { const baseOptions = { method: 'POST', - pfx: fs.readFileSync(certFile), - passphrase: fs.readFileSync(keyFile), + cert: fs.readFileSync(certFile), + key: fs.readFileSync(keyFile), timeout: 300000, }; return baseOptions; @@ -35,14 +35,14 @@ const getBaseOptions = () => { const getMirrors = async (storeId) => { const url = `${CONFIG.DATALAYER_URL}/get_mirrors`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: storeId }); const data = response.body; @@ -88,12 +88,12 @@ const addMirror = async (storeId, url, forceAddMirror = false) => { fee: _.get(CONFIG, 'DEFAULT_FEE', 300000000), }; - const { pfx, passphrase, timeout } = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); const response = await superagent .post(`${CONFIG.DATALAYER_URL}/add_mirror`) - .key(passphrase) - .pfx(pfx) + .key(key) + .cert(cert) .send(options) .timeout(timeout); @@ -107,7 +107,8 @@ const addMirror = async (storeId, url, forceAddMirror = false) => { logger.error(`FAILED ADDING MIRROR FOR ${storeId}`); return false; } catch (error) { - logger.error(error); + logger.error('ADD_MIRROR', error); + console.trace(error); return false; } }; @@ -127,14 +128,14 @@ const removeMirror = async (storeId, coinId) => { } const url = `${CONFIG.DATALAYER_URL}/delete_mirror`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: coinId, fee: _.get(CONFIG, 'DEFAULT_FEE', 300000000), @@ -157,14 +158,14 @@ const removeMirror = async (storeId, coinId) => { const getRootDiff = async (storeId, root1, root2) => { const url = `${CONFIG.DATALAYER_URL}/get_kv_diff`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: storeId, hash_1: root1, @@ -186,14 +187,14 @@ const getRootDiff = async (storeId, root1, root2) => { const getRootHistory = async (storeId) => { const url = `${CONFIG.DATALAYER_URL}/get_root_history`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: storeId, }); @@ -213,16 +214,16 @@ const getRootHistory = async (storeId) => { const unsubscribeFromDataLayerStore = async (storeId) => { const url = `${CONFIG.DATALAYER_URL}/unsubscribe`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); logger.info(`RPC Call: ${url} ${storeId}`); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: storeId, fee: _.get(CONFIG, 'DEFAULT_FEE', 300000000), @@ -244,14 +245,14 @@ const unsubscribeFromDataLayerStore = async (storeId) => { const dataLayerAvailable = async () => { const url = `${CONFIG.DATALAYER_URL}/get_routes`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({}); const data = response.body; @@ -279,14 +280,14 @@ const getStoreData = async (storeId, rootHash) => { } const url = `${CONFIG.DATALAYER_URL}/get_keys_values`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send(payload); const data = response.body; @@ -315,14 +316,14 @@ const getStoreData = async (storeId, rootHash) => { const getRoot = async (storeId, ignoreEmptyStore = false) => { const url = `${CONFIG.DATALAYER_URL}/get_root`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: storeId }); const data = response.body; @@ -345,14 +346,14 @@ const getRoot = async (storeId, ignoreEmptyStore = false) => { const getRoots = async (storeIds) => { const url = `${CONFIG.DATALAYER_URL}/get_roots`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ ids: storeIds }); const data = response.body; @@ -373,13 +374,13 @@ const pushChangeListToDataLayer = async (storeId, changelist) => { await wallet.waitForAllTransactionsToConfirm(); const url = `${CONFIG.DATALAYER_URL}/batch_update`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ changelist, id: storeId, @@ -418,14 +419,14 @@ const pushChangeListToDataLayer = async (storeId, changelist) => { const createDataLayerStore = async () => { const url = `${CONFIG.DATALAYER_URL}/create_data_store`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ fee: _.get(CONFIG, 'DEFAULT_FEE', 300000000), }); @@ -464,16 +465,16 @@ const subscribeToStoreOnDataLayer = async (storeId) => { } const url = `${CONFIG.DATALAYER_URL}/subscribe`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); logger.info(`Subscribing to: ${storeId}`); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ id: storeId, fee: _.get(CONFIG, 'DEFAULT_FEE', 300000000), @@ -507,14 +508,14 @@ const getSubscriptions = async () => { } const url = `${CONFIG.DATALAYER_URL}/subscriptions`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({}); const data = response.body; @@ -534,14 +535,14 @@ const getSubscriptions = async () => { const makeOffer = async (offer) => { const url = `${CONFIG.DATALAYER_URL}/make_offer`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ ...offer, fee: _.get(CONFIG, 'DEFAULT_FEE', 300000000), @@ -562,14 +563,14 @@ const makeOffer = async (offer) => { const takeOffer = async (offer) => { const url = `${CONFIG.DATALAYER_URL}/take_offer`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send(offer); const data = response.body; @@ -589,14 +590,14 @@ const takeOffer = async (offer) => { const verifyOffer = async (offer) => { console.log(offer); const url = `${CONFIG.DATALAYER_URL}/verify_offer`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send(offer); const data = response.body; @@ -616,14 +617,14 @@ const verifyOffer = async (offer) => { const cancelOffer = async (tradeId) => { const url = `${CONFIG.DATALAYER_URL}/cancel_offer`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) - .timeout({ response: baseOptions.timeout }) + .key(key) + .cert(cert) + .timeout(timeout) .send({ trade_id: tradeId, secure: true, diff --git a/src/datalayer/wallet.js b/src/datalayer/wallet.js index 7d72ec09..4a79c6b5 100644 --- a/src/datalayer/wallet.js +++ b/src/datalayer/wallet.js @@ -13,27 +13,31 @@ const USE_SIMULATOR = getConfig().APP.USE_SIMULATOR; const getBaseOptions = () => { const chiaRoot = getChiaRoot(); const certFile = path.resolve( - `${chiaRoot}/config/ssl/wallet/private_wallet.crt`, + `${chiaRoot}/config/ssl/data_layer/private_data_layer.crt`, ); const keyFile = path.resolve( - `${chiaRoot}/config/ssl/wallet/private_wallet.key`, + `${chiaRoot}/config/ssl/data_layer/private_data_layer.key`, ); const baseOptions = { - pfx: fs.readFileSync(certFile), - passphrase: fs.readFileSync(keyFile), + method: 'POST', + cert: fs.readFileSync(certFile), + key: fs.readFileSync(keyFile), + timeout: 300000, }; - return baseOptions; }; const walletIsSynced = async () => { try { + const { cert, key, timeout } = getBaseOptions(); + const response = await superagent .post(`${rpcUrl}/get_sync_status`) .send({}) - .key(getBaseOptions().passphrase) - .cert(getBaseOptions().pfx); + .key(key) + .cert(cert) + .timeout(timeout); const data = JSON.parse(response.text); @@ -58,13 +62,16 @@ const getWalletBalance = async () => { return Promise.resolve('999.00'); } + const { cert, key, timeout } = getBaseOptions(); + const response = await superagent .post(`${rpcUrl}/get_wallet_balance`) .send({ wallet_id: 1, }) - .key(getBaseOptions().passphrase) - .cert(getBaseOptions().pfx); + .key(key) + .cert(cert) + .timeout(timeout); if (response.text) { const data = JSON.parse(response.text); @@ -95,14 +102,17 @@ const waitForAllTransactionsToConfirm = async () => { }; const hasUnconfirmedTransactions = async () => { + const { cert, key, timeout } = getBaseOptions(); + const response = await superagent .post(`${rpcUrl}/get_transactions`) .send({ wallet_id: '1', sort_key: 'RELEVANCE', }) - .key(getBaseOptions().passphrase) - .cert(getBaseOptions().pfx); + .key(key) + .cert(cert) + .timeout(timeout); const data = JSON.parse(response.text); @@ -124,11 +134,14 @@ const getPublicAddress = async () => { return Promise.resolve('xch33300ddsje98f33hkkdf9dfuSIMULATED_ADDRESS'); } + const { cert, key, timeout } = getBaseOptions(); + const response = await superagent .post(`${rpcUrl}/get_next_address`) .send({ wallet_id: 1, new_address: false }) - .key(getBaseOptions().passphrase) - .cert(getBaseOptions().pfx); + .key(key) + .cert(cert) + .timeout(timeout); const data = JSON.parse(response.text); @@ -141,13 +154,14 @@ const getPublicAddress = async () => { const getActiveNetwork = async () => { const url = `${rpcUrl}/get_network_info`; - const baseOptions = getBaseOptions(); + const { cert, key, timeout } = getBaseOptions(); try { const response = await superagent .post(url) - .key(baseOptions.passphrase) - .cert(baseOptions.pfx) + .key(key) + .cert(cert) + .timeout(timeout) .send(JSON.stringify({})); const data = response.body; From 6c2b9cfab2a9fe2a66914c316ef45b77a9f84228 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Wed, 31 May 2023 14:55:36 -0400 Subject: [PATCH 05/11] chore: bump to 1.6.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bde99c42..3003ec40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cadt", - "version": "1.6.0", + "version": "1.6.1", "_comment": "DONT CHANGE MAJOR UNLESS DATAMODEL CHANGES: The major version corresponds to the datamodel version your using, so 2.0.0 means it'll use datamodel v2", "private": true, "bin": "build/server.js", From 3d0a9c11042bc3129f84d5b1c8fd04e5c416597a Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Wed, 31 May 2023 13:26:35 -0700 Subject: [PATCH 06/11] docs: README bind address update --- README.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c6820efc..48c43d75 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,10 @@ chmod ug+x .git/hooks/* npm run start ``` +### Ports, Networking, and Security + +The port for the CADT API can be set with the parameter `CW_PORT` in the `config.yaml` file discussed above. The default port is 31310. The CADT API will listen on all network interfaces on this port so care must be taken to block this port at the firewall or networking level to avoid this API being public. In many cases, the API will need to be public for either the [CADT UI](https://github.com/Chia-Network/climate-warehouse-ui) or to integrate with existing tools and scripts. To add authentication to the API, use the `CADT_API_KEY` parameter. Alternatively, the API can be served behind an authentication proxy to restrict access and the `CADT_API_KEY` can be left blank. If running an observer node with `READ_ONLY` set to `true`, the CADT API will only share data from the public blockchain, and running without authentication is usually safe. If `READ_ONLY` is set to `false`, authentication must be used to prevent unauthorized writes to the blockchain. + ### Configuration In the `CHIA_ROOT` directory (usually `~/.chia/mainnet` on Linux), CADT will add a directory called `climate-warehouse/v1` when the application is first run (in fact, this directory could be deleted at any time and CADT will recreate it next time it is started). The main CADT configuration file is called `config.yaml` and can be found in this directory. The options in this file are as follows (the full list of available options can be seen in the [config template](src/utils/defaultConfig.json)): @@ -108,6 +112,7 @@ In the `CHIA_ROOT` directory (usually `~/.chia/mainnet` on Linux), CADT will add * **DB_HOST**: Hostname of the MySQL database * **APP**: This section is for configuring the CADT application. * **CW_PORT**: CADT port where the API will be available. 31310 by default. + * **BIND_ADDRESS**: By default, CADT listens on localhost only. To enable remote connections to CADT, change this to `0.0.0.0` to listen on all network interfaces, or to an IP address to listen on a specific network interface. * **DATALAYER_URL**: URL and port to connect to the [Chia DataLayer RPC](https://docs.chia.net/datalayer-rpc). If Chia is installed locally with default settings, https://localhost:8562 will work. * **WALLET_URL**: URL and port to conned to the [Chia Wallet RPC](https://docs.chia.net/wallet-rpc). If Chia is installed on the same machine as CADT with default settings, https://localhost:9256 will work. * **USE_SIMULATOR**: Developer setting to populate CADT from a governance file and enables some extra APIs. Should always be "false" under normal usage. @@ -119,21 +124,18 @@ In the `CHIA_ROOT` directory (usually `~/.chia/mainnet` on Linux), CADT will add * **DEFAULT_FEE**: [Fee](https://docs.chia.net/mempool/) for each transaction on the Chia blockchain in mojos. The default is 300000000 mojos (0.0003 XCH) and can be set higher or lower depending on how [busy](https://dashboard.chia.net/d/46EAA05E/mempool-transactions-and-fees?orgId=1) the Chia network is. If a fee is set very low, it may cause a delay in transaction processing. * **DEFAULT_COIN_AMOUNT**: Units are mojo. Each DataLayer transaction needs a coin amount and the default is 300000000 mojo. * **DATALAYER_FILE_SERVER_URL**: Chia DataLayer HTTP URL and port. If serving DataLayer files from S3, this would be the public URL of the S3 bucket. Must be publicly available. + * **TASKS**: Section for configuring sync intervals + * **AUDIT_SYNC_TASK_INTERVAL**: Default 30 + * **DATAMODEL_SYNC_TASK_INTERVAL**: Default 60 + * **GOVERNANCE_SYNC_TASK_INTERVAL**: Default 86400 + * **ORGANIZATION_META_SYNC_TASK_INTERVAL**: Default 86400 + * **PICKLIST_SYNC_TASK_INTERVAL**: Default 30 * **GOVERNANCE**: Section on settings for the Governance body to connect to. - * **GOVERNANCE_BODY_ID**: This determines the governance body your CADT network will be connected to. While there could be multiple governance body IDs, the default of 23f6498e015ebcd7190c97df30c032de8deb5c8934fc1caa928bc310e2b8a57e is the right ID for most people. -* **TASKS**: Section for configuring sync intervals - * **AUDIT_SYNC_TASK_INTERVAL**: Default 30 - * **DATAMODEL_SYNC_TASK_INTERVAL**: Default 60 - * **GOVERNANCE_SYNC_TASK_INTERVAL**: Default 86400 - * **ORGANIZATION_META_SYNC_TASK_INTERVAL**: Default 86400 - * **PICKLIST_SYNC_TASK_INTERVAL**: Default 30 + * **GOVERNANCE_BODY_ID**: This determines the governance body your CADT network will be connected to. While there could be multiple governance body IDs, the default of `23f6498e015ebcd7190c97df30c032de8deb5c8934fc1caa928bc310e2b8a57e` is the right ID for most people. + ​ Note that the CADT application will need to be restarted after any changes to the config.yaml file. -### Ports, Networking, and Security - -The port for the CADT API can be set with the parameter `CW_PORT` in the `config.yaml` file discussed above. The default port is 31310. The CADT API will listen on all network interfaces on this port so care must be taken to block this port at the firewall or networking level to avoid this API being public. In many cases, the API will need to be public for either the [CADT UI](https://github.com/Chia-Network/climate-warehouse-ui) or to integrate with existing tools and scripts. To add authentication to the API, use the `CADT_API_KEY` parameter. Alternatively, the API can be served behind an authentication proxy to restrict access and the `CADT_API_KEY` can be left blank. If running an observer node with `READ_ONLY` set to `true`, the CADT API will only share data from the public blockchain, and running without authentication is usually safe. If `READ_ONLY` is set to `false`, authentication must be used to prevent unauthorized writes to the blockchain. - ## Developer Guide ​ ### Build Binaries From ae8632c1a624be0dbfefef78ac0b4ea866921934 Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Wed, 31 May 2023 13:27:06 -0700 Subject: [PATCH 07/11] ci: auto-update dev dependencies in the develop branch --- .github/workflows/auto-release.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index e4532b60..3826a4ae 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -45,6 +45,14 @@ jobs: git push origin main fi + - name: Checkout develop branch + uses: actions/checkout@v3 + with: + # Need PACKAGE_ADMIN_PAT token so when the tag is created, the tag automation runs + token: ${{ secrets.PACKAGE_ADMIN_PAT }} + fetch-depth: 0 + ref: 'develop' + - name: Auto-update dev dependencies run: | echo "Checking and updating the package.json file now..." @@ -59,5 +67,5 @@ jobs: git config --global user.name 'ChiaAutomation' git config --global user.email 'automation@chia.net' git commit -m "chore: Updating npm dev dependencies" - git push origin main + git push origin develop fi From 636b764115d92449fc7ada60692b37380fb608ae Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Wed, 31 May 2023 13:29:13 -0700 Subject: [PATCH 08/11] build: upgrade to node v16.14 --- .nvmrc | 2 +- check_node_version.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.nvmrc b/.nvmrc index 946789e6..0cf077e6 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.0.0 +16.14 diff --git a/check_node_version.js b/check_node_version.js index 0a217762..ba1c7ae9 100644 --- a/check_node_version.js +++ b/check_node_version.js @@ -1,5 +1,5 @@ import semver from 'semver'; -import config from './package.json'; +import config from './package.json' assert { type: 'json' }; const { engines } = config; const version = engines.node; From e20b67116a81c91da3c43b4357f5042f4881f4fd Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Wed, 31 May 2023 14:29:02 -0700 Subject: [PATCH 09/11] docs: BIND_ADDRESS and proxying documentation --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 48c43d75..bb420f1b 100644 --- a/README.md +++ b/README.md @@ -99,11 +99,15 @@ npm run start ### Ports, Networking, and Security -The port for the CADT API can be set with the parameter `CW_PORT` in the `config.yaml` file discussed above. The default port is 31310. The CADT API will listen on all network interfaces on this port so care must be taken to block this port at the firewall or networking level to avoid this API being public. In many cases, the API will need to be public for either the [CADT UI](https://github.com/Chia-Network/climate-warehouse-ui) or to integrate with existing tools and scripts. To add authentication to the API, use the `CADT_API_KEY` parameter. Alternatively, the API can be served behind an authentication proxy to restrict access and the `CADT_API_KEY` can be left blank. If running an observer node with `READ_ONLY` set to `true`, the CADT API will only share data from the public blockchain, and running without authentication is usually safe. If `READ_ONLY` is set to `false`, authentication must be used to prevent unauthorized writes to the blockchain. +By default, the CADT API will listen on localhost only on port 31310. If running a node with `READ_ONLY` set to `false`, it is highly recommended that CADT is run on a private network or with access limited by IP address. To allow remote connections to CADT, set the `BIND_ADDRESS` (see the [Configuration](#configuration) section below) to the IP to listen on, or `0.0.0.0` to listen on all interfaces. The port for the CADT API can be set with the parameter `CW_PORT`. The default port is 31310. In many cases, users will need to access the API from their workstations for either the [CADT UI](https://github.com/Chia-Network/climate-warehouse-ui) or to integrate with existing tools and scripts. To add authentication to the API, use the `CADT_API_KEY` parameter. Alternatively, the API can be served behind an authentication proxy to restrict access and the `CADT_API_KEY` can be left blank. If running an observer node with `READ_ONLY` set to `true`, the CADT API will only share data from the public blockchain, and running without authentication is usually safe. If `READ_ONLY` is set to `false`, authentication must be used to prevent unauthorized writes to the blockchain. + +### Adding Encryption to the CADT API + +The CADT API uses HTTP and is unencrypted. To add encryption, use a reverse proxy like [Nginx](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) with an SSL certificate. In this scenario, the CADT application can be set to listen only on localhost and Nginx (on the same server) would proxy incoming requests to port 31310. ### Configuration -In the `CHIA_ROOT` directory (usually `~/.chia/mainnet` on Linux), CADT will add a directory called `climate-warehouse/v1` when the application is first run (in fact, this directory could be deleted at any time and CADT will recreate it next time it is started). The main CADT configuration file is called `config.yaml` and can be found in this directory. The options in this file are as follows (the full list of available options can be seen in the [config template](src/utils/defaultConfig.json)): +In the `CHIA_ROOT` directory (usually `~/.chia/mainnet` on Linux), CADT will add a directory called `cadt/v1` when the application is first run (in fact, this directory could be deleted at any time and CADT will recreate it next time it is started). The main CADT configuration file is called `config.yaml` and can be found in this directory. The options in this file are as follows (the full list of available options can be seen in the [config template](src/utils/defaultConfig.json)): * **MIRROR_DB**: This section is for configuring the MySQL-compatible database that can be used for easy querying for report generation. This is optional and only provides a read-only mirror of the data CADT uses. * **DB_USERNAME**: MySQL username From a81898eab0f614c751efd2987bd84e0e37881350 Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Wed, 31 May 2023 14:33:35 -0700 Subject: [PATCH 10/11] ci: node 16.14 everywhere --- .github/workflows/build-docker.yaml | 2 +- .github/workflows/build.yaml | 4 ++-- .github/workflows/tests.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docker.yaml b/.github/workflows/build-docker.yaml index d659a2a5..b8fc4545 100644 --- a/.github/workflows/build-docker.yaml +++ b/.github/workflows/build-docker.yaml @@ -31,7 +31,7 @@ jobs: - name: Setup Node 16.x uses: actions/setup-node@v3 with: - node-version: '16.13' + node-version: '16.14' - name: Ignore Husky run: npm pkg delete scripts.prepare diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ec95ef36..a0065c57 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,8 +42,8 @@ jobs: - name: Setup Node 16.x uses: actions/setup-node@v3 with: - node-version: '16.13' - + node-version: '16.14' + - name: Install Husky run: npm install --save-dev husky diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 1e3daadd..331ece17 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -16,7 +16,7 @@ jobs: name: NPM Tests runs-on: ubuntu-latest container: - image: node:16.13 + image: node:16.14 steps: - uses: Chia-Network/actions/clean-workspace@main From 5c9944e1a6a91c6bcf9b6cd331b9a079e98d2ba2 Mon Sep 17 00:00:00 2001 From: Zachary Brown Date: Wed, 31 May 2023 14:42:16 -0700 Subject: [PATCH 11/11] ci: update to node 16.14 in more places --- .github/workflows/build.yaml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a0065c57..2c8e228e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -181,7 +181,7 @@ jobs: - name: Build arm 64 dist run: | mkdir pkgcache - docker run --rm --platform linux/arm64 -v $(pwd):/app -w /app -e PKG_CACHE_PATH=pkgcache node:16.13 /bin/bash -c "npm pkg delete scripts.prepare && npm install && npm i -g @babel/cli @babel/preset-env pkg && npm run create-linux-arm64-dist" + docker run --rm --platform linux/arm64 -v $(pwd):/app -w /app -e PKG_CACHE_PATH=pkgcache node:16.14 /bin/bash -c "npm pkg delete scripts.prepare && npm install && npm i -g @babel/cli @babel/preset-env pkg && npm run create-linux-arm64-dist" - name: Copy sqlite3 run: | diff --git a/package.json b/package.json index bde99c42..8327ed3c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "bin": "build/server.js", "type": "module", "engines": { - "node": ">=16.0" + "node": ">=16.14" }, "scripts": { "requirements-check": "node --experimental-json-modules check_node_version.js",