diff --git a/README.md b/README.md index de81fc5..4a304bb 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,6 @@ sudo systemctl enable climate-tokenization-engine@ In the `CHIA_ROOT` directory (usually `~/.chia/mainnet` on Linux), Climate Tokenization Engine will add a directory called `climate-tokenization-engine` when the application is first run (in fact, this directory could be deleted at any time and it will be recreated the next time it is started). The main Climate Tokenization Engine configuration file is called `config.yaml` and can be found in this directory. The options in this file are as follows: * **DATA_LAYER_HOST**: Defaults to https://localhost:8562 which is where the Chia DataLayer service should be running. This should only be changed if Chia is running on a different machine than the Climate Tokenization Engine, or DataLayer is running on a non-standard port. -* **HOME_ORG**: The OrgUid that has been created by [CADT](https://github.com/Chia-Network/cadt). You can find this OrgUid by using the [Climate Action Data Trust UI](https://github.com/Chia-Network/cadt-ui) in the `My Organization` section. * **CLIMATE_TOKENIZATION_ENGINE_API_KEY**: Set the API key used to access the Climate Tokenization Engine service. This is useful if you plan to use the [Climate Tokenization Engine User Interface](https://github.com/Chia-Network/Climate-Tokenization-Engine-UI) remotely to access the service. * **CADT_API_SERVER_HOST**: Defaults to localhost. It is strongly recommended to run the Climate Tokenization Engine on the same machine as the CADT API server. * **CADT_API_KEY**: If your CADT API server is protected with an API key, add the same key here so the Climate Tokenization Engine can make the proper requests to the CADT service. diff --git a/package.json b/package.json index e688f47..844e9b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "climate-tokenization-engine", - "version": "1.3.0", + "version": "1.3.1", "bin": "./server.js", "description": "", "main": "proxy.js", diff --git a/server.js b/server.js index 3383ef5..33ba437 100644 --- a/server.js +++ b/server.js @@ -10,6 +10,8 @@ const os = require("os"); const formData = require("express-form-data"); const scheduler = require("./tasks"); +const { getHomeOrgUid } = require("./utils/coreRegApi"); + const { createProxyMiddleware } = require("http-proxy-middleware"); const validator = joiExpress.createValidator({ passError: true }); @@ -32,11 +34,14 @@ app.use( }) ); -app.use("/*", function (req, res, next) { - if (CONFIG.HOME_ORG) { +app.use("/*", async (req, res, next) => { + const homeOrgUid = await getHomeOrgUid(); + + if (homeOrgUid) { res.header("Access-Control-Expose-Headers", "x-org-uid"); - res.header("x-org-uid", CONFIG.HOME_ORG); + res.header("x-org-uid", homeOrgUid); } + logger.debug(req.headers, { method: req.method, url: req.url }); next(); }); @@ -102,10 +107,15 @@ app.post("/connect", validator.body(connectToOrgSchema), async (req, res) => { app.use(async function (req, res, next) { try { - if (CONFIG.HOME_ORG === null) { - logger.error("Configuration does not contain valid HOME_ORG"); + const homeOrgUid = await getHomeOrgUid(); + + if (homeOrgUid === null) { + logger.error( + "CADT does not contain valid HOME_ORG please create one to use this software" + ); throw new Error("Home Org does not exist."); } + next(); } catch (err) { res.status(400).json({ @@ -122,6 +132,8 @@ app.use( changeOrigin: true, secure: false, pathRewrite: async function (path, req) { + const homeOrgUid = await getHomeOrgUid(); + const currentUrl = new URL(`${CONFIG.CADT_API_SERVER_HOST}${path}`); const newQuery = updateQueryWithParam( @@ -132,7 +144,7 @@ app.use( }, { param: "orgUid", - value: CONFIG.HOME_ORG, + value: homeOrgUid, }, { param: "includeProjectInfoInSearch", @@ -143,10 +155,12 @@ app.use( const newPath = "/v1/units" + newQuery; return newPath; }, - onProxyRes(proxyRes, req, res) { - if (CONFIG.HOME_ORG) { + async onProxyRes(proxyRes, req, res) { + const homeOrgUid = await getHomeOrgUid(); + + if (homeOrgUid) { proxyRes.headers["Access-Control-Expose-Headers"] = "x-org-uid"; - proxyRes.headers["x-org-uid"] = CONFIG.HOME_ORG; + proxyRes.headers["x-org-uid"] = homeOrgUid; } }, onProxyReq(proxyReq) { @@ -164,20 +178,22 @@ app.use( changeOrigin: true, secure: false, pathRewrite: async function (path, req) { + const homeOrgUid = await getHomeOrgUid(); const currentUrl = new URL(`${CONFIG.CADT_API_SERVER_HOST}${path}`); const newQuery = updateQueryWithParam(currentUrl.search, { param: "orgUid", - value: CONFIG.HOME_ORG, + value: homeOrgUid, }); const newPath = "/v1/projects" + newQuery; return newPath; }, - onProxyRes(proxyRes, req, res) { - if (CONFIG.HOME_ORG) { + async onProxyRes(proxyRes, req, res) { + const homeOrgUid = await getHomeOrgUid(); + if (homeOrgUid) { proxyRes.headers["Access-Control-Expose-Headers"] = "x-org-uid"; - proxyRes.headers["x-org-uid"] = CONFIG.HOME_ORG; + proxyRes.headers["x-org-uid"] = homeOrgUid; } }, onProxyReq(proxyReq) { @@ -195,6 +211,7 @@ app.use( changeOrigin: true, secure: false, pathRewrite: async function (path, req) { + const homeOrgUid = await getHomeOrgUid(); const currentUrl = new URL(`${CONFIG.CADT_API_SERVER_HOST}${path}`); const newQuery = updateQueryWithParam( @@ -205,7 +222,7 @@ app.use( }, { param: "orgUid", - value: CONFIG.HOME_ORG, + value: homeOrgUid, }, { param: "includeProjectInfoInSearch", @@ -220,10 +237,11 @@ app.use( const newPath = "/v1/units" + newQuery; return newPath; }, - onProxyRes(proxyRes, req, res) { - if (CONFIG.HOME_ORG) { + async onProxyRes(proxyRes, req, res) { + const homeOrgUid = await getHomeOrgUid(); + if (homeOrgUid) { proxyRes.headers["Access-Control-Expose-Headers"] = "x-org-uid"; - proxyRes.headers["x-org-uid"] = CONFIG.HOME_ORG; + proxyRes.headers["x-org-uid"] = homeOrgUid; } }, onProxyReq(proxyReq) { @@ -621,9 +639,11 @@ app.use((err, req, res, next) => { next(); }); -app.use((req, res, next) => { - if (CONFIG.HOME_ORG) { - res.setHeader(headerKeys.ORG_UID, CONFIG.HOME_ORG); +app.use(async (req, res, next) => { + const homeOrgUid = await getHomeOrgUid(); + + if (homeOrgUid) { + res.setHeader(headerKeys.ORG_UID, homeOrgUid); } next(); diff --git a/utils/coreRegApi.js b/utils/coreRegApi.js index 85af351..f2c9ae8 100644 --- a/utils/coreRegApi.js +++ b/utils/coreRegApi.js @@ -84,9 +84,11 @@ const updateUnit = async (unit) => { const getLastProcessedHeight = async () => { try { + const homeOrgUid = await getHomeOrgUid(); + const request = superagent .get(`${CONFIG.CADT_API_SERVER_HOST}/v1/organizations/metadata`) - .query({ orgUid: CONFIG.HOME_ORG }); + .query({ orgUid: homeOrgUid }); if (CONFIG.CADT_API_KEY) { request.set("x-api-key", CONFIG.CADT_API_KEY); @@ -106,6 +108,45 @@ const getLastProcessedHeight = async () => { } }; +const getHomeOrgUid = async () => { + try { + const request = superagent.get( + `${CONFIG.CADT_API_SERVER_HOST}/v1/organizations` + ); + + if (CONFIG.CADT_API_KEY) { + request.set("x-api-key", CONFIG.CADT_API_KEY); + } + + const response = await request; + + if (response.status !== 200) { + throw new Error(`Received non-200 status code: ${response.status}`); + } + + // Iterate through the response keys and find the object where "isHome" is true + let homeOrgUid = null; + for (const key in response.body) { + if (response.body[key].isHome === true) { + homeOrgUid = response.body[key].orgUid; + break; + } + } + + if (!homeOrgUid) { + throw new Error( + 'No organization with "isHome" equal to true found in the response' + ); + } + + return homeOrgUid; + } catch (error) { + console.error(`Could not get home organization UID: ${error}`); + return null; + } +}; + + const setLastProcessedHeight = async (height) => { try { console.log(`Setting last processed height to ${height}`); @@ -132,4 +173,5 @@ module.exports = { retireUnit, getLastProcessedHeight, setLastProcessedHeight, + getHomeOrgUid, }; diff --git a/utils/defaultConfig.json b/utils/defaultConfig.json index b847ef3..fe140ce 100644 --- a/utils/defaultConfig.json +++ b/utils/defaultConfig.json @@ -1,7 +1,6 @@ { "DATA_LAYER_HOST": "https://localhost:8562", "WALLET_HOST": "https://localhost:9256", - "HOME_ORG": null, "CLIMATE_TOKENIZATION_ENGINE_API_KEY": null, "CADT_API_SERVER_HOST": "http://localhost:31310", "CADT_API_KEY": null,